summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-27 18:32:32 +0200
committerAnton Kling <anton@kling.gg>2024-04-27 18:32:32 +0200
commite3ff175cc3a5fdd1d65a34d081955b9808c49eca (patch)
tree3cf41a97d8800ca92c4781847185975a0c95dbef /kernel
parent02c27583a539c4e8073509536d328581cf1ba346 (diff)
Kernel: Make "relist" able to dynamically resize
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fs/vfs.c5
-rw-r--r--kernel/kmalloc.c21
-rw-r--r--kernel/kmalloc.h1
-rw-r--r--kernel/lib/relist.c73
-rw-r--r--kernel/lib/relist.h2
-rw-r--r--kernel/sched/scheduler.c8
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(&current_task->file_descriptors, org_fd, (void **)&orig)) {
+ if (!relist_get(&current_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++;