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:
Ingo Weinhold
2009-04-04 23:54:01 +00:00
parent aeab3755ee
commit 53e1017720
3 changed files with 40 additions and 44 deletions
+10 -10
View File
@@ -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);
} }