Kernel/x86_64 - Separated task switching from timer interrupt
[tpg/acess2.git] / Kernel / arch / x86_64 / proc.c
index 2ee2d4a..4971395 100644 (file)
@@ -5,67 +5,85 @@
 #include <acess.h>
 #include <proc.h>
 #include <threads.h>
+#include <threads_int.h>
 #include <desctab.h>
 #include <mm_virt.h>
 #include <errno.h>
 #if USE_MP
 # include <mp.h>
 #endif
+#include <arch_config.h>
+#include <hal_proc.h>
 
 // === FLAGS ===
 #define DEBUG_TRACE_SWITCH     0
+#define BREAK_ON_SWITCH        0       // Break into bochs debugger on a task switch
 
 // === CONSTANTS ===
-#define        SWITCH_MAGIC    0x55ECAFFF##FFFACE55    // There is no code in this area
-// Base is 1193182
-#define TIMER_DIVISOR  11931   //~100Hz
+
+// === TYPES ===
+typedef struct sCPU
+{
+       Uint8   APICID;
+       Uint8   State;  // 0: Unavaliable, 1: Idle, 2: Active
+       Uint16  Resvd;
+       tThread *Current;
+       tThread *IdleThread;
+}      tCPU;
 
 // === IMPORTS ===
 extern tGDT    gGDT[];
 extern void    APStartup(void);        // 16-bit AP startup code
+
 extern Uint    GetRIP(void);   // start.asm
+extern Uint    SaveState(Uint *RSP, Uint *Regs);
+extern Uint    Proc_CloneInt(Uint *RSP, Uint *CR3);
+extern void    NewTaskHeader(void);    // Actually takes cdecl args
+
 extern Uint64  gInitialPML4[512];      // start.asm
-extern char    gInitialKernelStack[];
-extern tSpinlock       glThreadListLock;
+extern tShortSpinlock  glThreadListLock;
 extern int     giNumCPUs;
 extern int     giNextTID;
 extern int     giTotalTickets;
 extern int     giNumActiveThreads;
 extern tThread gThreadZero;
-extern tThread *gActiveThreads;
-extern tThread *gSleepingThreads;
-extern tThread *gDeleteThreads;
-extern tThread *Threads_GetNextToRun(int CPU);
 extern void    Threads_Dump(void);
-extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
 extern void    Proc_ReturnToUser(void);
-extern int     GetCPUNum(void);
+extern void    Time_UpdateTimestamp(void);
+extern void    SwitchTasks(Uint NewSP, Uint *OldSP, Uint NewIP, Uint *OldIO, Uint CR3);
 
 // === PROTOTYPES ===
-void   ArchThreads_Init(void);
+//void ArchThreads_Init(void);
 #if USE_MP
 void   MP_StartAP(int CPU);
 void   MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode);
 #endif
-void   Proc_Start(void);
-tThread        *Proc_GetCurThread(void);
-void   Proc_ChangeStack(void);
- int   Proc_Clone(Uint *Err, Uint Flags);
-void   Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP);
-void   Proc_CallFaultHandler(tThread *Thread);
-void   Proc_Scheduler(int CPU);
+void   Proc_IdleTask(void *unused);
+//void Proc_Start(void);
+//tThread      *Proc_GetCurThread(void);
+ int   Proc_NewKThread(void (*Fcn)(void*), void *Data);
+// int Proc_Clone(Uint *Err, Uint Flags);
+// int Proc_SpawnWorker(void);
+Uint   Proc_MakeUserStack(void);
+//void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);
+void   Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NORETURN;
+ int   Proc_Demote(Uint *Err, int Dest, tRegs *Regs);
+//void Proc_CallFaultHandler(tThread *Thread);
+//void Proc_DumpThreadCPUState(tThread *Thread);
+//void Proc_Reschedule(void);
+void   Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
 
 // === GLOBALS ===
+//!\brief Used by desctab.asm in SyscallStub
+const int ci_offsetof_tThread_KernelStack = offsetof(tThread, KernelStack);
 // --- Multiprocessing ---
 #if USE_MP
 volatile int   giNumInitingCPUs = 0;
 tMPInfo        *gMPFloatPtr = NULL;
 tAPIC  *gpMP_LocalAPIC = NULL;
 Uint8  gaAPIC_to_CPU[256] = {0};
-tCPU   gaCPUs[MAX_CPUS];
-#else
-tThread        *gCurrentThread = NULL;
 #endif
+tCPU   gaCPUs[MAX_CPUS];
 tTSS   *gTSSs = NULL;
 tTSS   gTSS0 = {0};
 // --- Error Recovery ---
@@ -278,30 +296,34 @@ void ArchThreads_Init(void)
        #if USE_MP
        }
        for(pos=0;pos<giNumCPUs;pos++) {
-       #endif
                __asm__ __volatile__ ("ltr %%ax"::"a"(0x38+pos*16));
-       #if USE_MP
        }
+       #else
+       __asm__ __volatile__ ("ltr %%ax"::"a"(0x38));
        #endif
        
-       #if USE_MP
+       // Set Debug registers
+       __asm__ __volatile__ ("mov %0, %%db0" : : "r"(&gThreadZero));
+       __asm__ __volatile__ ("mov %%rax, %%db1" : : "a"(0));
+       
        gaCPUs[0].Current = &gThreadZero;
-       #else
-       gCurrentThread = &gThreadZero;
-       #endif
        
        gThreadZero.MemState.CR3 = (Uint)gInitialPML4 - KERNEL_BASE;
+       gThreadZero.CurCPU = 0;
+       gThreadZero.KernelStack = 0xFFFFA00000000000 + KERNEL_STACK_SIZE;
        
        // Set timer frequency
        outb(0x43, 0x34);       // Set Channel 0, Low/High, Rate Generator
-       outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
-       outb(0x40, (TIMER_DIVISOR>>8)&0xFF);    // High Byte
+       outb(0x40, PIT_TIMER_DIVISOR&0xFF);     // Low Byte of Divisor
+       outb(0x40, (PIT_TIMER_DIVISOR>>8)&0xFF);        // High Byte
        
        // Create Per-Process Data Block
-       MM_Allocate(MM_PPD_CFG);
-       
-       // Change Stacks
-       Proc_ChangeStack();
+       if( !MM_Allocate(MM_PPD_CFG) )
+       {
+               Warning("Oh, hell, Unable to allocate PPD for Thread#0");
+       }
+
+       Log_Log("Proc", "Multithreading initialised");
 }
 
 #if USE_MP
@@ -332,14 +354,63 @@ void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode)
 }
 #endif
 
