mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
hw: don't take the log backend's mutex in kernel
To prevent the kernel to deadlock, or call itself with a syscall when using a lock potentially hold by a core thread, the log console's backend for core (hw) gets replaced by a specific variant that checks whether it runs in the kernel context before using the mutex. Fix genodelabs/genode#3280
This commit is contained in:
parent
b59ec55d50
commit
8fe7fa5532
@ -10,3 +10,8 @@ include $(BASE_DIR)/lib/mk/base-common.inc
|
||||
SRC_CC += rpc_dispatch_loop.cc
|
||||
SRC_CC += thread.cc thread_myself.cc thread_bootstrap.cc
|
||||
SRC_CC += signal_transmitter.cc
|
||||
|
||||
# filter out log.cc from the generic base library
|
||||
# in core and hw kernel we have to implement it differently
|
||||
SRC_CC_WITH_LOG_CC := $(SRC_CC)
|
||||
SRC_CC = $(filter-out log.cc,$(SRC_CC_WITH_LOG_CC))
|
||||
|
@ -1,5 +1,6 @@
|
||||
include $(BASE_DIR)/lib/mk/base.inc
|
||||
|
||||
SRC_CC += log.cc
|
||||
SRC_CC += thread_start.cc
|
||||
SRC_CC += capability.cc
|
||||
SRC_CC += cache.cc
|
||||
|
@ -12,15 +12,22 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/output.h>
|
||||
#include <base/internal/raw_write_string.h>
|
||||
|
||||
#include <core_log.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/log.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Genode::Core_log::out(char const c) { Kernel::log(c); }
|
||||
|
||||
void Core_log::out(char const c) { Kernel::log(c); }
|
||||
|
||||
|
||||
void Genode::raw_write_string(char const *str)
|
||||
@ -28,3 +35,75 @@ void Genode::raw_write_string(char const *str)
|
||||
while (char c = *str++)
|
||||
Kernel::log(c);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
** Utility to check whether kernel or core code is active **
|
||||
************************************************************/
|
||||
|
||||
extern void const * const kernel_stack;
|
||||
|
||||
static inline bool running_in_kernel()
|
||||
{
|
||||
addr_t const stack_base = reinterpret_cast<addr_t>(&kernel_stack);
|
||||
static constexpr size_t stack_size =
|
||||
NR_OF_CPUS * Kernel::Cpu::KERNEL_STACK_SIZE;
|
||||
|
||||
/* check stack variable against kernel stack area */
|
||||
return ((addr_t)&stack_base) >= stack_base &&
|
||||
((addr_t)&stack_base) < (stack_base + stack_size);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************
|
||||
** Implementation of src/lib/base/log.cc **
|
||||
*******************************************/
|
||||
|
||||
void Log::_acquire(Type type)
|
||||
{
|
||||
if (!running_in_kernel()) _mutex.acquire();
|
||||
|
||||
/*
|
||||
* Mark warnings and errors via distinct colors.
|
||||
*/
|
||||
switch (type) {
|
||||
case LOG: break;
|
||||
case WARNING: _output.out_string("\033[34mWarning: "); break;
|
||||
case ERROR: _output.out_string("\033[31mError: "); break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Log::_release()
|
||||
{
|
||||
/*
|
||||
* Reset color and add newline
|
||||
*/
|
||||
_output.out_string("\033[0m\n");
|
||||
|
||||
if (!running_in_kernel()) _mutex.release();
|
||||
}
|
||||
|
||||
|
||||
void Raw::_acquire()
|
||||
{
|
||||
/*
|
||||
* Mark raw output with distinct color
|
||||
*/
|
||||
_output().out_string("\033[32mKernel: ");
|
||||
}
|
||||
|
||||
|
||||
void Raw::_release()
|
||||
{
|
||||
/*
|
||||
* Reset color and add newline
|
||||
*/
|
||||
_output().out_string("\033[0m\n");
|
||||
}
|
||||
|
||||
|
||||
void Trace_output::Write_trace_fn::operator () (char const *s)
|
||||
{
|
||||
Thread::trace(s);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user