kernel:
* The kernel syslog ring buffer is no longer emptied by the syslog sender thread. Instead we only drop the oldest data from the buffer when we're writing to it and there's not enough free space in it. Advantages: We drop old data rather than the most recent data when the buffer is full. The "syslog" KDL command has more data available now. So the odds are that kernel syslog messages not written to disk yet are at least still in the kernel buffer. * Changed dprintf_no_syslog() semantics: Now it writes to the syslog, but doesn't notify the syslog sender thread. boot loader: * Added the ring_buffer implementation and a dummy user_memcpy(). * bios_x86: Moved the syslog stuff from serial.{cpp,h} to debug.{cpp.h}. * Moved the debug options from the "Select safe mode options" menu to a new "Select debug options" menu. * Added option "Enable debug syslog" to the new menu (ATM available on x86 only). It allocates a 1 MB in-memory buffer for the syslog for this session in such a way that it can be accessed by the boot loader after a reset. * Added item "Display syslog from previous session" to the new menu, doing what its name suggests. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35816 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
90bf6bef34
commit
28a2172c3f
|
@ -78,6 +78,7 @@ typedef struct kernel_args {
|
|||
|
||||
void *debug_output;
|
||||
uint32 debug_size;
|
||||
bool keep_debug_output_buffer;
|
||||
|
||||
platform_kernel_args platform_args;
|
||||
arch_kernel_args arch_args;
|
||||
|
|
|
@ -50,17 +50,19 @@ UsePrivateHeaders shared storage ;
|
|||
}
|
||||
|
||||
KernelStaticLibrary boot_loader :
|
||||
main.cpp
|
||||
vfs.cpp
|
||||
RootFileSystem.cpp
|
||||
partitions.cpp
|
||||
heap.cpp
|
||||
stdio.cpp
|
||||
elf.cpp
|
||||
menu.cpp
|
||||
loader.cpp
|
||||
heap.cpp
|
||||
kernel_args.cpp
|
||||
load_driver_settings.cpp
|
||||
loader.cpp
|
||||
main.cpp
|
||||
menu.cpp
|
||||
pager.cpp
|
||||
partitions.cpp
|
||||
RootFileSystem.cpp
|
||||
stdio.cpp
|
||||
vfs.cpp
|
||||
vm.cpp
|
||||
|
||||
# libroot
|
||||
driver_settings.c
|
||||
|
@ -69,6 +71,7 @@ KernelStaticLibrary boot_loader :
|
|||
kernel_cpp.cpp
|
||||
KMessage.cpp
|
||||
list.cpp
|
||||
ring_buffer.cpp
|
||||
safemode_settings.cpp
|
||||
|
||||
: -fno-pic
|
||||
|
@ -89,7 +92,7 @@ KernelStaticLibrary boot_partitions :
|
|||
;
|
||||
|
||||
# Tell Jam where to find the utility sources
|
||||
SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ]
|
||||
SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ring_buffer.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
|
||||
SEARCH on [ FGristFiles KMessage.cpp ]
|
||||
|
|
|
@ -5,23 +5,26 @@
|
|||
|
||||
|
||||
#include "menu.h"
|
||||
#include "loader.h"
|
||||
#include "RootFileSystem.h"
|
||||
#include "load_driver_settings.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
#include <boot/menu.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <safemode.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
#include <util/ring_buffer.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "load_driver_settings.h"
|
||||
#include "loader.h"
|
||||
#include "pager.h"
|
||||
#include "RootFileSystem.h"
|
||||
|
||||
|
||||
#define TRACE_MENU
|
||||
|
@ -375,6 +378,48 @@ user_menu_boot_volume(Menu *menu, MenuItem *item)
|
|||
}
|
||||
|
||||
|
||||
static bool
|
||||
debug_menu_display_syslog(Menu *menu, MenuItem *item)
|
||||
{
|
||||
ring_buffer* buffer = (ring_buffer*)gKernelArgs.debug_output;
|
||||
if (buffer == NULL)
|
||||
return true;
|
||||
|
||||
struct TextSource : PagerTextSource {
|
||||
TextSource(ring_buffer* buffer)
|
||||
:
|
||||
fBuffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
virtual size_t BytesAvailable() const
|
||||
{
|
||||
return ring_buffer_readable(fBuffer);
|
||||
}
|
||||
|
||||
virtual size_t Read(size_t offset, void* buffer, size_t size) const
|
||||
{
|
||||
return ring_buffer_peek(fBuffer, offset, buffer, size);
|
||||
}
|
||||
|
||||
private:
|
||||
ring_buffer* fBuffer;
|
||||
};
|
||||
|
||||
pager(TextSource(buffer));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
debug_menu_toggle_debug_syslog(Menu *menu, MenuItem *item)
|
||||
{
|
||||
gKernelArgs.keep_debug_output_buffer = item->IsMarked();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static Menu *
|
||||
add_boot_volume_menu(Directory *bootVolume)
|
||||
{
|
||||
|
@ -459,34 +504,66 @@ add_safe_mode_menu()
|
|||
|
||||
platform_add_menus(safeMenu);
|
||||
|
||||
safeMenu->AddSeparatorItem();
|
||||
safeMenu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
|
||||
|
||||
return safeMenu;
|
||||
}
|
||||
|
||||
|
||||
static Menu *
|
||||
add_debug_menu()
|
||||
{
|
||||
Menu *menu = new(nothrow) Menu(SAFE_MODE_MENU, "Debug Options");
|
||||
MenuItem *item;
|
||||
|
||||
#if DEBUG_SPINLOCK_LATENCIES
|
||||
item = new(std::nothrow) MenuItem("Disable latency checks");
|
||||
if (item != NULL) {
|
||||
item->SetType(MENU_ITEM_MARKABLE);
|
||||
item->SetData(B_SAFEMODE_DISABLE_LATENCY_CHECK);
|
||||
item->SetHelpText("Disables latency check panics.");
|
||||
safeMenu->AddItem(item);
|
||||
menu->AddItem(item);
|
||||
}
|
||||
#endif
|
||||
|
||||
safeMenu->AddItem(item
|
||||
menu->AddItem(item
|
||||
= new(nothrow) MenuItem("Enable serial debug output"));
|
||||
item->SetData("serial_debug_output");
|
||||
item->SetType(MENU_ITEM_MARKABLE);
|
||||
item->SetHelpText("Turns on forwarding the syslog output to the serial "
|
||||
"interface.");
|
||||
|
||||
safeMenu->AddItem(item
|
||||
menu->AddItem(item
|
||||
= new(nothrow) MenuItem("Enable on screen debug output"));
|
||||
item->SetData("debug_screen");
|
||||
item->SetType(MENU_ITEM_MARKABLE);
|
||||
item->SetHelpText("Displays debug output on screen while the system "
|
||||
"is booting, instead of the normal boot logo.");
|
||||
|
||||
safeMenu->AddSeparatorItem();
|
||||
safeMenu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
|
||||
menu->AddItem(item = new(nothrow) MenuItem("Enable debug syslog"));
|
||||
item->SetType(MENU_ITEM_MARKABLE);
|
||||
item->SetMarked(gKernelArgs.keep_debug_output_buffer);
|
||||
item->SetTarget(&debug_menu_toggle_debug_syslog);
|
||||
item->SetHelpText("Enables a special in-memory syslog buffer for this "
|
||||
"session that the boot loader will be able to access after rebooting.");
|
||||
|
||||
return safeMenu;
|
||||
ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output;
|
||||
if (syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0) {
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
menu->AddItem(item
|
||||
= new(nothrow) MenuItem("Display syslog from previous session"));
|
||||
item->SetTarget(&debug_menu_display_syslog);
|
||||
item->SetType(MENU_ITEM_NO_CHOICE);
|
||||
item->SetHelpText(
|
||||
"Displays the syslog from the previous Haiku session.");
|
||||
}
|
||||
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
||||
|
@ -527,6 +604,7 @@ user_menu(Directory **_bootVolume)
|
|||
{
|
||||
Menu *menu = new(nothrow) Menu(MAIN_MENU);
|
||||
Menu *safeModeMenu = NULL;
|
||||
Menu *debugMenu = NULL;
|
||||
MenuItem *item;
|
||||
|
||||
TRACE(("user_menu: enter\n"));
|
||||
|
@ -539,6 +617,10 @@ user_menu(Directory **_bootVolume)
|
|||
menu->AddItem(item = new(nothrow) MenuItem("Select safe mode options",
|
||||
safeModeMenu = add_safe_mode_menu()));
|
||||
|
||||
// add debug menu
|
||||
menu->AddItem(item = new(nothrow) MenuItem("Select debug options",
|
||||
debugMenu = add_debug_menu()));
|
||||
|
||||
// Add platform dependent menus
|
||||
platform_add_menus(menu);
|
||||
|
||||
|
@ -561,6 +643,7 @@ user_menu(Directory **_bootVolume)
|
|||
*_bootVolume = (Directory *)item->Data();
|
||||
|
||||
apply_safe_mode_options(safeModeMenu);
|
||||
apply_safe_mode_options(debugMenu);
|
||||
delete menu;
|
||||
|
||||
TRACE(("user_menu: leave\n"));
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
status_t
|
||||
user_memcpy(void* to, const void* from, size_t size)
|
||||
{
|
||||
memcpy(to, from, size);
|
||||
return B_OK;
|
||||
}
|
|
@ -27,7 +27,7 @@ local genericPlatformSources =
|
|||
KernelMergeObject boot_platform_bios_ia32.o :
|
||||
shell.S
|
||||
start.c
|
||||
debug.c
|
||||
debug.cpp
|
||||
bios.S
|
||||
console.cpp
|
||||
serial.cpp
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "serial.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/*! This works only after console_init() was called.
|
||||
*/
|
||||
void
|
||||
panic(const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
platform_switch_to_text_mode();
|
||||
|
||||
puts("*** PANIC ***");
|
||||
|
||||
va_start(list, format);
|
||||
vprintf(format, list);
|
||||
va_end(list);
|
||||
|
||||
puts("\nPress key to reboot.");
|
||||
|
||||
clear_key_buffer();
|
||||
wait_for_key();
|
||||
platform_exit();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dprintf(const char *format, ...)
|
||||
{
|
||||
char buffer[512];
|
||||
va_list list;
|
||||
int length;
|
||||
|
||||
va_start(list, format);
|
||||
length = vsnprintf(buffer, sizeof(buffer), format, list);
|
||||
va_end(list);
|
||||
|
||||
if (length >= (int)sizeof(buffer))
|
||||
length = sizeof(buffer) - 1;
|
||||
|
||||
serial_puts(buffer, length);
|
||||
|
||||
if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)
|
||||
fprintf(stderr, "%s", buffer);
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <kernel.h>
|
||||
#include <util/ring_buffer.h>
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "mmu.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
static const char* const kDebugSyslogSignature = "Haiku syslog";
|
||||
|
||||
static char sBuffer[16384];
|
||||
static uint32 sBufferPosition;
|
||||
|
||||
static ring_buffer* sDebugSyslogBuffer = NULL;
|
||||
|
||||
|
||||
/*! This works only after console_init() was called.
|
||||
*/
|
||||
void
|
||||
panic(const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
platform_switch_to_text_mode();
|
||||
|
||||
puts("*** PANIC ***");
|
||||
|
||||
va_start(list, format);
|
||||
vprintf(format, list);
|
||||
va_end(list);
|
||||
|
||||
puts("\nPress key to reboot.");
|
||||
|
||||
clear_key_buffer();
|
||||
wait_for_key();
|
||||
platform_exit();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dprintf(const char *format, ...)
|
||||
{
|
||||
char buffer[512];
|
||||
va_list list;
|
||||
int length;
|
||||
|
||||
va_start(list, format);
|
||||
length = vsnprintf(buffer, sizeof(buffer), format, list);
|
||||
va_end(list);
|
||||
|
||||
if (length >= (int)sizeof(buffer))
|
||||
length = sizeof(buffer) - 1;
|
||||
|
||||
if (sBufferPosition + length < sizeof(sBuffer)) {
|
||||
memcpy(sBuffer + sBufferPosition, buffer, length);
|
||||
sBufferPosition += length;
|
||||
}
|
||||
|
||||
serial_puts(buffer, length);
|
||||
|
||||
if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)
|
||||
fprintf(stderr, "%s", buffer);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
debug_init_post_mmu(void)
|
||||
{
|
||||
// allocate 1 MB memory at 16 MB
|
||||
addr_t base = 16 * 1024 * 1024;
|
||||
size_t size = 1024 * 1024;
|
||||
if (!mmu_allocate_physical(base, size))
|
||||
return;
|
||||
|
||||
void* buffer = (void*)mmu_map_physical_memory(base, size,
|
||||
kDefaultPageFlags);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
// check whether there's a previous syslog we can recover
|
||||
size_t signatureLength = strlen(kDebugSyslogSignature);
|
||||
bool recover = memcmp(buffer, kDebugSyslogSignature, signatureLength) == 0;
|
||||
|
||||
// clear the signature
|
||||
memset(buffer, 0, signatureLength);
|
||||
|
||||
size -= signatureLength;
|
||||
buffer = (uint8*)buffer + ROUNDUP(signatureLength, sizeof(void*));
|
||||
|
||||
sDebugSyslogBuffer = create_ring_buffer_etc(buffer, size,
|
||||
recover ? RING_BUFFER_INIT_FROM_BUFFER : 0);
|
||||
|
||||
gKernelArgs.debug_output = sDebugSyslogBuffer;
|
||||
gKernelArgs.debug_size = sDebugSyslogBuffer->size;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_cleanup(void)
|
||||
{
|
||||
if (gKernelArgs.keep_debug_output_buffer && sDebugSyslogBuffer != NULL) {
|
||||
// copy the output gathered so far into the ring buffer
|
||||
ring_buffer_clear(sDebugSyslogBuffer);
|
||||
ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer, sBufferPosition);
|
||||
|
||||
// set the buffer signature, so we'll accept it as valid after reboot
|
||||
size_t signatureLength = strlen(kDebugSyslogSignature);
|
||||
memcpy((void*)ROUNDDOWN((addr_t)sDebugSyslogBuffer, B_PAGE_SIZE),
|
||||
kDebugSyslogSignature, signatureLength);
|
||||
} else {
|
||||
gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
|
||||
if (gKernelArgs.debug_output != NULL) {
|
||||
memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
|
||||
gKernelArgs.debug_size = sBufferPosition;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void debug_init_post_mmu(void);
|
||||
void debug_cleanup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // DEBUG_H
|
|
@ -34,10 +34,6 @@ static const uint32 kSerialBaudRate = 115200;
|
|||
static int32 sSerialEnabled = 0;
|
||||
static uint16 sSerialBasePort = 0x3f8;
|
||||
|
||||
static char sBuffer[16384];
|
||||
static uint32 sBufferPosition;
|
||||
|
||||
|
||||
static void
|
||||
serial_putc(char c)
|
||||
{
|
||||
|
@ -55,11 +51,6 @@ serial_puts(const char* string, size_t size)
|
|||
if (sSerialEnabled <= 0)
|
||||
return;
|
||||
|
||||
if (sBufferPosition + size < sizeof(sBuffer)) {
|
||||
memcpy(sBuffer + sBufferPosition, string, size);
|
||||
sBufferPosition += size;
|
||||
}
|
||||
|
||||
while (size-- != 0) {
|
||||
char c = string[0];
|
||||
|
||||
|
@ -92,20 +83,6 @@ serial_enable(void)
|
|||
}
|
||||
|
||||
|
||||
extern "C" void
|
||||
serial_cleanup(void)
|
||||
{
|
||||
if (sSerialEnabled <= 0)
|
||||
return;
|
||||
|
||||
gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
|
||||
if (gKernelArgs.debug_output != NULL) {
|
||||
memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
|
||||
gKernelArgs.debug_size = sBufferPosition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" void
|
||||
serial_init(void)
|
||||
{
|
||||
|
@ -133,4 +110,3 @@ serial_init(void)
|
|||
serial_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
extern void serial_init(void);
|
||||
extern void serial_init_post_mmu(void);
|
||||
extern void serial_cleanup(void);
|
||||
|
||||
extern void serial_puts(const char *string, size_t size);
|
||||
|
|
|
@ -4,24 +4,26 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "serial.h"
|
||||
#include "console.h"
|
||||
#include "apm.h"
|
||||
#include "cpu.h"
|
||||
#include "mmu.h"
|
||||
#include "smp.h"
|
||||
#include "acpi.h"
|
||||
#include "keyboard.h"
|
||||
#include "bios.h"
|
||||
#include "multiboot.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/heap.h>
|
||||
#include <boot/stage2.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "acpi.h"
|
||||
#include "apm.h"
|
||||
#include "bios.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "keyboard.h"
|
||||
#include "mmu.h"
|
||||
#include "multiboot.h"
|
||||
#include "serial.h"
|
||||
#include "smp.h"
|
||||
|
||||
|
||||
#define HEAP_SIZE (128 * 1024)
|
||||
|
@ -79,7 +81,7 @@ platform_start_kernel(void)
|
|||
= gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
|
||||
|
||||
smp_init_other_cpus();
|
||||
serial_cleanup();
|
||||
debug_cleanup();
|
||||
mmu_init_for_kernel();
|
||||
smp_boot_other_cpus();
|
||||
|
||||
|
@ -128,6 +130,7 @@ _start(void)
|
|||
console_init();
|
||||
cpu_init();
|
||||
mmu_init();
|
||||
debug_init_post_mmu();
|
||||
parse_multiboot_commandline(&args);
|
||||
|
||||
// reading the keyboard doesn't seem to work in graphics mode
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
|
@ -91,6 +91,7 @@ static int32 sDebuggerOnCPU = -1;
|
|||
static sem_id sSyslogNotify = -1;
|
||||
static struct syslog_message* sSyslogMessage;
|
||||
static struct ring_buffer* sSyslogBuffer;
|
||||
static size_t sSyslogBufferOffset = 0;
|
||||
static bool sSyslogDropped = false;
|
||||
|
||||
static const char* sCurrentKernelDebuggerMessagePrefix;
|
||||
|
@ -106,7 +107,7 @@ static DebugOutputFilter* sDebugOutputFilter = NULL;
|
|||
DefaultDebugOutputFilter gDefaultDebugOutputFilter;
|
||||
static mutex sOutputLock = MUTEX_INITIALIZER("debug output");
|
||||
|
||||
static void flush_pending_repeats(bool syslogOutput);
|
||||
static void flush_pending_repeats(bool notifySyslog);
|
||||
static void check_pending_repeats(void* data, int iter);
|
||||
|
||||
static int64 sMessageRepeatFirstTime = 0;
|
||||
|
@ -180,7 +181,7 @@ void
|
|||
DefaultDebugOutputFilter::Print(const char* format, va_list args)
|
||||
{
|
||||
vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, format, args);
|
||||
flush_pending_repeats(sInDebugger == 0);
|
||||
flush_pending_repeats(false);
|
||||
PrintString(sInterruptOutputBuffer);
|
||||
}
|
||||
|
||||
|
@ -1065,12 +1066,14 @@ syslog_sender(void* data)
|
|||
cpu_status state = disable_interrupts();
|
||||
acquire_spinlock(&sSpinlock);
|
||||
|
||||
length = ring_buffer_readable(sSyslogBuffer);
|
||||
length = ring_buffer_readable(sSyslogBuffer)
|
||||
- sSyslogBufferOffset;
|
||||
if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH)
|
||||
length = SYSLOG_MAX_MESSAGE_LENGTH;
|
||||
|
||||
length = ring_buffer_read(sSyslogBuffer,
|
||||
length = ring_buffer_peek(sSyslogBuffer, sSyslogBufferOffset,
|
||||
(uint8*)sSyslogMessage->message, length);
|
||||
sSyslogBufferOffset += length;
|
||||
if (sSyslogDropped) {
|
||||
// Add drop marker - since parts had to be dropped, it's
|
||||
// guaranteed that we have enough space in the buffer now.
|
||||
|
@ -1111,28 +1114,32 @@ syslog_sender(void* data)
|
|||
|
||||
|
||||
static void
|
||||
syslog_write(const char* text, int32 length)
|
||||
syslog_write(const char* text, int32 length, bool notify)
|
||||
{
|
||||
bool trunc = false;
|
||||
|
||||
if (sSyslogBuffer == NULL)
|
||||
return;
|
||||
|
||||
if ((int32)ring_buffer_writable(sSyslogBuffer) < length) {
|
||||
// truncate data
|
||||
length = ring_buffer_writable(sSyslogBuffer);
|
||||
if (length > sSyslogBuffer->size) {
|
||||
text = "<DROP>";
|
||||
length = 6;
|
||||
}
|
||||
|
||||
if (length > 8) {
|
||||
trunc = true;
|
||||
length -= 8;
|
||||
} else
|
||||
int32 writable = ring_buffer_writable(sSyslogBuffer);
|
||||
if (writable < length) {
|
||||
// drop old data
|
||||
size_t toDrop = length - writable;
|
||||
ring_buffer_flush(sSyslogBuffer, toDrop);
|
||||
|
||||
if (toDrop > sSyslogBufferOffset) {
|
||||
sSyslogBufferOffset = 0;
|
||||
sSyslogDropped = true;
|
||||
} else
|
||||
sSyslogBufferOffset -= toDrop;
|
||||
}
|
||||
|
||||
ring_buffer_write(sSyslogBuffer, (uint8*)text, length);
|
||||
if (trunc)
|
||||
ring_buffer_write(sSyslogBuffer, (uint8*)"<TRUNC>", 7);
|
||||
|
||||
if (notify)
|
||||
release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
@ -1163,7 +1170,7 @@ syslog_init_post_threads(void)
|
|||
|
||||
|
||||
static status_t
|
||||
syslog_init(struct kernel_args* args)
|
||||
syslog_init_post_vm(struct kernel_args* args)
|
||||
{
|
||||
status_t status;
|
||||
int32 length = 0;
|
||||
|
@ -1177,7 +1184,7 @@ syslog_init(struct kernel_args* args)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
{
|
||||
if (sSyslogBuffer == NULL) {
|
||||
size_t bufferSize = DEFAULT_SYSLOG_BUFFER_SIZE;
|
||||
void* handle = load_driver_settings("kernel");
|
||||
if (handle != NULL) {
|
||||
|
@ -1195,11 +1202,18 @@ syslog_init(struct kernel_args* args)
|
|||
}
|
||||
|
||||
sSyslogBuffer = create_ring_buffer(bufferSize);
|
||||
}
|
||||
|
||||
if (sSyslogBuffer == NULL) {
|
||||
status = B_NO_MEMORY;
|
||||
goto err2;
|
||||
}
|
||||
} else {
|
||||
// create an area for the debug syslog buffer
|
||||
void* base = (void*)ROUNDDOWN((addr_t)args->debug_output, B_PAGE_SIZE);
|
||||
size_t size = ROUNDUP(args->debug_size, B_PAGE_SIZE);
|
||||
create_area("syslog debug", &base, B_EXACT_ADDRESS, size,
|
||||
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
}
|
||||
|
||||
// initialize syslog message
|
||||
sSyslogMessage->from = 0;
|
||||
|
@ -1209,14 +1223,14 @@ syslog_init(struct kernel_args* args)
|
|||
//strcpy(sSyslogMessage->ident, "KERNEL");
|
||||
|
||||
if (args->debug_output != NULL)
|
||||
syslog_write((const char*)args->debug_output, args->debug_size);
|
||||
syslog_write((const char*)args->debug_output, args->debug_size, false);
|
||||
|
||||
char revisionBuffer[64];
|
||||
length = snprintf(revisionBuffer, sizeof(revisionBuffer),
|
||||
"Welcome to syslog debug output!\nHaiku revision: %lu\n",
|
||||
get_haiku_revision());
|
||||
syslog_write(revisionBuffer,
|
||||
std::min(length, (ssize_t)sizeof(revisionBuffer) - 1));
|
||||
std::min(length, (ssize_t)sizeof(revisionBuffer) - 1), false);
|
||||
|
||||
add_debugger_command_etc("syslog", &cmd_dump_syslog,
|
||||
"Dumps the syslog buffer.",
|
||||
|
@ -1236,6 +1250,19 @@ err1:
|
|||
}
|
||||
|
||||
|
||||
static status_t
|
||||
syslog_init(struct kernel_args* args)
|
||||
{
|
||||
if (!args->keep_debug_output_buffer)
|
||||
return B_OK;
|
||||
|
||||
sSyslogBuffer = create_ring_buffer_etc(args->debug_output, args->debug_size,
|
||||
RING_BUFFER_INIT_FROM_BUFFER);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
debug_memcpy_trampoline(void* _parameters)
|
||||
{
|
||||
|
@ -1273,7 +1300,7 @@ call_modules_hook(bool enter)
|
|||
|
||||
//! Must be called with the sSpinlock held.
|
||||
static void
|
||||
debug_output(const char* string, int32 length, bool syslogOutput)
|
||||
debug_output(const char* string, int32 length, bool notifySyslog)
|
||||
{
|
||||
if (length >= OUTPUT_BUFFER_SIZE)
|
||||
length = OUTPUT_BUFFER_SIZE - 1;
|
||||
|
@ -1285,12 +1312,12 @@ debug_output(const char* string, int32 length, bool syslogOutput)
|
|||
if (sMessageRepeatFirstTime == 0)
|
||||
sMessageRepeatFirstTime = sMessageRepeatLastTime;
|
||||
} else {
|
||||
flush_pending_repeats(syslogOutput);
|
||||
flush_pending_repeats(notifySyslog);
|
||||
|
||||
if (sSerialDebugEnabled)
|
||||
arch_debug_serial_puts(string);
|
||||
if (sSyslogOutputEnabled && syslogOutput)
|
||||
syslog_write(string, length);
|
||||
if (sSyslogOutputEnabled)
|
||||
syslog_write(string, length, notifySyslog);
|
||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||
blue_screen_puts(string);
|
||||
if (sSerialDebugEnabled) {
|
||||
|
@ -1308,7 +1335,7 @@ debug_output(const char* string, int32 length, bool syslogOutput)
|
|||
|
||||
//! Must be called with the sSpinlock held.
|
||||
static void
|
||||
flush_pending_repeats(bool syslogOutput)
|
||||
flush_pending_repeats(bool notifySyslog)
|
||||
{
|
||||
if (sMessageRepeatCount <= 0)
|
||||
return;
|
||||
|
@ -1321,8 +1348,8 @@ flush_pending_repeats(bool syslogOutput)
|
|||
|
||||
if (sSerialDebugEnabled)
|
||||
arch_debug_serial_puts(temp);
|
||||
if (sSyslogOutputEnabled && syslogOutput)
|
||||
syslog_write(temp, length);
|
||||
if (sSyslogOutputEnabled)
|
||||
syslog_write(temp, length, notifySyslog);
|
||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||
blue_screen_puts(temp);
|
||||
if (sSerialDebugEnabled) {
|
||||
|
@ -1337,8 +1364,8 @@ flush_pending_repeats(bool syslogOutput)
|
|||
|
||||
if (sSerialDebugEnabled)
|
||||
arch_debug_serial_puts(sLastOutputBuffer);
|
||||
if (sSyslogOutputEnabled && syslogOutput)
|
||||
syslog_write(sLastOutputBuffer, length);
|
||||
if (sSyslogOutputEnabled)
|
||||
syslog_write(sLastOutputBuffer, length, notifySyslog);
|
||||
if (sBlueScreenEnabled || sDebugScreenEnabled)
|
||||
blue_screen_puts(sLastOutputBuffer);
|
||||
if (sSerialDebugEnabled) {
|
||||
|
@ -1374,7 +1401,7 @@ check_pending_repeats(void* /*data*/, int /*iteration*/)
|
|||
|
||||
|
||||
static void
|
||||
dprintf_args(const char* format, va_list args, bool syslogOutput)
|
||||
dprintf_args(const char* format, va_list args, bool notifySyslog)
|
||||
{
|
||||
if (are_interrupts_enabled()) {
|
||||
MutexLocker locker(sOutputLock);
|
||||
|
@ -1384,7 +1411,7 @@ dprintf_args(const char* format, va_list args, bool syslogOutput)
|
|||
length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1);
|
||||
|
||||
InterruptsSpinLocker _(sSpinlock);
|
||||
debug_output(sOutputBuffer, length, syslogOutput);
|
||||
debug_output(sOutputBuffer, length, notifySyslog);
|
||||
} else {
|
||||
InterruptsSpinLocker _(sSpinlock);
|
||||
|
||||
|
@ -1392,7 +1419,7 @@ dprintf_args(const char* format, va_list args, bool syslogOutput)
|
|||
format, args);
|
||||
length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1);
|
||||
|
||||
debug_output(sInterruptOutputBuffer, length, syslogOutput);
|
||||
debug_output(sInterruptOutputBuffer, length, notifySyslog);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1452,7 @@ void
|
|||
debug_puts(const char* string, int32 length)
|
||||
{
|
||||
InterruptsSpinLocker _(sSpinlock);
|
||||
debug_output(string, length, sSyslogOutputEnabled);
|
||||
debug_output(string, length, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1441,6 +1468,8 @@ debug_init(kernel_args* args)
|
|||
{
|
||||
new(&gDefaultDebugOutputFilter) DefaultDebugOutputFilter;
|
||||
|
||||
syslog_init(args);
|
||||
|
||||
debug_paranoia_init();
|
||||
return arch_debug_console_init(args);
|
||||
}
|
||||
|
@ -1484,7 +1513,7 @@ debug_init_post_vm(kernel_args* args)
|
|||
if (sDebugScreenEnabled)
|
||||
blue_screen_enter(true);
|
||||
|
||||
syslog_init(args);
|
||||
syslog_init_post_vm(args);
|
||||
|
||||
return arch_debug_init(args);
|
||||
}
|
||||
|
@ -1785,7 +1814,7 @@ dprintf(const char* format, ...)
|
|||
return;
|
||||
|
||||
va_start(args, format);
|
||||
dprintf_args(format, args, sSyslogOutputEnabled);
|
||||
dprintf_args(format, args, true);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue