summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-27 15:26:39 +0200
committerAnton Kling <anton@kling.gg>2024-04-27 15:26:39 +0200
commit02c27583a539c4e8073509536d328581cf1ba346 (patch)
tree67c8de59e04b118116f039e724be3ee9268b507f /kernel
parent7ab3153f92f38223157c4c1f4af1c30e33c94a76 (diff)
Kernel: Make file descriptor numbers reusable.
Instead of using the "append only" list it now uses "relist" which allows for indexes to be removed.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/drivers/mouse.c2
-rw-r--r--kernel/fs/ext2.c2
-rw-r--r--kernel/fs/vfs.c10
-rw-r--r--kernel/lib/relist.c120
-rw-r--r--kernel/lib/relist.h19
-rw-r--r--kernel/sched/scheduler.c8
-rw-r--r--kernel/sched/scheduler.h3
-rw-r--r--kernel/socket.c2
9 files changed, 154 insertions, 14 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index ffa835a..240f7df 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,6 +1,6 @@
CC="i686-sb-gcc"
AS="i686-sb-as"
-OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o queue.o syscalls/queue.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o queue.o syscalls/queue.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o lib/relist.o
CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
LDFLAGS=
INCLUDE=-I./includes/ -I../include/ -I./libc/include/
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
index 93e3be6..af13b44 100644
--- a/kernel/drivers/mouse.c
+++ b/kernel/drivers/mouse.c
@@ -42,7 +42,7 @@ void add_mouse(void) {
// Don't look at this
int fd = vfs_open("/dev/mouse", O_RDWR, 0);
mouse_fd = get_vfs_fd(fd, NULL);
- list_set(&current_task->file_descriptors, fd, NULL);
+ relist_remove(&current_task->file_descriptors, fd);
}
void what(registers_t *r) {
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index db947c0..613cf53 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -814,7 +814,7 @@ vfs_inode_t *ext2_mount(void) {
mount_fd = get_vfs_fd(fd, NULL);
// Remove the FD from the current task
// FIXME: This is a hacky solution
- list_set(&current_task->file_descriptors, fd, NULL);
+ relist_remove(&current_task->file_descriptors, fd);
parse_superblock();
return vfs_create_inode(
0 /*inode_num*/, 0 /*type*/, 0 /*has_data*/, 0 /*can_write*/,
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 63db938..16f9186 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -18,7 +18,7 @@ vfs_fd_t *get_vfs_fd(int fd, process_t *p) {
}
vfs_fd_t *r;
- if (!list_get(&p->file_descriptors, fd, (void **)&r)) {
+ if (!relist_get(&p->file_descriptors, fd, (void **)&r)) {
return NULL;
}
return r;
@@ -73,7 +73,7 @@ int vfs_create_fd(int flags, int mode, int is_tty, vfs_inode_t *inode,
*fd = r;
}
int index;
- list_add(&current_task->file_descriptors, r, &index);
+ relist_add(&current_task->file_descriptors, r, &index);
return index;
}
@@ -294,7 +294,7 @@ int vfs_close_process(process_t *p, int fd) {
assert(0 < fd_ptr->reference_count);
// Remove process reference
fd_ptr->reference_count--;
- list_set(&p->file_descriptors, fd, NULL);
+ assert(relist_remove(&p->file_descriptors, fd));
// If no references left then free the contents
if (0 == fd_ptr->reference_count) {
if (fd_ptr->inode->close) {
@@ -411,12 +411,12 @@ vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset) {
int vfs_dup2(int org_fd, int new_fd) {
vfs_fd_t *orig;
- if (!list_get(&current_task->file_descriptors, org_fd, (void **)&orig)) {
+ if (!relist_get(&current_task->file_descriptors, org_fd, (void **)&orig)) {
assert(0);
return -1;
}
assert(1 <= orig->reference_count);
- if (!list_set(&current_task->file_descriptors, new_fd, orig)) {
+ if (!relist_set(&current_task->file_descriptors, new_fd, orig)) {
assert(0);
return -1;
}
diff --git a/kernel/lib/relist.c b/kernel/lib/relist.c
new file mode 100644
index 0000000..6ad30d2
--- /dev/null
+++ b/kernel/lib/relist.c
@@ -0,0 +1,120 @@
+#include <assert.h>
+#include <kmalloc.h>
+#include <lib/relist.h>
+
+void relist_init(struct relist *list) {
+ list->bitmap_capacity = 100;
+ list->bitmap = kcalloc(sizeof(u64), list->bitmap_capacity);
+ if (!list->bitmap) {
+ goto relist_init_error;
+ }
+ list->entries = kallocarray(sizeof(void *), (sizeof(u64) * 8));
+ if (!list->entries) {
+ goto relist_init_error;
+ }
+ return;
+
+// Can't allocate now but future appends can try to allocate anyways so
+// there is no reason to "fail" the init.
+relist_init_error:
+ list->bitmap_capacity = 0;
+ list->entries = NULL;
+ list->bitmap = NULL;
+ return;
+}
+
+void relist_reset(struct relist *list) {
+ memset(list->bitmap, 0, list->bitmap_capacity * sizeof(u64));
+}
+
+int relist_clone(struct relist *in, struct relist *out) {
+ relist_init(out);
+ for (int i = 0;; i++) {
+ void *output;
+ if (!relist_get(in, i, &output)) {
+ break;
+ }
+ if (!relist_add(out, output, NULL)) {
+ relist_free(out);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int relist_find_free_entry(struct relist *list, u32 *entry) {
+ for (u32 i = 0; i < list->bitmap_capacity; i++) {
+ if (0 == ~(list->bitmap[i])) {
+ continue;
+ }
+
+ for (int c = 0; c < 64; c++) {
+ if (!(list->bitmap[i] & ((u64)1 << c))) {
+ *entry = i * 64 + c;
+ return 1;
+ }
+ }
+ }
+ *entry = 0;
+ return 0;
+}
+
+int relist_add(struct relist *list, void *value, u32 *index) {
+ u32 entry;
+ if (!relist_find_free_entry(list, &entry)) {
+ assert(0);
+ }
+ list->entries[entry] = value;
+ if (index) {
+ *index = entry;
+ }
+ list->bitmap[entry / 64] |= ((u64)1 << (entry % 64));
+ return 1;
+}
+
+int relist_remove(struct relist *list, u32 index) {
+ if ((index / 64) > list->bitmap_capacity) {
+ assert(0);
+ return 0;
+ }
+ int is_used = (list->bitmap[index / 64] & ((u64)1 << (index % 64)));
+ if (!is_used) {
+ assert(0);
+ return 0;
+ }
+ list->bitmap[index / 64] &= ~((u64)1 << (index % 64));
+ return 1;
+}
+
+int relist_set(struct relist *list, u32 index, void *value) {
+ assert(value);
+ if ((index / 64) > list->bitmap_capacity) {
+ assert(0);
+ return 0;
+ }
+ int is_used = (list->bitmap[index / 64] & ((u64)1 << (index % 64)));
+ assert(is_used);
+ list->entries[index] = value;
+ return 1;
+}
+
+int relist_get(const struct relist *list, u32 index, void **out) {
+ if ((index / 64) > list->bitmap_capacity) {
+ assert(0);
+ return 0;
+ }
+ int is_used = (list->bitmap[index / 64] & ((u64)1 << (index % 64)));
+ if (!is_used) {
+ return 0;
+ }
+ *out = list->entries[index];
+ return 1;
+}
+
+void relist_free(struct relist *list) {
+ list->bitmap_capacity = 0;
+ kfree(list->entries);
+ kfree(list->bitmap);
+ list->entries = NULL;
+ list->bitmap = NULL;
+}
diff --git a/kernel/lib/relist.h b/kernel/lib/relist.h
new file mode 100644
index 0000000..96625ba
--- /dev/null
+++ b/kernel/lib/relist.h
@@ -0,0 +1,19 @@
+#ifndef RELIST_H
+#define RELIST_H
+#include <typedefs.h>
+
+struct relist {
+ void **entries;
+ u32 bitmap_capacity;
+ u64 *bitmap;
+};
+
+void relist_init(struct relist *list);
+void relist_reset(struct relist *list);
+void relist_free(struct relist *list);
+int relist_clone(struct relist *in, struct relist *out);
+int relist_add(struct relist *list, void *value, u32 *index);
+int relist_set(struct relist *list, u32 index, void *value);
+int relist_get(const struct relist *list, u32 index, void **out);
+int relist_remove(struct relist *list, u32 index);
+#endif
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index 6454775..42d4dc7 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -120,14 +120,14 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) {
}
if (p) {
- if (!list_clone(&p->file_descriptors, &r->file_descriptors)) {
+ if (!relist_clone(&p->file_descriptors, &r->file_descriptors)) {
kfree(r->tcb);
kfree(r);
return NULL;
}
for (int i = 0;; i++) {
vfs_fd_t *out;
- if (!list_get(&p->file_descriptors, i, (void **)&out)) {
+ if (!relist_get(&r->file_descriptors, i, (void **)&out)) {
break;
}
if (out) {
@@ -135,7 +135,7 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) {
}
}
} else {
- list_init(&r->file_descriptors);
+ relist_init(&r->file_descriptors);
}
if (p) {
@@ -208,7 +208,7 @@ void free_process(process_t *p) {
list_free(&p->tcp_sockets);
list_free(&p->tcp_listen);
list_free(&p->event_queue);
- list_free(&p->file_descriptors);
+ relist_free(&p->file_descriptors);
kfree(p->tcb);
mmu_free_pagedirectory(p->cr3);
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index 7e42cc7..feb6aa5 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -5,6 +5,7 @@ typedef struct Process process_t;
#include <fs/vfs.h>
#include <lib/list.h>
#include <lib/stack.h>
+#include <lib/relist.h>
#include <mmu.h>
#include <signal.h>
#include <stdbool.h>
@@ -61,7 +62,7 @@ struct Process {
void *interrupt_handler;
PageDirectory *cr3;
- struct list file_descriptors;
+ struct relist file_descriptors;
struct list read_list;
struct list write_list;
diff --git a/kernel/socket.c b/kernel/socket.c
index 53dd71e..d3dfd1a 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -261,7 +261,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
}
int index;
- assert(list_add(&current_task->file_descriptors, s->incoming_fd, &index));
+ assert(relist_add(&current_task->file_descriptors, s->incoming_fd, &index));
assert(1 <= s->incoming_fd->reference_count);
s->incoming_fd = NULL;
// for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);)