diff options
| -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++;  |