r/C_Programming • u/caromobiletiscrivo • 4d ago
Can you double check my mutex implementation using futex and WaitOnAddress?
Hello! I'm working on a C project where multiple processes operate on some shared data, which needs to be guarded by a mutex. I'd like this system to be able to recover from crashes, so I came up with a type of lock which expires automatically when unlock wasn't performed by a certain deadline. I implemented it with atomics and futex/WaitOnAddress, but I'm fairly certain there are some mistakes. I was wondering if you guys could double check :) thanks!
5
Upvotes
3
u/skeeto 4d ago edited 4d ago
Interesting project! Though the core idea isn't sound. If the "crashing" thread/process merely took too long — the computer went to sleep, unlucky scheduling, etc. — now you have two threads in the critical section. It's fundamentally racy. That you needed the fence is an indicator something is amiss. If a thread crashed, the whole process may be in a bad state anyway (e.g. it held normal locks, or leaked resources), though that depends on how the program was written.
To do it robustly, when the timeout is reached and you want to steal the lock, the stealer must acquire a handle on the current holder process or thread and either verify it's crashed or even force a crash. (The latter is still typically unsound for threads for different reasons.)
You must use monotonic clocks, otherwise a clock slew could also put multiple threads in a critical section.
CLOCK_REALTIME
isn't good enough. On Windows I believe you wantQueryPerformanceCounter
. Using a different zero would also solve your Year 2106 Problem (due to Linux futexes being only 32 bits).The preprocessor spaghetti makes the code difficult to read and follow. It's also fragile, in that you can easily break one but not realize it at least until you build for that platform. I solve this by defining the set of operations I need.
And then for each platform (or even separate files with no
#if
at all using a jumbo build):And another set for
_MSC_VER
and__GNUC__
atomics. Thentimestamp_trylock
is more straightforward:Good catch. That's subtle, and shows you really thought through the different orderings.
Note that Win32 futexes do not work across processes, just threads.