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
No related merge requests found
...@@ -14,8 +14,9 @@ extern "C" void mutex_lock(mutex_t *mutex) ...@@ -14,8 +14,9 @@ extern "C" void mutex_lock(mutex_t *mutex)
w.thread = sched::thread::current(); w.thread = sched::thread::current();
spin_lock(&mutex->_wait_lock); spin_lock(&mutex->_wait_lock);
if (!mutex->_owner) { if (!mutex->_owner || mutex->_owner == w.thread) {
mutex->_owner = w.thread; mutex->_owner = w.thread;
++mutex->_depth;
spin_unlock(&mutex->_wait_lock); spin_unlock(&mutex->_wait_lock);
return; return;
} }
...@@ -43,8 +44,9 @@ extern "C" bool mutex_trylock(mutex_t *mutex) ...@@ -43,8 +44,9 @@ extern "C" bool mutex_trylock(mutex_t *mutex)
{ {
bool ret = false; bool ret = false;
spin_lock(&mutex->_wait_lock); spin_lock(&mutex->_wait_lock);
if (!mutex->_owner) { if (!mutex->_owner || mutex->_owner == sched::thread::current()) {
mutex->_owner = sched::thread::current(); mutex->_owner = sched::thread::current();
++mutex->_depth;
ret = true; ret = true;
} }
spin_unlock(&mutex->_wait_lock); spin_unlock(&mutex->_wait_lock);
...@@ -54,11 +56,16 @@ extern "C" bool mutex_trylock(mutex_t *mutex) ...@@ -54,11 +56,16 @@ extern "C" bool mutex_trylock(mutex_t *mutex)
extern "C" void mutex_unlock(mutex_t *mutex) extern "C" void mutex_unlock(mutex_t *mutex)
{ {
spin_lock(&mutex->_wait_lock); spin_lock(&mutex->_wait_lock);
if (mutex->_wait_list.first) { if (mutex->_depth == 1) {
mutex->_owner = mutex->_wait_list.first->thread; if (mutex->_wait_list.first) {
mutex->_wait_list.first->thread->wake(); mutex->_owner = mutex->_wait_list.first->thread;
mutex->_wait_list.first->thread->wake();
} else {
mutex->_owner = nullptr;
--mutex->_depth;
}
} else { } else {
mutex->_owner = nullptr; --mutex->_depth;
} }
spin_unlock(&mutex->_wait_lock); spin_unlock(&mutex->_wait_lock);
} }
......
...@@ -21,6 +21,7 @@ static inline void spinlock_init(spinlock_t *sl) ...@@ -21,6 +21,7 @@ static inline void spinlock_init(spinlock_t *sl)
struct cmutex { struct cmutex {
spinlock_t _wait_lock; spinlock_t _wait_lock;
unsigned _depth;
void *_owner; void *_owner;
struct wait_list { struct wait_list {
struct waiter *first; struct waiter *first;
...@@ -38,6 +39,7 @@ void mutex_unlock(mutex_t* m); ...@@ -38,6 +39,7 @@ void mutex_unlock(mutex_t* m);
static __always_inline void mutex_init(mutex_t* m) static __always_inline void mutex_init(mutex_t* m)
{ {
m->_depth = 0;
m->_owner = 0; m->_owner = 0;
m->_wait_list.first = 0; m->_wait_list.first = 0;
m->_wait_list.last = 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