summaryrefslogtreecommitdiff
path: root/src/kernel/task.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/task.c')
-rw-r--r--src/kernel/task.c101
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
+}