+/**
+ * \brief Idle task
+ */
+void Proc_IdleTask(void *ptr)
+{
+       tCPU    *cpu = ptr;
+       cpu->IdleThread = Proc_GetCurThread();
+       cpu->IdleThread->ThreadName = (char*)"Idle Thread";
+       Threads_SetPriority( cpu->IdleThread, -1 );     // Never called randomly
+       cpu->IdleThread->Quantum = 1;   // 1 slice quantum
+       for(;;) HALT(); // Just yeilds
+}
+
 /**
  * \fn void Proc_Start(void)
  * \brief Start process scheduler
  */
 void Proc_Start(void)
 {
+       #if USE_MP
+        int    i;
+       #endif
+       
+       #if USE_MP
+       // Start APs
+       for( i = 0; i < giNumCPUs; i ++ )
+       {
+                int    tid;
+               if(i)   gaCPUs[i].Current = NULL;
+               
+               Proc_NewKThread(Proc_IdleTask, &gaCPUs[i]);             
+
+               // Create Idle Task
+               gaCPUs[i].IdleThread = Threads_GetThread(tid);
+               
+               
+               // Start the AP
+               if( i != giProc_BootProcessorID ) {
+                       MP_StartAP( i );
+               }
+       }
+       
+       // BSP still should run the current task
+       gaCPUs[0].Current = &gThreadZero;
+       
+       // Start interrupts and wait for APs to come up
+       Log("Waiting for APs to come up\n");
+       __asm__ __volatile__ ("sti");
+       while( giNumInitingCPUs )       __asm__ __volatile__ ("hlt");
+       #else
+       Proc_NewKThread(Proc_IdleTask, &gaCPUs[0]);
+       
        // Start Interrupts (and hence scheduler)
        __asm__ __volatile__("sti");
+       #endif
+       MM_FinishVirtualInit();
+       Log("Multithreading started");
 }
 
 /**
@@ -351,133 +422,83 @@ tThread *Proc_GetCurThread(void)
        #if USE_MP
        return gaCPUs[ GetCPUNum() ].Current;
        #else
-       return gCurrentThread;
+       return gaCPUs[ 0 ].Current;
        #endif
 }
 
-/**
- * \fn void Proc_ChangeStack(void)
- * \brief Swaps the current stack for a new one (in the proper stack reigon)
- */
-void Proc_ChangeStack(void)
+int Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
-       Uint    rsp, rbp;
-       Uint    tmp_rbp, old_rsp;
-       Uint    curBase, newBase;
-
-       __asm__ __volatile__ ("mov %%rsp, %0":"=r"(rsp));
-       __asm__ __volatile__ ("mov %%rbp, %0":"=r"(rbp));
-
-       old_rsp = rsp;
+       Uint    rsp;
+       tThread *newThread, *cur;
+       
+       cur = Proc_GetCurThread();
+       newThread = Threads_CloneTCB(NULL, 0);
+       if(!newThread)  return -1;
+       
+       // Set CR3
+       newThread->MemState.CR3 = cur->MemState.CR3;
 
        // Create new KStack
-       newBase = MM_NewKStack();
+       newThread->KernelStack = MM_NewKStack();
        // Check for errors
-       if(newBase == 0) {
-               Panic("What the?? Unable to allocate space for initial kernel stack");
-               return;
+       if(newThread->KernelStack == 0) {
+               free(newThread);
+               return -1;
        }
 
-       curBase = (Uint)&gInitialKernelStack;
+       rsp = newThread->KernelStack;
+       *(Uint*)(rsp-=8) = (Uint)Data;  // Data (shadowed)
+       *(Uint*)(rsp-=8) = 1;   // Number of params
+       *(Uint*)(rsp-=8) = (Uint)Fcn;   // Function to call
+       *(Uint*)(rsp-=8) = (Uint)newThread;     // Thread ID
        
-       Log("curBase = 0x%x, newBase = 0x%x", curBase, newBase);
-
-       // Get ESP as a used size
-       rsp = curBase - rsp;
-       Log("memcpy( %p, %p, 0x%x )", (void*)(newBase - rsp), (void*)(curBase - rsp), rsp );
-       // Copy used stack
-       memcpy( (void*)(newBase - rsp), (void*)(curBase - rsp), rsp );
-       // Get ESP as an offset in the new stack
-       rsp = newBase - rsp;
-       // Adjust EBP
-       rbp = newBase - (curBase - rbp);
-
-       Log("Update stack");
-       // Repair EBPs & Stack Addresses
-       // Catches arguments also, but may trash stack-address-like values
-       for(tmp_rbp = rsp; tmp_rbp < newBase; tmp_rbp += sizeof(Uint))
-       {
-               if(old_rsp < *(Uint*)tmp_rbp && *(Uint*)tmp_rbp < curBase)
-                       *(Uint*)tmp_rbp += newBase - curBase;
-       }
+       newThread->SavedState.RSP = rsp;
+       newThread->SavedState.RIP = (Uint)&NewTaskHeader;
+       Log("New (KThread) %p, rsp = %p\n", newThread->SavedState.RIP, newThread->SavedState.RSP);
        
-       Log("Applying Changes");
-       Proc_GetCurThread()->KernelStack = newBase;
-       __asm__ __volatile__ ("mov %0, %%rsp"::"r"(rsp));
-       __asm__ __volatile__ ("mov %0, %%rbp"::"r"(rbp));
+//     MAGIC_BREAK();  
+       Threads_AddActive(newThread);
+
+       return newThread->TID;
 }
 
 /**
- * \fn int Proc_Clone(Uint *Err, Uint Flags)
+ * \fn int Proc_Clone(Uint Flags)
  * \brief Clone the current process
  */
