diff options
author | Anton Kling <anton@kling.gg> | 2023-10-30 20:46:36 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-10-30 21:49:48 +0100 |
commit | ecf1e4c6c6efc3edeb006ff120ac60a191ddce50 (patch) | |
tree | db5e312704d43ec8ff0a81bc87c9a1cdf6b01970 /sched | |
parent | c7a07bf214ef9b3fabc15c8e70f696ede9644c2c (diff) |
Kernel/LibC: Add signals and support for custom signal handlers to processes.
Diffstat (limited to 'sched')
-rw-r--r-- | sched/scheduler.c | 65 | ||||
-rw-r--r-- | sched/scheduler.h | 12 |
2 files changed, 68 insertions, 9 deletions
diff --git a/sched/scheduler.c b/sched/scheduler.c index ed85f9b..a6ace7d 100644 --- a/sched/scheduler.c +++ b/sched/scheduler.c @@ -19,6 +19,14 @@ extern uint32_t read_eip(void); process_t *get_current_task(void) { return current_task; } +void set_signal_handler(int sig, void (*handler)(int)) { + if (sig >= 20 || sig < 0) + return; + if (9 == sig) + return; + current_task->signal_handlers[sig] = handler; +} + process_t *create_process(process_t *p) { process_t *r; r = ksbrk(sizeof(process_t)); @@ -37,9 +45,15 @@ process_t *create_process(process_t *p) { r->cr3 = (p) ? clone_directory(get_active_pagedirectory()) : get_active_pagedirectory(); r->next = 0; + r->incoming_signal = 0; r->parent = p; r->child = NULL; r->halt_list = NULL; + + mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW, + r->cr3); + r->signal_handler_stack = 0x80000000; + strcpy(r->current_working_directory, "/"); r->data_segment_end = (p) ? p->data_segment_end : NULL; memset((void *)r->halts, 0, 2 * sizeof(uint32_t)); @@ -50,6 +64,8 @@ process_t *create_process(process_t *p) { r->file_descriptors[i]->reference_count++; } } + if (i < 20) + r->signal_handlers[i] = NULL; r->read_halt_inode[i] = NULL; r->write_halt_inode[i] = NULL; r->disconnect_halt_inode[i] = NULL; @@ -132,7 +148,8 @@ void exit(int status) { } uint32_t setup_stack(uint32_t stack_pointer, int argc, char **argv) { - mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW); + mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW, + NULL); flush_tlb(); uint32_t ptr = stack_pointer; @@ -244,6 +261,8 @@ process_t *next_task(process_t *c) { c = c->next; if (!c) c = ready_queue; + if (c->incoming_signal) + break; if (c->sleep_until > pit_num_ms()) continue; if (is_halted(c) || c->dead) @@ -271,6 +290,25 @@ int task_save_state(void) { return 1; } +int kill(pid_t pid, int sig) { + process_t *p = current_task; + p = p->next; + if (!p) + p = ready_queue; + for (; p->pid != pid;) { + if (p == current_task) + break; + p = p->next; + if (!p) + p = ready_queue; + } + if (p->pid != pid) + return -ESRCH; + p->incoming_signal = sig; + return 0; +} + +void jump_signal_handler(void *func, uint32_t esp); void switch_task() { if (!current_task) return; @@ -283,15 +321,32 @@ void switch_task() { active_directory = current_task->cr3; - asm(" \ + if (current_task->incoming_signal) { + uint8_t sig = current_task->incoming_signal; + current_task->incoming_signal = 0; + asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address)); + + void *handler = current_task->signal_handlers[sig]; + if (9 == sig) { + klog("Task recieved SIGKILL", LOG_NOTE); + exit(0); + } + if (!handler) { + klog("Task recieved unhandeled signal. Killing process.", LOG_WARN); + exit(1); + } + jump_signal_handler(handler, current_task->signal_handler_stack); + } else { + asm(" \ mov %0, %%esp; \ mov %1, %%ebp; \ mov %2, %%ecx; \ mov %3, %%cr3; \ mov $0x1, %%eax; \ jmp *%%ecx" ::"r"(current_task->esp), - "r"(current_task->ebp), "r"(current_task->eip), - "r"(current_task->cr3->physical_address)); + "r"(current_task->ebp), "r"(current_task->eip), + "r"(current_task->cr3->physical_address)); + } } MemoryMap **get_free_map(void) { @@ -318,7 +373,7 @@ void *allocate_virtual_user_memory(size_t length, int prot, int flags) { if ((void *)-1 == rc) return (void *)-1; - mmu_allocate_region(rc, length, MMU_FLAG_RW); + mmu_allocate_region(rc, length, MMU_FLAG_RW, NULL); return rc; } diff --git a/sched/scheduler.h b/sched/scheduler.h index 7df7c40..fc92ff3 100644 --- a/sched/scheduler.h +++ b/sched/scheduler.h @@ -4,6 +4,7 @@ #include <fs/vfs.h> #include <halts.h> #include <mmu.h> +#include <signal.h> #define MAX_PATH 256 #define KEYBOARD_HALT 0 @@ -19,6 +20,8 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset); int munmap(void *addr, size_t length); int msync(void *addr, size_t length, int flags); +int kill(pid_t pid, int sig); +void set_signal_handler(int sig, void (*handler)(int)); typedef struct { void *u_address; @@ -34,25 +37,26 @@ struct Process { char program_name[100]; char current_working_directory[MAX_PATH]; uint32_t eip, esp, ebp; + uint8_t incoming_signal; + uint32_t signal_handler_stack; + void *signal_handlers[20]; PageDirectory *cr3; vfs_fd_t *file_descriptors[100]; vfs_inode_t *read_halt_inode[100]; vfs_inode_t *write_halt_inode[100]; vfs_inode_t *disconnect_halt_inode[100]; - // struct vfs_fd_t ** file_descriptors; uint32_t halts[2]; struct Halt *halt_list; void *data_segment_end; - // uint32_t *halts; process_t *next; process_t *parent; + // TODO: Create a linkedlist of childs so that the parent process + // can do stuff such as reap zombies and get status. process_t *child; MemoryMap *maps[100]; uint32_t sleep_until; int child_rc; int dead; - // FIXME: Create a linkedlisti of childs so that the parent process - // can do stuff such as reap zombies and get status. }; process_t *get_current_task(void); |