diff --git a/KernelLand/Kernel/arch/x86/common.inc.asm b/KernelLand/Kernel/arch/x86/common.inc.asm
new file mode 100644
index 0000000000000000000000000000000000000000..ec7f8441028186cf503ae8e8447d495d0dee3971
--- /dev/null
+++ b/KernelLand/Kernel/arch/x86/common.inc.asm
@@ -0,0 +1,24 @@
+%macro PUSH_CC	0
+	; Don't bother being too picky, just take the time
+	pusha
+%endmacro
+%macro PUSH_SEG	0
+	push ds
+	push es
+	push fs
+	push gs
+	mov ax, 0x10
+	mov ds, ax
+	mov es, ax
+	mov fs, ax
+	mov gs, ax
+%endmacro
+%macro POP_CC	0
+	popa
+%endmacro
+%macro POP_SEG	0
+	pop gs
+	pop fs
+	pop es
+	pop ds
+%endmacro
diff --git a/KernelLand/Kernel/arch/x86/desctab.asm b/KernelLand/Kernel/arch/x86/desctab.asm
index 354a001eb375b3a1e747d7930aa3f18694f3a02c..338253474392d1efa09152c76122b9b3a017cf6e 100644
--- a/KernelLand/Kernel/arch/x86/desctab.asm
+++ b/KernelLand/Kernel/arch/x86/desctab.asm
@@ -1,6 +1,7 @@
 ; AcessOS Microkernel Version
 ;
 ; desctab.asm
+%include "arch/x86/common.inc.asm"
 [BITS 32]
 
 
@@ -182,14 +183,14 @@ Isr0xED:
 	jmp .jmp
 
 [global Isr0xEE]
-[extern SchedulerBase]
+[extern Proc_EventTimer_LAPIC]
 ; AP's Timer Interrupt
 Isr0xEE:
 	push eax	; Line up with interrupt number
 	mov eax, dr1	; CPU Number
 	push eax
 	mov eax, [esp+4]	; Load EAX back
-	jmp SchedulerBase
+	jmp Proc_EventTimer_LAPIC
 ; Spurious Interrupt
 [global Isr0xEF]
 Isr0xEF:
@@ -201,7 +202,7 @@ Isr0xEF:
 ; - Timer
 [global Isr240]
 [global Isr240.jmp]
-[extern SchedulerBase]
+[extern Proc_EventTimer_PIT]
 [extern SetAPICTimerCount]
 Isr240:
 	push 0	; Line up with Argument in errors
@@ -211,7 +212,7 @@ Isr240.jmp:
 	%if USE_MP
 	jmp SetAPICTimerCount	; This is reset once the bus speed has been calculated
 	%else
-	jmp SchedulerBase
+	jmp Proc_EventTimer_PIT
 	%endif
 ; - Assignable
 %assign i	0xF1
@@ -254,11 +255,8 @@ ErrorCommon:
 ; --------------------------
 [extern SyscallHandler]
 SyscallCommon:
-	pusha
-	push ds
-	push es
-	push fs
-	push gs
+	PUSH_CC	; Actually a pusha
+	PUSH_SEG
 	
 	push esp
 	call SyscallHandler
@@ -286,17 +284,8 @@ SyscallCommon:
 [global IRQCommon_handled]
 IRQCommon_handled equ IRQCommon.handled
 IRQCommon:
-	pusha
-	push ds
-	push es
-	push fs
-	push gs
-	
-	mov ax, 0x10
-	mov ds, ax
-	mov es, ax
-	mov fs, ax
-	mov gs, ax
+	PUSH_CC
+	PUSH_SEG
 	
 	push esp
 	call IRQ_Handler
diff --git a/KernelLand/Kernel/arch/x86/proc.asm b/KernelLand/Kernel/arch/x86/proc.asm
index be4c10d37b2bd61b4047a2bb0a4a5d7c6af2dd13..1987166d6c2ff1d6e5a8a120eaea6b62c7e89288 100644
--- a/KernelLand/Kernel/arch/x86/proc.asm
+++ b/KernelLand/Kernel/arch/x86/proc.asm
@@ -1,5 +1,6 @@
 ; AcessOS Microkernel Version
 ; Start.asm
