From 9967e907feda967f237c30430f47357bc91332f5 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Tue, 30 Jan 2018 20:44:24 +0100 Subject: Fix condition variable broadcasting The broadcast implementation is based on an invalid assumption, namely that the first mutex_unlock call following condition_wait would be invoked on the same mutex. Fixing this while guarding against the thundering herd effect requires augmenting mutexes with a pointer to the condition variable they may be associated with. Since the size of mutexes is currently more important than broadcast scalability, the implementation is simplified into one which suffers from the thundering herd effect. --- kern/condition.c | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) (limited to 'kern/condition.c') diff --git a/kern/condition.c b/kern/condition.c index e6d65951..c407e949 100644 --- a/kern/condition.c +++ b/kern/condition.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Richard Braun. + * Copyright (c) 2013-2018 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 @@ -27,46 +27,21 @@ #include #include #include -#include 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); - /* - * Special case : - * - * mutex_lock(lock); - * - * for (;;) { - * while (!done) { - * condition_wait(condition, lock); - * } - * - * do_something(); - * } - * - * Pull the last condition before unlocking the mutex to prevent - * mutex_unlock() from reacquiring the condition sleep queue. - */ - last_cond = thread_pull_last_cond(); - sleepq = sleepq_lend(condition, true, &flags); mutex_unlock(mutex); - if (last_cond != NULL) { - assert(last_cond == condition); - sleepq_wakeup(sleepq); - } - if (timed) { error = sleepq_timedwait(sleepq, "cond", ticks); } else { @@ -74,10 +49,6 @@ condition_wait_common(struct condition *condition, struct mutex *mutex, error = 0; } - if (!error) { - thread_set_last_cond(condition); - } - sleepq_return(sleepq, flags); mutex_lock(mutex); @@ -134,20 +105,3 @@ condition_broadcast(struct condition *condition) sleepq_release(sleepq, flags); } - -void -condition_wakeup(struct condition *condition) -{ - struct sleepq *sleepq; - unsigned long flags; - - sleepq = sleepq_acquire(condition, true, &flags); - - if (sleepq == NULL) { - return; - } - - sleepq_wakeup(sleepq); - - sleepq_release(sleepq, flags); -} -- cgit v1.2.3