* \fn tVAddr MM_NewWorkerStack()
* \brief Creates a new worker stack
*/
-tVAddr MM_NewWorkerStack()
+tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize)
{
- Uint esp, ebp;
- Uint oldstack;
Uint base, addr;
- int i, j;
- Uint *tmpPage;
- tPAddr pages[WORKER_STACK_SIZE>>12];
-
- // Get the old ESP and EBP
- __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp));
- __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp));
+ tVAddr tmpPage;
+ tPAddr page;
// TODO: Thread safety
// Find a free worker stack address
// Mapping Time!
for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 )
- //for( addr = WORKER_STACK_SIZE; addr; addr -= 0x1000 )
{
- pages[ addr >> 12 ] = MM_AllocPhys();
- gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3;
+ page = MM_AllocPhys();
+ gaTmpTable[ (base + addr) >> 12 ] = page | 3;
}
*gpTmpCR3 = 0;
// Release the temp mapping lock
Mutex_Release(&glTempFractal);
-
- // Copy the old stack
- oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1);
- esp = oldstack - esp; // ESP as an offset in the stack
-
- // Make `base` be the top of the stack
- base += WORKER_STACK_SIZE;
-
- i = (WORKER_STACK_SIZE>>12) - 1;
- // Copy the contents of the old stack to the new one, altering the addresses
- // `addr` is refering to bytes from the stack base (mem downwards)
- for(addr = 0; addr < esp; addr += 0x1000)
- {
- Uint *stack = (Uint*)( oldstack-(addr+0x1000) );
- tmpPage = (void*)MM_MapTemp( pages[i] );
- // Copy old stack
- for(j = 0; j < 1024; j++)
- {
- // Possible Stack address?
- if(oldstack-esp < stack[j] && stack[j] < oldstack)
- tmpPage[j] = base - (oldstack - stack[j]);
- else // Seems not, best leave it alone
- tmpPage[j] = stack[j];
- }
- MM_FreeTemp((tVAddr)tmpPage);
- i --;
- }
+
+ // NOTE: Max of 1 page
+ // `page` is the last allocated page from the previious for loop
+ tmpPage = MM_MapTemp( page );
+ memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize);
+ MM_FreeTemp(tmpPage);
//Log("MM_NewWorkerStack: RETURN 0x%x", base);
- return base;
+ return base + WORKER_STACK_SIZE;
}
/**
#define DEBUG_VERY_SLOW_SWITCH 0
// === CONSTANTS ===
-#define SWITCH_MAGIC 0xFF5317C8 // FF SWITCH - There is no code in this area
// Base is 1193182
#define TIMER_BASE 1193182
#if DEBUG_VERY_SLOW_PERIOD
extern void APStartup(void); // 16-bit AP startup code
extern Uint GetEIP(void); // start.asm
extern Uint GetEIP_Sched(void); // proc.asm
+extern void NewTaskHeader(tThread *Thread, void *Fcn, int nArgs, ...); // Actually takes cdecl args
extern Uint32 gaInitPageDir[1024]; // start.asm
extern char Kernel_Stack_Top[];
extern tShortSpinlock glThreadListLock;
newThread->SavedState.ESP = esp;
newThread->SavedState.EBP = ebp;
eip = GetEIP();
- if(eip == SWITCH_MAGIC) {
+ if(eip == 0) {
//__asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) );
#if USE_MP
// ACK the interrupt
* \fn int Proc_SpawnWorker(void)
* \brief Spawns a new worker thread
*/
-int Proc_SpawnWorker(void (*Fcn)(void*), void *Data);
+int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- tThread *new, *cur;
- Uint eip, esp, ebp;
-
- cur = Proc_GetCurThread();
+ tThread *new;
+ Uint stack_contents[4];
// Create new thread
new = Threads_CloneThreadZero();
Warning("Proc_SpawnWorker - Out of heap space!\n");
return -1;
}
- // Create a new worker stack (in PID0's address space)
- // - The stack is relocated by this function
- new->KernelStack = MM_NewWorkerStack();
- // Get ESP and EBP based in the new stack
- __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp));
- __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp));
- esp = new->KernelStack - (cur->KernelStack - esp);
- ebp = new->KernelStack - (cur->KernelStack - ebp);
+ // 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)
+ new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
+
// Save core machine state
- new->SavedState.ESP = esp;
- new->SavedState.EBP = ebp;
- eip = GetEIP();
- if(eip == SWITCH_MAGIC) {
- //__asm__ __volatile__ ("mov %0, %%db0" : : "r"(new));
- #if USE_MP
- // ACK the interrupt
- if(GetCPUNum())
- gpMP_LocalAPIC->EOI.Val = 0;
- else
- #endif
- outb(0x20, 0x20); // ACK Timer and return as child
- __asm__ __volatile__ ("sti"); // Restart interrupts
- return 0;
- }
+ new->SavedState.ESP = new->KernelStack - sizeof(stack_contents);
+ new->SavedState.EBP = 0;
+ new->SavedState.EIP = (Uint)NewTaskHeader;
- // Set EIP as parent
- new->SavedState.EIP = eip;
// Mark as active
+ new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
return new->TID;
__asm__ __volatile__ ( "mov %%esp, %0" : "=r" (esp) );
__asm__ __volatile__ ( "mov %%ebp, %0" : "=r" (ebp) );
eip = GetEIP();
- if(eip == SWITCH_MAGIC) {
+ if(eip == 0) {
__asm__ __volatile__ ( "nop" : : : "eax","ebx","ecx","edx","edi","esi");
regs = (tRegs*)(ebp+(2+2)*4); // EBP,Ret + CPU,CurThread
#if USE_MP
__asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(thread) );
// Switch threads
__asm__ __volatile__ (
- "mov %4, %%cr3\n\t" // Set address space
- "mov %1, %%esp\n\t" // Restore ESP
- "mov %2, %%ebp\n\t" // and EBP
- "or %5, 72(%%ebp)\n\t" // or trace flag to eflags (2+2+4+8+2)*4
- "jmp *%3" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler)
- "a"(SWITCH_MAGIC), "b"(thread->SavedState.ESP),
- "d"(thread->SavedState.EBP), "c"(thread->SavedState.EIP),
+ "mov %3, %%cr3\n\t" // Set address space
+ "mov %0, %%esp\n\t" // Restore ESP
+ "mov %1, %%ebp\n\t" // and EBP
+ "test %4, %4\n\t"
+ "jz 1f\n\t"
+ "or %4, 72(%%ebp)\n\t" // or trace flag to eflags (2+2+4+8+2)*4
+ "1:"
+ "xor %%eax, %%eax\n\t"
+ "jmp *%2" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler)
+ "r"(thread->SavedState.ESP),
+ "r"(thread->SavedState.EBP),
+ "r"(thread->SavedState.EIP),
"r"(thread->MemState.CR3),
"r"(thread->bInstrTrace&&thread->SavedState.EIP==(Uint)&GetEIP_Sched_ret?0x100:0)
);