+%include "arch/x86/common.inc.asm"
 
 [bits 32]
 
@@ -11,19 +12,6 @@ KSTACK_USERSTATE_SIZE	equ	(4+8+1+5)*4	; SRegs, GPRegs, CPU, IRET
 
 [section .text]
 
-[global NewTaskHeader]
-NewTaskHeader:
-	mov eax, [esp]
-	mov dr0, eax
-
-	mov eax, [esp+4]
-	add esp, 12	; Thread, Function, Arg Count
-	call eax
-	
-	push eax	; Ret val
-	push 0  	; 0 = This Thread
-	call Threads_Exit
-
 [extern MM_Clone]
 [global Proc_CloneInt]
 Proc_CloneInt:
@@ -53,7 +41,7 @@ Proc_CloneInt:
 ; +16 = Old RIP save loc
 ; +20 = CR3
 SwitchTasks:
-	pusha
+	PUSH_CC
 	
 	; Old IP
 	mov eax, [esp+0x20+16]
@@ -78,7 +66,7 @@ SwitchTasks:
 	jmp ecx
 
 .restore:
-	popa
+	POP_CC
 	xor eax, eax
 	ret
 
@@ -122,17 +110,8 @@ Proc_RestoreSSE:
 [extern Isr240.jmp]
 [global SetAPICTimerCount]
 SetAPICTimerCount:
-	pusha
-	push ds
-	push es
-	push fs
-	push gs
-	
-	mov ax, 0x10
-	mov ds, ax
-	mov es, ax
-	mov fs, ax
-	mov gs, ax
+	PUSH_CC
+	PUSH_SEG
 	
 	mov eax, [gpMP_LocalAPIC]
 	mov ecx, [eax+0x320]
@@ -152,7 +131,7 @@ SetAPICTimerCount:
 	mov DWORD [eax+0x380], 0
 
 	; Update Timer IRQ to the IRQ code
-	mov eax, SchedulerBase
+	mov eax, Proc_EventTimer_PIT
 	sub eax, Isr240.jmp+5
 	mov DWORD [Isr240.jmp+1], eax
 
@@ -160,72 +139,55 @@ SetAPICTimerCount:
 .ret:
 	mov dx, 0x20
 	mov al, 0x20
-	out dx, al		; ACK IRQ
-	pop gs
-	pop fs
-	pop es
-	pop ds
-	popa
+	out 0x20, al		; ACK IRQ
+	POP_SEG
+	POP_CC
 	add esp, 8	; CPU ID / Error Code
 	iret
 %endif
-; --------------
-; Task Scheduler
-; --------------
-[extern Proc_Scheduler]
-[global SchedulerBase]
-SchedulerBase:
-	pusha
-	push ds
-	push es
-	push fs
-	push gs
+
+%if USE_MP
+[global Proc_EventTimer_LAPIC]
+Proc_EventTimer_LAPIC:
+	push eax
+	mov eax, SS:[gpMP_LocalAPIC]
+	mov DWORD SS:[eax + 0xB0], 0
+	pop eax
+	jmp Proc_EventTimer_Common
+%endif
+[global Proc_EventTimer_PIT]
+Proc_EventTimer_PIT:
+	push eax
+	mov al, 0x20
+	out 0x20, al		; ACK IRQ
+	pop eax
+	jmp Proc_EventTimer_Common
+[extern Proc_HandleEventTimer]
+[global Proc_EventTimer_Common]
+Proc_EventTimer_Common:
+	PUSH_CC
+	PUSH_SEG
 	
+	; Clear the Trace/Trap flag
 	pushf
 	and BYTE [esp+1], 0xFE	; Clear Trap Flag
 	popf
-	
-	mov eax, dr0
-	push eax	; Debug Register 0, Current Thread
-	
-	mov ax, 0x10
-	mov ds, ax
-	mov es, ax
-	mov fs, ax
-	mov gs, ax
+	; Re-enable interrupts
+	; - TODO: This is quite likely racy, if we get an interrupt flood
+	sti
 	
 	%if USE_MP
 	call GetCPUNum
-	mov ebx, eax
 	push eax	; Push as argument
 	%else
 	push 0
 	%endif
 	
