diff options
Diffstat (limited to 'src/kernel/task.c')
-rw-r--r-- | src/kernel/task.c | 101 |
1 files changed, 65 insertions, 36 deletions
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 +} |