summaryrefslogtreecommitdiff
path: root/kernel/ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/ipc.c')
-rw-r--r--kernel/ipc.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/kernel/ipc.c b/kernel/ipc.c
new file mode 100644
index 0000000..3422cc7
--- /dev/null
+++ b/kernel/ipc.c
@@ -0,0 +1,95 @@
+#include <assert.h>
+#include <ipc.h>
+#include <math.h>
+#include <sched/scheduler.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct IpcEndpoint {
+ u8 in_use;
+ u32 pid;
+};
+
+struct IpcEndpoint ipc_endpoints[100];
+
+bool ipc_register_endpoint(u32 endpoint) {
+ if (endpoint >= 100)
+ return false;
+ if (ipc_endpoints[endpoint].in_use)
+ return false;
+ ipc_endpoints[endpoint].in_use = 1;
+ ipc_endpoints[endpoint].pid = get_current_task()->pid;
+ return true;
+}
+
+bool ipc_endpoint_to_pid(u32 endpoint, u32 *pid) {
+ if (endpoint >= 100)
+ return false;
+ if (!ipc_endpoints[endpoint].in_use)
+ return false;
+ *pid = ipc_endpoints[endpoint].pid;
+ return true;
+}
+
+int ipc_get_mailbox(u32 id, struct IpcMailbox **out) {
+ process_t *p;
+ if (!get_task_from_pid(id, &p))
+ return 0;
+ *out = &p->ipc_mailbox;
+ return 1;
+}
+
+int ipc_read(u8 *buffer, u32 length, u32 *sender_pid) {
+ struct IpcMailbox *handler = &get_current_task()->ipc_mailbox;
+
+ u32 read_ptr = handler->read_ptr;
+ struct IpcMessage *ipc_message = NULL;
+ for (;;) {
+ ipc_message = &handler->data[read_ptr];
+ if (!ipc_message->is_used) {
+ asm("sti");
+ continue;
+ }
+ break;
+ }
+ ipc_message->is_used = 0;
+ // TODO: Verify sender_pid is a valid address
+ if (sender_pid)
+ *sender_pid = ipc_message->sender_pid;
+
+ u32 len = min(length, ipc_message->size);
+ memcpy(buffer, ipc_message->buffer, len);
+
+ // Update read_ptr
+ read_ptr++;
+ if (read_ptr >= IPC_NUM_DATA)
+ read_ptr = 0;
+ handler->read_ptr = read_ptr;
+ return len;
+}
+
+int ipc_write_to_process(int pid, u8 *buffer, u32 length) {
+ struct IpcMailbox *handler;
+ assert(ipc_get_mailbox(pid, &handler));
+
+ u32 write_ptr = handler->write_ptr;
+ struct IpcMessage *ipc_message = &handler->data[write_ptr];
+ ipc_message->is_used = 1;
+ u32 len = min(IPC_BUFFER_SIZE, length);
+ ipc_message->sender_pid = get_current_task()->pid;
+ ipc_message->size = len;
+ memcpy(ipc_message->buffer, buffer, len);
+
+ // Update write_ptr
+ write_ptr++;
+ if (write_ptr >= IPC_NUM_DATA)
+ write_ptr = 0;
+ handler->write_ptr = write_ptr;
+ return len;
+}
+
+int ipc_write(int endpoint, u8 *buffer, u32 length) {
+ u32 pid;
+ assert(ipc_endpoint_to_pid(endpoint, &pid));
+ return ipc_write_to_process(pid, buffer, length);
+}