summaryrefslogtreecommitdiff
path: root/src/kernel/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/lib')
-rw-r--r--src/kernel/lib/earray.c156
-rw-r--r--src/kernel/lib/earray.h40
-rw-r--r--src/kernel/lib/std.c8
-rw-r--r--src/kernel/lib/std.h2
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