diff options
Diffstat (limited to 'kernel.soso/process.c')
-rw-r--r-- | kernel.soso/process.c | 713 |
1 files changed, 0 insertions, 713 deletions
diff --git a/kernel.soso/process.c b/kernel.soso/process.c deleted file mode 100644 index 7964467b..00000000 --- a/kernel.soso/process.c +++ /dev/null @@ -1,713 +0,0 @@ -#include "process.h" -#include "common.h" -#include "alloc.h" -#include "vmm.h" -#include "descriptortables.h" -#include "elf.h" -#include "screen.h" -#include "debugprint.h" -#include "isr.h" -#include "timer.h" -#include "message.h" - -#define MESSAGE_QUEUE_SIZE 64 - -Process* gKernelProcess = NULL; - -Thread* gFirstThread = NULL; -Thread* gCurrentThread = NULL; - -Thread* gDestroyedThread = NULL; - -uint32 gProcessIdGenerator = 0; -uint32 gThreadIdGenerator = 0; - -uint32 gSystemContextSwitchCount = 0; -uint32 gLastUptimeSeconds = 0; - -extern Tss gTss; - -uint32 generateProcessId() { - return gProcessIdGenerator++; -} - -uint32 generateThreadId() { - return gThreadIdGenerator++; -} - -uint32 getSystemContextSwitchCount() { - return gSystemContextSwitchCount; -} - -void initializeTasking() { - Process* process = (Process*)kmalloc(sizeof(Process)); - memset((uint8*)process, 0, sizeof(Process)); - strcpy(process->name, "[kernel]"); - process->pid = generateProcessId(); - process->pd = (uint32*) KERN_PAGE_DIRECTORY; - process->workingDirectory = getFileSystemRootNode(); - - gKernelProcess = process; - - - Thread* thread = (Thread*)kmalloc(sizeof(Thread)); - memset((uint8*)thread, 0, sizeof(Thread)); - - thread->owner = gKernelProcess; - - thread->threadId = generateThreadId(); - - thread->userMode = 0; - thread->state = TS_RUN; - thread->messageQueue = FifoBuffer_create(sizeof(SosoMessage) * MESSAGE_QUEUE_SIZE); - Spinlock_Init(&(thread->messageQueueLock)); - thread->regs.cr3 = (uint32) process->pd; - - uint32 selector = 0x10; - - thread->regs.ss = selector; - thread->regs.eflags = 0x0; - thread->regs.cs = 0x08; - thread->regs.eip = NULL; - thread->regs.ds = selector; - thread->regs.es = selector; - thread->regs.fs = selector; - thread->regs.gs = selector; - - thread->regs.esp = 0; //no need because this is already main kernel thread. ESP will written to this in first schedule. - - thread->kstack.ss0 = 0x10; - thread->kstack.esp0 = 0;//For kernel threads, this is not required - - - gFirstThread = thread; - gCurrentThread = thread; -} - -static int getStringArrayItemCount(char *const array[]) { - if (NULL == array) { - return 0; - } - - int i = 0; - const char* a = array[0]; - while (NULL != a) { - a = array[++i]; - } - - return i; -} - -static char** cloneStringArray(char *const array[]) { - int itemCount = getStringArrayItemCount(array); - - char** newArray = kmalloc(sizeof(char*) * (itemCount + 1)); - - for (int i = 0; i < itemCount; ++i) { - const char* str = array[i]; - int len = strlen(str); - - char* newStr = kmalloc(len + 1); - strcpy(newStr, str); - - newArray[i] = newStr; - } - - newArray[itemCount] = NULL; - - return newArray; -} - -static void destroyStringArray(char** array) { - char* a = array[0]; - - int i = 0; - - while (NULL != a) { - kfree(a); - - a = array[++i]; - } - - kfree(array); -} - -//This function must be called within the correct page directory for target process -static void copyArgvEnvToProcess(char *const argv[], char *const envp[]) { - char** destination = (char**)USER_ARGV_ENV_LOC; - int destinationIndex = 0; - - //printkf("ARGVENV: destination:%x\n", destination); - - int argvCount = getStringArrayItemCount(argv); - int envpCount = getStringArrayItemCount(envp); - - //printkf("ARGVENV: argvCount:%d envpCount:%d\n", argvCount, envpCount); - - char* stringTable = (char*)USER_ARGV_ENV_LOC + sizeof(char*) * (argvCount + envpCount + 2); - - //printkf("ARGVENV: stringTable:%x\n", stringTable); - - for (int i = 0; i < argvCount; ++i) { - strcpy(stringTable, argv[i]); - - destination[destinationIndex] = stringTable; - - stringTable += strlen(argv[i]) + 2; - - destinationIndex++; - } - - destination[destinationIndex++] = NULL; - - for (int i = 0; i < envpCount; ++i) { - strcpy(stringTable, envp[i]); - - destination[destinationIndex] = stringTable; - - stringTable += strlen(envp[i]) + 2; - - destinationIndex++; - } - - destination[destinationIndex++] = NULL; -} - -Process* createUserProcessFromElfData(const char* name, uint8* elfData, char *const argv[], char *const envp[], Process* parent, FileSystemNode* tty) { - return createUserProcessEx(name, generateProcessId(), generateThreadId(), NULL, elfData, argv, envp, parent, tty); -} - -Process* createUserProcessEx(const char* name, uint32 processId, uint32 threadId, Function0 func, uint8* elfData, char *const argv[], char *const envp[], Process* parent, FileSystemNode* tty) { - printkf("createUserProcessEx: %s %d %d\n", name, processId, threadId); - if (0 == processId) { - processId = generateProcessId(); - } - - if (0 == threadId) { - threadId = generateThreadId(); - } - - Process* process = (Process*)kmalloc(sizeof(Process)); - memset((uint8*)process, 0, sizeof(Process)); - strcpy(process->name, name); - process->pid = processId; - process->pd = createPd();//our page directories are identity mapped so this is also a physical address. - process->workingDirectory = getFileSystemRootNode(); - - Thread* thread = (Thread*)kmalloc(sizeof(Thread)); - memset((uint8*)thread, 0, sizeof(Thread)); - - thread->owner = process; - - thread->threadId = threadId; - - thread->userMode = 1; - - thread->state = TS_RUN; - - thread->messageQueue = FifoBuffer_create(sizeof(SosoMessage) * MESSAGE_QUEUE_SIZE); - Spinlock_Init(&(thread->messageQueueLock)); - - thread->regs.cr3 = (uint32) process->pd; - - //Since stack grows backwards, we must allocate previous page. So lets substract a small amount. - uint32 stackp = USER_STACK-4; - - if (parent) { - process->parent = parent; - - process->workingDirectory = parent->workingDirectory; - - process->tty = parent->tty; - } - - if (tty) { - process->tty = tty; - } - - char** newArgv = cloneStringArray(argv); - char** newEnvp = cloneStringArray(envp); - - //Change memory view (page directory) - asm("mov %0, %%eax; mov %%eax, %%cr3"::"m"(process->pd)); - - initializeProcessHeap(process); - - initializeProcessMmap(process); - - copyArgvEnvToProcess(newArgv, newEnvp); - - destroyStringArray(newArgv); - destroyStringArray(newEnvp); - - uint32 selector = 0x23; - - thread->regs.ss = selector; - thread->regs.eflags = 0x0; - thread->regs.cs = 0x1B; - thread->regs.eip = (uint32)func; - thread->regs.ds = selector; - thread->regs.es = selector; - thread->regs.fs = selector; - thread->regs.gs = selector; - - thread->regs.esp = stackp; - - char* p_addr = getPageFrame4M(); - char* v_addr = (char *) (USER_STACK - PAGESIZE_4M); - addPageToPd(process->pd, v_addr, p_addr, PG_USER); - - thread->kstack.ss0 = 0x10; - uint8* stack = (uint8*)kmalloc(KERN_STACK_SIZE); - thread->kstack.esp0 = (uint32)(stack + KERN_STACK_SIZE - 4); - thread->kstack.stackStart = (uint32)stack; - - Thread* p = gCurrentThread; - - while (p->next != NULL) { - p = p->next; - } - - p->next = thread; - - if (elfData) { - printkf("about to load ELF data\n"); - uint32 startLocation = loadElf((char*)elfData); - - if (startLocation > 0) { - thread->regs.eip = startLocation; - } - } - - //Restore memory view (page directory) - asm("mov %0, %%eax ;mov %%eax, %%cr3":: "m"(gCurrentThread->regs.cr3)); - - open_fs_forProcess(thread, process->tty, 0);//0: standard input - open_fs_forProcess(thread, process->tty, 0);//1: standard output - open_fs_forProcess(thread, process->tty, 0);//2: standard error - - printkf("running process %d\n", process->pid); - return process; -} - -//This function should be called in interrupts disabled state -void destroyThread(Thread* thread) { - Spinlock_Lock(&(thread->messageQueueLock)); - - //TODO: signal the process somehow - Thread* previousThread = getPreviousThread(thread); - if (NULL != previousThread) { - previousThread->next = thread->next; - - kfree((void*)thread->kstack.stackStart); - - FifoBuffer_destroy(thread->messageQueue); - - Debug_PrintF("destroying thread %d\n", thread->threadId); - - kfree(thread); - - if (thread == gCurrentThread) { - gCurrentThread = NULL; - } - } - else { - printkf("Could not find previous thread for thread %d\n", thread->threadId); - PANIC("This should not be happened!\n"); - } -} - -//This function should be called in interrupts disabled state -void destroyProcess(Process* process) { - Thread* thread = gFirstThread; - Thread* previous = NULL; - while (thread) { - if (process == thread->owner) { - if (NULL != previous) { - previous->next = thread->next; - - kfree((void*)thread->kstack.stackStart); - - Spinlock_Lock(&(thread->messageQueueLock)); - FifoBuffer_destroy(thread->messageQueue); - - Debug_PrintF("destroying thread id:%d (owner process %d)\n", thread->threadId, process->pid); - - kfree(thread); - - if (thread == gCurrentThread) { - gCurrentThread = NULL; - } - - thread = previous->next; - continue; - } - } - - previous = thread; - thread = thread->next; - } - - //Cleanup opened files - for (int i = 0; i < MAX_OPENED_FILES; ++i) { - if (process->fd[i] != NULL) { - close_fs(process->fd[i]); - } - } - - if (process->parent) { - thread = gFirstThread; - while (thread) { - if (process->parent == thread->owner) { - if (thread->state == TS_WAITCHILD) { - thread->state = TS_RUN; - } - } - - thread = thread->next; - } - } - - Debug_PrintF("destroying process %d\n", process->pid); - - destroyPd(process->pd); - kfree(process); -} - -void threadStateToString(ThreadState state, uint8* buffer, uint32 bufferSize) { - if (bufferSize < 1) { - return; - } - - buffer[0] = '\0'; - - if (bufferSize < 10) { - return; - } - - switch (state) { - case TS_RUN: - strcpy((char*)buffer, "run"); - break; - case TS_SLEEP: - strcpy((char*)buffer, "sleep"); - break; - case TS_SUSPEND: - strcpy((char*)buffer, "suspend"); - break; - case TS_WAITCHILD: - strcpy((char*)buffer, "waitchild"); - break; - case TS_WAITIO: - strcpy((char*)buffer, "waitio"); - break; - case TS_YIELD: - strcpy((char*)buffer, "yield"); - break; - default: - break; - } -} - -void waitForSchedule() { - //printkf("Waiting for a schedule()\n"); - - enableInterrupts(); - while (TRUE) { - halt(); - } - disableInterrupts(); - PANIC("waitForSchedule(): Should not be reached here!!!\n"); -} - -void yield(uint32 count) { - gCurrentThread->yield = count; - gCurrentThread->state = TS_YIELD; - enableInterrupts(); - while (gCurrentThread->yield > 0) { - halt(); - } - disableInterrupts(); -} - -int32 getEmptyFd(Process* process) { - int32 result = -1; - - beginCriticalSection(); - - for (int i = 0; i < MAX_OPENED_FILES; ++i) { - if (process->fd[i] == NULL) { - result = i; - break; - } - } - - endCriticalSection(); - - return result; -} - -int32 addFileToProcess(Process* process, File* file) { - int32 result = -1; - - beginCriticalSection(); - - //printkf("addFileToProcess: pid:%d\n", process->pid); - - for (int i = 0; i < MAX_OPENED_FILES; ++i) { - //printkf("addFileToProcess: i:%d fd[%d]:%x\n", i, i, process->fd[i]); - if (process->fd[i] == NULL) { - result = i; - file->fd = i; - process->fd[i] = file; - break; - } - } - - endCriticalSection(); - - return result; -} - -int32 removeFileFromProcess(Process* process, File* file) { - int32 result = -1; - - beginCriticalSection(); - - for (int i = 0; i < MAX_OPENED_FILES; ++i) { - if (process->fd[i] == file) { - result = i; - process->fd[i] = NULL; - break; - } - } - - endCriticalSection(); - - return result; -} - -Thread* getThreadById(uint32 threadId) { - Thread* p = gFirstThread; - - while (p != NULL) { - if (p->threadId == threadId) { - return p; - } - p = p->next; - } - - return NULL; -} - -Thread* getPreviousThread(Thread* thread) { - Thread* t = gFirstThread; - - while (t->next != NULL) { - if (t->next == thread) { - return t; - } - t = t->next; - } - - return NULL; -} - -Thread* getMainKernelThread() { - return gFirstThread; -} - -Thread* getCurrentThread() { - return gCurrentThread; -} - -BOOL isThreadValid(Thread* thread) { - Thread* p = gFirstThread; - - while (p != NULL) { - if (p == thread) { - return TRUE; - } - p = p->next; - } - - return FALSE; -} - -BOOL isProcessValid(Process* process) { - Thread* p = gFirstThread; - - while (p != NULL) { - if (p->owner == process) { - return TRUE; - } - p = p->next; - } - - return FALSE; -} - -static void switchToTask(Thread* current); - -static void updateMetrics(Thread* thread) { - uint32 seconds = getUptimeSeconds(); - - if (seconds > gLastUptimeSeconds) { - gLastUptimeSeconds = seconds; - - Thread* t = gFirstThread; - - while (t != NULL) { - t->contextSwitchCount = t->totalContextSwitchCount - t->totalContextSwitchCountPrevious; - t->totalContextSwitchCountPrevious = t->totalContextSwitchCount; - - t = t->next; - } - } - - ++gSystemContextSwitchCount; - - ++thread->totalContextSwitchCount; -} - -void schedule(TimerInt_Registers* registers) { - Thread* current = gCurrentThread; - - if (NULL != current) { - if (current->next == NULL && current == gFirstThread) { - //We are the only process, no need to schedule - return; - } - - current->regs.eflags = registers->eflags; - current->regs.cs = registers->cs; - current->regs.eip = registers->eip; - current->regs.eax = registers->eax; - current->regs.ecx = registers->ecx; - current->regs.edx = registers->edx; - current->regs.ebx = registers->ebx; - current->regs.ebp = registers->ebp; - current->regs.esi = registers->esi; - current->regs.edi = registers->edi; - current->regs.ds = registers->ds; - current->regs.es = registers->es; - current->regs.fs = registers->fs; - current->regs.gs = registers->gs; - - if (current->regs.cs != 0x08) { - //Debug_PrintF("schedule() - 2.1\n"); - current->regs.esp = registers->esp_if_privilege_change; - current->regs.ss = registers->ss_if_privilege_change; - } - else { - //Debug_PrintF("schedule() - 2.2\n"); - current->regs.esp = registers->esp + 12; - current->regs.ss = gTss.ss0; - } - - //Save the TSS from the old process - current->kstack.ss0 = gTss.ss0; - current->kstack.esp0 = gTss.esp0; - - current = current->next; - while (NULL != current) { - if (current->state == TS_YIELD) { - if (current->yield > 0) { - --current->yield; - } - - if (current->yield == 0) { - current->state = TS_RUN; - } - } - - if (current->state == TS_SLEEP) { - uint32 uptime = getUptimeMilliseconds(); - uint32 target = (uint32)current->state_privateData; - - if (uptime >= target) { - current->state = TS_RUN; - current->state_privateData = NULL; - } - } - - if (current->state == TS_RUN) { - break; - } - current = current->next; - } - - if (current == NULL) { - //reached last process returning to first - current = gFirstThread; - } - } - else { - //current is NULL. This means thread is destroyed, so start from the begining - - current = gFirstThread; - } - - gCurrentThread = current;//Now gCurrentThread is the thread we are about to schedule to - - /* - if (gCurrentThread->threadId == 5) { - printkf("I am scheduling to %d and its EIP is %x\n", gCurrentThread->threadId, gCurrentThread->regs.eip); - } - */ - - updateMetrics(current); - switchToTask(current); -} - -static void switchToTask(Thread* current) { - uint32 kesp, eflags; - uint16 kss, ss, cs; - - //Set TSS values - gTss.ss0 = current->kstack.ss0; - gTss.esp0 = current->kstack.esp0; - - ss = current->regs.ss; - cs = current->regs.cs; - eflags = (current->regs.eflags | 0x200) & 0xFFFFBFFF; - - int oldMode; - if (cs != 0x08) { - oldMode = USERMODE; - kss = current->kstack.ss0; - kesp = current->kstack.esp0; - } - else { - oldMode = KERNELMODE; - kss = current->regs.ss; - kesp = current->regs.esp; - } - - //switchTask is in task.asm - - asm(" mov %0, %%ss; \ - mov %1, %%esp; \ - cmpl %[KMODE], %[mode]; \ - je nextt; \ - push %2; \ - push %3; \ - nextt: \ - push %4; \ - push %5; \ - push %6; \ - push %7; \ - ljmp $0x08, $switchTask" - :: \ - "m"(kss), \ - "m"(kesp), \ - "m"(ss), \ - "m"(current->regs.esp), \ - "m"(eflags), \ - "m"(cs), \ - "m"(current->regs.eip), \ - "m"(current), \ - [KMODE] "i"(KERNELMODE), \ - [mode] "g"(oldMode) - ); -} |