summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-08-27 16:45:37 +0200
committerRichard Braun <rbraun@sceen.net>2017-08-27 16:45:37 +0200
commit791a6563cd955f59e04084f1fc20aadbbc6ae25f (patch)
tree914569337e26f75f5294007507f44ab65b807864
parentd3d0b5245942055aa7478d2adb20f1359ef772f7 (diff)
kern/condition: implement timed waits
-rw-r--r--kern/condition.c110
-rw-r--r--kern/condition.h17
-rw-r--r--kern/condition_types.h3
3 files changed, 44 insertions, 86 deletions
diff --git a/kern/condition.c b/kern/condition.c
index c8ea5f39..e6d65951 100644
--- a/kern/condition.c
+++ b/kern/condition.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <kern/condition.h>
#include <kern/condition_types.h>
@@ -28,52 +29,14 @@
#include <kern/sleepq.h>
#include <kern/thread.h>
-static void
-condition_inc_nr_sleeping_waiters(struct condition *condition)
-{
- condition->nr_sleeping_waiters++;
- assert(condition->nr_sleeping_waiters != 0);
-}
-
-static void
-condition_dec_nr_sleeping_waiters(struct condition *condition)
-{
- assert(condition->nr_sleeping_waiters != 0);
- condition->nr_sleeping_waiters--;
-}
-
-static void
-condition_inc_nr_pending_waiters(struct condition *condition)
-{
- condition->nr_pending_waiters++;
- assert(condition->nr_pending_waiters != 0);
-}
-
-static void
-condition_dec_nr_pending_waiters(struct condition *condition)
-{
- assert(condition->nr_pending_waiters != 0);
- condition->nr_pending_waiters--;
-}
-
-static void
-condition_move_waiters(struct condition *condition)
-{
- unsigned short old;
-
- assert(condition->nr_sleeping_waiters != 0);
- old = condition->nr_pending_waiters;
- condition->nr_pending_waiters += condition->nr_sleeping_waiters;
- assert(old < condition->nr_pending_waiters);
- condition->nr_sleeping_waiters = 0;
-}
-
-void
-condition_wait(struct condition *condition, struct mutex *mutex)
+static int
+condition_wait_common(struct condition *condition, struct mutex *mutex,
+ bool timed, uint64_t ticks)
{
struct condition *last_cond;
struct sleepq *sleepq;
unsigned long flags;
+ int error;
mutex_assert_locked(mutex);
@@ -101,23 +64,41 @@ condition_wait(struct condition *condition, struct mutex *mutex)
if (last_cond != NULL) {
assert(last_cond == condition);
-
- if (condition->nr_pending_waiters != 0) {
- sleepq_signal(sleepq);
- }
+ sleepq_wakeup(sleepq);
}
- condition_inc_nr_sleeping_waiters(condition);
- sleepq_wait(sleepq, "cond");
- condition_dec_nr_pending_waiters(condition);
+ if (timed) {
+ error = sleepq_timedwait(sleepq, "cond", ticks);
+ } else {
+ sleepq_wait(sleepq, "cond");
+ error = 0;
+ }
- if (condition->nr_pending_waiters != 0) {
+ if (!error) {
thread_set_last_cond(condition);
}
sleepq_return(sleepq, flags);
mutex_lock(mutex);
+
+ return error;
+}
+
+void
+condition_wait(struct condition *condition, struct mutex *mutex)
+{
+ int error;
+
+ error = condition_wait_common(condition, mutex, false, 0);
+ assert(!error);
+}
+
+int
+condition_timedwait(struct condition *condition,
+ struct mutex *mutex, uint64_t ticks)
+{
+ return condition_wait_common(condition, mutex, true, ticks);
}
void
@@ -132,16 +113,8 @@ condition_signal(struct condition *condition)
return;
}
- if (condition->nr_sleeping_waiters == 0) {
- goto out;
- }
-
sleepq_signal(sleepq);
- condition_dec_nr_sleeping_waiters(condition);
- condition_inc_nr_pending_waiters(condition);
-
-out:
sleepq_release(sleepq, flags);
}
@@ -157,15 +130,8 @@ condition_broadcast(struct condition *condition)
return;
}
- if (condition->nr_sleeping_waiters == 0) {
- goto out;
- }
-
- sleepq_signal(sleepq);
-
- condition_move_waiters(condition);
+ sleepq_broadcast(sleepq);
-out:
sleepq_release(sleepq, flags);
}
@@ -181,17 +147,7 @@ condition_wakeup(struct condition *condition)
return;
}
- if (condition->nr_pending_waiters == 0) {
- goto out;
- }
-
- /*
- * Rely on the FIFO ordering of sleep queues so that signalling multiple
- * times always wakes up the same thread, as long as that thread didn't
- * reacquire the sleep queue.
- */
- sleepq_signal(sleepq);
+ sleepq_wakeup(sleepq);
-out:
sleepq_release(sleepq, flags);
}
diff --git a/kern/condition.h b/kern/condition.h
index 0ce8d94f..90a59f0d 100644
--- a/kern/condition.h
+++ b/kern/condition.h
@@ -27,6 +27,8 @@
#ifndef _KERN_CONDITION_H
#define _KERN_CONDITION_H
+#include <stdint.h>
+
#include <kern/condition_types.h>
#include <kern/mutex_types.h>
@@ -35,20 +37,21 @@ struct condition;
/*
* Initialize a condition variable.
*/
-static inline void
-condition_init(struct condition *condition)
-{
- condition->nr_sleeping_waiters = 0;
- condition->nr_pending_waiters = 0;
-}
+#define condition_init(c) ((void)(c))
/*
- * Wait for a wake-up on the given condition variable.
+ * Wait for a signal on the given condition variable.
*
* The associated mutex must be locked when calling this function.
* It is unlocked before waiting and relocked before returning.
+ *
+ * When bounding the duration of the wait, the caller must pass an absolute
+ * time in ticks, and ERROR_TIMEDOUT is returned if that time is reached
+ * before the sleep queue is signalled.
*/
void condition_wait(struct condition *condition, struct mutex *mutex);
+int condition_timedwait(struct condition *condition,
+ struct mutex *mutex, uint64_t ticks);
/*
* Wake up one (signal) or all (broadcast) threads waiting on a
diff --git a/kern/condition_types.h b/kern/condition_types.h
index 13a29205..abd42f21 100644
--- a/kern/condition_types.h
+++ b/kern/condition_types.h
@@ -22,8 +22,7 @@
#define _KERN_CONDITION_TYPES_H
struct condition {
- unsigned short nr_sleeping_waiters;
- unsigned short nr_pending_waiters;
+ unsigned int _unused;
};
#endif /* _KERN_CONDITION_TYPES_H */