-	call Proc_Scheduler
+	call Proc_HandleEventTimer
 [global scheduler_return]
 scheduler_return:	; Used by some hackery in Proc_DumpThreadCPUState
-	
 	add esp, 4	; Remove CPU Number (thread is poped later)
 
-	%if USE_MP
-	test ebx, ebx
-	jnz .sendEOI
-	%endif
-	
-	mov al, 0x20
-	out 0x20, al		; ACK IRQ
-
-	%if USE_MP
-	jmp .ret
-.sendEOI:
-	mov eax, DWORD [gpMP_LocalAPIC]
-	mov DWORD [eax+0x0B0], 0
-	%endif
-.ret:
-	pop eax	; Debug Register 0, Current Thread
-	mov dr0, eax
-	
 	jmp ReturnFromInterrupt
 
 ;
diff --git a/KernelLand/Kernel/arch/x86/proc.c b/KernelLand/Kernel/arch/x86/proc.c
index 999ac679ed6234dbde6710f007648819c0a84632..b1dcb99dc1180ae1f993d2d438c92452d9ca0458 100644
--- a/KernelLand/Kernel/arch/x86/proc.c
+++ b/KernelLand/Kernel/arch/x86/proc.c
@@ -44,7 +44,6 @@ extern tGDT	gGDT[];
 extern tIDT	gIDT[];
 extern void	APWait(void);	// 16-bit AP pause code
 extern void	APStartup(void);	// 16-bit AP startup code
-extern void	NewTaskHeader(tThread *Thread, void *Fcn, int nArgs, ...);	// Actually takes cdecl args
 extern Uint	Proc_CloneInt(Uint *ESP, Uint32 *CR3, int bNoUserClone);
 extern Uint32	gaInitPageDir[1024];	// start.asm
 extern char	Kernel_Stack_Top[];
@@ -71,6 +70,7 @@ void	Proc_IdleThread(void *Ptr);
 //tThread	*Proc_GetCurThread(void);
 void	Proc_ChangeStack(void);
 // int	Proc_NewKThread(void (*Fcn)(void*), void *Data);
+void	NewTaskHeader(tThread *Thread, void (*Fcn)(void*), void *Data);	// Actually takes cdecl args
 // int	Proc_Clone(Uint *Err, Uint Flags);
 Uint	Proc_MakeUserStack(void);
 //void	Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);
@@ -78,7 +78,7 @@ void	Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NO
 void	Proc_CallUser(Uint32 UserIP, Uint32 UserSP, const void *StackData, size_t StackDataLen);
 //void	Proc_CallFaultHandler(tThread *Thread);
 //void	Proc_DumpThreadCPUState(tThread *Thread);
-void	Proc_Scheduler(int CPU);
+void	Proc_HandleEventTimer(int CPU);
 
 // === GLOBALS ===
 // --- Multiprocessing ---
@@ -307,10 +307,12 @@ void Proc_IdleThread(void *Ptr)
 	cpu->Current->ThreadName = strdup("Idle Thread");
 	Threads_SetPriority( cpu->Current, -1 );	// Never called randomly
 	cpu->Current->Quantum = 1;	// 1 slice quantum
-	for(;;) {
+	LOG("Idle thread for CPU %i ready", GetCPUNum());
+	for(;;)
+	{
 		__asm__ __volatile__ ("sti");	// Make sure interrupts are enabled
-		__asm__ __volatile__ ("hlt");
-		Proc_Reschedule();
+		Proc_Reschedule();	// Reshedule
+		__asm__ __volatile__ ("hlt");	// And wait for an interrupt if we get scheduled again
 	}
 }
 
@@ -432,10 +434,7 @@ void Proc_ClearThread(tThread *Thread)
 
 tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
-	Uint	esp;
-	tThread	*newThread;
-	
-	newThread = Threads_CloneTCB(0);
+	tThread *newThread = Threads_CloneTCB(0);
 	if(!newThread)	return -1;
 	
 	// Create new KStack
@@ -445,12 +444,14 @@ tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 		free(newThread);
 		return -1;
 	}
