HelenOS sources
This source file includes following definitions.
- mutex_initialize
- mutex_locked
- mutex_lock_active
- mutex_lock
- mutex_lock_timeout
- mutex_trylock
- mutex_unlock
#include <assert.h>
#include <errno.h>
#include <synch/mutex.h>
#include <synch/semaphore.h>
#include <arch.h>
#include <stacktrace.h>
#include <cpu.h>
#include <proc/thread.h>
void mutex_initialize(mutex_t *mtx, mutex_type_t type)
{
mtx->type = type;
mtx->owner = NULL;
mtx->nesting = 0;
semaphore_initialize(&mtx->sem, 1);
}
bool mutex_locked(mutex_t *mtx)
{
errno_t rc = semaphore_trydown(&mtx->sem);
if (rc == EOK) {
semaphore_up(&mtx->sem);
}
return rc != EOK;
}
static void mutex_lock_active(mutex_t *mtx)
{
assert((mtx->type == MUTEX_ACTIVE) || !THREAD);
const unsigned deadlock_treshold = 100000000;
unsigned int cnt = 0;
bool deadlock_reported = false;
while (semaphore_trydown(&mtx->sem) != EOK) {
if (cnt++ > deadlock_treshold) {
printf("cpu%u: looping on active mutex %p\n", CPU->id, mtx);
stack_trace();
cnt = 0;
deadlock_reported = true;
}
}
if (deadlock_reported)
printf("cpu%u: not deadlocked\n", CPU->id);
}
void mutex_lock(mutex_t *mtx)
{
if (mtx->type == MUTEX_RECURSIVE && mtx->owner == THREAD) {
assert(THREAD);
mtx->nesting++;
return;
}
if (mtx->type == MUTEX_ACTIVE || !THREAD) {
mutex_lock_active(mtx);
return;
}
semaphore_down(&mtx->sem);
mtx->owner = THREAD;
mtx->nesting = 1;
}
errno_t mutex_lock_timeout(mutex_t *mtx, uint32_t usec)
{
if (usec != 0) {
assert(mtx->type != MUTEX_ACTIVE);
assert(THREAD);
}
if (mtx->type == MUTEX_RECURSIVE && mtx->owner == THREAD) {
assert(THREAD);
mtx->nesting++;
return EOK;
}
errno_t rc = semaphore_down_timeout(&mtx->sem, usec);
if (rc == EOK) {
mtx->owner = THREAD;
mtx->nesting = 1;
}
return rc;
}
errno_t mutex_trylock(mutex_t *mtx)
{
return mutex_lock_timeout(mtx, 0);
}
void mutex_unlock(mutex_t *mtx)
{
if (mtx->type == MUTEX_RECURSIVE) {
assert(mtx->owner == THREAD);
if (--mtx->nesting > 0)
return;
mtx->owner = NULL;
}
semaphore_up(&mtx->sem);
}
HelenOS homepage, sources at GitHub