/*
- * AcessOS Microkernel Version
+ * Acess2 Kernel (x86)
+ * - By John Hodge (thePowersGang)
+ *
* proc.c
+ * - Low level thread management
*/
+#define DEBUG 0
#include <acess.h>
#include <threads.h>
#include <proc.h>
#define DEBUG_DISABLE_DOUBLEFAULT 1
#define DEBUG_VERY_SLOW_PERIOD 0
#define DEBUG_NOPREEMPT 1
+#define DISABLE_PIT 0
// === CONSTANTS ===
// Base is 1193182
#define TIMER_BASE 1193182
-#if DEBUG_VERY_SLOW_PERIOD
+#if DISABLE_PIT
+# define TIMER_DIVISOR 0xFFFF
+#elif DEBUG_VERY_SLOW_PERIOD
# define TIMER_DIVISOR 1193 //~10Hz switch, with 10 quantum = 1s per thread
#else
# define TIMER_DIVISOR 11932 //~100Hz
extern char IRQCommon[]; // Common IRQ handler code
extern char IRQCommon_handled[]; // IRQCommon call return location
extern char GetEIP_Sched_ret[]; // GetEIP call return location
+extern void Timer_CallTimers(void);
// === PROTOTYPES ===
//void ArchThreads_Init(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;
+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);
gProcessZero.MemState.CR3 = (Uint)gaInitPageDir - KERNEL_BASE;
// Create Per-Process Data Block
- if( !MM_Allocate(MM_PPD_CFG) )
+ if( MM_Allocate( (void*)MM_PPD_CFG ) == 0 )
{
Panic("OOM - No space for initial Per-Process Config");
}
return newThread->TID;
}
+#if 0
+tPID Proc_NewProcess(Uint Flags, void (*Fcn)(void*), size_t SaveSize, const void *Data)
+{
+ tThread *newThread = Threads_CloneTCB(CLONE_VM);
+ return 0;
+}
+#endif
+
/**
* \fn int Proc_Clone(Uint *Err, Uint Flags)
* \brief Clone the current process
tThread *cur = Proc_GetCurThread();
Uint eip;
+ Log_Warning("Proc", "Proc_Clone is deprecated");
// Sanity, please
if( !(Flags & CLONE_VM) ) {
Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
// New thread
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;
if( eip == 0 ) {
return 0;
}
+ //ASSERT(newThread->Process);
+ //ASSERT(CheckMem(newThread->Process, sizeof(tProcess)));
+ //LOG("newThread->Process = %p", newThread->Process);
newThread->SavedState.EIP = eip;
newThread->SavedState.SSE = NULL;
newThread->SavedState.bSSEModified = 0;
*/
tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- tThread *new;
Uint stack_contents[4];
+ LOG("(Fcn=%p,Data=%p)", Fcn, Data);
// Create new thread
- new = Threads_CloneThreadZero();
+ tThread *new = Threads_CloneThreadZero();
+ LOG("new=%p", new);
if(!new) {
Warning("Proc_SpawnWorker - Out of heap space!\n");
return NULL;
// Create a new worker stack (in PID0's address space)
new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
+ LOG("new->KernelStack = %p", new->KernelStack);
// Save core machine state
new->SavedState.ESP = new->KernelStack - sizeof(stack_contents);
// Mark as active
new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
+ LOG("Added to active");
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--; )
- if( MM_GetPhysAddr( (void*)(base + (i<<12)) ) != 0 )
- break;
-
- if(i != -1) return 0;
-
+ for( Uint i = USER_STACK_SZ/PAGE_SIZE; i--; )
+ {
+ if( MM_GetPhysAddr( base + i ) != 0 )
+ {
+ Warning("Proc_MakeUserStack: Address %p in use", base + i);
+ return 0;
+ }
+ }
// Allocate Stack - Allocate incrementally to clean up MM_Dump output
- for( i = 0; i < USER_STACK_SZ/0x1000; i++ )
+ for( Uint i = 0; i < USER_STACK_SZ/PAGE_SIZE; i++ )
{
- if( !MM_Allocate( base + (i<<12) ) )
+ if( MM_Allocate( base + i ) == 0 )
{
Warning("OOM: Proc_MakeUserStack");
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)
for(;;);
}
+void Proc_CallUser(Uint32 UserIP, Uint32 UserSP, const void *StackData, size_t StackDataLen)
+{
+ if( UserSP < StackDataLen )
+ return ;
+ if( !CheckMem( (void*)(UserSP - StackDataLen), StackDataLen ) )
+ return ;
+ memcpy( (void*)(UserSP - StackDataLen), StackData, StackDataLen );
+
+ __asm__ __volatile__ (
+ "mov $0x23,%%ax;\n\t"
+ "mov %%ax, %%ds;\n\t"
+ "mov %%ax, %%es;\n\t"
+ "mov %%ax, %%fs;\n\t"
+ "mov %%ax, %%gs;\n\t"
+ "push $0x23;\n\t"
+ "push %1;\n\t"
+ "push $0x202;\n\t"
+ "push $0x1B;\n\t"
+ "push %0;\n\t"
+ "iret;\n\t"
+ :
+ : "r" (UserIP), "r" (UserSP - StackDataLen)
+ : "eax"
+ );
+ for(;;)
+ ;
+}
+
/**
* \brief Calls a signal handler in user mode
* \note Used for signals
return ;
}
- Log(" at %04x:%08x", regs->cs, regs->eip);
+ Log(" at %04x:%08x [EAX:%x]", regs->cs, regs->eip, regs->eax);
+ Error_Backtrace(regs->eip, regs->ebp);
return ;
}
-
+
+ Log(" Saved = %p (SP=%p)", Thread->SavedState.EIP, Thread->SavedState.ESP);
+
tVAddr diffFromScheduler = Thread->SavedState.EIP - (tVAddr)SwitchTasks;
tVAddr diffFromClone = Thread->SavedState.EIP - (tVAddr)Proc_CloneInt;
tVAddr diffFromSpawn = Thread->SavedState.EIP - (tVAddr)NewTaskHeader;