[haiku-development] [PATCH 1/4] Allow non-interactive execution of KDL commands
- From: Jan Klötzke <jan.kloetzke@xxxxxxxxxx>
- To: haiku-development@xxxxxxxxxxxxx
- Date: Thu, 26 Jun 2008 21:14:53 +0200
* Add kernel_debugger_exec() which allows to execute a single command
* The optional parameter "halt" specifies if all other CPU's should be halted
while executing the KDL command
* Route the output of the non-interactive command to syslog too commands to the
syslog
---
headers/os/drivers/KernelExport.h | 1 +
src/system/kernel/debug/debug.cpp | 128 +++++++++++++++++++------
src/system/kernel/debug/debug_commands.cpp | 2 +-
src/system/kernel/debug/debug_output_filter.h | 7 +-
4 files changed, 106 insertions(+), 32 deletions(-)
diff --git a/headers/os/drivers/KernelExport.h
b/headers/os/drivers/KernelExport.h
index 3a88928..34b92e9 100644
--- a/headers/os/drivers/KernelExport.h
+++ b/headers/os/drivers/KernelExport.h
@@ -164,6 +164,7 @@ extern bool set_dprintf_enabled(bool
new_state);
extern void panic(const char *format, ...) _PRINTFLIKE(1,
2);
extern void kernel_debugger(const char *message);
+extern void kernel_debugger_exec(const char *command, bool
halt);
extern uint64 parse_expression(const char *string);
extern int add_debugger_command(char *name,
debugger_command_hook hook, char *help);
diff --git a/src/system/kernel/debug/debug.cpp
b/src/system/kernel/debug/debug.cpp
index 08ee466..1ec2ff5 100644
--- a/src/system/kernel/debug/debug.cpp
+++ b/src/system/kernel/debug/debug.cpp
@@ -70,7 +70,10 @@ static const char* sCurrentKernelDebuggerMessage;
static char sOutputBuffer[OUTPUT_BUFFER_SIZE];
static char sLastOutputBuffer[OUTPUT_BUFFER_SIZE];
static DebugOutputFilter* sDebugOutputFilter = NULL;
+DebugOutputFilter *gCurrentDebugOutputFilter = NULL;
DefaultDebugOutputFilter gDefaultDebugOutputFilter;
+ExecDebugOutputFilter gExecDebugOutputFilter;
+static vint32 sInDebugger = 0;
static void flush_pending_repeats(void);
static void check_pending_repeats(void *data, int iter);
@@ -92,6 +95,7 @@ static int32 sCurrentLine = 0;
#define distance(a, b) ((a) < (b) ? (b) - (a) : (a) - (b))
+static void syslog_write(const char *text, int32 length);
// #pragma mark - DebugOutputFilter
@@ -142,6 +146,18 @@ DefaultDebugOutputFilter::Print(const char* format,
va_list args)
}
+void
+ExecDebugOutputFilter::PrintString(const char* string)
+{
+ if (sSerialDebugEnabled)
+ arch_debug_serial_puts(string);
+ if (sBlueScreenEnabled || sDebugScreenEnabled)
+ blue_screen_puts(string);
+ if (sSyslogOutputEnabled)
+ syslog_write(string, strlen(string));
+}
+
+
// #pragma mark -
@@ -178,7 +194,8 @@ kputs(const char *s)
void
kputs_unfiltered(const char *s)
{
- gDefaultDebugOutputFilter.PrintString(s);
+ if (gCurrentDebugOutputFilter)
+ gCurrentDebugOutputFilter->PrintString(s);
}
@@ -907,6 +924,47 @@ call_modules_hook(bool enter)
}
+static cpu_status
+debugger_halt_cpus(bool halt)
+{
+ cpu_status state;
+
+ state = disable_interrupts();
+ while (atomic_add(&sInDebugger, 1) > 0) {
+ // The debugger is already running, find out where...
+ if (sDebuggerOnCPU != smp_get_current_cpu()) {
+ // Some other CPU must have entered the debugger and
tried to halt
+ // us. Process ICIs to ensure we get the halt request.
Then we are
+ // blocking there until everyone leaves the debugger
and we can
+ // try to enter it again.
+ atomic_add(&sInDebugger, -1);
+ smp_intercpu_int_handler();
+ } else {
+ // We are re-entering the debugger on the same CPU.
+ break;
+ }
+ }
+
+ if (sDebuggerOnCPU != smp_get_current_cpu() && smp_get_num_cpus() > 1
&& halt) {
+ // First entry on a MP system, send a halt request to all of
the other
+ // CPUs. Should they try to enter the debugger they will be
cought in
+ // the loop above.
+ smp_send_broadcast_ici(SMP_MSG_CPU_HALT, 0, 0, 0,
+ (void *)&sInDebugger, SMP_MSG_FLAG_SYNC);
+ }
+
+ return state;
+}
+
+
+static void
+debugger_resume_cpus(cpu_status state)
+{
+ atomic_add(&sInDebugger, -1);
+ restore_interrupts(state);
+}
+
+
// #pragma mark - private kernel API
@@ -980,6 +1038,7 @@ status_t
debug_init(kernel_args *args)
{
new(&gDefaultDebugOutputFilter) DefaultDebugOutputFilter;
+ new(&gExecDebugOutputFilter) ExecDebugOutputFilter;
debug_paranoia_init();
return arch_debug_console_init(args);
@@ -1095,43 +1154,21 @@ panic(const char *format, ...)
void
kernel_debugger(const char *message)
{
- static vint32 inDebugger = 0;
cpu_status state;
bool dprintfState;
- state = disable_interrupts();
- while (atomic_add(&inDebugger, 1) > 0) {
- // The debugger is already running, find out where...
- if (sDebuggerOnCPU != smp_get_current_cpu()) {
- // Some other CPU must have entered the debugger and
tried to halt
- // us. Process ICIs to ensure we get the halt request.
Then we are
- // blocking there until everyone leaves the debugger
and we can
- // try to enter it again.
- atomic_add(&inDebugger, -1);
- smp_intercpu_int_handler();
- } else {
- // We are re-entering the debugger on the same CPU.
- break;
- }
- }
+ state = debugger_halt_cpus(true);
arch_debug_save_registers(&dbg_register_file[smp_get_current_cpu()][0]);
dprintfState = set_dprintf_enabled(true);
- if (sDebuggerOnCPU != smp_get_current_cpu() && smp_get_num_cpus() > 1) {
- // First entry on a MP system, send a halt request to all of
the other
- // CPUs. Should they try to enter the debugger they will be
cought in
- // the loop above.
- smp_send_broadcast_ici(SMP_MSG_CPU_HALT, 0, 0, 0,
- (void *)&inDebugger, SMP_MSG_FLAG_SYNC);
- }
-
if (sBlueScreenOutput) {
if (blue_screen_enter(false) == B_OK)
sBlueScreenEnabled = true;
}
sDebugOutputFilter = &gDefaultDebugOutputFilter;
+ gCurrentDebugOutputFilter = sDebugOutputFilter;
if (message)
kprintf("PANIC: %s\n", message);
@@ -1149,15 +1186,43 @@ kernel_debugger(const char *message)
set_dprintf_enabled(dprintfState);
sDebugOutputFilter = NULL;
+ gCurrentDebugOutputFilter = NULL;
sBlueScreenEnabled = false;
- atomic_add(&inDebugger, -1);
- restore_interrupts(state);
+
+ debugger_resume_cpus(state);
// ToDo: in case we change dbg_register_file - don't we want to restore
it?
}
+void
+kernel_debugger_exec(const char *command, bool halt)
+{
+ cpu_status state;
+ bool dprintfState;
+
+ state = debugger_halt_cpus(halt);
+
+ dprintfState = set_dprintf_enabled(true);
+ arch_debug_save_registers(&dbg_register_file[smp_get_current_cpu()][0]);
+ sDebugOutputFilter = &gExecDebugOutputFilter;
+ gCurrentDebugOutputFilter = sDebugOutputFilter;
+ sCurrentKernelDebuggerMessage = NULL;
+
+ // sort the commands
+ sort_debugger_commands();
+
+ evaluate_debug_command(command);
+
+ set_dprintf_enabled(dprintfState);
+ sDebugOutputFilter = NULL;
+ gCurrentDebugOutputFilter = NULL;
+
+ debugger_resume_cpus(state);
+}
+
+
bool
set_dprintf_enabled(bool newState)
{
@@ -1321,9 +1386,12 @@ void
kprintf_unfiltered(const char *format, ...)
{
va_list args;
- va_start(args, format);
- gDefaultDebugOutputFilter.Print(format, args);
- va_end(args);
+
+ if (gCurrentDebugOutputFilter) {
+ va_start(args, format);
+ gCurrentDebugOutputFilter->Print(format, args);
+ va_end(args);
+ }
}
diff --git a/src/system/kernel/debug/debug_commands.cpp
b/src/system/kernel/debug/debug_commands.cpp
index ea42af7..111a5a5 100644
--- a/src/system/kernel/debug/debug_commands.cpp
+++ b/src/system/kernel/debug/debug_commands.cpp
@@ -155,7 +155,7 @@ invoke_pipe_segment(debugger_command_pipe* pipe, int32
index, char* argument)
// set debug output
DebugOutputFilter* oldFilter = set_debug_output_filter(
index == pipe->segment_count - 1
- ? &gDefaultDebugOutputFilter
+ ? gCurrentDebugOutputFilter
: (DebugOutputFilter*)&sPipeOutputFilters[index]);
// set last command argument
diff --git a/src/system/kernel/debug/debug_output_filter.h
b/src/system/kernel/debug/debug_output_filter.h
index 7a7ede2..e0dbc39 100644
--- a/src/system/kernel/debug/debug_output_filter.h
+++ b/src/system/kernel/debug/debug_output_filter.h
@@ -25,8 +25,13 @@ public:
virtual void Print(const char* format, va_list args);
};
+class ExecDebugOutputFilter : public DefaultDebugOutputFilter {
+public:
+ virtual void PrintString(const char* string);
+};
+
-extern DefaultDebugOutputFilter gDefaultDebugOutputFilter;
+extern DebugOutputFilter *gCurrentDebugOutputFilter;
DebugOutputFilter* set_debug_output_filter(DebugOutputFilter* filter);
--
1.5.4.2
- Follow-Ups:
- References:
- [haiku-development] Emergency keyboard shortcut handler
- From: Jan Klötzke
Other related posts:
- » [haiku-development] [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- » [haiku-development] Re: [PATCH 1/4] Allow non-interactive execution of KDL commands
- [haiku-development] Emergency keyboard shortcut handler
- From: Jan Klötzke