+	
+	LOG("%p(%i %s) SP=%p", newThread, newThread->TID, newThread->ThreadName, newThread->KernelStack);
 
-	esp = newThread->KernelStack;
+	Uint esp = newThread->KernelStack;
 	*(Uint*)(esp-=4) = (Uint)Data;	// Data (shadowed)
-	*(Uint*)(esp-=4) = 1;	// Number of params
 	*(Uint*)(esp-=4) = (Uint)Fcn;	// Function to call
 	*(Uint*)(esp-=4) = (Uint)newThread;	// Thread ID
+	*(Uint*)(esp-=4) = (Uint)0;	// Empty return address
 	
 	newThread->SavedState.ESP = esp;
 	newThread->SavedState.EIP = (Uint)&NewTaskHeader;
@@ -463,13 +464,16 @@ tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 	return newThread->TID;
 }
 
-#if 0
-tPID Proc_NewProcess(Uint Flags, void (*Fcn)(void*), size_t SaveSize, const void *Data)
+void NewTaskHeader(tThread *NewThread, void (*Fcn)(void*), void *Data)
 {
-	tThread	*newThread = Threads_CloneTCB(CLONE_VM);
-	return 0;
+	LOG("NewThread=%p, Fcn=%p, Data=%p", NewThread, Fcn, Data);
+	__asm__ __volatile__ ("mov %0, %%dr0" : : "r"(NewThread));
+	SHORTREL(&glThreadListLock);
+	Fcn(Data);
+	
+	Threads_Exit(0, 0);
+	for(;;);
 }
-#endif
 
 /**
  * \fn int Proc_Clone(Uint *Err, Uint Flags)
@@ -477,9 +481,7 @@ tPID Proc_NewProcess(Uint Flags, void (*Fcn)(void*), size_t SaveSize, const void
  */
 tPID Proc_Clone(Uint Flags)
 {
-	tThread	*newThread;
 	tThread	*cur = Proc_GetCurThread();
-	Uint	eip;
 
 	// Sanity, please
 	if( !(Flags & CLONE_VM) ) {
@@ -488,17 +490,17 @@ tPID Proc_Clone(Uint Flags)
 	}
 	
 	// New thread
-	newThread = Threads_CloneTCB(Flags);
+	tThread *newThread = Threads_CloneTCB(Flags);
 	if(!newThread)	return -1;
 	ASSERT(newThread->Process);
-	//ASSERT(CheckMem(newThread->Process, sizeof(tProcess)));
-	//LOG("newThread->Process = %p", newThread->Process);
 
 	newThread->KernelStack = cur->KernelStack;
 
 	// Clone state
-	eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->Process->MemState.CR3, Flags & CLONE_NOUSER);
+	Uint eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->Process->MemState.CR3, Flags & CLONE_NOUSER);
 	if( eip == 0 ) {
+		SHORTREL( &glThreadListLock );
+		LOG("In new thread");
 		return 0;
 	}
 	//ASSERT(newThread->Process);
@@ -536,12 +538,13 @@ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 		Warning("Proc_SpawnWorker - Out of heap space!\n");
 		return NULL;
 	}
+	LOG("new = (%i %s)", new->TID, new->ThreadName);
 
 	// Create the stack contents
 	stack_contents[3] = (Uint)Data;
-	stack_contents[2] = 1;
-	stack_contents[1] = (Uint)Fcn;
-	stack_contents[0] = (Uint)new;
+	stack_contents[2] = (Uint)Fcn;
+	stack_contents[1] = (Uint)new;
+	stack_contents[0] = 0;
 	
 	// Create a new worker stack (in PID0's address space)
 	new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
