Assume that the following code is being executed by 10 threads.
pthread_mutex_lock(&lock)
Some trivial code
pthread_mutex_unlock(&lock)
Here's my implementation. Low priority threads use prio_lock_low() and prio_unlock_low() to lock and unlock, high priority threads use prio_lock_high() and prio_unlock_high().
The design is quite simple. High priority threads are held at the critical section mutex ->cs_mutex, low priority threads are held at the condition variable. The condition variable mutex is only held around updates to the shared variable and signalling of the condition variable.
#include
typedef struct prio_lock {
pthread_cond_t cond;
pthread_mutex_t cv_mutex; /* Condition variable mutex */
pthread_mutex_t cs_mutex; /* Critical section mutex */
unsigned long high_waiters;
} prio_lock_t;
#define PRIO_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }
void prio_lock_low(prio_lock_t *prio_lock)
{
pthread_mutex_lock(&prio_lock->cv_mutex);
while (prio_lock->high_waiters || pthread_mutex_trylock(&prio_lock->cs_mutex))
{
pthread_cond_wait(&prio_lock->cond, &prio_lock->cv_mutex);
}
pthread_mutex_unlock(&prio_lock->cv_mutex);
}
void prio_unlock_low(prio_lock_t *prio_lock)
{
pthread_mutex_unlock(&prio_lock->cs_mutex);
pthread_mutex_lock(&prio_lock->cv_mutex);
if (!prio_lock->high_waiters)
pthread_cond_signal(&prio_lock->cond);
pthread_mutex_unlock(&prio_lock->cv_mutex);
}
void prio_lock_high(prio_lock_t *prio_lock)
{
pthread_mutex_lock(&prio_lock->cv_mutex);
prio_lock->high_waiters++;
pthread_mutex_unlock(&prio_lock->cv_mutex);
pthread_mutex_lock(&prio_lock->cs_mutex);
}
void prio_unlock_high(prio_lock_t *prio_lock)
{
pthread_mutex_unlock(&prio_lock->cs_mutex);
pthread_mutex_lock(&prio_lock->cv_mutex);
prio_lock->high_waiters--;
if (!prio_lock->high_waiters)
pthread_cond_signal(&prio_lock->cond);
pthread_mutex_unlock(&prio_lock->cv_mutex);
}