Add concurency handling when entering the kernel debugger. Previously there

was a race condition when more than one CPU would enter the debugger at the
same time (or rather before one CPU could stop all the others). We now use the
inDebugger variable to tell if someone is already in the debugger and then
only process inter CPU messages and retry entering the debugger.
Since sending the synchronous broadcast most of the time hung over here with
SMP enabled I removed the synchronous flag and added a simple spin to give the
other CPUs a chance to process the halt request. Added comments that explain
the reasons and a ToDo to revert to synchronous delivery once we fixed the
problem. The kernel debugger is now usable on my quad core.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23751 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2008-01-26 19:12:22 +00:00
parent f2e758e5da
commit 7f5698963f

View File

@ -576,8 +576,6 @@ kernel_debugger_loop(void)
line = sLineBuffer[sCurrentLine];
}
sDebuggerOnCPU = smp_get_current_cpu();
int rc = evaluate_debug_command(line);
if (rc == B_KDEBUG_QUIT)
@ -1043,23 +1041,43 @@ panic(const char *format, ...)
void
kernel_debugger(const char *message)
{
static vint32 inDebugger;
static vint32 inDebugger = 0;
cpu_status state;
bool dprintfState;
state = disable_interrupts();
atomic_add(&inDebugger, 1);
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;
}
}
arch_debug_save_registers(&dbg_register_file[smp_get_current_cpu()][0]);
dprintfState = set_dprintf_enabled(true);
if (sDebuggerOnCPU != smp_get_current_cpu()) {
// First entry, halt all of the other cpus
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 but don't block here if they currently can't process it.
// Should they try to enter the debugger they will be cought in the
// loop above.
// ToDo: investigate why we sometimes hang here with SMP_MSG_FLAG_SYNC
// and readd that flag and remove the spin below when it's fixed.
smp_send_broadcast_ici(SMP_MSG_CPU_HALT, 0, 0, 0,
(void *)&inDebugger, 0);
// XXX need to flush current smp mailbox to make sure this goes
// through. Otherwise it'll hang
smp_send_broadcast_ici(SMP_MSG_CPU_HALT, 0, 0, 0, (void *)&inDebugger,
SMP_MSG_FLAG_SYNC);
// Delay a bit to give other CPUs the chance to process the halt
// request. Otherwise we could get debug output of other CPUs mixed
// into our own when enabling debug output below.
spin(50000);
}
if (sBlueScreenOutput) {