aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/Makefile1
-rw-r--r--libc/inc/assert.h3
-rw-r--r--libc/inc/mem.h20
-rw-r--r--libc/inc/stack.h28
-rw-r--r--libc/inc/sys.h38
-rw-r--r--libc/mem.c355
-rw-r--r--libc/stack.c125
7 files changed, 465 insertions, 105 deletions
diff --git a/libc/Makefile b/libc/Makefile
index 1a8e0f0..a3d1300 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -10,6 +10,7 @@ COBJS = str.o \
cpu.o \
sys.o \
list.o \
+ stack.o \
random.o
CC = ccache ../cross/opt/bin/i686-elf-gcc
LD = ccache ../cross/opt/bin/i686-elf-ld
diff --git a/libc/inc/assert.h b/libc/inc/assert.h
index 3e45f44..e42fc5a 100644
--- a/libc/inc/assert.h
+++ b/libc/inc/assert.h
@@ -9,7 +9,8 @@
#include <proc.h>
#define assert(exp) \
if (!(exp)) { \
- printf("%s:%d: %s: Assertion '%s' failed\n", __FILE__, __LINE__, __func__, #exp); \
+ printf("%s:%d: %s: Kernel assertion '%s' failed\n", __FILE__, __LINE__, __func__, \
+ #exp); \
struct proc *assert_proc = proc_current(); \
if (assert_proc) \
proc_exit(assert_proc, 1); \
diff --git a/libc/inc/mem.h b/libc/inc/mem.h
index 15505fd..e35ee62 100644
--- a/libc/inc/mem.h
+++ b/libc/inc/mem.h
@@ -5,16 +5,21 @@
#include <def.h>
-// Huh
+int malloc_allocated;
+
+void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp);
+void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp);
+#define malloc(size) malloc_debug(size, __FILE__, __LINE__, __func__, #size)
+#define free(ptr) free_debug(ptr, __FILE__, __LINE__, __func__, #ptr)
+
+/* void *_malloc(u32 size); */
+/* void _free(void *ptr); */
+/* #define malloc(size) _malloc(size) */
+/* #define free(ptr) _free(ptr) */
+
#ifdef kernel
-#define HEAP_SIZE 0x10000
-#define HEAP_MAGIC 0x42
void heap_init(u32 start);
-void *malloc(u32 size);
-void free(void *ptr);
#elif defined(userspace)
-void *malloc(u32 size);
-void free(void *ptr);
#else
#error "No lib target specified. Please use -Dkernel or -Duserspace"
#endif
@@ -23,5 +28,6 @@ void *memcpy(void *dest, const void *src, u32 n);
void *memset(void *dest, int val, u32 n);
void *memchr(void *src, int c, u32 n);
int memcmp(const void *s1, const void *s2, u32 n);
+int mememp(const u8 *buf, u32 n);
#endif
diff --git a/libc/inc/stack.h b/libc/inc/stack.h
new file mode 100644
index 0000000..16725f8
--- /dev/null
+++ b/libc/inc/stack.h
@@ -0,0 +1,28 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#ifndef STACK_H
+#define STACK_H
+
+#include <def.h>
+
+struct stack_node {
+ void *data;
+ int nonce;
+ struct stack_node *next;
+ struct stack_node *prev;
+};
+
+struct stack {
+ struct stack_node *tail;
+};
+
+struct stack *stack_new();
+void stack_destroy(struct stack *stack);
+u32 stack_empty(struct stack *stack);
+u32 stack_push_bot(struct stack *stack, void *data);
+u32 stack_push(struct stack *stack, void *data);
+void *stack_pop(struct stack *stack);
+void *stack_peek(struct stack *stack);
+void stack_clear(struct stack *stack);
+
+#endif
diff --git a/libc/inc/sys.h b/libc/inc/sys.h
index 3145432..14f83dd 100644
--- a/libc/inc/sys.h
+++ b/libc/inc/sys.h
@@ -20,11 +20,6 @@ enum sys {
SYS_EXIT, // Exit current process // TODO: Free all memory of process
SYS_YIELD, // Switch to next process
SYS_TIME, // Get kernel time
- SYS_REGISTER, // Register for event
- SYS_UNREGISTER, // Unregister event
- SYS_SEND, // Send message to process
- SYS_RECEIVE, // Receive message (non-blocking/sync)
- SYS_GETPID, // Get the process ID
SYS_NET_OPEN, // Open network socket
SYS_NET_CLOSE, // Close network socket
SYS_NET_CONNECT, // Connect to destination
@@ -94,22 +89,33 @@ int sysv(enum sys num, ...);
#define yield() (int)sys0(SYS_YIELD)
#define time() (u32) sys0(SYS_TIME)
-#define event_register(id) sys1(SYS_REGISTER, (int)(id))
-#define event_unregister(id) sys1(SYS_UNREGISTER, (int)(id))
+static inline u32 getpid()
+{
+ u32 buf = 0;
+ read("/proc/self/pid", &buf, 0, sizeof(buf));
+ return buf;
+}
-#define msg_send(pid, type, msg) sys3(SYS_SEND, (int)(pid), (int)(type), (int)(msg))
-#define msg_receive() (struct message *)sys0(SYS_RECEIVE)
-#define getpid() (int)sys0(SYS_GETPID)
-static inline struct message *msg_receive_loop()
+// Hacky one-digit solution - TODO!
+#include <mem.h>
+#include <str.h>
+static inline u32 pidof(const char *name)
{
- struct message *msg;
- while (!(msg = msg_receive()))
- yield();
- return msg;
+ u32 curr = 1;
+ char buf[32] = { 0 };
+ char *path = (char *)"/proc/1/name"; // AAH
+ while (read(path, buf, 0, 32)) {
+ if (!strcmp(name, buf))
+ return curr;
+
+ curr++;
+ path[7]++;
+ }
+
+ return 0;
}
// Simple read wrapper
-#include <mem.h>
static inline void *sread(const char *path)
{
struct stat s = { 0 };
diff --git a/libc/mem.c b/libc/mem.c
index dc4e0e6..aab68b2 100644
--- a/libc/mem.c
+++ b/libc/mem.c
@@ -1,5 +1,6 @@
// MIT License, Copyright (c) 2020 Marvin Borner
+#include <assert.h>
#include <def.h>
#include <mem.h>
#include <sys.h>
@@ -68,126 +69,318 @@ int memcmp(const void *s1, const void *s2, u32 n)
return 0;
}
-#define ALIGNMENT 16ul
-#define ALIGN_TYPE char
-#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
+int mememp(const u8 *buf, u32 n)
+{
+ return buf[0] == 0 && !memcmp(buf, buf + 1, n - 1);
+}
-#define ALIGN(ptr) \
- if (ALIGNMENT > 1) { \
- u32 diff; \
- ptr = (void *)((u32)ptr + ALIGN_INFO); \
- diff = (u32)ptr & (ALIGNMENT - 1); \
- if (diff != 0) { \
- diff = ALIGNMENT - diff; \
- ptr = (void *)((u32)ptr + diff); \
- } \
- *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
- }
+/**
+ * Heap allocator
+ */
+
+#ifdef kernel
-#define UNALIGN(ptr) \
- if (ALIGNMENT > 1) { \
- u32 diff = *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)); \
- if (diff < (ALIGNMENT + ALIGN_INFO)) { \
- ptr = (void *)((u32)ptr - diff); \
- } \
+int malloc_allocated = 0;
+
+#define HEAP_MAGIC 0x42424242
+#define HEAP_INIT_SIZE 0xff000000
+#define HEAP_MIN_SIZE HEAP_INIT_SIZE
+#define MIN_ALLOC_SZ 4
+#define BIN_COUNT 9
+#define BIN_MAX_IDX (BIN_COUNT - 1)
+#define OVERHEAD (sizeof(struct h_footer) + sizeof(struct h_node))
+/* #define MIN_WILDERNESS 0x2000 */
+/* #define MAX_WILDERNESS 0x1000000 */
+
+struct h_node {
+ u32 magic;
+ u32 hole;
+ u32 size;
+ struct h_node *next;
+ struct h_node *prev;
+};
+
+struct h_footer {
+ struct h_node *header;
+};
+
+struct h_bin {
+ struct h_node *head;
+};
+
+struct heap {
+ u32 start;
+ u32 end;
+ struct h_bin bins[BIN_COUNT];
+};
+
+void node_add(struct h_bin *bin, struct h_node *node)
+{
+ node->magic = HEAP_MAGIC;
+ node->next = NULL;
+ node->prev = NULL;
+ if (!bin->head) {
+ bin->head = node;
+ return;
+ }
+ struct h_node *curr = bin->head;
+ struct h_node *prev = NULL;
+ while (curr && curr->size <= node->size) {
+ prev = curr;
+ curr = curr->next;
}
+ if (!curr) {
+ prev->next = node;
+ node->prev = prev;
+ } else if (prev) {
+ node->next = curr;
+ prev->next = node;
+ node->prev = prev;
+ curr->prev = node;
+ } else {
+ node->next = bin->head;
+ bin->head->prev = node;
+ bin->head = node;
+ }
+}
-#ifdef kernel
+void node_remove(struct h_bin *bin, struct h_node *node)
+{
+ if (!bin->head)
+ return;
+ if (bin->head == node) {
+ bin->head = bin->head->next;
+ return;
+ }
-static u32 *heap;
-static u32 index;
+ struct h_node *temp = bin->head->next;
+ while (temp) {
+ if (temp == node) {
+ if (!temp->next) {
+ temp->prev->next = NULL;
+ } else {
+ temp->prev->next = temp->next;
+ temp->next->prev = temp->prev;
+ }
+ return;
+ }
+ temp = temp->next;
+ }
+}
-void heap_init(u32 start)
+struct h_node *node_best_fit(struct h_bin *bin, u32 size)
{
- heap = (u32 *)start;
- for (int i = 0; i < HEAP_SIZE; i++)
- heap[i] = 0;
- heap[0] = HEAP_MAGIC;
- index = 1;
+ if (!bin->head)
+ return NULL;
+
+ struct h_node *temp = bin->head;
+ while (temp) {
+ if (temp->size >= size)
+ return temp;
+ temp = temp->next;
+ }
+ return NULL;
}
-int count()
+struct h_node *node_last(struct h_bin *bin)
{
- int i = 0;
- u32 *iterator = heap + 1;
- do {
- iterator += iterator[0] + 1;
- i++;
- } while (iterator[0] != 0);
- return i;
+ struct h_node *temp = bin->head;
+ while (temp->next)
+ temp = temp->next;
+ return temp;
}
-// TODO: Identify by pid (for freeing)
-void *malloc(u32 size)
+struct h_footer *node_foot(struct h_node *node)
{
- if (size < 1)
- return NULL;
+ return (struct h_footer *)((char *)node + sizeof(*node) + node->size);
+}
- size = size + ALIGNMENT + ALIGN_INFO;
+void node_create_foot(struct h_node *head)
+{
+ struct h_footer *foot = node_foot(head);
+ foot->header = head;
+}
- heap[index] = size;
- index += size + 1;
+u32 bin_index(u32 sz)
+{
+ u32 index = 0;
+ sz = sz < 4 ? 4 : sz;
+ while (sz >>= 1)
+ index++;
+ index -= 2;
+ if (index > BIN_MAX_IDX)
+ index = BIN_MAX_IDX;
+ return index;
+}
- void *p = (void *)(heap + index - size);
- ALIGN(p);
+/* struct h_node *wilderness_get(struct heap *heap) */
+/* { */
+/* struct h_footer *wild_foot = (struct h_footer *)((char *)heap->end - sizeof(*wild_foot)); */
+/* return wild_foot->header; */
+/* } */
- return p;
+u32 expand(struct heap *heap, u32 sz)
+{
+ (void)heap;
+ (void)sz;
+ return 0;
}
-// TODO: Implement free, realloc and find_smallest_hole
-void free(void *ptr)
+u32 contract(struct heap *heap, u32 sz)
{
- (void)ptr;
- /* UNALIGN(ptr); */
+ (void)heap;
+ (void)sz;
+ return 0;
}
-void *realloc(void *ptr, u32 size)
+static struct heap heap = { 0 };
+void heap_init(u32 start)
{
- (void)size;
- return ptr;
+ struct h_node *init_region = (struct h_node *)start;
+ init_region->hole = 1;
+ init_region->size = HEAP_INIT_SIZE - OVERHEAD;
+ node_create_foot(init_region);
+ node_add(&heap.bins[bin_index(init_region->size)], init_region);
+ heap.start = start;
+ heap.end = start + HEAP_INIT_SIZE;
}
-#elif defined(userspace)
+void *_malloc(u32 size)
+{
+ malloc_allocated += size;
+ u32 index = bin_index(size);
+ struct h_bin *temp = (struct h_bin *)&heap.bins[index];
+ struct h_node *found = node_best_fit(temp, size);
-#define HEAP_SIZE 100000
+ while (!found) {
+ assert(index + 1 < BIN_COUNT);
-#define kmalloc(n) (void *)sys1(SYS_MALLOC, n)
-#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr))
+ temp = &heap.bins[++index];
+ found = node_best_fit(temp, size);
+ }
-/* static u32 *heap = NULL; */
-/* static u32 index = 0; */
-/* static u32 malloced = 0; */
+ assert(found->magic == HEAP_MAGIC);
-// TODO: Fix userspace malloc (for size > HEAP_SIZE)!
-void *malloc(u32 size)
-{
- return kmalloc(size);
+ if ((found->size - size) > (OVERHEAD + MIN_ALLOC_SZ)) {
+ struct h_node *split = (struct h_node *)(((char *)found + OVERHEAD) + size);
+ split->magic = HEAP_MAGIC;
+ split->size = found->size - size - OVERHEAD;
+ split->hole = 1;
- /* if (size < 1) */
- /* return NULL; */
+ node_create_foot(split);
- /* size = size + ALIGNMENT + ALIGN_INFO; */
+ u32 new_idx = bin_index(split->size);
- /* if (!malloced || size > malloced) { */
- /* heap = kmalloc(HEAP_SIZE); */
- /* malloced = HEAP_SIZE; */
+ node_add(&heap.bins[new_idx], split);
+
+ found->size = size;
+ node_create_foot(found);
+ }
+
+ found->hole = 0;
+ node_remove(&heap.bins[index], found);
+
+ // TODO: Implement expand/contract
+ /* struct h_node *wild = wilderness_get(&heap); */
+ /* if (wild->size < MIN_WILDERNESS) { */
+ /* assert(expand(&heap, 0x1000)); */
+ /* } else if (wild->size > MAX_WILDERNESS) { */
+ /* assert(contract(&heap, 0x1000)); */
/* } */
- /* malloced -= size; */
- /* heap[index] = size; */
- /* index += size + 1; */
+ found->prev = NULL;
+ found->next = NULL;
+ return &found->next;
+}
+
+void _free(void *p)
+{
+ if (!p)
+ return;
+
+ struct h_bin *list;
+ struct h_footer *new_foot, *old_foot;
+
+ struct h_node *head = (struct h_node *)((char *)p - 12);
+ assert(head->magic == HEAP_MAGIC && head->hole == 0);
+ malloc_allocated -= head->size;
+ if (head == (struct h_node *)(u32 *)heap.start) {
+ head->hole = 1;
+ node_add(&heap.bins[bin_index(head->size)], head);
+ return;
+ }
+
+ struct h_node *next = (struct h_node *)((char *)node_foot(head) + sizeof(struct h_footer));
+ struct h_footer *f = (struct h_footer *)((char *)head - sizeof(struct h_footer));
+ struct h_node *prev = f->header;
+
+ if (prev->hole) {
+ list = &heap.bins[bin_index(prev->size)];
+ node_remove(list, prev);
+
+ prev->size += OVERHEAD + head->size;
+ new_foot = node_foot(head);
+ new_foot->header = prev;
+
+ head = prev;
+ }
+
+ if (next->hole) {
+ list = &heap.bins[bin_index(next->size)];
+ node_remove(list, next);
+
+ head->size += OVERHEAD + next->size;
+
+ old_foot = node_foot(next);
+ old_foot->header = 0;
+ next->size = 0;
+ next->hole = 0;
+
+ new_foot = node_foot(head);
+ new_foot->header = head;
+ }
+
+ head->hole = 1;
+ node_add(&heap.bins[bin_index(head->size)], head);
+}
- /* void *p = (void *)(heap + index - size); */
- /* ALIGN(p); */
+#elif defined(userspace)
+
+#define kmalloc(n) (void *)sys1(SYS_MALLOC, n)
+#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr))
+
+void *_malloc(u32 size)
+{
+ return kmalloc(size);
+}
- /* return p; */
+void _free(void *ptr)
+{
+ kfree(ptr);
}
-// TODO: Implement free, realloc and find_smallest_hole
-void free(void *ptr)
+#endif
+
+void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp)
{
- (void)ptr;
- /* UNALIGN(ptr); */
+ void *ret = _malloc(size);
+#ifdef kernel
+ printf("K");
+#else
+ printf("U");
+#endif
+ printf("MALLOC\t%s:%d: %s: 0x%x %dB (%s)\n", file, line, func, ret, size, inp);
+ return ret;
}
+void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp)
+{
+#ifdef kernel
+ printf("K");
+#else
+ printf("U");
#endif
+ printf("FREE\t%s:%d: %s: 0x%x (%s)\n", file, line, func, ptr, inp);
+ if (ptr)
+ _free(ptr);
+}
diff --git a/libc/stack.c b/libc/stack.c
new file mode 100644
index 0000000..c47dd59
--- /dev/null
+++ b/libc/stack.c
@@ -0,0 +1,125 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <def.h>
+#include <mem.h>
+#include <stack.h>
+
+static int nonce = 0;
+
+struct stack *stack_new()
+{
+ struct stack *stack = malloc(sizeof(*stack));
+ stack->tail = NULL;
+ return stack;
+}
+
+void stack_destroy(struct stack *stack)
+{
+ struct stack_node *iterator = stack->tail;
+ while (iterator) {
+ if (!iterator->prev) {
+ free(iterator);
+ break;
+ }
+ iterator = iterator->prev;
+ free(iterator->next);
+ }
+ stack->tail = NULL;
+ free(stack);
+ stack = NULL;
+}
+
+struct stack_node *stack_new_node()
+{
+ struct stack_node *node = malloc(sizeof(*node));
+ node->data = NULL;
+ node->prev = NULL;
+ node->next = NULL;
+ node->nonce = nonce++;
+ return node;
+}
+
+u32 stack_push_bot_node(struct stack *stack, struct stack_node *node)
+{
+ if (!stack || !node)
+ return 0;
+
+ if (stack->tail) {
+ struct stack_node *iterator = stack->tail;
+ while (iterator) {
+ if (!iterator->prev)
+ break;
+ iterator = iterator->prev;
+ }
+ iterator->prev = node;
+ node->next = iterator;
+ } else {
+ stack->tail = node;
+ }
+
+ return 1;
+}
+
+u32 stack_push_node(struct stack *stack, struct stack_node *node)
+{
+ if (!stack || !node)
+ return 0;
+
+ if (stack->tail) {
+ stack->tail->next = node;
+ node->prev = stack->tail;
+ stack->tail = node;
+ } else {
+ stack->tail = node;
+ }
+
+ return 1;
+}
+
+u32 stack_empty(struct stack *stack)
+{
+ return !stack->tail;
+}
+
+u32 stack_push_bot(struct stack *stack, void *data)
+{
+ struct stack_node *node = stack_new_node();
+ node->data = data;
+ return stack_push_bot_node(stack, node);
+}
+
+u32 stack_push(struct stack *stack, void *data)
+{
+ struct stack_node *node = stack_new_node();
+ node->data = data;
+ return stack_push_node(stack, node);
+}
+
+void *stack_pop(struct stack *stack)
+{
+ if (!stack || !stack->tail)
+ return NULL;
+
+ struct stack_node *prev = stack->tail;
+
+ stack->tail->prev->next = NULL;
+ stack->tail = stack->tail->prev;
+
+ void *data = prev->data;
+ free(prev);
+ return data;
+}
+
+void *stack_peek(struct stack *stack)
+{
+ if (!stack || !stack->tail)
+ return NULL;
+
+ return stack->tail;
+}
+
+void stack_clear(struct stack *stack)
+{
+ while (stack_pop(stack))
+ ;
+}