Skip to content
Snippets Groups Projects
Commit ec1d09c0 authored by Avi Kivity's avatar Avi Kivity
Browse files

mutex: allow recusrive locking

prex code depends on this.

TODO: make it optional
parent e74f5a0d
No related branches found
No related tags found
Loading
......@@ -14,8 +14,9 @@ extern "C" void mutex_lock(mutex_t *mutex)
w.thread = sched::thread::current();
spin_lock(&mutex->_wait_lock);
if (!mutex->_owner) {
if (!mutex->_owner || mutex->_owner == w.thread) {
mutex->_owner = w.thread;
++mutex->_depth;
spin_unlock(&mutex->_wait_lock);
return;
}
......@@ -43,8 +44,9 @@ extern "C" bool mutex_trylock(mutex_t *mutex)
{
bool ret = false;
spin_lock(&mutex->_wait_lock);
if (!mutex->_owner) {
if (!mutex->_owner || mutex->_owner == sched::thread::current()) {
mutex->_owner = sched::thread::current();
++mutex->_depth;
ret = true;
}
spin_unlock(&mutex->_wait_lock);
......@@ -54,11 +56,16 @@ extern "C" bool mutex_trylock(mutex_t *mutex)
extern "C" void mutex_unlock(mutex_t *mutex)
{
spin_lock(&mutex->_wait_lock);
if (mutex->_wait_list.first) {
mutex->_owner = mutex->_wait_list.first->thread;
mutex->_wait_list.first->thread->wake();
if (mutex->_depth == 1) {
if (mutex->_wait_list.first) {
mutex->_owner = mutex->_wait_list.first->thread;
mutex->_wait_list.first->thread->wake();
} else {
mutex->_owner = nullptr;
--mutex->_depth;
}
} else {
mutex->_owner = nullptr;
--mutex->_depth;
}
spin_unlock(&mutex->_wait_lock);
}
......
......@@ -21,6 +21,7 @@ static inline void spinlock_init(spinlock_t *sl)
struct cmutex {
spinlock_t _wait_lock;
unsigned _depth;
void *_owner;
struct wait_list {
struct waiter *first;
......@@ -38,6 +39,7 @@ void mutex_unlock(mutex_t* m);
static __always_inline void mutex_init(mutex_t* m)
{
m->_depth = 0;
m->_owner = 0;
m->_wait_list.first = 0;
m->_wait_list.last = 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment