I wrote this recently for one of my projects, any error you guys can spot or a feature which could be implemented without eating up resources or some optimisations ? Oh and it isn't meant for Multi cores.
/*******************************************************************************
* @file mutex.c
* @date 31st August 2012
* @brief Generic implementation of mutex, read /notes/thread-safety
******************************************************************************/
#include <mutex.h>
OS_ERR mutex_acquire_try(mutex_t *mutex)
{
if(unlikely(cpu_atomic_cmpxchg(&mutex->lock, OS_UNLOCKED, OS_LOCKED) != OS_OKAY))
{
if(mutex->owner == current_thread)
goto recursive;
return OS_EBUSY;
}
mutex->owner = current_thread;
recursive:
mutex->recnt++;
return OS_OKAY;
}
static inline OS_ERR mutex_acquire_helper(mutex_t *mutex, time_t timeout)
{
while(unlikely(cpu_atomic_cmpxchg(&mutex->lock, OS_UNLOCKED, OS_LOCKED) != OS_OKAY))
{
if(mutex->owner == current_thread)
goto recursive;
if(mutex->lock == OS_DEAD)
return OS_EINVAL;
if(current_thread->priority >= mutex->owner->priority)
thread_boost(mutex->owner);
if(thread_queue_block(&mutex->queue, timeout) != OS_OKAY)
return OS_ETIMEOUT;
}
mutex->owner = current_thread;
recursive:
mutex->recnt++;
return OS_OKAY;
}
OS_ERR mutex_acquire_timeout(mutex_t *mutex, time_t timeout)
{
return mutex_acquire_helper(mutex, timeout);
}
OS_ERR mutex_acquire(mutex_t *mutex)
{
return mutex_acquire_helper(mutex, OS_TIME_INFINITE);
}
OS_ERR mutex_release(mutex_t *mutex)
{
if(mutex->owner != current_thread)
return OS_EINVAL;
if(--mutex->recnt)
goto exit;
thread_deboost(mutex->owner);
mutex->owner = NULL;
cpu_atomic_set(&mutex->lock, OS_UNLOCKED);
thread_queue_wake_one_now(&mutex->queue);
exit:
return OS_OKAY;
}
void mutex_init(mutex_t *mutex)
{
mutex->recnt = 0;
mutex->owner = NULL;
thread_queue_init(&mutex->queue);
cpu_atomic_set(&mutex->lock, OS_UNLOCKED);
}
void mutex_deinit(mutex_t *mutex)
{
if(mutex->owner == current_thread)
{
if(mutex->recnt > 1)
LOGE("Mutex: Deinit called on recursive lock @ %p\n", mutex);
mutex_release(mutex);
}
do {
while(thread_queue_count(&mutex->queue))
thread_yield();
} while(cpu_atomic_cmpxchg(&mutex->lock, OS_DEAD, OS_UNLOCKED) != OS_OKAY);
}
TRUEandFALSEdefined? Unless they have weird definitions (and I’d question that), their use in the above code is totally redundant. You can simply writereturn mutex->owner == NULL;etc. No need for the conditional. – Konrad Rudolph Aug 9 '12 at 10:08