Kyösti Mälkki has uploaded this change for review.

View Change

[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 */

To view, visit change 60280. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Id5a48afe40ca86e55e91a00b8a4ee31da09fb9cb
Gerrit-Change-Number: 60280
Gerrit-PatchSet: 1
Gerrit-Owner: Kyösti Mälkki <kyosti.malkki@gmail.com>
Gerrit-MessageType: newchange