extern Uint GetRIP(void); // start.asm
extern Uint SaveState(Uint *RSP, Uint *Regs);
-extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3);
+extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM);
extern void NewTaskHeader(void); // Actually takes cdecl args
extern void Proc_InitialiseSSE(void);
extern void Proc_SaveSSE(Uint DestPtr);
//void Proc_DumpThreadCPUState(tThread *Thread);
//void Proc_Reschedule(void);
void Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
+Uint Proc_int_SetIRQIP(Uint RIP);
// === GLOBALS ===
//!\brief Used by desctab.asm in SyscallStub
tAPIC *gpMP_LocalAPIC = NULL;
Uint8 gaAPIC_to_CPU[256] = {0};
#endif
-tCPU gaCPUs[MAX_CPUS];
+tCPU gaCPUs[MAX_CPUS] = {
+ {.Current = &gThreadZero}
+ };
tTSS *gTSSs = NULL;
tTSS gTSS0 = {0};
// --- Error Recovery ---
outb(0x40, (PIT_TIMER_DIVISOR>>8)&0xFF); // High Byte
// Create Per-Process Data Block
- if( !MM_Allocate(MM_PPD_CFG) )
+ if( !MM_Allocate( (void*)MM_PPD_CFG ) )
{
Warning("Oh, hell, Unable to allocate PPD for Thread#0");
}
tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
{
Uint rsp;
- tThread *newThread, *cur;
+ tThread *newThread;
- cur = Proc_GetCurThread();
newThread = Threads_CloneTCB(0);
if(!newThread) return -1;
if(!newThread) return -1;
// Save core machine state
- rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
- if(rip == 0) return 0; // Child
+ rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
+ if(rip == 0) {
+ SHORTREL(&glThreadListLock);
+ return 0; // Child
+ }
newThread->KernelStack = cur->KernelStack;
newThread->SavedState.RIP = rip;
newThread->SavedState.SSE = NULL;
* \fn int Proc_SpawnWorker(void)
* \brief Spawns a new worker thread
*/
-int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
+tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- tThread *new, *cur;
+ tThread *new;
Uint stack_contents[3];
- cur = Proc_GetCurThread();
-
// Create new thread
new = Threads_CloneThreadZero();
if(!new) {
Warning("Proc_SpawnWorker - Out of heap space!\n");
- return -1;
+ return NULL;
}
// Create the stack contents
new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
- return new->TID;
+ return new;
}
/**
*/
Uint Proc_MakeUserStack(void)
{
- int i;
- Uint base = USER_STACK_TOP - USER_STACK_SZ;
+ tPage *base = (void*)(USER_STACK_TOP - USER_STACK_SZ);
// Check Prospective Space
- for( i = USER_STACK_SZ >> 12; i--; )
+ for( int i = USER_STACK_SZ/PAGE_SIZE; i--; )
{
- if( MM_GetPhysAddr( (void*)(base + (i<<12)) ) != 0 )
- break;
+ if( MM_GetPhysAddr( base + i ) != 0 )
+ {
+ return 0;
+ }
}
- if(i != -1) return 0;
-
// Allocate Stack - Allocate incrementally to clean up MM_Dump output
// - Most of the user stack is the zero page
- for( i = 0; i < (USER_STACK_SZ-USER_STACK_PREALLOC)/0x1000; i++ )
+ int i = 0;
+ for( ; i < (USER_STACK_SZ-USER_STACK_PREALLOC)/PAGE_SIZE; i++ )
{
- MM_AllocateZero( base + (i<<12) );
+ MM_AllocateZero( base + i );
}
// - but the top USER_STACK_PREALLOC pages are actually allocated
- for( ; i < USER_STACK_SZ/0x1000; i++ )
+ for( ; i < USER_STACK_SZ/PAGE_SIZE; i++ )
{
- tPAddr alloc = MM_Allocate( base + (i<<12) );
+ tPAddr alloc = MM_Allocate( base + i );
if( !alloc )
{
// Error
- Log_Error("Proc", "Unable to allocate user stack (%i pages requested)", USER_STACK_SZ/0x1000);
+ Log_Error("Proc", "Unable to allocate user stack (%i pages requested)", USER_STACK_SZ/PAGE_SIZE);
while( i -- )
- MM_Deallocate( base + (i<<12) );
+ MM_Deallocate( base + i );
return 0;
}
}
- return base + USER_STACK_SZ;
+ return (tVAddr)( base + USER_STACK_SZ/PAGE_SIZE );
}
void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, const char **ArgV, int DataSize)
void Proc_DumpThreadCPUState(tThread *Thread)
{
- Log(" At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ if( Thread->CurCPU == GetCPUNum() ) {
+ // TODO: Backtrace to IRQ
+ Log(" IRQ %016llx", Thread->SavedState.UserRIP);
+ }
+ else {
+ Log(" At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP);
+ Log(" User %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(CPU_HAS_LOCK(&glThreadListLock))
+ return;
+ SHORTLOCK(&glThreadListLock);
- if(nextthread == curthread) return ;
+ tThread *curthread = gaCPUs[cpu].Current;
+ tThread *nextthread = Threads_GetNextToRun(cpu, curthread);
+
if(!nextthread)
nextthread = gaCPUs[cpu].IdleThread;
- if(!nextthread)
- return ;
-
- #if DEBUG_TRACE_SWITCH
- LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
- nextthread->Process->MemState.CR3,
- nextthread->SavedState.RIP,
- nextthread->SavedState.RSP,
- nextthread->TID,
- nextthread->ThreadName
- );
- #endif
- // Update CPU state
- gaCPUs[cpu].Current = nextthread;
- gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
- __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
-
- if( curthread )
+ if(nextthread && nextthread != curthread)
{
- // Save FPU/MMX/XMM/SSE state
- if( curthread->SavedState.SSE )
+ #if DEBUG_TRACE_SWITCH
+ LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
+ nextthread->Process->MemState.CR3,
+ nextthread->SavedState.RIP,
+ nextthread->SavedState.RSP,
+ nextthread->TID,
+ nextthread->ThreadName
+ );
+ #endif
+
+ // Update CPU state
+ gaCPUs[cpu].Current = nextthread;
+ gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
+ __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
+
+ if( curthread )
{
- Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
- curthread->SavedState.bSSEModified = 0;
- Proc_DisableSSE();
+ // Save FPU/MMX/XMM/SSE state
+ if( curthread->SavedState.SSE )
+ {
+ Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
+ curthread->SavedState.bSSEModified = 0;
+ Proc_DisableSSE();
+ }
+ SwitchTasks(
+ nextthread->SavedState.RSP, &curthread->SavedState.RSP,
+ nextthread->SavedState.RIP, &curthread->SavedState.RIP,
+ nextthread->Process->MemState.CR3
+ );
+ }
+ else
+ {
+ Uint tmp;
+ SwitchTasks(
+ nextthread->SavedState.RSP, &tmp,
+ nextthread->SavedState.RIP, &tmp,
+ nextthread->Process->MemState.CR3
+ );
}
- SwitchTasks(
- nextthread->SavedState.RSP, &curthread->SavedState.RSP,
- nextthread->SavedState.RIP, &curthread->SavedState.RIP,
- nextthread->Process->MemState.CR3
- );
- }
- else
- {
- Uint tmp;
- SwitchTasks(
- nextthread->SavedState.RSP, &tmp,
- nextthread->SavedState.RIP, &tmp,
- nextthread->Process->MemState.CR3
- );
}
- return ;
+ SHORTREL(&glThreadListLock);
}
/**
#endif
}
+Uint Proc_int_SetIRQIP(Uint RIP)
+{
+ int cpu = GetCPUNum();
+ tThread *thread = gaCPUs[cpu].Current;
+ Uint rv = thread->SavedState.UserRIP;
+ thread->SavedState.UserRIP = RIP;
+ return rv;
+}
+
// === EXPORTS ===
EXPORT(Proc_SpawnWorker);