diff options
author | Anton Kling <anton@kling.gg> | 2024-04-27 18:32:32 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-04-27 18:32:32 +0200 |
commit | e3ff175cc3a5fdd1d65a34d081955b9808c49eca (patch) | |
tree | 3cf41a97d8800ca92c4781847185975a0c95dbef /kernel | |
parent | 02c27583a539c4e8073509536d328581cf1ba346 (diff) |
Kernel: Make "relist" able to dynamically resize
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/fs/vfs.c | 5 | ||||
-rw-r--r-- | kernel/kmalloc.c | 21 | ||||
-rw-r--r-- | kernel/kmalloc.h | 1 | ||||
-rw-r--r-- | kernel/lib/relist.c | 73 | ||||
-rw-r--r-- | kernel/lib/relist.h | 2 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 8 |
6 files changed, 86 insertions, 24 deletions
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 16f9186..9312c2a 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 (!relist_get(&p->file_descriptors, fd, (void **)&r)) { + if (!relist_get(&p->file_descriptors, fd, (void **)&r, NULL)) { return NULL; } return r; @@ -411,7 +411,8 @@ 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 (!relist_get(¤t_task->file_descriptors, org_fd, (void **)&orig)) { + if (!relist_get(¤t_task->file_descriptors, org_fd, (void **)&orig, + NULL)) { assert(0); return -1; } diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c index 12e8232..ce96d54 100644 --- a/kernel/kmalloc.c +++ b/kernel/kmalloc.c @@ -236,6 +236,27 @@ void *kallocarray(size_t nmemb, size_t size) { return kreallocarray(NULL, nmemb, size); } +void *krecalloc(void *ptr, size_t nelem, size_t elsize) { + if ((nelem >= MUL_NO_OVERFLOW || elsize >= MUL_NO_OVERFLOW) && nelem > 0 && + SIZE_MAX / nelem < elsize) { + return NULL; + } + if (!ptr) { + return kcalloc(nelem, elsize); + } + size_t new_size = nelem * elsize; + void *rc = int_kmalloc(new_size); + if (!rc) { + return NULL; + } + size_t l = get_mem_size(ptr); + size_t to_copy = min(l, new_size); + memset(rc, 0, new_size); + memcpy(rc, ptr, to_copy); + kfree(ptr); + return rc; +} + void *kcalloc(size_t nelem, size_t elsize) { if ((nelem >= MUL_NO_OVERFLOW || elsize >= MUL_NO_OVERFLOW) && nelem > 0 && SIZE_MAX / nelem < elsize) { diff --git a/kernel/kmalloc.h b/kernel/kmalloc.h index 8b9d59d..9ea67d7 100644 --- a/kernel/kmalloc.h +++ b/kernel/kmalloc.h @@ -14,5 +14,6 @@ void *krealloc(void *ptr, size_t size); void *kreallocarray(void *ptr, size_t nmemb, size_t size); void *kallocarray(size_t nmemb, size_t size); void *kcalloc(size_t nelem, size_t elsize); +void *krecalloc(void *ptr, size_t nelem, size_t elsize); void kfree(void *p); int init_heap(void); diff --git a/kernel/lib/relist.c b/kernel/lib/relist.c index 6ad30d2..a2f9ce5 100644 --- a/kernel/lib/relist.c +++ b/kernel/lib/relist.c @@ -1,15 +1,18 @@ #include <assert.h> #include <kmalloc.h> #include <lib/relist.h> +#include <math.h> void relist_init(struct relist *list) { - list->bitmap_capacity = 100; + list->bitmap_capacity = 1; list->bitmap = kcalloc(sizeof(u64), list->bitmap_capacity); if (!list->bitmap) { goto relist_init_error; } - list->entries = kallocarray(sizeof(void *), (sizeof(u64) * 8)); + list->entries = + kallocarray(sizeof(void *) * sizeof(u64) * 8, list->bitmap_capacity); if (!list->entries) { + kfree(list->bitmap); goto relist_init_error; } return; @@ -28,18 +31,27 @@ void relist_reset(struct relist *list) { } 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; - } + out->bitmap_capacity = in->bitmap_capacity; + out->bitmap = kcalloc(sizeof(u64), out->bitmap_capacity); + if (!out->bitmap) { + goto relist_clone_error; + } + out->entries = + kallocarray(sizeof(void *) * sizeof(u64) * 8, out->bitmap_capacity); + if (!out->entries) { + kfree(out->bitmap); + goto relist_clone_error; } + memcpy(out->bitmap, in->bitmap, sizeof(u64) * out->bitmap_capacity); + memcpy(out->entries, in->entries, + sizeof(void *) * sizeof(u64) * 8 * out->bitmap_capacity); return 1; + +relist_clone_error: + out->bitmap_capacity = 0; + out->entries = NULL; + out->bitmap = NULL; + return 0; } static int relist_find_free_entry(struct relist *list, u32 *entry) { @@ -62,7 +74,26 @@ static int relist_find_free_entry(struct relist *list, u32 *entry) { int relist_add(struct relist *list, void *value, u32 *index) { u32 entry; if (!relist_find_free_entry(list, &entry)) { - assert(0); + u32 new_capacity = list->bitmap_capacity + 1; + u64 *new_allocation = kcalloc(sizeof(u64), new_capacity); + if (!new_allocation) { + return 0; + } + void *new_entry = krecalloc(list->entries, sizeof(void *) * sizeof(u64) * 8, + new_capacity); + if (!new_entry) { + kfree(new_allocation); + return 0; + } + if (list->bitmap) { + size_t to_copy = min(list->bitmap_capacity, new_capacity) * sizeof(u64); + memcpy(new_allocation, list->bitmap, to_copy); + kfree(list->bitmap); + } + list->bitmap = new_allocation; + list->bitmap_capacity = new_capacity; + list->entries = new_entry; + assert(relist_find_free_entry(list, &entry)); } list->entries[entry] = value; if (index) { @@ -73,7 +104,7 @@ int relist_add(struct relist *list, void *value, u32 *index) { } int relist_remove(struct relist *list, u32 index) { - if ((index / 64) > list->bitmap_capacity) { + if (index >= list->bitmap_capacity * 64) { assert(0); return 0; } @@ -87,8 +118,7 @@ int relist_remove(struct relist *list, u32 index) { } int relist_set(struct relist *list, u32 index, void *value) { - assert(value); - if ((index / 64) > list->bitmap_capacity) { + if (index >= list->bitmap_capacity * 64) { assert(0); return 0; } @@ -98,9 +128,14 @@ int relist_set(struct relist *list, u32 index, void *value) { return 1; } -int relist_get(const struct relist *list, u32 index, void **out) { - if ((index / 64) > list->bitmap_capacity) { - assert(0); +int relist_get(const struct relist *list, u32 index, void **out, int *end) { + if (end) { + *end = 0; + } + if (index >= list->bitmap_capacity * 64) { + if (end) { + *end = 1; + } return 0; } int is_used = (list->bitmap[index / 64] & ((u64)1 << (index % 64))); diff --git a/kernel/lib/relist.h b/kernel/lib/relist.h index 96625ba..734e5dc 100644 --- a/kernel/lib/relist.h +++ b/kernel/lib/relist.h @@ -14,6 +14,6 @@ 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_get(const struct relist *list, u32 index, void **out, int *end); int relist_remove(struct relist *list, u32 index); #endif diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c index 42d4dc7..639dd05 100644 --- a/kernel/sched/scheduler.c +++ b/kernel/sched/scheduler.c @@ -127,8 +127,12 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) { } for (int i = 0;; i++) { vfs_fd_t *out; - if (!relist_get(&r->file_descriptors, i, (void **)&out)) { - break; + int empty; + if (!relist_get(&r->file_descriptors, i, (void **)&out, &empty)) { + if (empty) { + break; + } + continue; } if (out) { out->reference_count++; |