diff options
author | Richard Braun <rbraun@sceen.net> | 2017-03-04 16:09:51 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-03-04 16:52:29 +0100 |
commit | 3ae5551b3368b16ddbc1441710e1f272b1c0ad22 (patch) | |
tree | ca8910cf5638fb390bf9b34ab3ca98a3a9e66c8a /kern/mutex.h | |
parent | ef9426483f2f388c4874c6b12e0800645c3dbce4 (diff) |
kern/{condition,mutex}: reimplement on top of sleep queues
Diffstat (limited to 'kern/mutex.h')
-rw-r--r-- | kern/mutex.h | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/kern/mutex.h b/kern/mutex.h index 64efa350..2804fc44 100644 --- a/kern/mutex.h +++ b/kern/mutex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 Richard Braun. + * Copyright (c) 2013-2017 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,9 +15,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * - * Mutual exclusion locks. + * Mutual exclusion sleep locks. * * Unlike spin locks, acquiring a mutex may make the calling thread sleep. + * + * TODO Adaptive spinning. */ #ifndef _KERN_MUTEX_H @@ -25,23 +27,30 @@ #include <kern/assert.h> #include <kern/error.h> -#include <kern/list.h> #include <kern/mutex_i.h> #include <kern/mutex_types.h> -#include <kern/spinlock.h> +#include <kern/thread.h> struct mutex; +#define mutex_assert_locked(mutex) assert((mutex)->state != MUTEX_UNLOCKED) + +/* + * Initialize a mutex. + */ static inline void mutex_init(struct mutex *mutex) { mutex->state = MUTEX_UNLOCKED; - spinlock_init(&mutex->lock); - list_init(&mutex->waiters); } -#define mutex_assert_locked(mutex) assert((mutex)->state != MUTEX_UNLOCKED) - +/* + * Attempt to lock the given mutex. + * + * This function may not sleep. + * + * Return 0 on success, ERROR_BUSY if the mutex is already locked. + */ static inline int mutex_trylock(struct mutex *mutex) { @@ -56,6 +65,14 @@ mutex_trylock(struct mutex *mutex) return ERROR_BUSY; } +/* + * Lock a mutex. + * + * If the mutex is already locked, the calling thread sleeps until the + * mutex is unlocked. + * + * A mutex can only be locked once. + */ static inline void mutex_lock(struct mutex *mutex) { @@ -72,6 +89,12 @@ mutex_lock(struct mutex *mutex) mutex_lock_slow(mutex); } +/* + * Unlock a mutex. + * + * The mutex must be locked, and must have been locked by the calling + * thread. + */ static inline void mutex_unlock(struct mutex *mutex) { @@ -79,13 +102,16 @@ mutex_unlock(struct mutex *mutex) state = mutex_release(mutex); - if (state == MUTEX_LOCKED) { - return; + if (state != MUTEX_LOCKED) { + assert(state == MUTEX_CONTENDED); + mutex_unlock_slow(mutex); } - assert(state == MUTEX_CONTENDED); - - mutex_unlock_slow(mutex); + /* + * If this mutex was used along with a condition variable, wake up + * a potential pending waiter. + */ + thread_wakeup_last_cond(); } #endif /* _KERN_MUTEX_H */ |