Using pthreads it mandatory to call pthread_mutex_init() on any mutex before obtaining the lock.
According to POSIX the locking an uninitialized mutex is only defined for mutex with priority protection (opengroup : pthread_mutex_lock)
According to the manpage pthread_mutex_lock.3thr it should return EINVAL if called on an uninitalized mutex. Assuming portability is not an issue, would it be valid (a good idea?) to write code like:
pthread_mutex_t lock;
int ret = pthread_mutex_lock(&lock);
if (ret != 0){
if(ret == EINVAL){
pthread_mutex_init(&lock, NULL);
} else {
/* other error */
}
}
Is there another way to check if a pthread_mutex has been initialized?
The whole scenario is part of a library (by politics unfortunately not C++) and I want to avoid to the maximum wrong usage. I.e. A client may initialize the object created twice, may pass the object to other functions before properly initialize it etc.
Currently there is an aditional flag in the object that marks if the mutex has been initialized, I was wondereing if this is really necessary.
Looking at the expansion of the macro PTHREAD_MUTEX_INITIALIZER
for static mutex initialization it just expands into a struct with all members set to 0.
Can I assume that is not required to call mutex_destroy if it is no longer required, given the ressource itself is freed (sure if noone else uses it)?
Update: Jens' answer is absolutely correct. The following program yields completely undefined behavior:
int main(int argc, char** argv)
{
pthread_mutex_t lock;
int ret = pthread_mutex_lock(&lock);
if (ret != 0) {
printf(" ERR : %d %s \n", ret, strerror(ret));
if (ret == EINVAL) {
pthread_mutex_init(&lock, NULL);
}
} else {
printf(" ok \n");
}
pthread_mutex_unlock(&lock);
return 0;
}
Sometimes it deadlocks, somtimes it prints o.k. .....
A mutex can be statically initialized by assigning PTHREAD_MUTEX_INITIALIZER in its definition, as follows: pthread_mutex_t def_mutex = PTHREAD_MUTEX_INITIALIZER; A mutex must be initialized (either by calling pthread_mutex_init(), or statically) before it may be used in any other mutex functions.
The pthread_mutex_init() function initializes a mutex with the specified attributes for use. The new mutex may be used immediately for serializing critical resources. If attr is specified as NULL, all attributes are set to the default mutex attributes for the newly created mutex.
The pthread_mutex_destroy() function may fail if: [EBUSY] The implementation has detected an attempt to destroy the object referenced by mutex while it is locked or referenced (for example, while being used in a pthread_cond_wait() or pthread_cond_timedwait()) by another thread.
Pthread mutexes are quite the same as RIOT mutexes. Recursive locking is not supported. A thread can unlock a mutex even if it does not hold it. Definition at line 33 of file pthread_mutex.
No you can't detect that. EINVAL
may be returned for an uninitialized mutex, but it mustn't necessarily.
In addition POSIX states:
Attempting to initialize an already initialized mutex results in undefined behavior.
so you shouldn't try that.
The best way is to avoid that situation completely and to initialize the variable properly. This should be done with the macro PTHREAD_MUTEX_INITIALIZER
.
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With