-int Proc_Clone(Uint *Err, Uint Flags)
+int Proc_Clone(Uint Flags)
 {
-       tThread *newThread;
-       tThread *cur = Proc_GetCurThread();
-       Uint    rip, rsp, rbp;
-       
-       __asm__ __volatile__ ("mov %%rsp, %0": "=r"(rsp));
-       __asm__ __volatile__ ("mov %%rbp, %0": "=r"(rbp));
-       
-       newThread = Threads_CloneTCB(Err, Flags);
-       if(!newThread)  return -1;
-       
-       Log("Proc_Clone: newThread = %p", newThread);
-       
-       // Initialise Memory Space (New Addr space or kernel stack)
-       if(Flags & CLONE_VM) {
-               Log("Proc_Clone: Cloning VM");
-               newThread->MemState.CR3 = MM_Clone();
-               newThread->KernelStack = cur->KernelStack;
-       } else {
-               Uint    tmp_rbp, old_rsp = rsp;
-
-               // Set CR3
-               newThread->MemState.CR3 = cur->MemState.CR3;
-
-               // Create new KStack
-               newThread->KernelStack = MM_NewKStack();
-               Log("Proc_Clone: newKStack = %p", newThread->KernelStack);
-               // Check for errors
-               if(newThread->KernelStack == 0) {
-                       free(newThread);
-                       return -1;
-               }
+       tThread *newThread, *cur = Proc_GetCurThread();
+       Uint    rip;
 
-               // Get ESP as a used size
-               rsp = cur->KernelStack - rsp;
-               // Copy used stack
-               memcpy(
-                       (void*)(newThread->KernelStack - rsp),
-                       (void*)(cur->KernelStack - rsp),
-                       rsp
-                       );
-               // Get ESP as an offset in the new stack
-               rsp = newThread->KernelStack - rsp;
-               // Adjust EBP
-               rbp = newThread->KernelStack - (cur->KernelStack - rbp);
-
-               // Repair EBPs & Stack Addresses
-               // Catches arguments also, but may trash stack-address-like values
-               for(tmp_rbp = rsp; tmp_rbp < newThread->KernelStack; tmp_rbp += sizeof(Uint))
-               {
-                       if(old_rsp < *(Uint*)tmp_rbp && *(Uint*)tmp_rbp < cur->KernelStack)
-                               *(Uint*)tmp_rbp += newThread->KernelStack - cur->KernelStack;
-               }
+       // Sanity check 
+       if( !(Flags & CLONE_VM) ) {
+               Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
+               return -1;
        }
+
+       // Create new TCB
+       newThread = Threads_CloneTCB(NULL, Flags);
+       if(!newThread)  return -1;
        
        // Save core machine state
-       newThread->SavedState.RSP = rsp;
-       newThread->SavedState.RBP = rbp;
-       rip = GetRIP();
-       if(rip == SWITCH_MAGIC) {
+       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->MemState.CR3);
+       if(rip == 0) {
                outb(0x20, 0x20);       // ACK Timer and return as child
+               __asm__ __volatile__ ("sti");
                return 0;
        }
-       
-       // Set EIP as parent
+       newThread->KernelStack = cur->KernelStack;
        newThread->SavedState.RIP = rip;
+
+       // DEBUG        
+       Log("New (Clone) %p, rsp = %p, cr3 = %p", rip, newThread->SavedState.RSP, newThread->MemState.CR3);
+       {
+               Uint cr3;
+               __asm__ __volatile__ ("mov %%cr3, %0" : "=r" (cr3));
+               Log("Current CR3 = 0x%x, PADDR(RSP) = 0x%x", cr3, MM_GetPhysAddr(newThread->SavedState.RSP));
+       }
+       // /DEBUG
        
        // Lock list and add to active
        Threads_AddActive(newThread);
@@ -489,11 +510,11 @@ int Proc_Clone(Uint *Err, Uint Flags)
  * \fn int Proc_SpawnWorker(void)
  * \brief Spawns a new worker thread
  */
-int Proc_SpawnWorker(void)
+int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 {
        tThread *new, *cur;
-       Uint    rip, rsp, rbp;
-       
+       Uint    stack_contents[4];
+
        cur = Proc_GetCurThread();
        
        // Create new thread
@@ -505,29 +526,24 @@ int Proc_SpawnWorker(void)
        memcpy(new, &gThreadZero, sizeof(tThread));
        // Set Thread ID
        new->TID = giNextTID++;
+
+       // Create the stack contents
+       stack_contents[3] = (Uint)Data;
+       stack_contents[2] = 1;
+       stack_contents[1] = (Uint)Fcn;
+       stack_contents[0] = (Uint)new;
+       
        // Create a new worker stack (in PID0's address space)
        // The stack is relocated by this code
-       new->KernelStack = MM_NewWorkerStack();
+       new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
 
-       // Get ESP and EBP based in the new stack
-       __asm__ __volatile__ ("mov %%rsp, %0": "=r"(rsp));
-       __asm__ __volatile__ ("mov %%rbp, %0": "=r"(rbp));
-       rsp = new->KernelStack - (cur->KernelStack - rsp);
-       rbp = new->KernelStack - (cur->KernelStack - rbp);      
+       new->SavedState.RSP = new->KernelStack - sizeof(stack_contents);
+       new->SavedState.RIP = (Uint)&NewTaskHeader;
        
-       // Save core machine state
-       new->SavedState.RSP = rsp;
-       new->SavedState.RBP = rbp;
-       rip = GetRIP();
-       if(rip == SWITCH_MAGIC) {
-               outb(0x20, 0x20);       // ACK Timer and return as child
-               return 0;
-       }
+       Log("New (Worker) %p, rsp = %p\n", new->SavedState.RIP, new->SavedState.RSP);
        
-       // Set EIP as parent
-       new->SavedState.RIP = rip;
        // Mark as active
-       new->Status = THREAD_STAT_ACTIVE;
+       new->Status = THREAD_STAT_PREINIT;
        Threads_AddActive( new );
        
        return new->TID;
@@ -550,8 +566,17 @@ Uint Proc_MakeUserStack(void)
        if(i != -1)     return 0;
        
        // Allocate Stack - Allocate incrementally to clean up MM_Dump output
-       for( i = 0; i < USER_STACK_SZ/4069; i++ )
-               MM_Allocate( base + (i<<12) );
+       for( i = 0; i < USER_STACK_SZ/0x1000; i++ )
+       {
+               if( !MM_Allocate( base + (i<<12) ) )
+               {
+                       // Error
+                       Log_Error("Proc", "Unable to allocate user stack (%i pages requested)", USER_STACK_SZ/0x1000);
+                       while( i -- )
+                               MM_Deallocate( base + (i<<12) );
+                       return 0;
+               }
+       }
        
        return base + USER_STACK_SZ;
 }
@@ -583,7 +608,8 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **
        for( i = 0; EnvP[i]; i++ )      EnvP[i] += delta;
        
        // User Mode Segments
-       ss = 0x23;      cs = 0x1B;
+       // 0x2B = 64-bit
+       ss = 0x23;      cs = 0x2B;
        
        // Arguments
        *--stack = (Uint)EnvP;
@@ -591,34 +617,39 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **
        *--stack = (Uint)ArgC;
        while(*Bases)
                *--stack = *Bases++;
-       *--stack = 0;   // Return Address
        
        Proc_StartProcess(ss, (Uint)stack, 0x202, cs, Entrypoint);
 }
 
 void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP)
 {
-       Uint    *stack = (void*)Stack;
-       *--stack = SS;          //Stack Segment
-       *--stack = Stack;       //Stack Pointer
-       *--stack = Flags;       //EFLAGS (Resvd (0x2) and IF (0x20))
-       *--stack = CS;          //Code Segment
-       *--stack = IP;  //EIP
-       //PUSHAD
-       *--stack = 0xAAAAAAAA;  // eax
-       *--stack = 0xCCCCCCCC;  // ecx
-       *--stack = 0xDDDDDDDD;  // edx
-       *--stack = 0xBBBBBBBB;  // ebx
-       *--stack = 0xD1D1D1D1;  // edi
-       *--stack = 0x54545454;  // rsp - NOT POPED
-       *--stack = 0x51515151;  // esi
-       *--stack = 0xB4B4B4B4;  // rbp
-       //Individual PUSHs
-       *--stack = SS;  // ds
-       
-       __asm__ __volatile__ (
-       "mov %%rax,%%rsp;\n\t"  // Set stack pointer
-       "iret;\n\t" : : "a" (stack));
+       if( !(CS == 0x1B || CS == 0x2B) || SS != 0x23 ) {
+               Log_Error("Proc", "Proc_StartProcess: CS / SS are not valid (%x, %x)",
+                       CS, SS);
+               Threads_Exit(0, -1);
+       }
+       Log("Proc_StartProcess: (SS=%x, Stack=%p, Flags=%x, CS=%x, IP=%p)",
+               SS, Stack, Flags, CS, IP);
+       if(CS == 0x1B)
+       {
+               // 32-bit return
+               __asm__ __volatile__ (
+                       "mov %0, %%rsp;\n\t"    // Set stack pointer
+                       "mov %2, %%r11;\n\t"    // Set RFLAGS
+                       "sysret;\n\t"
+                       : : "r" (Stack), "c" (IP), "r" (Flags)
+                       );
+       }
+       else
+       {
+               // 64-bit return
+               __asm__ __volatile__ (
+                       "mov %0, %%rsp;\n\t"    // Set stack pointer
+                       "mov %2, %%r11;\n\t"    // Set RFLAGS
+                       "sysretq;\n\t"
+                       : : "r" (Stack), "c" (IP), "r" (Flags)
+                       );
+       }
        for(;;);
 }
 
