* Made struct ring_buffer public (within the kernel).
* Added "syslog" command that dumps the contents of the syslog ring buffer into KDL. Use the '-n' option to only show what hasn't been sent to the syslog daemon yet. * When entering the kernel debugger, the current thread ID and name are also printed (not only the current CPU). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26684 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -9,7 +9,13 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
struct ring_buffer;
|
struct ring_buffer {
|
||||||
|
int32 first;
|
||||||
|
int32 in;
|
||||||
|
int32 size;
|
||||||
|
uint8 buffer[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2008, Axel Dörfler, [email protected]
|
* Copyright 2002-2008, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -650,17 +650,20 @@ kernel_debugger_loop(void)
|
|||||||
int32 previousCPU = sDebuggerOnCPU;
|
int32 previousCPU = sDebuggerOnCPU;
|
||||||
sDebuggerOnCPU = smp_get_current_cpu();
|
sDebuggerOnCPU = smp_get_current_cpu();
|
||||||
|
|
||||||
// set a few temporary debug variables
|
kprintf("Welcome to Kernel Debugging Land...\n");
|
||||||
|
|
||||||
if (struct thread* thread = thread_get_current_thread()) {
|
if (struct thread* thread = thread_get_current_thread()) {
|
||||||
|
// set a few temporary debug variables
|
||||||
set_debug_variable("_thread", (uint64)(addr_t)thread);
|
set_debug_variable("_thread", (uint64)(addr_t)thread);
|
||||||
set_debug_variable("_threadID", thread->id);
|
set_debug_variable("_threadID", thread->id);
|
||||||
set_debug_variable("_team", (uint64)(addr_t)thread->team);
|
set_debug_variable("_team", (uint64)(addr_t)thread->team);
|
||||||
set_debug_variable("_teamID", thread->team->id);
|
set_debug_variable("_teamID", thread->team->id);
|
||||||
set_debug_variable("_cpu", sDebuggerOnCPU);
|
set_debug_variable("_cpu", sDebuggerOnCPU);
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("Welcome to Kernel Debugging Land...\n");
|
kprintf("Thread %ld \"%s\" running on CPU %ld\n", thread->id,
|
||||||
kprintf("Running on CPU %ld\n", sDebuggerOnCPU);
|
thread->name, sDebuggerOnCPU);
|
||||||
|
} else
|
||||||
|
kprintf("Running on CPU %ld\n", sDebuggerOnCPU);
|
||||||
|
|
||||||
int32 continuableLine = -1;
|
int32 continuableLine = -1;
|
||||||
// Index of the previous command line, if the command returned
|
// Index of the previous command line, if the command returned
|
||||||
@@ -718,6 +721,63 @@ cmd_dump_kdl_message(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_dump_syslog(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (!sSyslogOutputEnabled) {
|
||||||
|
kprintf("Syslog is not enabled.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool currentOnly = false;
|
||||||
|
if (argc > 1) {
|
||||||
|
if (!strcmp(argv[1], "-n"))
|
||||||
|
currentOnly = true;
|
||||||
|
else {
|
||||||
|
print_debugger_command_usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 start = sSyslogBuffer->first;
|
||||||
|
size_t end = start + sSyslogBuffer->in;
|
||||||
|
if (!currentOnly) {
|
||||||
|
// Start the buffer after the current end (we don't really know if
|
||||||
|
// this part has been written to already).
|
||||||
|
start = (start + sSyslogBuffer->in) % sSyslogBuffer->size;
|
||||||
|
end = start + sSyslogBuffer->size;
|
||||||
|
} else if (!ring_buffer_readable(sSyslogBuffer)) {
|
||||||
|
kprintf("Syslog is empty.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// break it down to lines to make it grep'able
|
||||||
|
|
||||||
|
bool newLine = false;
|
||||||
|
char line[256];
|
||||||
|
size_t linePos = 0;
|
||||||
|
for (int32 i = start; i < end; i++) {
|
||||||
|
char c = sSyslogBuffer->buffer[i % sSyslogBuffer->size];
|
||||||
|
if (c == '\0' || (uint8)c == 0xcc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
line[linePos++] = c;
|
||||||
|
newLine = false;
|
||||||
|
|
||||||
|
if (c == '\n' || linePos == sizeof(line) - 1) {
|
||||||
|
newLine = c == '\n';
|
||||||
|
line[linePos] = '\0';
|
||||||
|
linePos = 0;
|
||||||
|
kprintf(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!newLine)
|
||||||
|
kprintf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
syslog_sender(void *data)
|
syslog_sender(void *data)
|
||||||
{
|
{
|
||||||
@@ -879,6 +939,11 @@ syslog_init(struct kernel_args *args)
|
|||||||
"Welcome to syslog debug output!\nHaiku revision: %lu\n",
|
"Welcome to syslog debug output!\nHaiku revision: %lu\n",
|
||||||
get_haiku_revision());
|
get_haiku_revision());
|
||||||
syslog_write(revisionBuffer, length);
|
syslog_write(revisionBuffer, length);
|
||||||
|
|
||||||
|
add_debugger_command_etc("syslog", &cmd_dump_syslog,
|
||||||
|
"Dumps the syslog buffer.\n",
|
||||||
|
"[-n]\nDumps the whole syslog buffer, or, if -n is specified, only "
|
||||||
|
"the part that hasn't been send yet.\n", 0);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2005-2008, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#define user_memcpy(x...) (memcpy(x), B_OK)
|
#define user_memcpy(x...) (memcpy(x), B_OK)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** This is a light-weight ring_buffer implementation.
|
/*! This is a light-weight ring_buffer implementation.
|
||||||
* It does not provide any locking - you are supposed to ensure thread-safety
|
* It does not provide any locking - you are supposed to ensure thread-safety
|
||||||
* with the restrictions you choose. Unless you are passing in unsafe buffers,
|
* with the restrictions you choose. Unless you are passing in unsafe buffers,
|
||||||
* the functions are safe to be called with interrupts turned off as well (not
|
* the functions are safe to be called with interrupts turned off as well (not
|
||||||
@@ -26,13 +26,6 @@
|
|||||||
* They also don't use malloc() or any kind of locking after initialization.
|
* They also don't use malloc() or any kind of locking after initialization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ring_buffer {
|
|
||||||
int32 first;
|
|
||||||
int32 in;
|
|
||||||
int32 size;
|
|
||||||
uint8 buffer[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static inline int32
|
static inline int32
|
||||||
space_left_in_buffer(struct ring_buffer *buffer)
|
space_left_in_buffer(struct ring_buffer *buffer)
|
||||||
|
|||||||
Reference in New Issue
Block a user