diff options
author | Richard Braun <rbraun@sceen.net> | 2017-08-27 16:45:37 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-08-27 16:45:37 +0200 |
commit | 791a6563cd955f59e04084f1fc20aadbbc6ae25f (patch) | |
tree | 914569337e26f75f5294007507f44ab65b807864 | |
parent | d3d0b5245942055aa7478d2adb20f1359ef772f7 (diff) |
kern/condition: implement timed waits
-rw-r--r-- | kern/condition.c | 110 | ||||
-rw-r--r-- | kern/condition.h | 17 | ||||
-rw-r--r-- | kern/condition_types.h | 3 |
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 */ |