diff options
Diffstat (limited to 'src/kernel/task')
-rw-r--r-- | src/kernel/task/idt.c | 191 | ||||
-rw-r--r-- | src/kernel/task/idt.h | 33 | ||||
-rw-r--r-- | src/kernel/task/idt_.asm | 155 | ||||
-rw-r--r-- | src/kernel/task/syscall.c | 21 | ||||
-rw-r--r-- | src/kernel/task/syscall.h | 9 | ||||
-rw-r--r-- | src/kernel/task/task.c | 245 | ||||
-rw-r--r-- | src/kernel/task/task.h | 55 | ||||
-rw-r--r-- | src/kernel/task/task_.asm | 10 | ||||
-rw-r--r-- | src/kernel/task/timer.c | 36 | ||||
-rw-r--r-- | src/kernel/task/timer.h | 10 |
10 files changed, 765 insertions, 0 deletions
diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c new file mode 100644 index 0000000..360ac91 --- /dev/null +++ b/src/kernel/task/idt.c @@ -0,0 +1,191 @@ +#include "idt.h" +#include <core/monitor.h> +#include <core/sys.h> +#include <mem/paging.h> +#include "task.h" +#include "syscall.h" + +#include <stdlib.h> + +extern void isr0(); +extern void isr1(); +extern void isr2(); +extern void isr3(); +extern void isr4(); +extern void isr5(); +extern void isr6(); +extern void isr7(); +extern void isr8(); +extern void isr9(); +extern void isr10(); +extern void isr11(); +extern void isr12(); +extern void isr13(); +extern void isr14(); +extern void isr15(); +extern void isr16(); +extern void isr17(); +extern void isr18(); +extern void isr19(); +extern void isr20(); +extern void isr21(); +extern void isr22(); +extern void isr23(); +extern void isr24(); +extern void isr25(); +extern void isr26(); +extern void isr27(); +extern void isr28(); +extern void isr29(); +extern void isr30(); +extern void isr31(); + +extern void irq0(); +extern void irq1(); +extern void irq2(); +extern void irq3(); +extern void irq4(); +extern void irq5(); +extern void irq6(); +extern void irq7(); +extern void irq8(); +extern void irq9(); +extern void irq10(); +extern void irq11(); +extern void irq12(); +extern void irq13(); +extern void irq14(); +extern void irq15(); + +extern void syscall64(); + +extern void idt_flush(int32_t ptr); + +struct idt_entry idt_entries[256]; +struct idt_ptr idt_ptr; + +static int_callback irq_handlers[16] = {0}; + +void idt_isrHandler(struct registers regs) { + if ((regs.int_no == 14 && paging_fault(®s) != 0) || regs.int_no != 14) { + if (tasking_handleException(®s) == 0) { + monitor_write(" >> >> SOMETHING BAD HAPPENNED << <<\n"); + monitor_write("Unhandled exception "); + monitor_writeHex(regs.int_no); + monitor_write(" @"); monitor_writeHex(regs.eip); + monitor_put('\n'); + PANIC("unhandled exception"); + } + } +} + +void idt_irqHandler(struct registers regs) { + uint32_t doSwitch = 0; + doSwitch |= (regs.int_no == 32); //IRQ0 = timer + if (regs.err_code > 7) { + outb(0xA0, 0x20); + } + outb(0x20, 0x20); + if (irq_handlers[regs.err_code] != 0) { + irq_handlers[regs.err_code](®s); + } else { + monitor_write("Unhandled IRQ "); monitor_writeHex(regs.int_no - 32); monitor_write("\n"); + } + if (doSwitch) tasking_switch(); +} + +void idt_syscallHandler(struct registers regs) { + if (syscalls[regs.eax] != 0) { + syscalls[regs.eax](®s); + } else { + PANIC("unhandled syscall"); + } +} + +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; + + idt_entries[num].sel = sel; + idt_entries[num].always0 = 0; + idt_entries[num].flags = flags; +} + +void idt_init() { + idt_ptr.limit = (sizeof(struct idt_entry) * 256) - 1; + idt_ptr.base = (uint32_t)&idt_entries; + + memset((uint8_t*)&idt_entries, 0, sizeof(struct idt_entry) * 256); + + //Remap the IRQ table + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0x21, 0x20); + outb(0xA1, 0x28); + outb(0x21, 0x04); + outb(0xA1, 0x02); + outb(0x21, 0x01); + outb(0xA1, 0x01); + outb(0x21, 0x0); + outb(0xA1, 0x0); + + idt_setGate(0, (int32_t)isr0, 0x08, 0x8E); + idt_setGate(1, (int32_t)isr1, 0x08, 0x8E); + idt_setGate(2, (int32_t)isr2, 0x08, 0x8E); + idt_setGate(3, (int32_t)isr3, 0x08, 0x8E); + idt_setGate(4, (int32_t)isr4, 0x08, 0x8E); + idt_setGate(5, (int32_t)isr5, 0x08, 0x8E); + idt_setGate(6, (int32_t)isr6, 0x08, 0x8E); + idt_setGate(7, (int32_t)isr7, 0x08, 0x8E); + idt_setGate(8, (int32_t)isr8, 0x08, 0x8E); + idt_setGate(9, (int32_t)isr9, 0x08, 0x8E); + idt_setGate(10, (int32_t)isr10, 0x08, 0x8E); + idt_setGate(11, (int32_t)isr11, 0x08, 0x8E); + idt_setGate(12, (int32_t)isr12, 0x08, 0x8E); + idt_setGate(13, (int32_t)isr13, 0x08, 0x8E); + idt_setGate(14, (int32_t)isr14, 0x08, 0x8E); + idt_setGate(15, (int32_t)isr15, 0x08, 0x8E); + idt_setGate(16, (int32_t)isr16, 0x08, 0x8E); + idt_setGate(17, (int32_t)isr17, 0x08, 0x8E); + idt_setGate(18, (int32_t)isr18, 0x08, 0x8E); + idt_setGate(19, (int32_t)isr19, 0x08, 0x8E); + idt_setGate(20, (int32_t)isr20, 0x08, 0x8E); + idt_setGate(21, (int32_t)isr21, 0x08, 0x8E); + idt_setGate(22, (int32_t)isr22, 0x08, 0x8E); + idt_setGate(23, (int32_t)isr23, 0x08, 0x8E); + idt_setGate(24, (int32_t)isr24, 0x08, 0x8E); + idt_setGate(25, (int32_t)isr25, 0x08, 0x8E); + idt_setGate(26, (int32_t)isr26, 0x08, 0x8E); + idt_setGate(27, (int32_t)isr27, 0x08, 0x8E); + idt_setGate(28, (int32_t)isr28, 0x08, 0x8E); + idt_setGate(29, (int32_t)isr29, 0x08, 0x8E); + idt_setGate(30, (int32_t)isr30, 0x08, 0x8E); + idt_setGate(31, (int32_t)isr31, 0x08, 0x8E); + + idt_setGate(32, (int32_t)irq0, 0x08, 0x8E); + idt_setGate(33, (int32_t)irq1, 0x08, 0x8E); + idt_setGate(34, (int32_t)irq2, 0x08, 0x8E); + idt_setGate(35, (int32_t)irq3, 0x08, 0x8E); + idt_setGate(36, (int32_t)irq4, 0x08, 0x8E); + idt_setGate(37, (int32_t)irq5, 0x08, 0x8E); + idt_setGate(38, (int32_t)irq6, 0x08, 0x8E); + idt_setGate(39, (int32_t)irq7, 0x08, 0x8E); + idt_setGate(40, (int32_t)irq8, 0x08, 0x8E); + idt_setGate(41, (int32_t)irq9, 0x08, 0x8E); + idt_setGate(42, (int32_t)irq10, 0x08, 0x8E); + idt_setGate(43, (int32_t)irq11, 0x08, 0x8E); + idt_setGate(44, (int32_t)irq12, 0x08, 0x8E); + idt_setGate(45, (int32_t)irq13, 0x08, 0x8E); + idt_setGate(46, (int32_t)irq14, 0x08, 0x8E); + idt_setGate(47, (int32_t)irq15, 0x08, 0x8E); + + idt_setGate(64, (int32_t)syscall64, 0x08, 0x8E); + + idt_flush((int32_t)&idt_ptr); + + monitor_write("IDT ok\n"); +} + +void idt_handleIrq(int number, int_callback func) { + irq_handlers[number] = func; +} diff --git a/src/kernel/task/idt.h b/src/kernel/task/idt.h new file mode 100644 index 0000000..bb89013 --- /dev/null +++ b/src/kernel/task/idt.h @@ -0,0 +1,33 @@ +#ifndef DEF_IDT_H +#define DEF_IDT_H + +#include <types.h> + +struct idt_entry { + uint16_t base_lo; //Low part of address to jump to + uint16_t sel; //Kernel segment selector + uint8_t always0; + uint8_t flags; //Flags + uint16_t base_hi; //High part of address to jump to +} __attribute__((packed)); + +struct idt_ptr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + +struct registers { + uint32_t cr3; //page directory physical address + uint32_t ds; // Data segment selector + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha. + uint32_t int_no, err_code; // Interrupt number and error code (if applicable) + uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically. +}; + +typedef void (*int_callback)(struct registers*); + +void idt_init(); +void idt_handleIrq(int number, int_callback func); + +#endif + diff --git a/src/kernel/task/idt_.asm b/src/kernel/task/idt_.asm new file mode 100644 index 0000000..63d1570 --- /dev/null +++ b/src/kernel/task/idt_.asm @@ -0,0 +1,155 @@ +; UNRELATED + +[GLOBAL gdt_flush] + +gdt_flush: + mov eax, [esp+4] + lgdt [eax] + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:.flush + +.flush: + ret + +; RELATED + +[GLOBAL idt_flush] +idt_flush: + mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter. + lidt [eax] ; Load the IDT pointer. + ret + +;************************************************************************************ + +%macro COMMONSTUB 1 +[EXTERN idt_%1Handler] +%1_common_stub: + pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + + mov ax, ds ; Lower 16-bits of eax = ds. + push eax ; save the data segment descriptor + + mov ax, 0x10 ; load the kernel data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov eax, cr3 + push eax + + call idt_%1Handler + + pop eax + mov cr3, eax + + pop eax ; reload the original data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + popa ; Pops edi,esi,ebp... + add esp, 8 ; Cleans up the pushed error code and pushed ISR number + sti + iret +%endmacro + +COMMONSTUB isr +COMMONSTUB irq +COMMONSTUB syscall + +;************************************************************************************ + +%macro ISR_NOERRCODE 1 ; define a macro, taking one parameter + [GLOBAL isr%1] ; %1 accesses the first parameter. + isr%1: + cli + push byte 0 + push byte %1 + jmp isr_common_stub +%endmacro + +%macro ISR_ERRCODE 1 + [GLOBAL isr%1] + isr%1: + cli + push byte %1 + jmp isr_common_stub +%endmacro + +%macro IRQ 2 + [GLOBAL irq%1] + irq%1: + cli + push byte %1 ;push irq number + push byte %2 ;push int number + jmp irq_common_stub +%endmacro + +%macro SYSCALL 1 + [GLOBAL syscall%1] + syscall%1: + cli + push byte 0 + push byte %1 + jmp syscall_common_stub +%endmacro + +ISR_NOERRCODE 0 +ISR_NOERRCODE 1 +ISR_NOERRCODE 2 +ISR_NOERRCODE 3 +ISR_NOERRCODE 4 +ISR_NOERRCODE 5 +ISR_NOERRCODE 6 +ISR_NOERRCODE 7 +ISR_ERRCODE 8 +ISR_NOERRCODE 9 +ISR_ERRCODE 10 +ISR_ERRCODE 11 +ISR_ERRCODE 12 +ISR_ERRCODE 13 +ISR_ERRCODE 14 +ISR_NOERRCODE 15 +ISR_NOERRCODE 16 +ISR_NOERRCODE 17 +ISR_NOERRCODE 18 +ISR_NOERRCODE 19 +ISR_NOERRCODE 20 +ISR_NOERRCODE 21 +ISR_NOERRCODE 22 +ISR_NOERRCODE 23 +ISR_NOERRCODE 24 +ISR_NOERRCODE 25 +ISR_NOERRCODE 26 +ISR_NOERRCODE 27 +ISR_NOERRCODE 28 +ISR_NOERRCODE 29 +ISR_NOERRCODE 30 +ISR_NOERRCODE 31 + +IRQ 0, 32 +IRQ 1, 33 +IRQ 2, 34 +IRQ 3, 35 +IRQ 4, 36 +IRQ 5, 37 +IRQ 6, 38 +IRQ 7, 39 +IRQ 8, 40 +IRQ 9, 41 +IRQ 10, 42 +IRQ 11, 43 +IRQ 12, 44 +IRQ 13, 45 +IRQ 14, 46 +IRQ 15, 47 + +SYSCALL 64 diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c new file mode 100644 index 0000000..5aab011 --- /dev/null +++ b/src/kernel/task/syscall.c @@ -0,0 +1,21 @@ +#include "syscall.h" + +#define CALL0(name, scname) static void scname(struct registers* r) { r->eax = name(); } +#define CALL1(name, scname) static void scname(struct registers* r) { \ + r->eax = name(r->ebx); } +#define CALL2(name, scname) static void scname(struct registers* r) { \ + r->eax = name(r->ebx, r->ecx); } + +CALL0(thread_exit, thread_exit_sc); +CALL0(tasking_switch, schedule_sc); +CALL1(thread_sleep, thread_sleep_sc); +CALL1(process_exit, process_exit_sc); +CALL1(monitor_write, printk_sc); + +int_callback syscalls[] = { + thread_exit_sc, + schedule_sc, + thread_sleep_sc, + process_exit_sc, + printk_sc, + 0 }; diff --git a/src/kernel/task/syscall.h b/src/kernel/task/syscall.h new file mode 100644 index 0000000..54af108 --- /dev/null +++ b/src/kernel/task/syscall.h @@ -0,0 +1,9 @@ +#ifndef DEF_SYSCALL_H +#define DEF_SYSCALL_H + +#include "idt.h" + +extern int_callback syscalls[]; + +#endif + diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..804adc2 --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,245 @@ +#include "task.h" +#include <core/sys.h> +#include <core/monitor.h> +#include <mem/mem.h> +#include "timer.h" + +#define KSTACKSIZE 0x8000 + +//Static routines for handling threads exiting and all cleanup +static void thread_exit_stackJmp(uint32_t reason); +static void thread_exit2(uint32_t reason); +static void thread_delete(struct thread *th); +static void process_delete(struct process *pr); + +//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[0x4000]; + +void tasking_init() { + cli(); + kernel_process = kmalloc(sizeof(struct process)); //This process must be hidden to users + kernel_process->pid = kernel_process->uid = kernel_process->threads = 0; + kernel_process->privilege = PL_KERNEL; + kernel_process->parent = kernel_process; + kernel_process->pagedir = kernel_pagedir; + kernel_process->next = 0; + current_thread = 0; + idle_thread = thread_new(kernel_process, task_idle, 0); + threads = 0; //Do not include idle thread in threads + sti(); + monitor_write("Tasking set up\n"); +} + +static struct thread *thread_next() { + if (current_thread == 0 || current_thread == idle_thread) current_thread = threads; + struct thread *ret = current_thread; + while (1) { + ret = ret->next; + if (ret == 0) ret = threads; + if (thread_runnable(ret)) { + return ret; + } + if (ret == current_thread) return idle_thread; + } +} + +void tasking_switch() { + if (threads == 0) PANIC("No more threads to run !"); + asm volatile("cli"); + + uint32_t esp, ebp, eip; + + asm volatile("mov %%esp, %0" : "=r"(esp)); + asm volatile("mov %%ebp, %0" : "=r"(ebp)); + eip = read_eip(); + + if (eip == 0x12345) { + return; + } + + if (current_thread != 0) { + current_thread->esp = esp; + current_thread->ebp = ebp; + current_thread->eip = eip; + } + + current_thread = thread_next(); + + asm volatile(" \ + mov %0, %%ebp; \ + mov %1, %%esp; \ + mov %2, %%ecx; \ + mov $0x12345, %%eax; \ + jmp *%%ecx;" + : : "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; + } +} + +uint32_t tasking_handleException(struct registers *regs) { + if (current_thread == 0) return 0; //No tasking yet + monitor_write("\n(task.c:99) Unhandled exception : "); + char *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint", + "Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor", "Double Fault", + "Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault", + "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; + monitor_write(exception_messages[regs->int_no]); + monitor_write(" at "); monitor_writeHex(regs->eip); + monitor_write(" >>> Thread exiting.\n"); + thread_exit_stackJmp(EX_TH_EXCEPTION); + PANIC("This should never have happened. Please report this."); +} + +void thread_sleep(uint32_t msecs) { + if (current_thread == 0) return; + current_thread->state = TS_SLEEPING; + current_thread->timeWait = timer_time() + msecs; + asm volatile("int $64" : : "a"(1)); +} + +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 + * if reason == EX_TH_EXCEPTION, it is just one thread exiting because of an exception + * if reason is none of the two cases above, it is the whole process exiting (with error code = reason) + */ + struct thread *th = current_thread; + struct process *pr = th->process; + if ((reason == EX_TH_NORMAL || reason == EX_TH_EXCEPTION) && pr->threads > 1) { + thread_delete(th); + } else { + process_delete(pr); + } + sti(); + tasking_switch(); +} + +void thread_exit_stackJmp(uint32_t reason) { + uint32_t *stack; + cli(); + stack = tasking_tmpStack + 0x4000; + stack--; *stack = reason; + stack--; *stack = 0; + asm volatile(" \ + mov %0, %%esp; \ + mov %1, %%ebp; \ + mov %2, %%ecx; \ + mov %3, %%cr3; \ + jmp *%%ecx;" : : + "r"(stack), "r"(stack), "r"(thread_exit2), "r"(kernel_pagedir->physicalAddr)); +} + +void thread_exit() { + thread_exit_stackJmp(EX_TH_NORMAL); +} + +void process_exit(uint32_t retval) { + if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION; + thread_exit_stackJmp(retval); +} + +static uint32_t thread_runnable(struct thread *t) { + if (t->state == TS_RUNNING) return 1; + if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) return 1; + return 0; +} + +static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { + pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level + asm volatile("sti"); + entry_point(data); + thread_exit(0); +} + +struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { + struct thread *t = kmalloc(sizeof(struct thread)); + t->process = proc; + proc->threads++; + t->kernelStack_addr = kmalloc(KSTACKSIZE); + t->kernelStack_size = KSTACKSIZE; + + uint32_t *stack = (uint32_t*)((size_t)t->kernelStack_addr + t->kernelStack_size); + + //Pass parameters + stack--; *stack = (uint32_t)data; + stack--; *stack = (uint32_t)entry_point; + stack--; *stack = (uint32_t)t; + stack--; *stack = 0; + t->esp = (uint32_t)stack; + t->ebp = t->esp + 8; + t->eip = (uint32_t)thread_run; + + t->state = TS_RUNNING; + + if (threads == 0) { + threads = t; + } else { + struct thread *i = threads; + while (i->next != 0) i = i->next; + i->next = t; + } + return t; +} + +struct process *process_new(struct process* parent, uint32_t uid, uint32_t privilege) { + struct process* p = kmalloc(sizeof(struct process)); + p->pid = (nextpid++); + p->uid = uid; + p->threads = 0; + p->privilege = privilege; + p->parent = parent; + p->pagedir = pagedir_new(); + p->next = processes; + processes = p; + return p; +} + +static void thread_delete(struct thread *th) { + kfree(th->kernelStack_addr); + th->process->threads--; + if (threads == th) { + threads = th->next; + } else { + struct thread *it = threads; + while (it->next != th && it->next != 0) it = it->next; + if (it->next == th) it->next = th->next; + } + kfree(th); +} + +static void process_delete(struct process *pr) { + struct thread *it; + while (threads != 0 && threads->process == pr) thread_delete(threads); + it = threads; + while (it != 0) { + while (it->next->process == pr) thread_delete(it->next); + it = it->next; + } + pagedir_delete(pr->pagedir); + if (processes == pr) { + processes = pr->next; + } else { + struct process *it = processes; + while (it != 0 && it->next != pr) it = it->next; + if (it != 0 && it->next == pr) it->next = pr->next; + } + kfree(pr); +} diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h new file mode 100644 index 0000000..c9f1794 --- /dev/null +++ b/src/kernel/task/task.h @@ -0,0 +1,55 @@ +#ifndef DEF_TASK_H +#define DEF_TASK_H + +#include <types.h> +#include <mem/paging.h> +#include "idt.h" + +#define TS_RUNNING 0 +#define TS_SLEEPING 1 //Sleeping for a defined amount of time +#define TS_WAIKWAIT 2 //Waiting to be waked up by something precise (thread currently blocked) + +#define PL_USER 3 +#define PL_SERVICE 2 +#define PL_DRIVER 1 +#define PL_KERNEL 0 + +#define EX_TH_NORMAL 0x10000 //ERROR code : just one thread exits, because it has to +#define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception +#define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception + +typedef void (*thread_entry)(void*); + +struct process { + uint32_t pid, uid, privilege, threads; + struct process *parent; + struct page_directory *pagedir; + + struct process *next; //Forms a linked list +}; + +struct thread { + struct process *process; + uint32_t esp, ebp, eip; + uint8_t state; + uint32_t timeWait; + void* kernelStack_addr; + uint32_t kernelStack_size; + + struct thread *next; //Forms a linked list +}; + +extern struct thread *current_thread; + +void tasking_init(); +void tasking_switch(); +void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical); +uint32_t tasking_handleException(struct registers *regs); + +void thread_sleep(uint32_t msecs); +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); + +#endif diff --git a/src/kernel/task/task_.asm b/src/kernel/task/task_.asm new file mode 100644 index 0000000..ae45c68 --- /dev/null +++ b/src/kernel/task/task_.asm @@ -0,0 +1,10 @@ +[GLOBAL read_eip] +read_eip: + pop eax + jmp eax + +[GLOBAL task_idle] +task_idle: + sti + hlt + jmp task_idle diff --git a/src/kernel/task/timer.c b/src/kernel/task/timer.c new file mode 100644 index 0000000..8c1a2b8 --- /dev/null +++ b/src/kernel/task/timer.c @@ -0,0 +1,36 @@ +#include "timer.h" +#include "idt.h" +#include <core/sys.h> +#include <core/monitor.h> + +static uint32_t tick = 0, frequency = 0, uptime = 0; + +void timer_callback(struct registers *regs) { + tick++; + if (tick == frequency) { + uptime++; + tick = 0; + } +} + +uint32_t timer_uptime() { return uptime; } + +uint32_t timer_time() { + return (uptime * 1000) + (tick * 1000 / frequency); +} + +void timer_init(uint32_t freq) { + frequency = freq; + + idt_handleIrq(0, timer_callback); + + uint32_t divisor = 1193180 / freq; + + outb(0x43, 0x36); //Command byte + + uint8_t l = (divisor & 0xFF), h = (divisor >> 8); + outb(0x40, l); + outb(0x40, h); + + monitor_write("Timer started\n"); +} diff --git a/src/kernel/task/timer.h b/src/kernel/task/timer.h new file mode 100644 index 0000000..4909245 --- /dev/null +++ b/src/kernel/task/timer.h @@ -0,0 +1,10 @@ +#ifndef DEF_TIMER_H +#define DEF_TIMER_H + +#include <types.h> + +void timer_init(uint32_t frequency); +uint32_t timer_time(); //Returns miliseconds (approximate) since computer started +uint32_t timer_uptime(); //Same thing in seconds + +#endif |