diff options
author | Anton Kling <anton@kling.gg> | 2024-03-26 11:40:39 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-03-26 11:40:39 +0100 |
commit | 297231bb3602d868d3891d357026c53f9fcc2402 (patch) | |
tree | 6c4f21db84912750f6f464b26bf1e4503d1fe479 /kernel | |
parent | 3deb2df8e62a5f0a5535ee734a5aa13b0959f53f (diff) |
Increase support for signals
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/arch/i386/mmu.c | 4 | ||||
-rw-r--r-- | kernel/cpu/syscall.c | 8 | ||||
-rw-r--r-- | kernel/fs/vfs.c | 12 | ||||
-rw-r--r-- | kernel/fs/vfs.h | 1 | ||||
-rw-r--r-- | kernel/includes/mmu.h | 2 | ||||
-rw-r--r-- | kernel/includes/signal.h | 1 | ||||
-rw-r--r-- | kernel/network/tcp.c | 2 | ||||
-rw-r--r-- | kernel/queue.c | 7 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 72 | ||||
-rw-r--r-- | kernel/sched/scheduler.h | 4 |
10 files changed, 74 insertions, 39 deletions
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c index 9b63a9a..7147c74 100644 --- a/kernel/arch/i386/mmu.c +++ b/kernel/arch/i386/mmu.c @@ -394,10 +394,10 @@ void *allocate_frame(Page *page, int rw, int is_kernel) { return (void *)(frame_address * 0x1000); } -void mmu_free_address_range(void *ptr, size_t length) { +void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd) { size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE; for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) { - Page *page = get_page(ptr, NULL, PAGE_NO_ALLOCATE, 0); + Page *page = get_page(ptr, pd, PAGE_NO_ALLOCATE, 0); if (!page) { continue; } diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c index 7734f4e..d47f858 100644 --- a/kernel/cpu/syscall.c +++ b/kernel/cpu/syscall.c @@ -87,9 +87,17 @@ void syscall_wait(int *status) { return; } do { + current_task->is_halted = 1; current_task->halts[WAIT_CHILD_HALT] = 1; switch_task(); + if (current_task->is_interrupted) { + break; + } } while (current_task->halts[WAIT_CHILD_HALT]); + if (current_task->is_interrupted) { + current_task->is_interrupted = 0; + return; + } if (status) { *status = current_task->child_rc; } diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 143dc9d..f2b763c 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -292,15 +292,15 @@ int vfs_open(const char *file, int flags, int mode) { return vfs_create_fd(flags, mode, 0 /*is_tty*/, inode, NULL); } -int vfs_close(int fd) { - vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL); +int vfs_close_process(process_t *p, int fd) { + vfs_fd_t *fd_ptr = get_vfs_fd(fd, p); if (NULL == fd_ptr) { return -1; } assert(0 < fd_ptr->reference_count); // Remove process reference fd_ptr->reference_count--; - current_task->file_descriptors[fd] = 0; + p->file_descriptors[fd] = 0; // If no references left then free the contents if (0 == fd_ptr->reference_count) { if (fd_ptr->inode->close) { @@ -312,6 +312,10 @@ int vfs_close(int fd) { return 0; } +int vfs_close(int fd) { + return vfs_close_process(current_task, fd); +} + int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset) { if (!(vfs_fd->flags & O_READ)) { return -EBADF; @@ -380,7 +384,7 @@ vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset) { return NULL; } assert(vfs_fd->inode); - if(!vfs_fd->inode->get_vm_object) { + if (!vfs_fd->inode->get_vm_object) { return NULL; } vfs_vm_object_t *r = vfs_fd->inode->get_vm_object(length, offset, vfs_fd); diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 74e5bf4..8e61e11 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -71,6 +71,7 @@ struct vfs_inode { }; int vfs_close(int fd); +int vfs_close_process(process_t *p, int fd); vfs_fd_t *get_vfs_fd(int fd, process_t *p); int vfs_open(const char *file, int flags, int mode); void vfs_mount(char *path, vfs_inode_t *local_root); diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h index 1a3f7c9..9a27c5b 100644 --- a/kernel/includes/mmu.h +++ b/kernel/includes/mmu.h @@ -37,7 +37,7 @@ int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, void mmu_allocate_shared_kernel_region(void *rc, size_t n); void *mmu_find_unallocated_virtual_range(void *addr, size_t length); void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length); -void mmu_free_address_range(void *ptr, size_t length); +void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd); void mmu_map_directories(void *dst, PageDirectory *d, void *src, PageDirectory *s, size_t length); u32 mmu_get_number_of_allocated_frames(void); diff --git a/kernel/includes/signal.h b/kernel/includes/signal.h index 7e9dd9c..b9ab4a7 100644 --- a/kernel/includes/signal.h +++ b/kernel/includes/signal.h @@ -6,6 +6,7 @@ #define SIGWINCH 2 #define SIGQUIT 3 #define SIG_IGN 4 +#define SIGTERM 15 typedef int sigset_t; union sigval { diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c index dd6e6a8..1a3641b 100644 --- a/kernel/network/tcp.c +++ b/kernel/network/tcp.c @@ -54,7 +54,7 @@ void tcp_wait_reply(struct TcpConnection *con) { if (con->unhandled_packet) { return; } - wait_for_interrupt(); + switch_task(); } } diff --git a/kernel/queue.c b/kernel/queue.c index d77af85..b1cf698 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -50,18 +50,14 @@ int queue_should_block(struct event_queue *q, int *is_empty) { if (!list_get(&q->events, i, (void **)&ev)) { break; } - kprintf("wait %d\n", i); *is_empty = 0; if (EVENT_TYPE_FD == ev->type) { - kprintf("found fd: %d\n", ev->internal_id); vfs_fd_t *fd = get_vfs_fd(ev->internal_id, q->p); - kprintf("fd->inode->has_data: %x\n", fd->inode->has_data); if (!fd) { kprintf("queue: Invalid fd given\n"); continue; } if (fd->inode->has_data) { - kprintf("no block\n"); return 0; } } else if (EVENT_TYPE_TCP_SOCKET == ev->type) { @@ -69,10 +65,7 @@ int queue_should_block(struct event_queue *q, int *is_empty) { assert(con); assert(con->data_file); if (con->data_file->has_data) { - kprintf("has data\n"); return 0; - } else { - kprintf("blocking queue\n"); } } } diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c index ebf2c32..7afd203 100644 --- a/kernel/sched/scheduler.c +++ b/kernel/sched/scheduler.c @@ -8,6 +8,7 @@ #include <fs/vfs.h> #include <interrupts.h> #include <queue.h> +#include <signal.h> // FIXME: Use the process_t struct instead or keep this contained in it. TCB *current_task_TCB; @@ -188,8 +189,7 @@ void tasking_init(void) { } int i = 0; -void free_process(void) { - process_t *p = current_task; +void free_process(process_t *p) { kprintf("pid: %x\n", p->pid); kprintf("Exiting process: %s\n", p->program_name); // free_process() will purge all contents such as allocated frames @@ -199,53 +199,57 @@ void free_process(void) { // Do a special free for shared memory which avoids labeling // underlying frames as "unused". for (int i = 0; i < 100; i++) { - vfs_close(i); - if (!current_task->maps[i]) { + vfs_close_process(p, i); + if (!p->maps[i]) { continue; } - MemoryMap *m = current_task->maps[i]; + MemoryMap *m = p->maps[i]; mmu_remove_virtual_physical_address_mapping(m->u_address, m->length); } // NOTE: Kernel stuff begins at 0x90000000 - mmu_free_address_range((void *)0x1000, 0x90000000); + mmu_free_address_range((void *)0x1000, 0x90000000, p->cr3); list_free(&p->read_list); list_free(&p->write_list); list_free(&p->disconnect_list); } -void exit(int status) { - assert(current_task->pid != 1); - if (current_task->parent) { - current_task->parent->halts[WAIT_CHILD_HALT] = 0; - current_task->parent->child_rc = status; +void exit_process(process_t *p, int status) { + assert(p->pid != 1); + if (p->parent) { + p->parent->halts[WAIT_CHILD_HALT] = 0; + p->parent->child_rc = status; } - process_t *new_task = current_task; - for (; new_task == current_task;) { + process_t *new_task = p; + for (; new_task == p;) { if (!new_task->next) { new_task = ready_queue; } new_task = new_task->next; } - free_process(); + free_process(p); + p->dead = 1; // Remove current_task from list for (process_t *tmp = ready_queue; tmp;) { - if (tmp == current_task) // current_task is ready_queue(TODO: - // Figure out whether this could even - // happen) + if (tmp == p) // current_task is ready_queue(TODO: + // Figure out whether this could even + // happen) { - ready_queue = current_task->next; + ready_queue = p->next; break; } - if (tmp->next == current_task) { + if (tmp->next == p) { tmp->next = tmp->next->next; break; } tmp = tmp->next; } - current_task->dead = 1; +} + +void exit(int status) { + exit_process(current_task, status); switch_task(); } @@ -434,13 +438,20 @@ process_t *next_task(process_t *s) { if (!c) { c = ready_queue; } + if (c->is_interrupted) { + break; + } if (s == c) { - wait_for_interrupt(); + // wait_for_interrupt(); } if (c->sleep_until > pit_num_ms()) { continue; } - if (is_halted(c) || c->dead) { + if (c->dead) { + kprintf("dead process\n"); + continue; + } + if (is_halted(c)) { continue; } break; @@ -448,6 +459,22 @@ process_t *next_task(process_t *s) { return c; } +void signal_process(process_t *p, int sig) { + assert(sig < 32); + kprintf("sending signal to: %x\n", p); + if (!p->signal_handlers[sig]) { + if (SIGTERM == sig) { + kprintf("HAS NO SIGTERM\n"); + exit_process(p, 1 /*TODO: what should the status be?*/); + } else { + // TODO: Should also exit proess(I think) + assert(0); + } + } + signal_t signal = {.handler_ip = (uintptr_t)p->signal_handlers[sig]}; + process_push_signal(p, signal); +} + int kill(pid_t pid, int sig) { process_t *p = current_task; p = p->next; @@ -466,6 +493,7 @@ int kill(pid_t pid, int sig) { if (p->pid != pid) { return -ESRCH; } + signal_process(p, sig); return 0; } diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h index 175f3ce..fbaed3e 100644 --- a/kernel/sched/scheduler.h +++ b/kernel/sched/scheduler.h @@ -56,7 +56,7 @@ struct Process { u32 pid; char program_name[100]; char current_working_directory[MAX_PATH]; - void *signal_handlers[20]; + void *signal_handlers[32]; void *interrupt_handler; PageDirectory *cr3; struct IpcMailbox ipc_mailbox; @@ -96,6 +96,6 @@ struct Process { bool get_task_from_pid(u32 pid, process_t **out); int get_free_fd(process_t *p, int allocate); -void free_process(void); +void free_process(process_t *p); void *get_free_virtual_memory(size_t length); #endif |