Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to lock a mutex and have it automatically unlock after a given time?

This is on Linux but ideally I'd like a POSIX compliant solution.

I have two threads each of which is able to write to a hardware bus via an API function. Only one thread is allowed to write to the bus at any given time, and after a bus write, the bus must not be written to for a given time of the order of several hundred milliseconds.

Both threads are implemented as state machines.

The obvious solution is to use a mutex to serialise access to the bus, set a counter or timestamp, and have the state machine unlock the mutex after the appropriate time has expired.

This seems a little fragile to me. If a future maintenance developer incorrectly modifies the state machine, the mutex might not get released, causing hard-to-diagnose deadlocks.

Is there an API call that locks a mutex, but automatically unlocks it after a given timeout? Google reveals pthread_mutex_timedlock(), but this isn't quite the same thing.

like image 381
Simon Elliott Avatar asked Dec 14 '25 06:12

Simon Elliott


2 Answers

I'm not aware of any pthreads API which allows locks to be automatically released.

Personally I'd try and serialise access to the bus through a single thread to avoid these complications. If that thread maintains an input queue and other threads post their requests to it, then it could do whatever serialisation and conflict resolution it wished, and this also makes it easier to implement the delay before further access. As long as you're careful not to use any blocking functions in this thread your only real failure case is that it might be terminated accidentally.

If you need to both read and write from the bus, you can give every thread an input queue and have worker threads post a "read request" to the IO thread and then wait for the response to be posted back to its own input queue. If there's only ever one outstanding request for a thread then you don't really need a queue, a simple condition variable and a pointer to the structure to fill in would probably work fine.

If you definitely want two threads to share the resource then I think you're always going to have a risk of the mutex becoming locked up. Even if you set a timer and forcibly release the mutex after a fixed time, that could simply cause different bugs where a thread goes on to use the resource believing it has the lock when in fact it's held by another thread entirely. Ultimately you're trying to plan robustness against future programming errors, which is a fine aim but there's a limit - mutexes are just something one has to be careful with.

I suggest your best approach, if you must go the mutex route, is to simply minimise the code which requires the mutex and avoid blocking calls within it. If you're implementing a state machine, try to ensure that the mutex doesn't have to stay locked between state transitions. If at all possible, scope your mutex locks so that they're only held for the duration of a single function call at some level in your call chain - this makes it a lot easier to spot lock/unlock mismatches by eye. If you're using C++ then use RAII to make releasing your locks more reliable.

But once again, I think you'll find life a lot easier serialising your requests in some way, typically by declaring one thread the arbiter (either one of the existing threads or a new one).

like image 138
Cartroo Avatar answered Dec 16 '25 22:12

Cartroo


How about having a timestamp of last bus access in shared (and mutex-covered) memory? Each write would than look like this:

  1. lock mutex
  2. check timestamp of last access; if your wait-time has not passed yet, sleep for remainder of this time, as you cannot do anything else in this thread anyway
  3. do the write
  4. update timestamp of last access
  5. unlock mutex
like image 28
che Avatar answered Dec 16 '25 20:12

che



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!