summaryrefslogblamecommitdiff
path: root/Source/Kernel/TaskManager/Task.ns.cpp
blob: 3ee21deb5e557cbe52287e7be18c053bf92b3c6e (plain) (tree)


















                                                                  

                                                      

                          
                                                            


                                                 
                             




























                                                                              
                                                                                        




















                                                            
                                

























































                                                                             
#include "Task.ns.h"
#include <Library/Vector.class.h>

//From Task.wtf.asm
extern "C" u32int read_eip();
extern "C" u32int idle_task();

namespace Task {

Vector <Process*> processes;	//TODO : use a linked list instead
Vector <Thread*> 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;
		}
	}
}

}