From c0018a3607947922a51597df12fd2a6528af2fa2 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Fri, 5 Feb 2010 19:37:47 +0100 Subject: More work on tasking, paging, syscalls, stuff. --- src/stem/core/kmain.c | 12 +- src/stem/core/sys.c | 2 +- src/stem/lib/stdlib.c | 18 +- src/stem/mem/paging.c | 14 ++ src/stem/mem/paging.h | 1 + src/stem/stem.map | 432 ++++++++++++++++++++++++------------------------ src/stem/task/idt.c | 6 +- src/stem/task/syscall.c | 6 +- src/stem/task/task.c | 108 +++++++++++- src/stem/task/task.h | 23 ++- 10 files changed, 383 insertions(+), 239 deletions(-) (limited to 'src/stem') diff --git a/src/stem/core/kmain.c b/src/stem/core/kmain.c index dbec8bd..28c2df7 100644 --- a/src/stem/core/kmain.c +++ b/src/stem/core/kmain.c @@ -10,13 +10,21 @@ #include void kmain_othertask(void *data) { - while(1) monitor_write("2task "); + uint32_t i; + for(i = 0; i < 100; i++) { + monitor_write("2task "); + thread_sleep(0); + } + process_exit(0); } void kmain_stage2(void *data) { sti(); thread_new(current_thread->process, kmain_othertask, 0); - while (1) monitor_write("TASK1 "); + while (1) { + monitor_write("TASK1 "); + thread_sleep(0); + } } void kmain(struct multiboot_info_t* mbd, int32_t magic) { diff --git a/src/stem/core/sys.c b/src/stem/core/sys.c index 71d1c31..36ed6d0 100644 --- a/src/stem/core/sys.c +++ b/src/stem/core/sys.c @@ -36,6 +36,6 @@ void cli() { } void sti() { - if_locks--; + if (if_locks > 0) if_locks--; if (if_locks == 0) asm volatile("sti"); } diff --git a/src/stem/lib/stdlib.c b/src/stem/lib/stdlib.c index 904126e..f4ebd33 100644 --- a/src/stem/lib/stdlib.c +++ b/src/stem/lib/stdlib.c @@ -1,12 +1,19 @@ #include "stdlib.h" -void *memcpy(void *dest, const void *src, int count) { - int i; - uint8_t *d = (uint8_t*)dest, *s = (uint8_t*)src; - for (i = 0; i < count; i++) { +void *memcpy(void *vd, const void *vs, int count) { + uint8_t *dest = vd, *src = vs; + uint32_t f = count % 4, n = count / 4, i; + const uint32_t* s = (uint32_t*)src; + uint32_t* d = (uint32_t*)dest; + for (i = 0; i < n; i++) { d[i] = s[i]; } - return dest; + if (f != 0) { + for (i = count - f; i < count; i++) { + dest[i] = src[i]; + } + } + return vd; } uint8_t *memset(uint8_t *dest, uint8_t val, int count) { @@ -14,6 +21,7 @@ uint8_t *memset(uint8_t *dest, uint8_t val, int count) { for (i = 0; i < count; i++) { dest[i] = val; } + return dest; } uint16_t *memsetw(uint16_t *dest, uint16_t val, int count) { diff --git a/src/stem/mem/paging.c b/src/stem/mem/paging.c index 4cc861c..4d98e75 100644 --- a/src/stem/mem/paging.c +++ b/src/stem/mem/paging.c @@ -30,6 +30,7 @@ void paging_init(size_t totalRam) { frames.bits = kmalloc(INDEX_FROM_BIT(frames.size)); kernel_pagedir = kmalloc(sizeof(struct page_directory)); + kernel_pagedir->mappedSegs = 0; kernel_pagedir->tablesPhysical = kmalloc_page(&kernel_pagedir->physicalAddr); for (i = 0; i < 1024; i++) { kernel_pagedir->tables[i] = 0; @@ -73,6 +74,7 @@ struct page_directory *pagedir_new() { struct page_directory *pd = kmalloc(sizeof(struct page_directory)); pd->tablesPhysical = kmalloc_page(&pd->physicalAddr); + pd->mappedSegs = 0; for (i = 768; i < 1024; i++) { pd->tables[i] = kernel_pagedir->tables[i]; @@ -82,6 +84,18 @@ struct page_directory *pagedir_new() { return pd; } +void pagedir_delete(struct page_directory *pd) { + uint32_t i; + //Unmap segments + while (pd->mappedSegs != 0) seg_unmap(pd->mappedSegs); + //Cleanup page tables + for (i = 0; i < 768; i++) { + kfree_page(pd->tables[i]); + } + kfree_page(pd->tablesPhysical); + kfree(pd); +} + uint32_t paging_fault(struct registers *regs) { size_t addr; struct segment_map *seg = 0; diff --git a/src/stem/mem/paging.h b/src/stem/mem/paging.h index 9ee6c4c..cb76cd6 100644 --- a/src/stem/mem/paging.h +++ b/src/stem/mem/paging.h @@ -35,6 +35,7 @@ void paging_init(size_t totalRam); void paging_cleanup(); void pagedir_switch(struct page_directory *pd); struct page_directory *pagedir_new(); //Creates a brand new empty page directory for a process, with kernel pages +void pagedir_delete(struct page_directory *pagedir); struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int make); void page_map(struct page *page, uint32_t frame, uint32_t user, uint32_t rw); void page_unmap(struct page *page); diff --git a/src/stem/stem.map b/src/stem/stem.map index a2d1d98..c35b1ee 100644 --- a/src/stem/stem.map +++ b/src/stem/stem.map @@ -26,238 +26,242 @@ Linker script and memory map 0x00100000 loader 0xe010003a . = (. + 0xe0000000) -.text 0xe0100040 0x2eed load address 0x00100040 +.text 0xe0100040 0x3395 load address 0x00100040 *(.text) .text 0xe0100040 0x25 core/loader_.o *fill* 0xe0100065 0x3 00 - .text 0xe0100068 0xef core/kmain.o + .text 0xe0100068 0x126 core/kmain.o 0xe0100068 kmain_othertask - 0xe010007c kmain_stage2 - 0xe01000b4 kmain - *fill* 0xe0100157 0x1 00 - .text 0xe0100158 0xed core/sys.o - 0xe0100158 outb - 0xe0100176 outw - 0xe0100196 inb - 0xe01001b3 inw - 0xe01001d2 panic - 0xe0100216 cli - 0xe0100229 sti - *fill* 0xe0100245 0x3 00 - .text 0xe0100248 0x310 core/monitor.o - 0xe0100359 monitor_put - 0xe0100465 monitor_clear - 0xe01004c2 monitor_write - 0xe01004eb monitor_writeHex - .text 0xe0100558 0x104 task/timer.o - 0xe0100558 timer_callback - 0xe0100590 timer_uptime - 0xe010059a timer_time - 0xe01005d1 timer_init - .text 0xe010065c 0x9fa task/idt.o - 0xe010065c idt_isrHandler - 0xe01006f4 idt_irqHandler - 0xe0100795 idt_syscallHandler - 0xe0100816 idt_init - 0xe0101044 idt_handleIrq - *fill* 0xe0101056 0xa 00 - .text 0xe0101060 0x293 task/idt_.o - 0xe0101060 gdt_flush - 0xe010107d idt_flush - 0xe0101115 isr0 - 0xe010111f isr1 - 0xe0101129 isr2 - 0xe0101133 isr3 - 0xe010113d isr4 - 0xe0101147 isr5 - 0xe0101151 isr6 - 0xe010115b isr7 - 0xe0101165 isr8 - 0xe010116d isr9 - 0xe0101177 isr10 - 0xe010117f isr11 - 0xe0101187 isr12 - 0xe010118f isr13 - 0xe0101197 isr14 - 0xe010119f isr15 - 0xe01011a9 isr16 - 0xe01011b3 isr17 - 0xe01011bd isr18 - 0xe01011c7 isr19 - 0xe01011d1 isr20 - 0xe01011db isr21 - 0xe01011e5 isr22 - 0xe01011ef isr23 - 0xe01011f9 isr24 - 0xe0101203 isr25 - 0xe010120d isr26 - 0xe0101217 isr27 - 0xe0101221 isr28 - 0xe010122b isr29 - 0xe0101235 isr30 - 0xe010123f isr31 - 0xe0101249 irq0 - 0xe0101253 irq1 - 0xe010125d irq2 - 0xe0101267 irq3 - 0xe0101271 irq4 - 0xe010127b irq5 - 0xe0101285 irq6 - 0xe010128f irq7 - 0xe0101299 irq8 - 0xe01012a3 irq9 - 0xe01012ad irq10 - 0xe01012b7 irq11 - 0xe01012c1 irq12 - 0xe01012cb irq13 - 0xe01012d5 irq14 - 0xe01012df irq15 - 0xe01012e9 syscall64 - *fill* 0xe01012f3 0x1 00 - .text 0xe01012f4 0x3dd task/task.o - 0xe01012f4 tasking_init - 0xe0101410 tasking_switch - 0xe01014a2 tasking_updateKernelPagetable - 0xe01014ec tasking_handleException - 0xe010156c thread_new - 0xe0101661 process_new - *fill* 0xe01016d1 0xf 00 - .text 0xe01016e0 0xa task/task_.o - 0xe01016e0 read_eip - 0xe01016e3 task_idle - *fill* 0xe01016ea 0x2 00 - .text 0xe01016ec 0x33 task/syscall.o - *fill* 0xe010171f 0x1 00 - .text 0xe0101720 0xca lib/stdlib.o - 0xe0101720 memcpy - 0xe010175d memset - 0xe010178c memsetw - 0xe01017c2 strlen - *fill* 0xe01017ea 0x2 00 - .text 0xe01017ec 0x173 lib/bitset.o - 0xe01017ec bitset_set - 0xe0101840 bitset_clear - 0xe0101896 bitset_test - 0xe01018d8 bitset_firstFree - *fill* 0xe010195f 0x1 00 - .text 0xe0101960 0x29f mem/mem.o - 0xe0101ac6 kmalloc_page - 0xe0101b0d kfree_page - 0xe0101b48 kheap_init - 0xe0101b9d kmalloc - 0xe0101bdb kfree - *fill* 0xe0101bff 0x1 00 - .text 0xe0101c00 0x645 mem/paging.o - 0xe0101c00 frame_alloc - 0xe0101c2d frame_free - 0xe0101c48 paging_init - 0xe0101de0 paging_cleanup - 0xe0101e3b pagedir_switch - 0xe0101e6a pagedir_new - 0xe0101ef2 paging_fault - 0xe010203f pagedir_getPage - 0xe0102156 page_map - 0xe01021de page_unmap - 0xe0102201 page_unmapFree - *fill* 0xe0102245 0x3 00 - .text 0xe0102248 0x19f mem/gdt.o - 0xe01022d7 gdt_init - *fill* 0xe01023e7 0x1 00 - .text 0xe01023e8 0x858 mem/heap.o - 0xe0102578 heap_create - 0xe010294b heap_alloc - 0xe0102aac heap_free - .text 0xe0102c40 0x2ed mem/seg.o - 0xe0102c40 seg_map - 0xe0102cae seg_unmap - 0xe0102d8d simpleseg_make - 0xe0102e0a simpleseg_map - 0xe0102e40 simpleseg_unmap - 0xe0102e93 simpleseg_handleFault - 0xe0102f28 simpleseg_delete + 0xe01000a7 kmain_stage2 + 0xe01000eb kmain + *fill* 0xe010018e 0x2 00 + .text 0xe0100190 0xf6 core/sys.o + 0xe0100190 outb + 0xe01001ae outw + 0xe01001ce inb + 0xe01001eb inw + 0xe010020a panic + 0xe010024e cli + 0xe0100261 sti + *fill* 0xe0100286 0x2 00 + .text 0xe0100288 0x310 core/monitor.o + 0xe0100399 monitor_put + 0xe01004a5 monitor_clear + 0xe0100502 monitor_write + 0xe010052b monitor_writeHex + .text 0xe0100598 0x104 task/timer.o + 0xe0100598 timer_callback + 0xe01005d0 timer_uptime + 0xe01005da timer_time + 0xe0100611 timer_init + .text 0xe010069c 0xa26 task/idt.o + 0xe010069c idt_isrHandler + 0xe0100734 idt_irqHandler + 0xe01007d5 idt_syscallHandler + 0xe0100882 idt_init + 0xe01010b0 idt_handleIrq + *fill* 0xe01010c2 0xe 00 + .text 0xe01010d0 0x293 task/idt_.o + 0xe01010d0 gdt_flush + 0xe01010ed idt_flush + 0xe0101185 isr0 + 0xe010118f isr1 + 0xe0101199 isr2 + 0xe01011a3 isr3 + 0xe01011ad isr4 + 0xe01011b7 isr5 + 0xe01011c1 isr6 + 0xe01011cb isr7 + 0xe01011d5 isr8 + 0xe01011dd isr9 + 0xe01011e7 isr10 + 0xe01011ef isr11 + 0xe01011f7 isr12 + 0xe01011ff isr13 + 0xe0101207 isr14 + 0xe010120f isr15 + 0xe0101219 isr16 + 0xe0101223 isr17 + 0xe010122d isr18 + 0xe0101237 isr19 + 0xe0101241 isr20 + 0xe010124b isr21 + 0xe0101255 isr22 + 0xe010125f isr23 + 0xe0101269 isr24 + 0xe0101273 isr25 + 0xe010127d isr26 + 0xe0101287 isr27 + 0xe0101291 isr28 + 0xe010129b isr29 + 0xe01012a5 isr30 + 0xe01012af isr31 + 0xe01012b9 irq0 + 0xe01012c3 irq1 + 0xe01012cd irq2 + 0xe01012d7 irq3 + 0xe01012e1 irq4 + 0xe01012eb irq5 + 0xe01012f5 irq6 + 0xe01012ff irq7 + 0xe0101309 irq8 + 0xe0101313 irq9 + 0xe010131d irq10 + 0xe0101327 irq11 + 0xe0101331 irq12 + 0xe010133b irq13 + 0xe0101345 irq14 + 0xe010134f irq15 + 0xe0101359 syscall64 + *fill* 0xe0101363 0x1 00 + .text 0xe0101364 0x6f6 task/task.o + 0xe0101364 tasking_init + 0xe01014af tasking_switch + 0xe0101556 tasking_updateKernelPagetable + 0xe01015a0 tasking_handleException + 0xe0101611 thread_sleep + 0xe01016f5 thread_exit + 0xe0101709 process_exit + 0xe01017a5 thread_new + 0xe010189a process_new + *fill* 0xe0101a5a 0x6 00 + .text 0xe0101a60 0xa task/task_.o + 0xe0101a60 read_eip + 0xe0101a63 task_idle + *fill* 0xe0101a6a 0x2 00 + .text 0xe0101a6c 0x66 task/syscall.o + *fill* 0xe0101ad2 0x2 00 + .text 0xe0101ad4 0x13a lib/stdlib.o + 0xe0101ad4 memcpy + 0xe0101b7e memset + 0xe0101bb0 memsetw + 0xe0101be6 strlen + *fill* 0xe0101c0e 0x2 00 + .text 0xe0101c10 0x173 lib/bitset.o + 0xe0101c10 bitset_set + 0xe0101c64 bitset_clear + 0xe0101cba bitset_test + 0xe0101cfc bitset_firstFree + *fill* 0xe0101d83 0x1 00 + .text 0xe0101d84 0x29f mem/mem.o + 0xe0101eea kmalloc_page + 0xe0101f31 kfree_page + 0xe0101f6c kheap_init + 0xe0101fc1 kmalloc + 0xe0101fff kfree + *fill* 0xe0102023 0x1 00 + .text 0xe0102024 0x6cc mem/paging.o + 0xe0102024 frame_alloc + 0xe0102051 frame_free + 0xe010206c paging_init + 0xe0102213 paging_cleanup + 0xe010226e pagedir_switch + 0xe010229d pagedir_new + 0xe0102332 pagedir_delete + 0xe010239d paging_fault + 0xe01024ea pagedir_getPage + 0xe0102601 page_map + 0xe0102689 page_unmap + 0xe01026ac page_unmapFree + .text 0xe01026f0 0x19f mem/gdt.o + 0xe010277f gdt_init + *fill* 0xe010288f 0x1 00 + .text 0xe0102890 0x858 mem/heap.o + 0xe0102a20 heap_create + 0xe0102df3 heap_alloc + 0xe0102f54 heap_free + .text 0xe01030e8 0x2ed mem/seg.o + 0xe01030e8 seg_map + 0xe0103156 seg_unmap + 0xe0103235 simpleseg_make + 0xe01032b2 simpleseg_map + 0xe01032e8 simpleseg_unmap + 0xe010333b simpleseg_handleFault + 0xe01033d0 simpleseg_delete -.iplt 0xe0102f30 0x0 load address 0x00102f2d +.iplt 0xe01033d8 0x0 load address 0x001033d5 .iplt 0x00000000 0x0 core/loader_.o -.rodata 0xe0103000 0x1a3 load address 0x00103000 +.rodata 0xe0104000 0x395 load address 0x00104000 *(.rodata) - .rodata 0xe0103000 0x52 core/kmain.o - .rodata 0xe0103052 0x2c core/sys.o - .rodata 0xe010307e 0xf task/timer.o - *fill* 0xe010308d 0x3 00 - .rodata 0xe0103090 0x78 task/idt.o - .rodata 0xe0103108 0x12 task/task.o - .rodata 0xe010311a 0x10 mem/mem.o - .rodata 0xe010312a 0x71 mem/paging.o - .rodata 0xe010319b 0x8 mem/gdt.o + .rodata 0xe0104000 0x52 core/kmain.o + .rodata 0xe0104052 0x2c core/sys.o + .rodata 0xe010407e 0xf task/timer.o + *fill* 0xe010408d 0x3 00 + .rodata 0xe0104090 0x8a task/idt.o + *fill* 0xe010411a 0x6 00 + .rodata 0xe0104120 0x1ec task/task.o + .rodata 0xe010430c 0x10 mem/mem.o + .rodata 0xe010431c 0x71 mem/paging.o + .rodata 0xe010438d 0x8 mem/gdt.o -.rel.dyn 0xe01031a4 0x0 load address 0x001031a3 +.rel.dyn 0xe0104398 0x0 load address 0x00104395 .rel.iplt 0x00000000 0x0 core/loader_.o .rel.text 0x00000000 0x0 core/loader_.o -.data 0xe0104000 0x24 load address 0x00104000 +.data 0xe0105000 0x24 load address 0x00105000 *(.data) - .data 0xe0104000 0x0 core/kmain.o - .data 0xe0104000 0x4 core/sys.o - .data 0xe0104004 0x4 core/monitor.o - .data 0xe0104008 0x0 task/timer.o - .data 0xe0104008 0x0 task/idt.o - .data 0xe0104008 0x4 task/task.o - .data 0xe010400c 0x18 task/syscall.o - 0xe010400c syscalls - .data 0xe0104024 0x0 lib/stdlib.o - .data 0xe0104024 0x0 lib/bitset.o - .data 0xe0104024 0x0 mem/mem.o - .data 0xe0104024 0x0 mem/paging.o - .data 0xe0104024 0x0 mem/gdt.o - .data 0xe0104024 0x0 mem/heap.o - .data 0xe0104024 0x0 mem/seg.o + .data 0xe0105000 0x0 core/kmain.o + .data 0xe0105000 0x4 core/sys.o + .data 0xe0105004 0x4 core/monitor.o + .data 0xe0105008 0x0 task/timer.o + .data 0xe0105008 0x0 task/idt.o + .data 0xe0105008 0x4 task/task.o + .data 0xe010500c 0x18 task/syscall.o + 0xe010500c syscalls + .data 0xe0105024 0x0 lib/stdlib.o + .data 0xe0105024 0x0 lib/bitset.o + .data 0xe0105024 0x0 mem/mem.o + .data 0xe0105024 0x0 mem/paging.o + .data 0xe0105024 0x0 mem/gdt.o + .data 0xe0105024 0x0 mem/heap.o + .data 0xe0105024 0x0 mem/seg.o -.igot.plt 0xe0104024 0x0 load address 0x00104024 +.igot.plt 0xe0105024 0x0 load address 0x00105024 .igot.plt 0x00000000 0x0 core/loader_.o -.bss 0xe0104040 0x10970 load address 0x00104040 - 0xe0104040 sbss = . +.bss 0xe0105040 0x10970 load address 0x00105040 + 0xe0105040 sbss = . *(COMMON) - COMMON 0xe0104040 0x820 task/idt.o - 0xe0104040 idt_ptr - 0xe0104060 idt_entries - COMMON 0xe0104860 0x10008 task/task.o - 0xe0104860 tasking_tmpStack - 0xe0114860 kernel_process - 0xe0114864 idle_thread - COMMON 0xe0114868 0x4 mem/mem.o - 0xe0114868 mem_placementAddr - COMMON 0xe011486c 0x8 mem/paging.o - 0xe011486c current_pagedir - 0xe0114870 kernel_pagedir + COMMON 0xe0105040 0x820 task/idt.o + 0xe0105040 idt_ptr + 0xe0105060 idt_entries + COMMON 0xe0105860 0x10008 task/task.o + 0xe0105860 tasking_tmpStack + 0xe0115860 kernel_process + 0xe0115864 idle_thread + COMMON 0xe0115868 0x4 mem/mem.o + 0xe0115868 mem_placementAddr + COMMON 0xe011586c 0x8 mem/paging.o + 0xe011586c current_pagedir + 0xe0115870 kernel_pagedir *(.bss) - .bss 0xe0114874 0x0 core/kmain.o - .bss 0xe0114874 0x0 core/sys.o - .bss 0xe0114874 0x8 core/monitor.o - .bss 0xe011487c 0xc task/timer.o - *fill* 0xe0114888 0x18 00 - .bss 0xe01148a0 0x40 task/idt.o - .bss 0xe01148e0 0xc task/task.o - 0xe01148e0 processes - 0xe01148e4 threads - 0xe01148e8 current_thread - .bss 0xe01148ec 0x0 task/syscall.o - .bss 0xe01148ec 0x0 lib/stdlib.o - .bss 0xe01148ec 0x0 lib/bitset.o - *fill* 0xe01148ec 0x14 00 - .bss 0xe0114900 0x60 mem/mem.o - 0xe0114900 freepagecount - .bss 0xe0114960 0x8 mem/paging.o - *fill* 0xe0114968 0x18 00 - .bss 0xe0114980 0x2e mem/gdt.o - *fill* 0xe01149ae 0x2 00 - .bss 0xe01149b0 0x0 mem/heap.o - .bss 0xe01149b0 0x0 mem/seg.o - 0xe01149b0 ebss = . - 0xe01149b0 end = . - 0xe01149b0 _end = . - 0xe01149b0 __end = . + .bss 0xe0115874 0x0 core/kmain.o + .bss 0xe0115874 0x0 core/sys.o + .bss 0xe0115874 0x8 core/monitor.o + .bss 0xe011587c 0xc task/timer.o + *fill* 0xe0115888 0x18 00 + .bss 0xe01158a0 0x40 task/idt.o + .bss 0xe01158e0 0xc task/task.o + 0xe01158e0 processes + 0xe01158e4 threads + 0xe01158e8 current_thread + .bss 0xe01158ec 0x0 task/syscall.o + .bss 0xe01158ec 0x0 lib/stdlib.o + .bss 0xe01158ec 0x0 lib/bitset.o + *fill* 0xe01158ec 0x14 00 + .bss 0xe0115900 0x60 mem/mem.o + 0xe0115900 freepagecount + .bss 0xe0115960 0x8 mem/paging.o + *fill* 0xe0115968 0x18 00 + .bss 0xe0115980 0x2e mem/gdt.o + *fill* 0xe01159ae 0x2 00 + .bss 0xe01159b0 0x0 mem/heap.o + .bss 0xe01159b0 0x0 mem/seg.o + 0xe01159b0 ebss = . + 0xe01159b0 end = . + 0xe01159b0 _end = . + 0xe01159b0 __end = . LOAD core/loader_.o LOAD core/kmain.o LOAD core/sys.o diff --git a/src/stem/task/idt.c b/src/stem/task/idt.c index 4866550..360ac91 100644 --- a/src/stem/task/idt.c +++ b/src/stem/task/idt.c @@ -95,7 +95,11 @@ void idt_irqHandler(struct registers regs) { } void idt_syscallHandler(struct registers regs) { - syscalls[regs.eax](®s); + 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) { diff --git a/src/stem/task/syscall.c b/src/stem/task/syscall.c index 6964b34..0878b30 100644 --- a/src/stem/task/syscall.c +++ b/src/stem/task/syscall.c @@ -6,13 +6,15 @@ #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(process_exit, process_exit_sc); CALL1(monitor_write, printk_sc); int_callback syscalls[] = { - 0, //Syscall 0 will be thread_exit + thread_exit_sc, schedule_sc, 0, //Syscall 2 will be thread_sleep - 0, //Syscall 3 will be process_exit + process_exit_sc, printk_sc, 0 }; diff --git a/src/stem/task/task.c b/src/stem/task/task.c index 8ed5190..5ab001c 100644 --- a/src/stem/task/task.c +++ b/src/stem/task/task.c @@ -6,6 +6,12 @@ #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*); @@ -28,15 +34,16 @@ void tasking_init(thread_entry whereToGo, void *data) { kernel_process->pagedir = kernel_pagedir; kernel_process->next = 0; current_thread = 0; - thread_new(kernel_process, task_idle, 0); + idle_thread = thread_new(kernel_process, task_idle, 0); + threads = 0; //Do not include idle thread in threads thread_new(kernel_process, whereToGo, data); sti(); monitor_write("Tasking starting\n"); tasking_switch(); } -static struct thread *thread_next() { //NOT OPTIMAL : will allocate time slices to idle thread even if busy - if (current_thread == 0) current_thread = threads; +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; @@ -44,12 +51,13 @@ static struct thread *thread_next() { //NOT OPTIMAL : will allocate time slices if (thread_runnable(ret)) { return ret; } + if (ret == current_thread) return idle_thread; } } void tasking_switch() { - if (threads == 0) return; //no tasking yet - cli(); + if (threads == 0) PANIC("No more threads to run !"); + asm volatile("cli"); uint32_t esp, ebp, eip; @@ -89,9 +97,65 @@ void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint3 uint32_t tasking_handleException(struct registers *regs) { if (threads == 0) return 0; //No tasking yet + monitor_write("\nUnhandled 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("\nThread exiting.\n"); + thread_exit_stackJmp(EX_TH_EXCEPTION); return 0; } +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; @@ -102,7 +166,7 @@ static void thread_run(struct thread *thread, thread_entry entry_point, void *da pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level asm volatile("sti"); entry_point(data); - asm volatile("int $64"); + thread_exit(0); } struct thread *thread_new(struct process *proc, thread_entry entry_point, void *data) { @@ -147,3 +211,35 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi 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->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/stem/task/task.h b/src/stem/task/task.h index f59bb2b..1d1d121 100644 --- a/src/stem/task/task.h +++ b/src/stem/task/task.h @@ -5,14 +5,6 @@ #include #include "idt.h" -struct process { - uint32_t pid, uid, privilege, threads; - struct process *parent; - struct page_directory *pagedir; - - struct process *next; //Forms a linked list -}; - #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) @@ -22,8 +14,20 @@ struct process { #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; @@ -42,6 +46,9 @@ 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); -- cgit v1.2.3