I have multiple threads which access a piece of hardware and I am preventing contention by using a mutex.

The software is very complex and its possible deadlocks may be in the system due to recursive calls to take the lock. For this reason I am using 'pthread_mutex_timedlock' instead of 'pthread_mutex_lock'. I would rather print an error message and continue than causing the system to watchdog and reset. This would allow me to see the issue without bringing the system down.

Here a snippets of code that should help you understand what I am trying to do.

There are other threads that also take the lock but that is not an issue. The problem I am having is that the timeout on the lock never occurs. It waits forever and watchdogs the system which is precisely what I am trying to avoid.

The 'abs_time.tv_sec' is correct - I have printed it and the system clock is already initialized by the time I try and use it.

I understand Windows will prevent a lock on the same process but Linux has no such protection. I realize I should not be recursively calling m_TAKE_LOCK() but the purpose of using the timedlock is to catch bugs (print a message and continue).

If you use pthread_mutexattr_settype(3posix) to set the mutex to type PTHREAD_MUTEX_RECURSIVE, you should be able to recursively acquire your locks within a single thread.
–
sarnoldDec 17 '11 at 1:09

1

Style issue: you should use do { ... } while(0) instead of { ... }, since it will allow to append a ; to its invocation -- which is much nicer. And use it for both TAKE and RELEASE.
–
fgeDec 17 '11 at 1:10

2 Answers
2

You cannot attempt to acquire a mutex you already hold. It's not permitted. You are assuming that it will produce a specific result and there is no guarantee it will do so.

You should be using a recursive mutex. And you should release it the same number of times you acquire it.

However, fundamentally, it is an absolute requirement that any code that acquires a mutex know, for sure, what mutexes it holds while it is running that relate to code that function might call into directly or indirectly. (It does not need to know about 'higher-level' mutexes held by code that calls it but untouched by functions it could ever call into.)

So, for example, if you are making a class called "Foo" that calls into "Bar", every function of the "Foo" class must know about any locks it holds that are associated with "Foo" or "Bar". If some new class, "Qux" calls it, the "Foo" code need not know what "Qux" locks are held, but if "Qux" calls into "Foo" while holding a lock on "Bar", the "Foo" function must know this. You must implement a sane lock hierarchy. (Unless you fully understand the rationale for this rule and know for sure that it doesn't apply.) Otherwise, your code will never work right except occasionally by luck.

The POSIX spec does not require it to time out: "If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall be terminated when the specified timeout expires." There is no other thread to wait for. Nor does it require an error, "The pthread_mutex_timedlock() function may fail if:
[EDEADLK] A deadlock condition was detected or the current thread already owns the mutex." "May" indicates error conditions whose support is optional, the term "shall fail if" is used to indicate required behavior.

Thanks for taking the time to answer this. Your quote of the posix spec makes is clear but I overlooked it. I will investigate a recursive lock. It seems that is better suited to my needs to prevent a system hang during unintended recursive calls to the mutex lock.
–
ObnoxiousKiwiDec 17 '11 at 4:45