@@ -774,82 +777,82 @@ void Proc_DumpThreadCPUState(tThread *Thread)
 
 void Proc_Reschedule(void)
 {
-	tThread	*nextthread, *curthread;
 	 int	cpu = GetCPUNum();
 
 	// TODO: Wait for the lock?
-	if(IS_LOCKED(&glThreadListLock))        return;
+	if(IS_LOCKED(&glThreadListLock)) {
+		LOG("Thread list locked, not rescheduling");
+		return;
+	}
 	
-	curthread = Proc_GetCurThread();
-
-	nextthread = Threads_GetNextToRun(cpu, curthread);
-
-	if(!nextthread || nextthread == curthread)
-		return ;
-
-	#if DEBUG_TRACE_SWITCH
-	// HACK: Ignores switches to the idle threads
-	if( nextthread->TID == 0 || nextthread->TID > giNumCPUs )
+	SHORTLOCK(&glThreadListLock);
+	
+	tThread *curthread = Proc_GetCurThread();
+	tThread *nextthread = Threads_GetNextToRun(cpu, curthread);
+	
+	if(nextthread && nextthread != curthread)
 	{
-		LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
-			GetCPUNum(),
-			nextthread, nextthread->TID, nextthread->ThreadName,
-			nextthread->Process->MemState.CR3,
-			nextthread->SavedState.EIP,
-			nextthread->SavedState.ESP
-			);
-		LogF("OldCR3 = %P\n", curthread->Process->MemState.CR3);
-	}
-	#endif
+		#if DEBUG_TRACE_SWITCH
+		// HACK: Ignores switches to the idle threads
+		//if( nextthread->TID == 0 || nextthread->TID > giNumCPUs )
+		{
+			LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
+				GetCPUNum(),
+				nextthread, nextthread->TID, nextthread->ThreadName,
+				nextthread->Process->MemState.CR3,
+				nextthread->SavedState.EIP,
+				nextthread->SavedState.ESP
+				);
+			LogF(" from %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
+				curthread, curthread->TID, curthread->ThreadName,
+				curthread->Process->MemState.CR3,
+				curthread->SavedState.EIP,
+				curthread->SavedState.ESP
+				);
+		}
+		#endif
 
-	// Update CPU state
-	gaCPUs[cpu].Current = nextthread;
-	gaCPUs[cpu].LastTimerThread = NULL;
-	gTSSs[cpu].ESP0 = nextthread->KernelStack-4;
-	__asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) );
+		// Update CPU state
+		gaCPUs[cpu].Current = nextthread;
+		gaCPUs[cpu].LastTimerThread = NULL;
+		gTSSs[cpu].ESP0 = nextthread->KernelStack-4;
+		__asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) );
 
-	// Save FPU/MMX/XMM/SSE state
-	if( curthread && curthread->SavedState.SSE )
-	{
-		Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
-		curthread->SavedState.bSSEModified = 0;
-		Proc_DisableSSE();
-	}
+		// Save FPU/MMX/XMM/SSE state
+		if( curthread && curthread->SavedState.SSE )
+		{
+			Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
+			curthread->SavedState.bSSEModified = 0;
+			Proc_DisableSSE();
+		}
 
-	if( curthread )
-	{
-		SwitchTasks(
-			nextthread->SavedState.ESP, &curthread->SavedState.ESP,
-			nextthread->SavedState.EIP, &curthread->SavedState.EIP,
-			nextthread->Process->MemState.CR3
-			);
-	}
-	else
-	{
-		SwitchTasks(
-			nextthread->SavedState.ESP, 0,
-			nextthread->SavedState.EIP, 0,
-			nextthread->Process->MemState.CR3
-			);
+		if( curthread )
+		{
+			SwitchTasks(
+				nextthread->SavedState.ESP, &curthread->SavedState.ESP,
+				nextthread->SavedState.EIP, &curthread->SavedState.EIP,
+				nextthread->Process->MemState.CR3
+				);
+		}
+		else
+		{
+			SwitchTasks(
+				nextthread->SavedState.ESP, 0,
+				nextthread->SavedState.EIP, 0,
+				nextthread->Process->MemState.CR3
+				);
+		}
 	}
-
-	return ;
+	
+	SHORTREL(&glThreadListLock);
 }
 
 /**
- * \fn void Proc_Scheduler(int CPU)
- * \brief Swap current thread and clears dead threads
+ * \brief Handle the per-CPU timer ticking
+ 
  */
