diff options
Diffstat (limited to 'src/kernel/lib')
-rw-r--r-- | src/kernel/lib/earray.c | 156 | ||||
-rw-r--r-- | src/kernel/lib/earray.h | 40 | ||||
-rw-r--r-- | src/kernel/lib/std.c | 8 | ||||
-rw-r--r-- | src/kernel/lib/std.h | 2 |
4 files changed, 206 insertions, 0 deletions
diff --git a/src/kernel/lib/earray.c b/src/kernel/lib/earray.c new file mode 100644 index 0000000..a17e823 --- /dev/null +++ b/src/kernel/lib/earray.c @@ -0,0 +1,156 @@ +#include "earray.h" + +#include <mem/mem.h> +#include <core/sys.h> + +void earray_init(struct earray *array) { + int i; + + if (array->data != 0) return; + + array->ref_vect_len = array->ref_vect_init_len; + array->elements = 0; + array->mutex = MUTEX_UNLOCKED; + + array->data = kmalloc(array->ref_vect_len * sizeof(void***)); + + for (i = 0; i < array->ref_vect_len; i++) { + array->data[i] = 0; + } +} + +void earray_free(struct earray *array) { + int i; + + mutex_lock(&array->mutex); + + for (i = 0; i < array->ref_vect_len; i++) { + if (array->data[i] != 0) kfree(array->data[i]); + } + kfree(array->data); + array->data = 0; + + //no need to unlock, the structure is never to be used again +} + +int earray_add(struct earray *array, void *ptr) { + if (ptr == 0) return -1; + + mutex_lock(&array->mutex); + + int i, j; + + for (i = 0; i < array->ref_vect_len; i++) { + if (array->data[i] == 0) { + // Allocate here + array->data[i] = kmalloc(array->vect_len * sizeof(void**)); + array->data[i][0] = ptr; + for (j = 1; j < array->vect_len; j++) array->data[i][j] = 0; + + j = i * array->vect_len; //ret val + + if (array->elements <= j) array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + } else { + // Look for free space + for (j = 0; j < array->vect_len; j++) { + if (array->data[i][j] == 0) { + array->data[i][j] = ptr; + + j = i * array->vect_len + j; // ret val + if (array->elements <= j) array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + } + } + } + } + // Nothing was allocated, we need MORE SPACE + void ***new_data = kmalloc(array->ref_vect_len + array->ref_vect_init_len); + for (i = 0; i < array->ref_vect_len; i++) { + new_data[i] = array->data[i]; + } + new_data[array->ref_vect_len] = kmalloc(array->vect_len * sizeof(void**)); + new_data[array->ref_vect_len][0] = ptr; + j = array->ref_vect_len * array->vect_len; // j = return value + for (i = 1; i < array->vect_len; i++) { + new_data[array->ref_vect_len][i] = 0; + } + for (i = array->ref_vect_len + 1; i < array->ref_vect_len + array->ref_vect_init_len; i++) { + new_data[i] = 0; + } + kfree(array->data); + array->data = new_data; + array->ref_vect_len += array->ref_vect_init_len; + + ASSERT(j >= array->elements); + array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + +} + +void *earray_at(struct earray *array, int num) { + mutex_lock(&array->mutex); + + int i = num / array->vect_len, j = num % array->vect_len; + if (i >= array->ref_vect_len || array->data[i] == 0) return 0; + void* ret = array->data[i][j]; + + mutex_unlock(&array->mutex); + return ret; +} + +void earray_set(struct earray *array, int num, void* ptr) { + mutex_lock(&array->mutex); + + int a = num / array->vect_len, b = num % array->vect_len, i, j; + if (a >= array->ref_vect_len) { + if (ptr == 0) { + mutex_unlock(&array->mutex); + return; + } + int new_vect_len = array->ref_vect_len; + while (a >= array->ref_vect_len) new_vect_len += array->ref_vect_init_len; + + void ***new_data = kmalloc(new_vect_len * sizeof(void***)); + for (i = 0; i < array->ref_vect_len; i++) { + new_data[i] = array->data[i]; + } + for (i = array->ref_vect_len; i < new_vect_len; i++) { + new_data[i] = 0; + } + kfree(array->data); + array->data = new_data; + array->ref_vect_len = new_vect_len; + } + if (ptr == 0) { + if (array->data[a] != 0) { + if (array->data[a][b] != 0) { + array->data[a][b] = 0; + j = 1; + for (i = 0; i < array->vect_len; i++) { + if (array->data[a][i] != 0) j = 0; + } + if (j == 1) { + kfree(array->data[a]); + array->data[a] = 0; + } + } + } + } else { + if (array->data[a] = 0) { + array->data[a] = kmalloc(array->vect_len * sizeof(void**)); + for (i = 0; i < array->vect_len; i++) array->data[a][i] = 0; + } + array->data[a][b] = ptr; + + if (num >= array->elements) array->elements = num + 1; + } + + mutex_unlock(&array->mutex); +} diff --git a/src/kernel/lib/earray.h b/src/kernel/lib/earray.h new file mode 100644 index 0000000..69849c9 --- /dev/null +++ b/src/kernel/lib/earray.h @@ -0,0 +1,40 @@ +#ifndef DEF_EARRAY_H +#define DEF_EARRAY_H + +#include <sched.h> + +/* + * This class implements a simple extensible array structure. + * An entry with a 0 value is considered free and can be allocated. + * The array will free as much space when elements are removed. + * The array will ALWAYS have array->data = 0 when uninitialized, !=0 when initialized and in use + * To initialize an earray: + * - allocate the struct earray + * - set its ref_vect_init_len and vect_len to desired values + * - set its data to 0 + * - all the rest doesn't matter + * - call earray_init + * Freeing an array does not free the struct earray, only the data it references. + */ + +struct earray { + int ref_vect_init_len; + int vect_len; // NEVER CHANGE THIS AFTER INITIALISATION!!!! + + int ref_vect_len; + int elements; + void ***data; + + mutex_t mutex; +}; + +void earray_init(struct earray *array); +void earray_free(struct earray *earray); // frees everything + +int earray_add(struct earray *array, void* ptr); // return element number or -1 if fail +void *earray_at(struct earray *array, int num); // returns 0 when nothing +void earray_set(struct earray *earray, int num, void* ptr); + + +#endif + diff --git a/src/kernel/lib/std.c b/src/kernel/lib/std.c index 316dfa3..85dff1a 100644 --- a/src/kernel/lib/std.c +++ b/src/kernel/lib/std.c @@ -1,5 +1,6 @@ #include "std.h" #include "core/sys.h" +#include <mem/mem.h> int errno = 0; @@ -9,3 +10,10 @@ void abort() { monitor_write("\n"); PANIC("abort() called, probably a memory manager failure."); } + +char *strdup(const char *src) { + char* ret = kmalloc(strlen(src) + 1); + if (ret == NULL) return ret; + strcpy(ret, src); + return ret; +} diff --git a/src/kernel/lib/std.h b/src/kernel/lib/std.h index 51e0435..7aaf1b9 100644 --- a/src/kernel/lib/std.h +++ b/src/kernel/lib/std.h @@ -11,4 +11,6 @@ void abort(); extern int errno; +char *strdup(const char *src); // uses malloc, so needs to be here + #endif |