Eyal Wurmbrand
Eyal Wurmbrand

Reputation: 119

linux pthread_mutex_lock only works in the second try

Edit: I'm attaching a snippet, I've initialized attr, and all calls were good.

I've been trying to use a mutex with PRIO_PROTECT, but first call returns EINVAL, while second call returns zero\success. here's what I've done:

pthread_mutexattr_setprioceiling(&attr, 99);
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_PROTECT);
pthread_mutex_init(&plock, &attr);
pthread_mutexattr_destroy(&attr);
ret = pthread_mutex_lock(&plock);  //now ret == EINVAL
ret = pthread_mutex_lock(&plock);  // ret == 0

I understand that EINVAL means that the caller priority is higher than the ceiling, so I have 2 questions:

  1. why does it work on the second try?

  2. How to lower the thread's priority to the ceiling? or rather, set the ceiling to the thread's priority?

Upvotes: 1

Views: 186

Answers (2)

user3629249
user3629249

Reputation: 16540

Are you trying to bump the current executing code priority or simply protect some data.

If simply trying to protect some data...

pthread_mutex_t  myMutex = PTHREAD_MUTEX_INITIALIZER;

then when wanting to use the mutex:

pthread_mutex_lock( &myMutex );
... // manipulate the 'critical' data

Then when ready to allow another thread to access that same data.

... // finished manipulation of the 'critical' data
pthread_mutex_unlock( &myMutex );

Note: there are other values for the initialization, but the above macro value is the most common.

Upvotes: 0

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136515

A call to pthread_mutexattr_init is missing.


PTHREAD_PRIO_PROTECT means:

When a thread owns one or more non-robust mutexes initialized with the PTHREAD_PRIO_PROTECT protocol, it shall execute at the higher of its priority or the highest of the priority ceilings of all the non-robust mutexes owned by this thread and initialized with this attribute, regardless of whether other threads are blocked on any of these non-robust mutexes or not.

Which means that pthread_mutex_lock sets the priority of the current thread to max(current_priority, prioceiling). Your prioceiling is 99 and such a priority requires a thread with real-time scheduling class (FIFO or round-robin).

In fact, any priority for pthread_mutexattr_setprioceiling requires a real-time scheduling class:

The values of prioceiling are within the maximum range of priorities defined by SCHED_FIFO.

This is because the functions you'd like to use belong to POSIX realtime extensions and the default scheduling class SCHED_OTHER is there for:

This policy is defined to allow strictly conforming applications to be able to indicate in a portable manner that they no longer need a realtime scheduling policy.

If you run your application with sudo chrt --fifo 1 <app> it assigns your process FIFO scheduling class of priority 1 which makes it succeed in locking the mutex on the first call.


Regarding why the 2nd call succeeds when the 1st one fails, that seems to be undocumented behaviour, if I am not mistaken, and is probably a bug in glibc.

Upvotes: 3

Related Questions