about summary refs log tree commit diff stats
path: root/kernel.soso/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel.soso/process.c')
-rw-r--r--kernel.soso/process.c713
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)
-        );
-}