Kyösti Mälkki has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/60280 )
Change subject: [WIP] src/console: Replace to mutex as printk serialization ......................................................................
[WIP] src/console: Replace to mutex as printk serialization
If COOP_MULTITASKING is enabled, printk() may call switch threads while console_lock is held. To avoid a deadlock, when failing to acquire console_lock, let other threads execute. Ultimately some of the other threads will call thread_yield() without holding console_lock and let another thread continue here.
Change-Id: Id5a48afe40ca86e55e91a00b8a4ee31da09fb9cb Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M src/console/printk.c A src/include/mutex.h 2 files changed, 37 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/80/60280/1
diff --git a/src/console/printk.c b/src/console/printk.c index 1ed39cb..b54cd9a 100644 --- a/src/console/printk.c +++ b/src/console/printk.c @@ -8,6 +8,7 @@ #include <console/console.h> #include <console/streams.h> #include <console/vtxprintf.h> +#include <mutex.h> #include <smp/spinlock.h> #include <smp/node.h> #include <timer.h> @@ -80,7 +81,7 @@ if (log_this < CONSOLE_LOG_FAST) return 0;
- spin_lock(&console_lock); + mutex_lock(&console_lock);
console_time_run();
@@ -93,7 +94,7 @@
console_time_stop();
- spin_unlock(&console_lock); + mutex_unlock(&console_lock);
return i; } diff --git a/src/include/mutex.h b/src/include/mutex.h new file mode 100644 index 0000000..d4642f9 --- /dev/null +++ b/src/include/mutex.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _MUTEX_H +#define _MUTEX_H + +#include <arch/cpu.h> +#include <smp/spinlock.h> +#include <thread.h> + +static inline void mutex_lock(struct spinlock *lock) +{ + while (!spinlock_try_lock(lock)) { + /* + * If we failed to get the lock, wait until it's been unlocked before trying to + * read-modify-write. This helps prevent excessive cache misses. + */ + while (spinlock_is_locked(lock)) { + /* + * Threads are only available on the BSP, so if this code is running + * on an AP, yielding will fail. In that case just sleep for a bit + * and try again. + */ + if (thread_yield() < 0) + cpu_relax(); + } + } +} + +static inline void mutex_unlock(struct spinlock *lock) +{ + spin_unlock(lock); +} + +#endif /* _MUTEX_H */