From 6ebb582e84d873e62bb93f3fd04eac3ef33ead08 Mon Sep 17 00:00:00 2001
From: Guy Zana <guy@cloudius-systems.com>
Date: Sun, 26 May 2013 19:46:50 +0300
Subject: [PATCH] debug: introduce debug_ll() and use it in abort()

the debug() console function is taking a lock before it access the console driver,
it does that by acquiring a mutex which may sleep.

since we want to be able to debug (and abort) in contexts where it's not possible sleep,
such as in page_fault, a lockless debug print method is introduced.

previousely to this patch, any abort on page_fault would cause an "endless" recursive
abort() loop which hanged the system in a peculiar state.
---
 core/debug.cc            | 6 ++++++
 drivers/console.cc       | 5 +++++
 drivers/console.hh       | 1 +
 drivers/debug-console.cc | 7 +++++++
 drivers/debug-console.hh | 2 ++
 include/osv/debug.h      | 4 ++++
 runtime.cc               | 2 +-
 7 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/core/debug.cc b/core/debug.cc
index d903b028a..690ecbc7e 100644
--- a/core/debug.cc
+++ b/core/debug.cc
@@ -170,4 +170,10 @@ extern "C" {
         console::write(msg, len, false);
     }
 
+    // lockless version
+    void debug_ll(const char *msg)
+    {
+        console::write_ll(msg, strlen(msg));
+    }
+
 }
diff --git a/drivers/console.cc b/drivers/console.cc
index f1968e8f9..84a6a9e93 100755
--- a/drivers/console.cc
+++ b/drivers/console.cc
@@ -24,6 +24,11 @@ void write(const char *msg, size_t len, bool lf)
         console.newline();
 }
 
+// lockless version
+void write_ll(const char *msg, size_t len)
+{
+    console.write_ll(msg, len);
+}
 
 mutex console_mutex;
 // characters available to be returned on read() from the console
diff --git a/drivers/console.hh b/drivers/console.hh
index a709feee6..d8caf6fbf 100644
--- a/drivers/console.hh
+++ b/drivers/console.hh
@@ -15,6 +15,7 @@ public:
 namespace console {
 
 void write(const char *msg, size_t len, bool lf);
+void write_ll(const char *msg, size_t len);
 
 }
 
diff --git a/drivers/debug-console.cc b/drivers/debug-console.cc
index 97dbfa616..5f0d7818e 100644
--- a/drivers/debug-console.cc
+++ b/drivers/debug-console.cc
@@ -10,6 +10,13 @@ void debug_console::write(const char* str, size_t len)
     with_lock(_lock, [=] { if (_impl) { _impl->write(str, len); }});
 }
 
+void debug_console::write_ll(const char *str, size_t len)
+{
+    if (_impl) {
+        _impl->write(str, len);
+    }
+}
+
 void debug_console::newline()
 {
     with_lock(_lock, [=] { if (_impl) { _impl->newline(); }});
diff --git a/drivers/debug-console.hh b/drivers/debug-console.hh
index 9c7e6cd9a..2aa3ced9c 100644
--- a/drivers/debug-console.hh
+++ b/drivers/debug-console.hh
@@ -11,6 +11,8 @@ class debug_console : public Console {
 public:
     void set_impl(Console* impl);
     virtual void write(const char *str, size_t len);
+    // write without taking any locks
+    void write_ll(const char *str, size_t len);
     virtual void newline();
     virtual bool input_ready() override;
     virtual char readch();
diff --git a/include/osv/debug.h b/include/osv/debug.h
index 0b417b35a..084719fb0 100644
--- a/include/osv/debug.h
+++ b/include/osv/debug.h
@@ -18,6 +18,10 @@ __BEGIN_DECLS
 void debug(const char *msg);
 void debug_write(const char *msg, size_t len);
 
+/* a lockless version that doesn't take any locks before printing,
+   should be used only to debug faults */
+void debug_ll(const char *msg);
+
 int vkprintf(const char *__restrict fmt, va_list ap)
 	__attribute__((format(printf, 1, 0)));
 int kprintf(const char *__restrict fmt, ...)
diff --git a/runtime.cc b/runtime.cc
index e040cfab6..e043ad792 100644
--- a/runtime.cc
+++ b/runtime.cc
@@ -86,7 +86,7 @@ void abort()
         already_aborted = true;
         // Since the debug() code is complex and might cause an additional
         // abort, we need to prevent endless abort() nesting.
-        debug("Aborted\n");
+        debug_ll("Aborted\n");
     }
     osv::halt();
 }
-- 
GitLab