summaryrefslogtreecommitdiff
path: root/kern/mutex.h
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-03-04 16:09:51 +0100
committerRichard Braun <rbraun@sceen.net>2017-03-04 16:52:29 +0100
commit3ae5551b3368b16ddbc1441710e1f272b1c0ad22 (patch)
treeca8910cf5638fb390bf9b34ab3ca98a3a9e66c8a /kern/mutex.h
parentef9426483f2f388c4874c6b12e0800645c3dbce4 (diff)
kern/{condition,mutex}: reimplement on top of sleep queues
Diffstat (limited to 'kern/mutex.h')
-rw-r--r--kern/mutex.h52
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 */