-void Proc_Scheduler(int CPU)
+void Proc_HandleEventTimer(int CPU)
 {
-	#if USE_MP
-	if( GetCPUNum() )
-		gpMP_LocalAPIC->EOI.Val = 0;
-	else
-	#endif
-		outb(0x20, 0x20);
-	__asm__ __volatile__ ("sti");	
-
 	// Call the timer update code
 	Timer_CallTimers();
 
@@ -857,6 +860,8 @@ void Proc_Scheduler(int CPU)
 	// If two ticks happen within the same task, and it's not an idle task, swap
 	if( gaCPUs[CPU].Current->TID > giNumCPUs && gaCPUs[CPU].Current == gaCPUs[CPU].LastTimerThread )
 	{
+		const tThread* const t = gaCPUs[CPU].Current;
+		LOG("Preempting thread %p(%i %s)", t, t->TID, t->ThreadName);
 		Proc_Reschedule();
 	}
 	
diff --git a/KernelLand/Kernel/arch/x86/vm8086.c b/KernelLand/Kernel/arch/x86/vm8086.c
index 93ea63ae5b6022fdb6feff0a31d489fc6439b61b..f1b50059989a0590d0871a35b296d512f5912be1 100644
--- a/KernelLand/Kernel/arch/x86/vm8086.c
+++ b/KernelLand/Kernel/arch/x86/vm8086.c
@@ -68,16 +68,14 @@ Uint32	gaVM8086_MemBitmap[VM8086_BLOCKCOUNT/32];
 // === FUNCTIONS ===
 int VM8086_Install(char **Arguments)
 {
-	tPID	pid;	
-
 	Semaphore_Init(&gVM8086_TasksToDo, 0, 10, "VM8086", "TasksToDo");
 	
 	// Lock to avoid race conditions
 	Mutex_Acquire( &glVM8086_Process );
 	
 	// Create BIOS Call process
-	pid = Proc_Clone(CLONE_VM);
-	//Log_Debug("VM8086", "pid = %i", pid);
+	tPID pid = Proc_Clone(CLONE_VM);
+	LOG("pid = %i", pid);
 	if(pid == -1)
 	{
 		Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
@@ -87,15 +85,14 @@ int VM8086_Install(char **Arguments)
 	{
 		Uint	* volatile stacksetup;	// Initialising Stack
 		Uint16	* volatile rmstack;	// Real Mode Stack
-		 int	i;
 
-		//Log_Debug("VM8086", "Initialising worker");	
+		LOG("Initialising worker");
 	
 		// Set Image Name
 		Threads_SetName("VM8086");
 
 		// Map ROM Area
-		for(i=0xA0;i<0x100;i++) {
+		for(unsigned int i = 0xA0;i<0x100;i++) {
 			MM_RefPhys(i * 0x1000);
 			MM_Map( (void*)(i * 0x1000), i * 0x1000 );
 		}
@@ -150,6 +147,7 @@ int VM8086_Install(char **Arguments)
 		stacksetup--;	*stacksetup = 0x20|3;	// ES - Kernel
 		stacksetup--;	*stacksetup = 0x20|3;	// FS
 		stacksetup--;	*stacksetup = 0x20|3;	// GS
+		LOG("stacksetup = %p, entering vm8086");
 		__asm__ __volatile__ (
 		"mov %%eax,%%esp;\n\t"	// Set stack pointer
 		"pop %%gs;\n\t"
@@ -164,6 +162,7 @@ int VM8086_Install(char **Arguments)
 	gVM8086_WorkerPID = pid;
 
 	// It's released when the GPF fires
+	LOG("Waiting for worker %i to start", gVM8086_WorkerPID);
 	Mutex_Acquire( &glVM8086_Process );
 	Mutex_Release( &glVM8086_Process );
 	
diff --git a/KernelLand/Kernel/events.c b/KernelLand/Kernel/events.c
index ec47a169e543856c787cd99e097413858e2a0d2d..a572d43362d1e66628a7cd258a7bdfee581892fa 100644
--- a/KernelLand/Kernel/events.c
+++ b/KernelLand/Kernel/events.c
@@ -87,7 +87,7 @@ Uint32 Threads_WaitEvents(Uint32 EventMask)
 	{
 		Threads_int_Sleep(THREAD_STAT_EVENTSLEEP, NULL, EventMask,
 			&us, NULL, &us->IsLocked);
-		// Woken when lock is acquired
+		// Woken when an event fires
 		SHORTLOCK( &us->IsLocked );
 	}
 	
diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c
index 80b2796680d39dba3c344d1b54aec7dc2f8b8140..469c5ec18dd3beae6afe01d71d9f4c14a1a67009 100644
--- a/KernelLand/Kernel/threads.c
+++ b/KernelLand/Kernel/threads.c
@@ -4,6 +4,7 @@
  * threads.c
  * - Common Thread Control
  */
+#define DEBUG	0
 #include <acess.h>
 #include <threads.h>
 #include <threads_int.h>
@@ -329,11 +330,10 @@ void Threads_SetPriority(tThread *Thread, int Pri)
  */
 tThread *Threads_CloneTCB(Uint Flags)
 {
-	tThread	*cur, *new;
-	cur = Proc_GetCurThread();
+	tThread *cur = Proc_GetCurThread();
 	
 	// Allocate and duplicate
-	new = malloc(sizeof(tThread));
+	tThread *new = malloc(sizeof(tThread));
 	if(new == NULL) { errno = -ENOMEM; return NULL; }
 	memcpy(new, cur, sizeof(tThread));
 	
@@ -760,6 +760,7 @@ void Threads_Yield(void)
 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
 {
 	tThread	*us = Proc_GetCurThread();
+	LOG("us = %p(%i %s), status=%i", us, us->TID, us->ThreadName, Status);
 	ASSERT(Status != THREAD_STAT_ACTIVE);
 	ASSERT(Status != THREAD_STAT_DEAD);
 	while( us->Status == Status )
@@ -1472,6 +1473,7 @@ tThread *Threads_int_GetRunnable(void)
 	// Single-list round-robin
 	// -----------------------------------
 	tThread *thread = gActiveThreads.Head;
+	LOG("thread = %p", thread);
 	if( thread )
 	{
 		gActiveThreads.Head = thread->Next;
@@ -1493,23 +1495,20 @@ tThread *Threads_int_GetRunnable(void)
  */
 tThread *Threads_GetNextToRun(int CPU, tThread *Last)
 {
-	// If this CPU has the lock, we must let it complete
-	if( CPU_HAS_LOCK( &glThreadListLock ) )
-		return Last;
+	ASSERT( CPU_HAS_LOCK(&glThreadListLock) );
 	
 	// Don't change threads if the current CPU has switches disabled
-	if( gaThreads_NoTaskSwitch[CPU] )
+	if( gaThreads_NoTaskSwitch[CPU] ) {
+		LOG("- Denied");
 		return Last;
-
-	// Lock thread list
-	SHORTLOCK( &glThreadListLock );
+	}
 	
 	// Make sure the current (well, old) thread is marked as de-scheduled	
 	if(Last)	Last->CurCPU = -1;
 
 	// No active threads, just take a nap
 	if(giNumActiveThreads == 0) {
-		SHORTREL( &glThreadListLock );
+		LOG("- No active");
 		#if DEBUG_TRACE_TICKETS
 		Log("No active threads");
 		#endif
@@ -1552,7 +1551,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
 
 	// Call actual scheduler	
 	tThread	*thread = Threads_int_GetRunnable();
-		
+	
 	// Anything to do?
 	if( thread )
 	{
@@ -1578,8 +1577,6 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
 		Warning("No runnable thread for CPU%i", CPU);
 	}
 	
-	SHORTREL( &glThreadListLock );
-	
 	return thread;
 }
 
diff --git a/KernelLand/Kernel/time.c b/KernelLand/Kernel/time.c
index 15b61907216536d3af5b50b178c8ace8866f431d..478c41f3d1410070e3bea1ddd922f1fd5eab70e1 100644
--- a/KernelLand/Kernel/time.c
+++ b/KernelLand/Kernel/time.c
@@ -76,8 +76,9 @@ void Timer_CallTimers()
 {
 	// Tick the random number generator every time timers are checked
 	rand();
-	
+
 	SHORTLOCK(&gTimers_ListLock);
+	LOG("gTimers = %p (%lli ms)", gTimers, (gTimers ? gTimers->FiresAfter : 0));
 	while( gTimers && gTimers->FiresAfter < now() )
 	{
 		ASSERT( gTimers != gTimers->Next );