diff options
author | Alexis211 <alexis211@gmail.com> | 2010-08-10 20:39:57 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2010-08-10 20:39:57 +0200 |
commit | f81bf65484fa8c81a1886f456c71f1e6eebe84e9 (patch) | |
tree | 146f304d8de8828003edd548df22cca581044017 /src/kernel/task | |
parent | 0ec0ca40a4fedfe97c49903a329b2a9ad2e22d03 (diff) | |
download | TCE-f81bf65484fa8c81a1886f456c71f1e6eebe84e9.tar.gz TCE-f81bf65484fa8c81a1886f456c71f1e6eebe84e9.zip |
Added a lot of comments in kernel code. A bit of cleaning too.
Diffstat (limited to 'src/kernel/task')
-rw-r--r-- | src/kernel/task/idt.c | 14 | ||||
-rw-r--r-- | src/kernel/task/idt.h | 6 | ||||
-rw-r--r-- | src/kernel/task/syscall.c | 2 | ||||
-rw-r--r-- | src/kernel/task/syscall.h | 2 | ||||
-rw-r--r-- | src/kernel/task/task.c | 55 | ||||
-rw-r--r-- | src/kernel/task/task.h | 7 | ||||
-rw-r--r-- | src/kernel/task/timer.c | 5 |
7 files changed, 71 insertions, 20 deletions
diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c index 80f13db..887ebf7 100644 --- a/src/kernel/task/idt.c +++ b/src/kernel/task/idt.c @@ -67,6 +67,8 @@ struct idt_ptr idt_ptr; static int_callback irq_handlers[16] = {0}; static struct thread* irq_wakeup[16] = {0}; +/* Called in idt_.asm when an exception fires (interrupt 0 to 31). + Tries to handle the exception, panics if fails. */ void idt_isrHandler(struct registers regs) { if ((regs.int_no == 14 && paging_fault(®s) != 0) || regs.int_no != 14) { if (tasking_handleException(®s) == 0) { @@ -80,6 +82,8 @@ void idt_isrHandler(struct registers regs) { } } +/* Called in idt_.asm when an IRQ fires (interrupt 32 to 47) + Possibly wakes up a thread that was waiting, possibly calls a handler. */ void idt_irqHandler(struct registers regs) { uint32_t doSwitch = (regs.err_code == 0); //IRQ0 = timer if (regs.err_code > 7) { @@ -97,14 +101,15 @@ void idt_irqHandler(struct registers regs) { if (doSwitch) tasking_switch(); } +/* Called in idt_.asm on a system call (interrupt 64). + Calls the correct syscall handler (if any). */ void idt_syscallHandler(struct registers regs) { - if (syscalls[regs.eax] != 0) { + if (regs.eax < NUMBER_OF_SYSCALLS && syscalls[regs.eax] != 0) { syscalls[regs.eax](®s); - } else { - monitor_write("Unhandled syscall...\n"); } } +/* For internal use only. Sets up an entry of the IDT with given parameters. */ static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt_entries[num].base_lo = base & 0xFFFF; idt_entries[num].base_hi = (base >> 16) & 0xFFFF; @@ -114,6 +119,7 @@ static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) idt_entries[num].flags = flags | 0x60; } +/* Remaps the IRQs. Sets up the IDT. */ void idt_init() { idt_ptr.limit = (sizeof(struct idt_entry) * 256) - 1; idt_ptr.base = (uint32_t)&idt_entries; @@ -189,12 +195,14 @@ void idt_init() { monitor_write("[IDT] "); } +/* Sets up an IRQ handler for given IRQ. */ void idt_handleIrq(int number, int_callback func) { if (number < 16 && number >= 0) { irq_handlers[number] = func; } } +/* Tells the IRQ handler to wake up the current thread when specified IRQ fires. */ void idt_waitIrq(int number) { if (number < 16 && number >= 0 && proc_priv() <= PL_DRIVER) { irq_wakeup[number] = current_thread; diff --git a/src/kernel/task/idt.h b/src/kernel/task/idt.h index b12d6c5..1ac03e2 100644 --- a/src/kernel/task/idt.h +++ b/src/kernel/task/idt.h @@ -1,6 +1,12 @@ #ifndef DEF_IDT_H #define DEF_IDT_H +/* The IDT is the system descriptor table that tells the CPU what to do when an interrupt fires. + There are three categories of interrupts : + - Exceptions ; ex: page fault, divide by 0 + - IRQ : interrupts caused by hardware + - System calls : when an applications asks the system to do something */ + #include <types.h> struct idt_entry { diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c index a5142eb..41cd0ea 100644 --- a/src/kernel/task/syscall.c +++ b/src/kernel/task/syscall.c @@ -38,7 +38,7 @@ static void thread_new_sc(struct registers* r) { thread_new(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx); } -int_callback syscalls[] = { +int_callback syscalls[NUMBER_OF_SYSCALLS] = { thread_exit_sc, //0 schedule_sc, thread_sleep_sc, diff --git a/src/kernel/task/syscall.h b/src/kernel/task/syscall.h index 54af108..f03be55 100644 --- a/src/kernel/task/syscall.h +++ b/src/kernel/task/syscall.h @@ -3,6 +3,8 @@ #include "idt.h" +#define NUMBER_OF_SYSCALLS 32 + extern int_callback syscalls[]; #endif diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index 8afc609..d8670a0 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -17,19 +17,20 @@ static void thread_exit2(uint32_t reason); static void thread_delete(struct thread *th); static void process_delete(struct process *pr); +static uint32_t thread_runnable(struct thread *th); + //From task_.asm extern uint32_t read_eip(); extern void task_idle(void*); -static uint32_t thread_runnable(struct thread *th); - static uint32_t nextpid = 1; - struct process *processes = 0, *kernel_process; struct thread *threads = 0, *current_thread = 0, *idle_thread; uint32_t tasking_tmpStack[KSTACKSIZE]; +/* Sets up tasking. Called by kmain on startup. + Creates a kernel process and an IDLE thread in it. */ void tasking_init() { cli(); kernel_process = kmalloc(sizeof(struct process)); //This process must be hidden to users @@ -45,6 +46,19 @@ void tasking_init() { monitor_write("[Tasking] "); } +/* Called by the paging functions when a page table is allocated in the kernel space (>0xE0000000). + Updates the page directories of all the processes. */ +void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { + if (idx < 896) return; + struct process* it = processes; + while (it != 0) { + it->pagedir->tables[idx] = table; + it->pagedir->tablesPhysical[idx] = tablephysical; + it = it->next; + } +} + +/* Looks through the list of threads, finds the next thread to run. */ static struct thread *thread_next() { if (current_thread == 0 || current_thread == idle_thread) current_thread = threads; struct thread *ret = current_thread; @@ -60,6 +74,7 @@ static struct thread *thread_next() { } } +/* Called when a timer IRQ fires. Does a context switch. */ void tasking_switch() { if (threads == 0) PANIC("No more threads to run !"); asm volatile("cli"); @@ -94,16 +109,8 @@ void tasking_switch() { : : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip)); } -void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) { - if (idx < 896) return; - struct process* it = processes; - while (it != 0) { - it->pagedir->tables[idx] = table; - it->pagedir->tablesPhysical[idx] = tablephysical; - it = it->next; - } -} - +/* Called when an exception happens. Provides a stack trace if it was in kernel land. + Ends the thread for most exceptions, ends the whole process for page faults. */ uint32_t tasking_handleException(struct registers *regs) { if (current_thread == 0) return 0; //No tasking yet NL; WHERE; monitor_write("Unhandled exception : "); @@ -134,6 +141,7 @@ uint32_t tasking_handleException(struct registers *regs) { return 0; } +/* Makes the current thread sleep. */ void thread_sleep(uint32_t msecs) { if (current_thread == 0) return; current_thread->state = TS_SLEEPING; @@ -141,20 +149,25 @@ void thread_sleep(uint32_t msecs) { tasking_switch(); } +/* Puts the current thread in an inactive state. */ void thread_goInactive() { current_thread->state = TS_WAKEWAIT; tasking_switch(); } +/* Wakes up the given thread. */ void thread_wakeUp(struct thread* t) { if (t->state == TS_WAKEWAIT) t->state = TS_RUNNING; } +/* Returns the privilege level of the current process. */ int proc_priv() { if (current_thread == 0 || current_thread->process == 0) return PL_UNKNOWN; return current_thread->process->privilege; } +/* For internal use only. Called by thread_exit_stackJmp on a stack that will not be deleted. + Exits current thread or process, depending on the reason. */ void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h /* * if reason == EX_TH_NORMAL, it is just one thread exiting because it has to @@ -170,9 +183,12 @@ void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h process_delete(pr); } retrn: + sti(); tasking_switch(); } +/* For internal use only. Called by thread_exit and process_exit. + Switches to a stack that will not be deleted when current thread is deleted. */ void thread_exit_stackJmp(uint32_t reason) { cli(); uint32_t *stack; @@ -188,15 +204,18 @@ void thread_exit_stackJmp(uint32_t reason) { "r"(stack), "r"(stack), "r"(thread_exit2), "r"(kernel_pagedir->physicalAddr)); } +/* System call. Exit the current thread. */ void thread_exit() { thread_exit_stackJmp(EX_TH_NORMAL); } +/* System call. Exit the current process. */ void process_exit(uint32_t retval) { if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION; thread_exit_stackJmp(retval); } +/* Nonzero if given thread is not in a waiting state. */ static uint32_t thread_runnable(struct thread *t) { if (t->state == TS_RUNNING) return 1; if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) { @@ -206,6 +225,9 @@ static uint32_t thread_runnable(struct thread *t) { return 0; } +/* For internal use only. This is called when a newly created thread first runs + (its address is the value given for EIP). + It switches to user mode if necessary and calls the entry point. */ static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { pagedir_switch(thread->process->pagedir); if (thread->process->privilege >= PL_SERVICE) { //User mode ! @@ -248,6 +270,9 @@ static void thread_run(struct thread *thread, thread_entry entry_point, void *da thread_exit(0); } +/* Creates a new thread for given process. + Allocates a kernel stack and a user stack if necessary. + Sets up the kernel stack for values to be passed to thread_run. */ struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { struct thread *t = kmalloc(sizeof(struct thread)); t->process = proc; @@ -284,6 +309,7 @@ struct thread *thread_new(struct process *proc, thread_entry entry_point, void * return t; } +/* Creates a new process. Creates a struct process and fills it up. */ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privilege) { struct process* p = kmalloc(sizeof(struct process)); p->pid = (nextpid++); @@ -307,6 +333,7 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi return p; } +/* Deletes given thread, freeing the stack(s). */ static void thread_delete(struct thread *th) { if (threads == th) { threads = th->next; @@ -327,6 +354,7 @@ static void thread_delete(struct thread *th) { kfree(th); } +/* Deletes a process. First, deletes all its threads. Also deletes the corresponding page directory. */ static void process_delete(struct process *pr) { struct thread *it = threads; while (it != 0) { @@ -354,6 +382,7 @@ static void process_delete(struct process *pr) { kfree(pr); } +/* System call. Called by the app to define the place for the heap. */ int process_setheapseg(size_t start, size_t end) { //syscall struct process *p = current_thread->process; if (start >= 0xE0000000 || end >= 0xE0000000) return -1; diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h index 3dad63d..ef93c9f 100644 --- a/src/kernel/task/task.h +++ b/src/kernel/task/task.h @@ -57,13 +57,14 @@ void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint3 uint32_t tasking_handleException(struct registers *regs); void thread_sleep(uint32_t msecs); -void thread_goInactive(); //Blocks the current thread. another one must be there to wake it up at some point. +void thread_goInactive(); //Blocks the current thread. it is then waked up by another thread or a system event. void thread_wakeUp(struct thread *t); int proc_priv(); //Returns current privilege level -void thread_exit(); -void process_exit(uint32_t retval); struct thread * thread_new(struct process *proc, thread_entry entry_point, void *data); struct process* process_new(struct process *parent, uint32_t uid, uint32_t privilege); + +void thread_exit(); //syscall +void process_exit(uint32_t retval); //syscall int process_setheapseg(size_t start, size_t end); //syscall #endif diff --git a/src/kernel/task/timer.c b/src/kernel/task/timer.c index e924657..1ec1523 100644 --- a/src/kernel/task/timer.c +++ b/src/kernel/task/timer.c @@ -5,6 +5,8 @@ static uint32_t tick = 0, frequency = 0, uptime = 0; +/* Called when IRQ0 fires. Updates the uptime variable. + DOES NOT provoke a task switch. The task switch is called in idt.c (IRQ handler). */ void timer_callback(struct registers *regs) { tick++; if (tick == frequency) { @@ -13,12 +15,15 @@ void timer_callback(struct registers *regs) { } } +/* Accessor function to get machine uptime. */ uint32_t timer_uptime() { return uptime; } +/* Accessor function, gets uptime in miliseconds. */ uint32_t timer_time() { return (uptime * 1000) + (tick * 1000 / frequency); } +/* Called by kmain. Sets up the PIT and the IRQ0 handler. */ void timer_init(uint32_t freq) { frequency = freq; |