From 47513bd32c256c4f35e3a8ced7d9fd7e15903530 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Tue, 16 Feb 2021 20:38:53 -0500 Subject: terminal application with ipc, shift+pause state dumper, hello world for terminal, meminfo popup program --- src/kernel/dump.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/elf-link.ld | 2 + src/kernel/elf.c | 9 ++- src/kernel/idt.c | 50 ++++++------- src/kernel/isrs.asm | 12 ++++ src/kernel/kbd.c | 6 +- src/kernel/kbd.h | 8 ++- src/kernel/log.c | 5 ++ src/kernel/log.h | 1 + src/kernel/paging.c | 5 +- src/kernel/paging.h | 4 +- src/kernel/task.c | 101 ++++++++++++++++---------- src/kernel/task.h | 12 ++-- src/kernel/window.c | 25 ++++++- src/kernel/window.h | 6 +- 15 files changed, 353 insertions(+), 80 deletions(-) create mode 100644 src/kernel/dump.c (limited to 'src/kernel') diff --git a/src/kernel/dump.c b/src/kernel/dump.c new file mode 100644 index 0000000..d0c02e6 --- /dev/null +++ b/src/kernel/dump.c @@ -0,0 +1,187 @@ +#include + +#include "paging.h" +#include "task.h" +#include "log.h" + +extern const void _kernel_data_start; +extern const void _kernel_data_end; +extern const void _kernel_bss_end; + +static inline char c(uint8_t n) { + return (n > 0x20) && (n < 0x7f) ? (char)n : '.'; +} + +static uint8_t last_line[16]; +enum { + SECTION_START, + DOT_DOT_DOT, + SKIP +} last_line_mode; + +static void write_mem_line(uint32_t addr) { + const uint8_t *const at = (const uint8_t *)addr; + if (last_line_mode != SECTION_START) { + for (uint8_t i = 0; i < 16; ++i) + if (at[i] != last_line[i]) + goto diff_line; + if (last_line_mode == DOT_DOT_DOT) { + logf(LOG_DUMP, " 0x%h ...", addr); + last_line_mode = SKIP; + } + return; + } +diff_line: + logf(LOG_DUMP, + " 0x%h %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", addr, + at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], + at[9], at[9], at[10], at[11], at[12], at[13], at[14], at[15], + c(at[0]), c(at[1]), c(at[2]), c(at[3]), + c(at[4]), c(at[5]), c(at[6]), c(at[7]), + c(at[8]), c(at[9]), c(at[10]), c(at[11]), + c(at[12]), c(at[13]), c(at[14]), c(at[15]) + ); + for (uint8_t i = 0; i < 16; ++i) + last_line[i] = at[1]; + last_line_mode = DOT_DOT_DOT; +} + +static void write_mem_page(uint32_t page) { + for (uint32_t i = page << 12; i < (page + 1) << 12; i += 16) + write_mem_line(i); +} + +#include "kbd.h" + +#define WAIT_TASK tasks[i].waits[t].task - tasks + 1, tasks[i].waits[t].task->name + +void dump(enum kbd_isr_result kind, const uint32_t edi, const uint32_t esi, const uint32_t ebx, const uint32_t edx, const uint32_t ecx, const uint32_t eax, const uint32_t eip, const uint32_t cs, const uint32_t eflags, const uint32_t esp, const uint32_t ss) { + uint32_t cr3; + asm volatile ( + "mov %%cr3, %0" + : "=a" (cr3)); + + logf(LOG_INFO, "Dump state..."); + + switch (kind) { + case DUMP: + logf(LOG_DUMP, "Tasks:"); + for (uint8_t t = 0; t < MAX_TASKS; ++t) + if (tasks[t].page_directory) { + logf(LOG_DUMP, " %s (0x%hb):", tasks[t].name, t + 1); + if (tasks + t == active_task) { + logf(LOG_DUMP, " *Active task*"); + logf(LOG_DUMP, " cr3: 0x%h", cr3); + logf(LOG_DUMP, " eip: 0x%h", eip); + logf(LOG_DUMP, " eax: 0x%h", eax); + logf(LOG_DUMP, " ebx: 0x%h", ebx); + logf(LOG_DUMP, " ecx: 0x%h", ecx); + logf(LOG_DUMP, " edx: 0x%h", edx); + logf(LOG_DUMP, " esi: 0x%h", esi); + logf(LOG_DUMP, " edi: 0x%h", edi); + logf(LOG_DUMP, " esp: 0x%h", esp); + logf(LOG_DUMP, " cs: 0x%hb", cs); + logf(LOG_DUMP, " ss: 0x%hb", ss); + logf(LOG_DUMP, " eflags: 0x%h", eflags); + } + else { + logf(LOG_DUMP, " Stored cr3: 0x%h", tasks[t].page_directory); + logf(LOG_DUMP, " Stored eip: 0x%h", tasks[t].ret_addr); + logf(LOG_DUMP, " Stored ebx: 0x%h", tasks[t].ebx); + logf(LOG_DUMP, " Stored ecx: 0x%h", tasks[t].ecx); + logf(LOG_DUMP, " Stored edx: 0x%h", tasks[t].edx); + logf(LOG_DUMP, " Stored esi: 0x%h", tasks[t].esi); + logf(LOG_DUMP, " Stored edi: 0x%h", tasks[t].edi); + logf(LOG_DUMP, " Stored ebp: 0x%h", tasks[t].ebp); + logf(LOG_DUMP, " Stored esp: 0x%h", tasks[t].esp); + } + logf(LOG_DUMP, " Stack size: %d kibibytes", -tasks[t].stack_bottom / 1024); + if (tasks[t].waiting) { + logf(LOG_DUMP, " Waits:"); + for (uint8_t i = 0; i < MAX_WAITS; ++i) + switch (tasks[i].waits[t].mode) { + case NONE: + continue; + case PROCESS_END: + logf(LOG_DUMP, " Waiting for task 0x%hb (%s) to end", WAIT_TASK); + continue; + case WINDOW_ACTION: + logf(LOG_DUMP, " Waiting for window action"); + continue; + case IPC_SENT: + logf(LOG_DUMP, " Waiting for IPC to be sent by 0x%hb (%s)", WAIT_TASK); + continue; + case IPC_SENT_ANY: + logf(LOG_DUMP, " Waiting for IPC to be sent by anyone"); + continue; + case IPC_READ: + logf(LOG_DUMP, " Waiting for IPC to be read by 0x%hb (%s)", WAIT_TASK); + continue; + default: + logf(LOG_DUMP, " Other (corrupted?)"); + continue; + } + } + else + logf(LOG_DUMP, " Not waiting."); + } + break; + + case SHIFT_DUMP: + + logf(LOG_DUMP, "Current task: 0x%hb (%s)", active_task - tasks + 1, active_task->name); + logf(LOG_DUMP, "Registers:"); + logf(LOG_DUMP, " cr3: 0x%h", cr3); + logf(LOG_DUMP, " eip: 0x%h", eip); + logf(LOG_DUMP, " esp: 0x%h", esp); + logf(LOG_DUMP, " eax: 0x%h", eax); + logf(LOG_DUMP, " ebx: 0x%h", ebx); + logf(LOG_DUMP, " ecx: 0x%h", ecx); + logf(LOG_DUMP, " edx: 0x%h", edx); + logf(LOG_DUMP, " esi: 0x%h", esi); + logf(LOG_DUMP, " edi: 0x%h", edi); + logf(LOG_DUMP, " eflags: 0x%h", eflags); + logf(LOG_DUMP, " cs: 0x%hb", cs); + logf(LOG_DUMP, " ss: 0x%hb", ss); + + logf(LOG_DUMP, "Kernel data section:"); + last_line_mode = SECTION_START; + for (uint32_t i = (uint32_t)&_kernel_data_start & ~0xf; i < (((uint32_t)&_kernel_data_end - 1) & ~0xf) + 0x10; i += 0x10) + write_mem_line(i); + logf(LOG_DUMP, "Kernel bss section:"); + last_line_mode = SECTION_START; + for (uint32_t i = 0x4000000; i < (((uint32_t)&_kernel_bss_end - 1) & ~0xf) + 1; i += 0x10) + write_mem_line(i); + logf(LOG_DUMP, "Kernel heap:"); + last_line_mode = SECTION_START; + const uint32_t first_heap_page = (((uint32_t)&_kernel_bss_end - 1) >> 12) + 1; + for (uint8_t n = first_heap_page & 7; n < 8; ++n) + if (*(uint8_t *)(0x40000 + (first_heap_page >> 3)) & (1 << n)) + write_mem_page((first_heap_page & ~7) | n); + for (uint8_t *i = (uint8_t *)(0x40000 + (first_heap_page >> 3) + 1); i < (uint8_t *)0x41000; ++i) + for (uint8_t n = 0; n < 8; ++n) + if (*i & (1 << n)) + write_mem_page((i - (uint8_t *)0x40000) * 8 + n); + + for (uint8_t t = 0; t < MAX_TASKS; ++t) + if (tasks[t].page_directory) { + logf(LOG_DUMP, "Task 0x%hb (%s)'s memory:", t + 1, tasks[t].name); + last_line_mode = SECTION_START; + const void *const pd = tasks[t].page_directory; + asm ( + "mov %0, %%cr3" + : : "a" (pd)); + for (uint32_t i = 0x08000000; i; i += 4096) + if (pd_is_mapped(pd, i)) + for (uint32_t j = i; j < i + 4096; j += 16) + write_mem_line(j); + } + break; + } + + logf(LOG_INFO, "Dumped state."); + + asm ( + "mov %0, %%cr3" + : : "a" (cr3)); +} \ No newline at end of file diff --git a/src/kernel/elf-link.ld b/src/kernel/elf-link.ld index 84d3f92..d0c6723 100644 --- a/src/kernel/elf-link.ld +++ b/src/kernel/elf-link.ld @@ -11,7 +11,9 @@ SECTIONS { *(.rodata) } .data : { + _kernel_data_start = .; *(.data) + _kernel_data_end = .; } . = 0x04000000; .bss : { diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 146035e..f601654 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -6,6 +6,8 @@ #include "paging.h" #include "pmap.h" +#include "log.h" + #define ELF_MAGIC 0x464c457f enum { @@ -129,9 +131,12 @@ uint32_t try_elf_run(const struct drive *d, const char *path, const char *pass_o tstate.ret_addr = ehead.entry_vma; tstate.stack_bottom = 0; +//logf(LOG_INFO, " tasks: 0x%h", tasks); +//logf(LOG_INFO, "active_task: 0x%h", active_task); +//logf(LOG_INFO, " new edi: 0x%hb", active_task - tasks + 1); tstate.edx = (uint32_t)pass_vma; - tstate.esi = active_task - tasks + 1; - tstate.edi = io_handle; + tstate.esi = io_handle; + tstate.edi = active_task - tasks + 1; tstate.esp = 0; const char *path_end_start = path; diff --git a/src/kernel/idt.c b/src/kernel/idt.c index b8990f2..9b3ba96 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -35,25 +35,23 @@ struct { //file handles as (drive_number << 8) + file_id_t -uint32_t sc_open_file(uint32_t drive_number, char *path) { //not static to ensure sysv abi +uint32_t sc_open_file(uint32_t drive_number, char *path) { return (drive_number << 8) + drives[drive_number].get_file(drives + drive_number, path); - //logf(LOG_INFO, "sc_open_file(%d, \"%s\") -> %d", drive_number, path, handle); } -void sc_close_file(uint32_t handle) { //not static to ensure sysv abi +void sc_close_file(uint32_t handle) { if (!handle) return; drives[handle >> 8].free_file(drives + (handle >> 8), handle & 0xff); } -uint32_t sc_file_get_size(uint32_t handle) { //not static to ensure sysv abi - //logf(LOG_INFO, "sc_file_get_size(%d)", handle); +uint32_t sc_file_get_size(uint32_t handle) { if (!handle) return 0; return drives[handle >> 8].get_file_length(drives + (handle >> 8), handle & 0xff); } -uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, void *buffer) { //not static to ensure sysv abi +uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, void *buffer) { if (!handle) return 0; uint32_t len = sc_file_get_size(handle); @@ -63,14 +61,14 @@ uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, voi return count; } -uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass, uint32_t esi_dummy, uint32_t io_task) { //not static to ensure sysv abi +uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass, uint32_t io_task) { switch_to_kernel_cr3(); uint32_t process_id = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass, io_task); switch_to_task_cr3(); return process_id; } -void *sc_allocate_ram(uint32_t pages) { //not static to ensure sysv abi +void *sc_allocate_ram(uint32_t pages) { return pd_user_allocate_anywhere_writable(active_task->page_directory, pages); } @@ -83,7 +81,7 @@ enum mi_arg { }; __attribute__ ((pure)) -uint32_t sc_memory_info(enum mi_arg arg) { //not static to ensure sysv abi +uint32_t sc_memory_info(enum mi_arg arg) { switch (arg) { case MI_KERNEL_MAX: return max_kernel_pages; @@ -100,7 +98,7 @@ uint32_t sc_memory_info(enum mi_arg arg) { //not static to ensure sysv abi } } -void sc_wait_for_task(uint32_t handle) { //not static to ensure sysv abi +void sc_wait_for_task(uint32_t handle) { add_wait((struct wait){.mode = PROCESS_END, .task = tasks + handle - 1}); } @@ -108,11 +106,11 @@ uint32_t sc_enumerate_dir(uint32_t drive_number, const char *path, struct direct return drives[drive_number].enumerate_dir(drives + drive_number, path, buffer, max_entries); } -uint32_t sc_count_of_dir(uint32_t drive_number, const char *path) { //not static to ensure sysv abi +uint32_t sc_count_of_dir(uint32_t drive_number, const char *path) { return drives[drive_number].n_dir_entries(drives + drive_number, path); } -void sc_get_next_window_action(struct window *w, struct window_action *action) { //not static to ensure sysv abi +void sc_get_next_window_action(struct window *w, struct window_action *action) { *action = next_window_action(w); } @@ -120,25 +118,27 @@ void sc_wait_window_action() { add_wait((struct wait){.mode = WINDOW_ACTION}); } -void sc_wait_ipc(uint32_t task_handle) { - add_wait((struct wait){.mode = IPC_RECEIVE, .task = tasks + task_handle - 1}); +void sc_wait_ipc_sent(uint32_t task_handle) { + add_wait((struct wait){.mode = IPC_SENT, .task = tasks + task_handle - 1}); } void sc_system_log(const char *sz) { logf(LOG_USER, "[%s] %s", active_task->name, sz); } -void sc_wait_any_ipc() { - add_wait((struct wait){.mode = IPC_RECEIVE_ANY}); +void sc_wait_any_ipc_sent() { + add_wait((struct wait){.mode = IPC_SENT_ANY}); } void sc_wait_ipc_read(uint32_t handle) { - add_wait((struct wait){.mode = IPC_SEND, .task = tasks + handle - 1}); + add_wait((struct wait){.mode = IPC_READ, .task = tasks + handle - 1}); } +//returns a uint32_t to ensure upper twenty-four bits of +// eax are set to zero - otherwise userland stuff break __attribute__ ((pure)) -bool sc_is_task_running(uint32_t handle) { - return tasks[handle - 1].page_directory; +uint32_t sc_is_task_running(uint32_t handle) { + return tasks[handle - 1].page_directory ? 1 : 0; } void const *syscall_table[] = { @@ -162,8 +162,8 @@ void const *syscall_table[] = { &push_window_paint, &sc_get_next_window_action, &sc_wait_window_action, - &sc_wait_ipc, - &sc_wait_any_ipc, + &sc_wait_ipc_sent, + &sc_wait_any_ipc_sent, &find_unread_ipc, &sc_wait_ipc_read, &sc_is_task_running @@ -240,17 +240,11 @@ void exception_halt(uint32_t eax, uint32_t ebx, uint32_t ecx, } //returns true if stack was expanded -bool pf_check_stack(uint32_t cr2/*, uint32_t edx, uint32_t ecx, uint32_t eax, - uint32_t code, uint32_t eip*/) { -//logf(LOG_INFO, "page fault in %s at 0x%h trying to access 0x%h", active_task->name, eip, cr2); -//logf(LOG_INFO, "stack bottom is 0x%h", active_task->stack_bottom); - +bool pf_check_stack(uint32_t cr2) { if (cr2 >= active_task->stack_bottom - 0x1000) { - //logf(LOG_INFO, "expanding stack"); switch_to_kernel_cr3(); pd_user_allocate(active_task->page_directory, active_task->stack_bottom -= 4096, 1, true); switch_to_task_cr3(); - //logf(LOG_INFO, "new stack bottom is 0x%h", active_task->stack_bottom); return true; } else { diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 02b046d..a4eb988 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -23,6 +23,7 @@ extern on_kbd_isr extern make_sure_tasks extern exception_halt extern pf_check_stack +extern dump n_syscalls equ 0x19 @@ -139,6 +140,17 @@ kbd_isr: call on_kbd_isr + test eax, eax + jz .no_debug + + push ebx + push esi + push edi + push eax + call dump + add esp, 16 + +.no_debug: mov al, 0x20 out 0x0020, al diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c index f7158bb..c09684d 100644 --- a/src/kernel/kbd.c +++ b/src/kernel/kbd.c @@ -91,7 +91,7 @@ static inline uint8_t get_next_code_byte() { static enum key_modifiers_t keymods = 0; -void on_kbd_isr() { +enum kbd_isr_result on_kbd_isr() { //logf(LOG_INFO, "on_kbd_isr()"); while (inb(PS2_CMD) & PS2S_CODE_READY) { last_code_byte = 0; @@ -201,6 +201,9 @@ void on_kbd_isr() { break; } + if (!is_up && (entry == KEY_PAUSE) && (keymods & ALTS)) + return (keymods & SHIFTS) ? SHIFT_DUMP : DUMP; + on_action((struct window_action){ .action_type = is_up ? KEY_UP : KEY_DOWN, .as_key = (struct key_packet){ @@ -209,4 +212,5 @@ void on_kbd_isr() { } }); } + return NORMAL; } diff --git a/src/kernel/kbd.h b/src/kernel/kbd.h index e9affad..7e03fd7 100644 --- a/src/kernel/kbd.h +++ b/src/kernel/kbd.h @@ -1,11 +1,17 @@ #ifndef KBD_H #define KBD_H +#include #include #include void init_kbd(); -void on_kbd_isr(); + +enum kbd_isr_result { + NORMAL, + DUMP, + SHIFT_DUMP +} on_kbd_isr(); #endif diff --git a/src/kernel/log.c b/src/kernel/log.c index 8ef2baf..6bad1cc 100644 --- a/src/kernel/log.c +++ b/src/kernel/log.c @@ -14,6 +14,7 @@ void init_log() { static const char *const log_prefixes[] = { " [USER] ", " [INFO] ", + " [DUMP] ", " [WARN] ", "[ERROR] ", "[PANIC] ", @@ -42,6 +43,10 @@ void logf(enum log_level level, const char *format, ...) { case '%': logch('%'); break; + case 'c':; + const char c = (char)va_arg(args, uint32_t); + logch(c); + break; case 's':; const char *s = va_arg(args, const char *); while (*s) diff --git a/src/kernel/log.h b/src/kernel/log.h index c5c4da7..daf90dd 100644 --- a/src/kernel/log.h +++ b/src/kernel/log.h @@ -6,6 +6,7 @@ enum log_level { LOG_USER, LOG_INFO, + LOG_DUMP, LOG_WARN, LOG_ERROR, LOG_PANIC diff --git a/src/kernel/paging.c b/src/kernel/paging.c index fbc33de..4672788 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -34,7 +34,7 @@ static void pd_map(void *pd, uint32_t physical_addr, uint32_t virtual_addr, bool } __attribute__ ((pure)) -static bool pd_is_mapped(void *pd, uint32_t vma) { +bool pd_is_mapped(const void *pd, uint32_t vma) { uint32_t pde = ((uint32_t *)pd)[vma >> 22]; return (pde & PE_PRESENT) && (((uint32_t *)(pde & PE_ADDR_MASK))[(vma >> 12) % 1024] & PE_PRESENT); } @@ -52,8 +52,7 @@ void free_task_pd(void *pd) { free_pages(pd, 1); } -__attribute__ ((aligned (4096))) -static uint32_t kmap[KERNEL_END / 4096]; +#define kmap ((uint32_t *)0x00060000) void *new_task_pd() { uint32_t *pd = allocate_kernel_pages(1); diff --git a/src/kernel/paging.h b/src/kernel/paging.h index 6c1a6f5..082f6c2 100644 --- a/src/kernel/paging.h +++ b/src/kernel/paging.h @@ -12,4 +12,6 @@ void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **v void *vma_to_pma(void *pd, const void *vma) __attribute__ ((pure)); void switch_to_kernel_cr3(); -void switch_to_task_cr3(); \ No newline at end of file +void switch_to_task_cr3(); + +bool pd_is_mapped(const void *pd, uint32_t vma) __attribute__ ((pure)); \ No newline at end of file diff --git a/src/kernel/task.c b/src/kernel/task.c index ab08e6b..e2412e1 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -1,4 +1,5 @@ #include "paging.h" +#include "window.h" #include "panic.h" #include "pmap.h" #include "task.h" @@ -42,34 +43,15 @@ struct tss { #define TSS ((struct tss *)0x00004f98) -#define MAX_TASKS 64 - struct task_state tasks[MAX_TASKS]; struct task_state *active_task; -void init_tasks() { - active_task = tasks; - - for (uint8_t i = 0; i < MAX_TASKS; ++i) - tasks[i].page_directory = 0; - - TSS->ss0 = 0x18; - TSS->esp0 = 0x00040000; -//TSS->cs = 0x13; -//TSS->ds = 0x1b; -//TSS->ss = 0x1b; - TSS->iomp = sizeof(struct tss); - - asm volatile ( - "mov $0x08, %%ax\n" - "ltr %%ax" - : : : "ax"); -} - +//puts the handle into ecx uint32_t new_task(struct task_state state) { for (uint8_t n = 0; n < MAX_TASKS; ++n) if (!tasks[n].page_directory) { tasks[n] = state; + tasks[n].ecx = n + 1; tasks[n].waiting = false; for (uint8_t i = 0; i < MAX_WAITS; ++i) tasks[n].waits[i].mode = NONE; @@ -129,22 +111,47 @@ struct ipc_pipe { bool delete_when_empty; } ipc_pipes[MAX_IPC_PIPES]; +void init_tasks() { + active_task = tasks; + + for (uint8_t i = 0; i < MAX_TASKS; ++i) + tasks[i].page_directory = 0; + + for (uint16_t i = 0; i < MAX_IPC_PIPES; ++i) + ipc_pipes[i].buffer = 0; + + TSS->ss0 = 0x18; + TSS->esp0 = 0x00040000; +//TSS->cs = 0x13; +//TSS->ds = 0x1b; +//TSS->ss = 0x1b; + TSS->iomp = sizeof(struct tss); + + asm volatile ( + "mov $0x08, %%ax\n" + "ltr %%ax" + : : : "ax"); +} + void delete_pipe(struct ipc_pipe *pipe) { free_pages(pipe->buffer, IPC_BUFFER_PAGES); pipe->buffer = 0; } void delete_task(struct task_state *state) { +//logf(LOG_INFO, "-- deleting 0x%h", state); switch_to_kernel_cr3(); free_task_pd(state->page_directory); switch_to_task_cr3(); + + delete_any_windows_from(state); state->page_directory = 0; +//logf(LOG_INFO, "-- unwaiting any waiting for 0x%h", state); unwait_any((struct wait){.mode = PROCESS_END, .task = state}); - unwait_any((struct wait){.mode = IPC_RECEIVE, .task = state}); - unwait_any((struct wait){.mode = IPC_SEND, .task = state}); + unwait_any((struct wait){.mode = IPC_SENT, .task = state}); - const uint32_t handle = active_task - tasks + 1; + const uint32_t handle = state - tasks + 1; for (struct ipc_pipe *pipe = ipc_pipes; pipe < ipc_pipes + MAX_IPC_PIPES; ++pipe) if (pipe->buffer) { if (pipe->reader_handle == handle) @@ -158,15 +165,19 @@ void delete_task(struct task_state *state) { } } +__attribute__ ((pure)) uint32_t find_unread_ipc() { const uint32_t r_handle = active_task - tasks + 1; for (struct ipc_pipe *pipe = ipc_pipes; pipe < ipc_pipes + MAX_IPC_PIPES; ++pipe) if (pipe->buffer && (pipe->reader_handle == r_handle) && - (pipe->buffer_next_read != pipe->buffer_next_send)) + (pipe->buffer_next_read != pipe->buffer_next_send)) { + //logf(LOG_INFO, "found %d bytes of unread ipc from 0x%hb to 0x%hb", pipe->buffer_next_send - pipe->buffer_next_read + (pipe->buffer_next_read < pipe->buffer_next_send ? 0 : IPC_BUFFER_PAGES * 4096), pipe->sender_handle, pipe->reader_handle); return pipe->sender_handle; + } return 0; } +__attribute__ ((pure)) struct ipc_pipe *get_existing_pipe(uint32_t sender_handle, uint32_t reader_handle) { for (struct ipc_pipe *i = ipc_pipes; i < ipc_pipes + MAX_IPC_PIPES; ++i) if (i->buffer && (i->sender_handle == sender_handle) && @@ -176,7 +187,7 @@ struct ipc_pipe *get_existing_pipe(uint32_t sender_handle, uint32_t reader_handl } uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) { - if (!reader_handle || !tasks[reader_handle - 1].page_directory) + if (!reader_handle || (reader_handle > MAX_TASKS) || !tasks[reader_handle - 1].page_directory) return -1; const uint32_t our_handle = active_task - tasks + 1; @@ -197,8 +208,8 @@ uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) { PANIC("out of ipc pipes"); } - unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_RECEIVE, .task = active_task}); - unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_RECEIVE_ANY}); + unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_SENT, .task = active_task}); + unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_SENT_ANY}); uint32_t send_left = pipe->buffer_next_read - pipe->buffer_next_send - 1; if (send_left < 0) @@ -220,17 +231,34 @@ uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) { } uint32_t ipc_read(uint32_t sender_handle, uint32_t count, void *buffer) { - if (!sender_handle || !tasks[sender_handle - 1].page_directory) +//logf(LOG_INFO, "kernel ipc_read(0x%hb, %u, 0x%h)", sender_handle, count, buffer); + if (!sender_handle || (sender_handle > MAX_TASKS)) return -1; const uint32_t our_handle = active_task - tasks + 1; - struct ipc_pipe *pipe = get_existing_pipe(sender_handle, our_handle); + struct ipc_pipe *const pipe = get_existing_pipe(sender_handle, our_handle); if (!pipe) - return 0; + return tasks[sender_handle - 1].page_directory ? 0 : -1; - unwait(tasks + sender_handle - 1, (struct wait){.mode = IPC_SEND, .task = active_task}); +//logf(LOG_INFO, "found pipe from 0x%hb to 0x%hb", pipe->sender_handle, pipe->reader_handle); - //TODO + unwait(tasks + sender_handle - 1, (struct wait){.mode = IPC_READ, .task = active_task}); + + uint8_t *write_to = buffer; + const uint8_t *read_from = pipe->buffer_next_read; + + //change this to memcpys like ipc_send once memcpy is more efficient + while ((read_from != pipe->buffer_next_send) && count--) { + *(write_to++) = *(read_from++); + if (read_from == pipe->buffer + IPC_BUFFER_PAGES * 4096) + read_from = pipe->buffer; + } + + if (pipe->delete_when_empty && (read_from == pipe->buffer_next_send)) + delete_pipe(pipe); + else + pipe->buffer_next_read = read_from; + return write_to - (uint8_t *)buffer; } void add_wait(struct wait wait) { @@ -257,12 +285,13 @@ void unwait(struct task_state *task, struct wait wait) { continue; switch (wait.mode) { case PROCESS_END: - case IPC_RECEIVE: + case IPC_SENT: + case IPC_READ: if (task->waits[i].task != wait.task) continue; break; case WINDOW_ACTION: - case IPC_RECEIVE_ANY: + case IPC_SENT_ANY: break; default: PANIC("Unwait matched with unrecognized wait mode."); @@ -272,4 +301,4 @@ void unwait(struct task_state *task, struct wait wait) { task->waiting = false; return; } -} \ No newline at end of file +} diff --git a/src/kernel/task.h b/src/kernel/task.h index 574dfa7..643c88e 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -4,17 +4,18 @@ #include #include -#define TASK_NAME_LEN 15 +#define TASK_NAME_LEN 86 #define MAX_WAITS 16 +#define MAX_TASKS 64 struct wait { enum { NONE, PROCESS_END, WINDOW_ACTION, - IPC_RECEIVE, - IPC_RECEIVE_ANY, - IPC_SEND + IPC_SENT, + IPC_SENT_ANY, + IPC_READ } mode; union { struct task_state *task; @@ -50,6 +51,7 @@ extern struct task_state *active_task; void init_tasks(); +//puts the handle into ecx uint32_t new_task(struct task_state state); void advance_active_task(); @@ -58,6 +60,6 @@ void delete_task(struct task_state *state); uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer); uint32_t ipc_read(uint32_t sender_handle, uint32_t count, void *buffer); -uint32_t find_unread_ipc(); +uint32_t find_unread_ipc() __attribute__ ((pure)); #endif \ No newline at end of file diff --git a/src/kernel/window.c b/src/kernel/window.c index 28798d1..078a194 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -99,7 +99,8 @@ got_window: return w; } -void del_window(struct window *w) { +static void del_no_paint(struct window *w) { +//logf(LOG_INFO, "-- deleting window 0x%h", w); if (w == top_window) top_window = w->below; if (w == bottom_window) @@ -109,17 +110,37 @@ void del_window(struct window *w) { if (w->above) w->above->below = w->below; +//logf(LOG_INFO, " -- action buffer was 0x%h", w->action_buffer); free_pages(w->action_buffer, ACTION_BUFFER_PAGES); w->pixel_buffer_pma = 0; +} +void del_window(struct window *w) { + del_no_paint(w); paint_all(); } -void resize_window(struct window *w, uint16_t width, uint16_t height) { +void delete_any_windows_from(struct task_state *tstate) { +//logf(LOG_INFO, "-- deleting windows from 0x%h", tstate); + bool need_to_paint = false; + for (struct window *w = windows; w < windows + MAX_WINDOWS; ++w) + if (w->pixel_buffer_pma && (w->from_task == tstate)) { + //logf(LOG_INFO, " -- found match at 0x%h", w); + del_no_paint(w); + need_to_paint = true; + } + if (need_to_paint) { + //logf(LOG_INFO, "-- trying to paint after deleting windows"); + paint_all(); + } +} + +void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer) { const bool smaller = (width < w->width) || (height < w->height); w->width = width; w->height = height; + reassign_pixel_buffer(w, pixel_buffer); if (smaller) paint_all(); diff --git a/src/kernel/window.h b/src/kernel/window.h index 60b81ea..0aa9b0f 100644 --- a/src/kernel/window.h +++ b/src/kernel/window.h @@ -5,6 +5,8 @@ #include +#include "task.h" + struct window; void paint_bg(); @@ -12,7 +14,7 @@ void paint_bg(); struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer); void del_window(struct window *w); -void resize_window(struct window *w, uint16_t width, uint16_t height); +void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer); void reassign_pixel_buffer(struct window *w, const void *pixel_buffer); void push_window_paint(const struct window *w); struct window_action next_window_action(struct window *w); @@ -20,4 +22,6 @@ void wait_window_action(); void on_action(struct window_action packet); +void delete_any_windows_from(struct task_state *tstate); + #endif -- cgit v1.2.3