diff --git a/TODO b/TODO index 83f6358..f65783e 100644 --- a/TODO +++ b/TODO @@ -25,7 +25,8 @@ TODO [x] Scheduler [ ] Priority scheduler [x] Task switching -[ ] Inter-process communication +[ ] Interprocess communication +[ ] ALL the message types [ ] Graphics [ ] Multicore support [ ] Networking :) diff --git a/docs/unix-syscalls.txt b/docs/unix-syscalls.txt new file mode 100644 index 0000000..f956d21 --- /dev/null +++ b/docs/unix-syscalls.txt @@ -0,0 +1,62 @@ +Unix-like system calls +====================== + +pid_t fork(void); +Creates a child process. + +void exit(int status); +Terminate the calling process. + +pid_t waitpid(pid_t pid); +Wait untill a process changes state. + +int kill(pid_t, int sig); +Send a signal to a process. + +pid_t getpid(void); +Get PID of calling process. + +void sleep(size_t t); +Sleep for **t** clock ticks. + +int exec(char* path, char** argv); +Execute a program. + +int brk(void* addr); +Change data segment size. + +int open(char* path, int flags); +Open and possibly create a file. + +int close(int fd); +Close a file descriptor. + +ssize_t read(int fd, void* buf, size_t count); +Read up to **count** bytes into **buf**. + +ssize_t write(int fd, void* buf, size_t count); +Write up to **count** bytes from **buf**. + +int dup(int oldfd); +Duplicate a file descriptor. + +int pipe(int pipe[2]); +Create a pipe and return it's file descriptors in **pipe**. + +int chdir(char* path); +Change the current directory of calling process. + +int mkdir(char* path); +Create a new directory. + +int mknod(char* path, int maj, int min); +Create a new device file. + +int link(char* f1, char* f2); +Creates another filename (**f2**) for **f1**. + +int unlink(char* path); +Delete a filename. + +int fstat(int fd, struct stat* statbuf); +Return info about a file. diff --git a/kernel/include/ipc.h b/kernel/include/ipc.h new file mode 100644 index 0000000..afeafe7 --- /dev/null +++ b/kernel/include/ipc.h @@ -0,0 +1,51 @@ +#ifndef _IPC_H +#define _IPC_H + +#include + +/* + * Message contents + */ + +// Basic data +struct msg_uint8 { uint8_t data[56]; }; +struct msg_uint16 { uint16_t data[28]; }; +struct msg_uint32 { uint32_t data[14]; }; +struct msg_uint64 { uint64_t data[7]; }; + +/* + * Message content types + */ +enum { + MSG_UINT8, + MSG_UINT16, + MSG_UINT32, + MSG_UINT64, +}; + +/* + * Message struct + */ +typedef struct { + pid_t sender; + uint32_t type; + union { + struct msg_uint8 m_uint8; + struct msg_uint16 m_uint16; + struct msg_uint32 m_uint32; + struct msg_uint64 m_uint64; + + // Makes sure that ipc_msg_t is at least 64 bytes + uint8_t size[56]; + }; +} ipc_msg_t __align(16); +// Compile time check that ipc_msg_t is 64 bytes +typedef int __ASSERT_ipc_msg_t[(sizeof(ipc_msg_t) == 64) ? 1 : -1]; + +/* + * IPC handlers + */ +int ipc_send(pid_t dst, ipc_msg_t* msg); +int ipc_recv(pid_t src, ipc_msg_t* msg); + +#endif diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index 0c9b4bf..81e5064 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -30,6 +30,9 @@ typedef char* va_list; /* * Utility macros */ +#define STATIC_ASSERT(_cond, _msg)\ + typedef int static_assert_##_msg[(_cond) ? 1 : -1] + #define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0])) #define BIT(_n) (1UL << (_n)) #define BIT_MASK(_n) (BIT(_n) - 1) @@ -84,6 +87,11 @@ typedef int32_t intptr_t; #define true 1 #define false 0 +/* + * System types + */ +typedef uint32_t pid_t; + /* * Linker defined values */ diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index e060c53..6584cba 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -2,14 +2,21 @@ #define _SYSCALL_H #include +#include #include -#define SYSCALL_MAX 2 -#define SYS_EXIT 0 -#define SYS_TEST 1 +#define SYSCALL_MAX 16 +enum { + SYS_SEND, + SYS_RECV, +}; int syscall_init(void); void syscall_register(size_t idx, void* handler); void syscall_handler(struct isr_int_frame* iframe); +// Syscall handlers +int sys_send(pid_t dst, ipc_msg_t* msg); +int sys_recv(pid_t src, ipc_msg_t* msg); + #endif diff --git a/kernel/include/task.h b/kernel/include/task.h index 4183618..1d091bc 100644 --- a/kernel/include/task.h +++ b/kernel/include/task.h @@ -9,6 +9,7 @@ enum { TASK_STATE_DEAD, TASK_STATE_IDLE, TASK_STATE_READY, + TASK_STATE_RECV, }; /* @@ -30,7 +31,7 @@ enum { * task.s which uses hardcoded offsets. */ struct task { - size_t id; + pid_t id; size_t kstack_pointer; size_t kstack_bottom; @@ -58,13 +59,13 @@ extern struct task* task_first; extern struct task* task_current; int task_init(void); -void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv); -void task_kill(size_t id); -void task_set_user_heap(struct task* task, size_t heap_end); -struct task* task_get(size_t id); -uint8_t task_get_state(size_t id); -void task_set_state(size_t id, uint8_t state); -size_t task_create_id(void); +void task_create(pid_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv); +void task_kill(pid_t id); +void task_set_user_heap(pid_t id, size_t heap_end); +struct task* task_get(pid_t id); +uint8_t task_get_state(pid_t id); +void task_set_state(pid_t id, uint8_t state); +pid_t task_create_id(void); // Defined in task.s extern void task_switch(struct task* old, struct task* new); diff --git a/kernel/src/ipc.c b/kernel/src/ipc.c new file mode 100644 index 0000000..25937dc --- /dev/null +++ b/kernel/src/ipc.c @@ -0,0 +1,16 @@ +#include + +#include + +int ipc_send(pid_t dst, ipc_msg_t* msg) { + (void)dst; + (void)msg; + return 0; +} + +int ipc_recv(pid_t src, ipc_msg_t* msg) { + (void)src; + (void)msg; + return 0; +} + diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index b29b1b4..de5c0fc 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -36,10 +36,6 @@ void kmain(void* ptr, uint32_t magic) { if (syscall_init() != 0) panic("Failed to initialize syscalls."); if (task_init() != 0) panic("Failed to initialize tasking."); - char* s = "Hello, World!"; - __asm__ volatile("int $0x80" :: "a"(SYS_TEST), "b"(s)); - - // TODO: Interprocess communication // TODO: Load & run /sbin/init // We don't want to halt diff --git a/kernel/src/syscall.c b/kernel/src/syscall.c index e5cdb3b..2a3c626 100644 --- a/kernel/src/syscall.c +++ b/kernel/src/syscall.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -7,24 +8,26 @@ // Syscall table void* syscalls[SYSCALL_MAX] = { 0 }; -void sys_exit(int code) { - debugf("[syscall] Task #%d exited with code %d.\n", task_current->id, code); - task_kill(task_current->id); -} - -void sys_test(char* msg) { - debugf("[syscall] Test: %s\n", msg); -} - int syscall_init(void) { - syscall_register(SYS_EXIT, (void*)sys_exit); - syscall_register(SYS_TEST, (void*)sys_test); + syscall_register(SYS_SEND, (void*)sys_send); + syscall_register(SYS_RECV, (void*)sys_recv); debugf("[syscall] Initiated syscalls!\n"); return 0; } +int sys_send(pid_t dst, ipc_msg_t* msg) { + msg->sender = task_current->id; + debugf("[syscall] Task #%d sent a message to Task #%d.\n", msg->sender, dst); + return ipc_send(dst, msg); +} + +int sys_recv(pid_t src, ipc_msg_t* msg) { + debugf("[syscall] Task #%d is receiving a message from Task #%d.\n", task_current->id, src); + return 0; +} + void syscall_register(size_t idx, void* handler) { if (idx > SYSCALL_MAX) { debugf("[syscall] Failed to register syscall #%d.\n", idx); diff --git a/kernel/src/task.c b/kernel/src/task.c index 60cd290..266cdd9 100644 --- a/kernel/src/task.c +++ b/kernel/src/task.c @@ -32,7 +32,7 @@ int task_init(void) { return 0; } -void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv) { +void task_create(pid_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv) { cli(); uint32_t kstack = (uint32_t)kmalloc(0x1000 - 16) + (0x1000 - 16); @@ -129,7 +129,7 @@ void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, in pag_set_pagedir(old_pagedir); } -void task_kill(size_t id) { +void task_kill(pid_t id) { cli(); struct task* current = task_first; @@ -174,7 +174,9 @@ void task_kill(size_t id) { sti(); } -void task_set_user_heap(struct task* task, size_t heap_end) { +void task_set_user_heap(pid_t id, size_t heap_end) { + struct task* task = task_get(id); + if (heap_end <= task->heap_start) { debugf("[task] Task %d tried to shrink heap bellow 0.\n", task->id); task_kill(task->id); @@ -212,7 +214,7 @@ void task_set_user_heap(struct task* task, size_t heap_end) { task->heap_end = heap_end; } -struct task* task_get(size_t id) { +struct task* task_get(pid_t id) { struct task* find = task_first; while (find != NULL) { if (find->id == id) break; @@ -222,22 +224,22 @@ struct task* task_get(size_t id) { return find; } -uint8_t task_get_state(size_t id) { +uint8_t task_get_state(pid_t id) { struct task* t = task_get(id); if (t == NULL) return TASK_STATE_DEAD; return t->state; } -void task_set_state(size_t id, uint8_t state) { +void task_set_state(pid_t id, uint8_t state) { struct task* t = task_get(id); if (t == NULL) return; t->state = state; } -size_t task_create_id(void) { +pid_t task_create_id(void) { struct task* current = task_first; - size_t max = current->id; + pid_t max = current->id; current = current->next; while (current != NULL) { if (max < current->id) max = current->id;