#include "Task.ns.h" #include //From Task.wtf.asm extern "C" u32int read_eip(); extern "C" u32int idle_task(); namespace Task { Vector processes; //TODO : use a linked list instead Vector threads; Thread* currentThread = NULL; Process* currentProcess = NULL; Thread* idleThread = NULL; u32int currentThreadId = 0; u32int nextpid = 1; void initialize(String cmdline, VirtualTerminal *vt) { asm volatile ("cli"); threads.clear(); processes.clear(); currentProcess = Process::createKernel(cmdline, vt); idleThread = new Thread(idle_task, true); currentThread = threads[0]; currentThreadId = 0; asm volatile ("sti"); } Thread* nextThread() { u32int nid = currentThreadId; while (1) { nid++; if (nid >= threads.size()) nid = 0; if (threads[nid]->runnable() and threads[nid] != idleThread) { currentThreadId = nid; return threads[nid]; } if (nid == currentThreadId) break; } return idleThread; } void doSwitch() { if (currentThread == NULL or currentProcess == NULL) return; u32int esp, ebp, eip, cr3; asm volatile("mov %%esp, %0" : "=r"(esp)); asm volatile("mov %%ebp, %0" : "=r"(ebp)); eip = read_eip(); if (eip == 0x12345) return; if ((u32int)currentThread != 0xFFFFFFFF) currentThread->setState(esp, ebp, eip); currentThread = nextThread(); currentProcess = currentThread->getProcess(); esp = currentThread->getEsp(); ebp = currentThread->getEbp(); eip = currentThread->getEip(); cr3 = currentProcess->getPagedir()->physicalAddr; asm volatile(" \ cli; \ mov %0, %%ebp; \ mov %1, %%esp; \ mov %2, %%ecx; \ mov %3, %%cr3; \ mov $0x12345, %%eax; \ jmp *%%ecx;" : : "r"(ebp), "r"(esp), "r"(eip), "r"(cr3)); } void triggerSwitch() { asm volatile("int $65"); } u32int nextPid() { return nextpid++; } bool IRQwakeup(u8int irq) { bool r = false; for (u32int i = 0; i < threads.size(); i++) { r = r or threads[i]->irqHappens(irq); } return r; } void allocKernelPageTable(u32int id, page_table_t *table, u32int tablePhys) { if (id < 768) return; //this would be a BUG for (u32int i = 1; i < processes.size(); i++) { processes[i]->getPagedir()->tables[id] = table; processes[i]->getPagedir()->tablesPhysical[id] = tablePhys; } } Process* getKernelProcess() { return processes[0]; } void registerThread(Thread* t) { unregisterThread(t); //...// threads.push(t); } void unregisterThread(Thread* t) { for (u32int i = 0; i < threads.size(); i++) { if (threads[i] == t) { threads[i] = threads.back(); threads.pop(); return; } } } void registerProcess(Process* p) { unregisterProcess(p); //...// processes.push(p); } void unregisterProcess(Process* p) { for (u32int i = 0; i < processes.size(); i++) { if (processes[i] == p) { processes[i] = processes.back(); processes.pop(); return; } } } }