summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-03-26 11:40:39 +0100
committerAnton Kling <anton@kling.gg>2024-03-26 11:40:39 +0100
commit297231bb3602d868d3891d357026c53f9fcc2402 (patch)
tree6c4f21db84912750f6f464b26bf1e4503d1fe479 /kernel
parent3deb2df8e62a5f0a5535ee734a5aa13b0959f53f (diff)
Increase support for signals
Diffstat (limited to 'kernel')
-rw-r--r--kernel/arch/i386/mmu.c4
-rw-r--r--kernel/cpu/syscall.c8
-rw-r--r--kernel/fs/vfs.c12
-rw-r--r--kernel/fs/vfs.h1
-rw-r--r--kernel/includes/mmu.h2
-rw-r--r--kernel/includes/signal.h1
-rw-r--r--kernel/network/tcp.c2
-rw-r--r--kernel/queue.c7
-rw-r--r--kernel/sched/scheduler.c72
-rw-r--r--kernel/sched/scheduler.h4
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