@@ -663,109 +694,86 @@ void Proc_CallFaultHandler(tThread *Thread)
        for(;;);
 }
 
+void Proc_DumpThreadCPUState(tThread *Thread)
+{
+       Log("  At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+}
+
+void Proc_Reschedule(void)
+{
+       tThread *nextthread, *curthread;
+        int    cpu = GetCPUNum();
+
+       // TODO: Wait for it?
+       if(IS_LOCKED(&glThreadListLock))        return;
+       
+       curthread = gaCPUs[cpu].Current;
+
+       nextthread = Threads_GetNextToRun(cpu, curthread);
+
+       if(nextthread == curthread)     return ;
+       if(!nextthread)
+               nextthread = gaCPUs[cpu].IdleThread;
+       if(!nextthread)
+               return ;
+
+       #if DEBUG_TRACE_SWITCH
+       LogF("\nSwitching to task %i, CR3 = 0x%x, RIP = %p, RSP = %p\n",
+               nextthread->TID,
+               nextthread->MemState.CR3,
+               nextthread->SavedState.RIP,
+               nextthread->SavedState.RSP
+               );
+       #endif
+
+       // Update CPU state
+       gaCPUs[cpu].Current = nextthread;
+       gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
+
+       SwitchTasks(
+               nextthread->SavedState.RSP, &curthread->SavedState.RSP,
+               nextthread->SavedState.RIP, &curthread->SavedState.RIP,
+               nextthread->MemState.CR3
+               );
+       return ;
+}
+
 /**
  * \fn void Proc_Scheduler(int CPU)
  * \brief Swap current thread and clears dead threads
  */
-void Proc_Scheduler(int CPU)
+void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
 {
-       Uint    rsp, rbp, rip;
        tThread *thread;
+
+       if( CPU == 0 )
+               Time_UpdateTimestamp();
        
        // If the spinlock is set, let it complete
        if(IS_LOCKED(&glThreadListLock))        return;
        
-       // Clear Delete Queue
-       while(gDeleteThreads)
-       {
-               thread = gDeleteThreads->Next;
-               if(gDeleteThreads->IsLocked) {  // Only free if structure is unused
-                       gDeleteThreads->Status = THREAD_STAT_NULL;
-                       free( gDeleteThreads );
-               }
-               gDeleteThreads = thread;
-       }
-       
-       // Check if there is any tasks running
-       if(giNumActiveThreads == 0) {
-               Log("No Active threads, sleeping");
-               __asm__ __volatile__ ("hlt");
-               return;
-       }
-       
        // Get current thread
-       #if USE_MP
        thread = gaCPUs[CPU].Current;
-       #else
-       thread = gCurrentThread;
-       #endif
-       
-       // Reduce remaining quantum and continue timeslice if non-zero
-       if(thread->Remaining--) return;
-       // Reset quantum for next call
-       thread->Remaining = thread->Quantum;
-       
-       // Get machine state
-       __asm__ __volatile__ ("mov %%rsp, %0":"=r"(rsp));
-       __asm__ __volatile__ ("mov %%rbp, %0":"=r"(rbp));
-       rip = GetRIP();
-       if(rip == SWITCH_MAGIC) return; // Check if a switch happened
-       
-       // Save machine state
-       thread->SavedState.RSP = rsp;
-       thread->SavedState.RBP = rbp;
-       thread->SavedState.RIP = rip;
-       
-       // Get next thread
-       thread = Threads_GetNextToRun(CPU);
-       
-       // Error Check
-       if(thread == NULL) {
-               Warning("Hmm... Threads_GetNextToRun returned NULL, I don't think this should happen.\n");
-               return;
-       }
-       
-       #if DEBUG_TRACE_SWITCH
-       Log("Switching to task %i, CR3 = 0x%x, RIP = %p",
-               thread->TID,
-               thread->MemState.CR3,
-               thread->SavedState.RIP
-               );
-       #endif
-       
-       // Set current thread
-       #if USE_MP
-       gaCPUs[CPU].Current = thread;
-       #else
-       gCurrentThread = thread;
-       #endif
-       
-       // Update Kernel Stack pointer
-       gTSSs[CPU].RSP0 = thread->KernelStack-4;
-       
-       // Set address space
-       #if USE_PAE
-       # error "Todo: Implement PAE Address space switching"
-       #else
-               __asm__ __volatile__ ("mov %0, %%cr3"::"a"(thread->MemState.CR3));
-       #endif
-       
-       #if 0
-       if(thread->SavedState.RSP > 0xC0000000
-       && thread->SavedState.RSP < thread->KernelStack-0x2000) {
-               Log_Warning("Proc", "Possible bad ESP %p (PID %i)", thread->SavedState.ESP);
+
+       if( thread )
+       {
+               tRegs   *regs;
+               // Reduce remaining quantum and continue timeslice if non-zero
+               if(thread->Remaining--) return;
+               // Reset quantum for next call
+               thread->Remaining = thread->Quantum;
+               
+               // TODO: Make this more stable somehow
+               {
+                       regs = (tRegs*)(RSP+(1)*8);     // CurThread
+                       thread->SavedState.UserCS = regs->CS;
+                       thread->SavedState.UserRIP = regs->RIP;
+               }
        }
-       #endif
-       
-       // Switch threads
-       __asm__ __volatile__ (
-               "mov %1, %%rsp\n\t"     // Restore RSP
-               "mov %2, %%rbp\n\t"     // and RBP
-               "jmp *%3" : :   // And return to where we saved state (Proc_Clone or Proc_Scheduler)
-               "a"(SWITCH_MAGIC), "b"(thread->SavedState.RSP),
-               "d"(thread->SavedState.RBP), "c"(thread->SavedState.RIP)
-               );
-       for(;;);        // Shouldn't reach here
+
+       // ACK Timer here?
+
+       Proc_Reschedule();
 }
 
 // === EXPORTS ===

UCC git Repository :: git.ucc.asn.au