bonefish + mmlr:
* We started the "main2" thread too late. Since the scheduler was already started on all CPUs, the idle thread could wait (for a mutex) while spawing the "main2" thread. This violated the assumption in the scheduler that all idle threads would always be ready or running. We now create the thread while the kernel runs still single-threaded. * scheduler_start() is now invoked with interrupts still disabled. We enable them after the function returns. This prevents scheduler_reschedule() from potentially being invoked before scheduler_start(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29914 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+10
-10
@@ -189,6 +189,13 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
swap_init();
|
swap_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Start a thread to finish initializing the rest of the system. Note,
|
||||||
|
// it won't be scheduled before calling scheduler_start() (on any CPU).
|
||||||
|
TRACE("spawning main2 thread\n");
|
||||||
|
thread_id thread = spawn_kernel_thread(&main2, "main2",
|
||||||
|
B_NORMAL_PRIORITY, NULL);
|
||||||
|
send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE);
|
||||||
|
|
||||||
// bring up the AP cpus in a lock step fashion
|
// bring up the AP cpus in a lock step fashion
|
||||||
TRACE("waking up AP cpus\n");
|
TRACE("waking up AP cpus\n");
|
||||||
sCpuRendezvous = sCpuRendezvous2 = 0;
|
sCpuRendezvous = sCpuRendezvous2 = 0;
|
||||||
@@ -202,16 +209,9 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
smp_cpu_rendezvous(&sCpuRendezvous2, 0);
|
smp_cpu_rendezvous(&sCpuRendezvous2, 0);
|
||||||
// release the AP cpus to go enter the scheduler
|
// release the AP cpus to go enter the scheduler
|
||||||
|
|
||||||
TRACE("enabling interrupts and starting scheduler on cpu 0\n");
|
TRACE("starting scheduler on cpu 0 and enabling interrupts\n");
|
||||||
enable_interrupts();
|
|
||||||
scheduler_start();
|
scheduler_start();
|
||||||
|
enable_interrupts();
|
||||||
// start a thread to finish initializing the rest of the system
|
|
||||||
TRACE("starting main2 thread\n");
|
|
||||||
thread_id thread = spawn_kernel_thread(&main2, "main2",
|
|
||||||
B_NORMAL_PRIORITY, NULL);
|
|
||||||
TRACE("resuming main2 thread...\n");
|
|
||||||
resume_thread(thread);
|
|
||||||
} else {
|
} else {
|
||||||
// lets make sure we're in sync with the main cpu
|
// lets make sure we're in sync with the main cpu
|
||||||
// the boot processor has probably been sending us
|
// the boot processor has probably been sending us
|
||||||
@@ -228,8 +228,8 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);
|
smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);
|
||||||
|
|
||||||
// welcome to the machine
|
// welcome to the machine
|
||||||
enable_interrupts();
|
|
||||||
scheduler_start();
|
scheduler_start();
|
||||||
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("main: done... begin idle loop on cpu %d\n", currentCPU);
|
TRACE("main: done... begin idle loop on cpu %d\n", currentCPU);
|
||||||
|
|||||||
@@ -516,19 +516,17 @@ affine_on_thread_destroy(struct thread* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This starts the scheduler. Must be run under the context of
|
/*! This starts the scheduler. Must be run in the context of the initial idle
|
||||||
the initial idle thread.
|
thread. Interrupts must be disabled and will be disabled when returning.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
affine_start(void)
|
affine_start(void)
|
||||||
{
|
{
|
||||||
cpu_status state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
affine_reschedule();
|
affine_reschedule();
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -401,19 +401,17 @@ simple_on_thread_destroy(struct thread* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This starts the scheduler. Must be run under the context of
|
/*! This starts the scheduler. Must be run in the context of the initial idle
|
||||||
the initial idle thread.
|
thread. Interrupts must be disabled and will be disabled when returning.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
simple_start(void)
|
simple_start(void)
|
||||||
{
|
{
|
||||||
cpu_status state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
simple_reschedule();
|
simple_reschedule();
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user