aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2019-11-22 22:17:54 +0100
committerMarvin Borner2019-11-22 22:17:54 +0100
commit4b178c0feb4c415be36be0e4c0def8c447ed42af (patch)
tree694f0226b419ec5b043830e12f96aa5e09c9305f
parent0ba991750314310a5e53b0d8135aef5b1352b261 (diff)
Added the most awesome c lib
-rw-r--r--Makefile4
-rw-r--r--src/mlibc/math.h6
-rw-r--r--src/mlibc/math/pow.c9
-rw-r--r--src/mlibc/stdio.h10
-rw-r--r--src/mlibc/stdio/printf.c53
-rw-r--r--src/mlibc/stdio/writec.c5
-rw-r--r--src/mlibc/stdlib.h22
-rw-r--r--src/mlibc/stdlib/atoi.c23
-rw-r--r--src/mlibc/stdlib/htoa.c29
-rw-r--r--src/mlibc/stdlib/htoi.c22
-rw-r--r--src/mlibc/stdlib/itoa.c43
-rw-r--r--src/mlibc/stdlib/liballoc.c446
-rw-r--r--src/mlibc/stdlib/liballoc.h24
-rw-r--r--src/mlibc/string.h22
-rw-r--r--src/mlibc/string/strcat.c9
-rw-r--r--src/mlibc/string/strcati.c7
-rw-r--r--src/mlibc/string/strcmp.c9
-rw-r--r--src/mlibc/string/strcpy.c8
-rw-r--r--src/mlibc/string/strdisp.c10
-rw-r--r--src/mlibc/string/strdup.c9
-rw-r--r--src/mlibc/string/strinv.c12
-rw-r--r--src/mlibc/string/strlen.c7
22 files changed, 787 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 81229f0..9ebee6c 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ build: clean
nasm -f elf ./src/kernel/boot.asm -o ./build/boot.o || exit; \
# Make all C files
- find ./src/kernel/ ./src/userspace/ -name \*.c >./build/tmp; \
+ find ./src/kernel/ ./src/userspace/ ./src/mlibc/ -name \*.c >./build/tmp; \
while read -r line; do \
stripped=$$(echo "$${line}" | sed -r 's/\//_/g'); \
stripped=$${stripped#??????}; \
@@ -69,7 +69,7 @@ debug:
@echo "Starting simulation"
@echo "[SERIAL OUTPUT]"
@head -c 10485760 /dev/zero > ./build/hdd10M.img
- @qemu-system-x86_64 -no-reboot -M accel=kvm:tcg -vga std -serial stdio -rtc base=localtime -d int,in_asm -D qemu.log -m 512M -cdrom ./build/melvix.iso -hda ./build/hdd10M.img
+ @qemu-system-x86_64 -no-reboot -M accel=kvm:tcg -vga std -serial stdio -rtc base=localtime -d int,in_asm -D qemu.log -m 128M -cdrom ./build/melvix.iso -hda ./build/hdd10M.img
@echo "[END OF CONNECTION]"
.PHONY: build clean cross test debug \ No newline at end of file
diff --git a/src/mlibc/math.h b/src/mlibc/math.h
new file mode 100644
index 0000000..c9abf7d
--- /dev/null
+++ b/src/mlibc/math.h
@@ -0,0 +1,6 @@
+#ifndef MELVIX_MATH_H
+#define MELVIX_MATH_H
+
+int pow(int base, int exp);
+
+#endif
diff --git a/src/mlibc/math/pow.c b/src/mlibc/math/pow.c
new file mode 100644
index 0000000..4f040bb
--- /dev/null
+++ b/src/mlibc/math/pow.c
@@ -0,0 +1,9 @@
+int pow(int base, int exp) {
+ if (exp < 0) return 0;
+
+ if (!exp) return 1;
+
+ int ret = base;
+ for (int i = 1; i < exp; i++) ret *= base;
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/stdio.h b/src/mlibc/stdio.h
new file mode 100644
index 0000000..ae377a2
--- /dev/null
+++ b/src/mlibc/stdio.h
@@ -0,0 +1,10 @@
+#ifndef MELVIX_STDIO_H
+#define MELVIX_STDIO_H
+
+// TODO: Input methods
+
+void writec(char c);
+
+void printf(const char *format, ...);
+
+#endif
diff --git a/src/mlibc/stdio/printf.c b/src/mlibc/stdio/printf.c
new file mode 100644
index 0000000..11516cf
--- /dev/null
+++ b/src/mlibc/stdio/printf.c
@@ -0,0 +1,53 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <mlibc/stdio.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+void __writes(const char *data) {
+ for (size_t i = 0; i < strlen(data); i++) writec(data[i]);
+}
+
+void printf(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ uint8_t readyToFormat = 0;
+
+ char buff = 0;
+
+ for (; *fmt; fmt++) {
+ if (readyToFormat) {
+ if (*fmt == '%') {
+ writec('%');
+ readyToFormat = 0;
+ continue;
+ }
+
+ buff = *fmt;
+ if (buff == 's') {
+ const char *str = va_arg(args, const char*);
+ __writes(str);
+ readyToFormat = 0;
+ } else if (buff == 'x') {
+ char *p = htoa((uint32_t) va_arg(args, int));
+ __writes(p);
+ kfree(p);
+ readyToFormat = 0;
+ } else if (buff == 'd') {
+ char *p = itoa(va_arg(args, int));
+ __writes(p);
+ kfree(p);
+ readyToFormat = 0;
+ } else if (buff == 'c') {
+ writec((char) va_arg(args, int));
+ readyToFormat = 0;
+ }
+ } else {
+ if (*fmt == '%')
+ readyToFormat = 1;
+ else
+ writec(*fmt);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mlibc/stdio/writec.c b/src/mlibc/stdio/writec.c
new file mode 100644
index 0000000..60f69e8
--- /dev/null
+++ b/src/mlibc/stdio/writec.c
@@ -0,0 +1,5 @@
+#include <kernel/graphics/vesa.h>
+
+void writec(char c) {
+ vesa_draw_char(c);
+} \ No newline at end of file
diff --git a/src/mlibc/stdlib.h b/src/mlibc/stdlib.h
new file mode 100644
index 0000000..7ae9c5a
--- /dev/null
+++ b/src/mlibc/stdlib.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_STDLIB_H
+#define MELVIX_STDLIB_H
+
+#include <stdint.h>
+
+#ifndef MELVIX_ALLOC_H
+#include <mlibc/stdlib/liballoc.h>
+#endif
+
+#ifndef MELVIX_STRING_H
+#include <mlibc/string.h>
+#endif
+
+char *itoa(int n);
+
+int atoi(char *str);
+
+char *htoa(uint32_t n);
+
+int htoi(char *str);
+
+#endif
diff --git a/src/mlibc/stdlib/atoi.c b/src/mlibc/stdlib/atoi.c
new file mode 100644
index 0000000..34f9991
--- /dev/null
+++ b/src/mlibc/stdlib/atoi.c
@@ -0,0 +1,23 @@
+#include <mlibc/math.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <mlibc/string.h>
+
+int atoi(char *str) {
+ size_t s_str = strlen(str);
+ if (!s_str) return 0;
+
+ uint8_t negative = 0;
+ if (str[0] == '-') negative = 1;
+
+ size_t i = 0;
+ if (negative) i++;
+
+ int ret = 0;
+ for (; i < s_str; i++) {
+ ret += (str[i] - '0') * pow(10, (s_str - i) - 1);
+ }
+
+ if (negative) ret *= -1;
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/stdlib/htoa.c b/src/mlibc/stdlib/htoa.c
new file mode 100644
index 0000000..5290c74
--- /dev/null
+++ b/src/mlibc/stdlib/htoa.c
@@ -0,0 +1,29 @@
+#include <stdint.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+static const char __HTOA_TABLE[] = "0123456789ABCDEF";
+
+char *htoa(uint32_t n) {
+ char *ret = kmalloc(10);
+
+ int i = 0;
+ while (n) {
+ ret[i++] = __HTOA_TABLE[n & 0xF];
+ n >>= 4;
+ }
+
+ if (!i) {
+ ret[0] = '0';
+ i++;
+ }
+
+ for (; i <= 9; i++) ret[i] = 0;
+
+ char *aux = strdup(ret);
+ kfree(ret);
+ ret = aux;
+
+ strinv(ret);
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/stdlib/htoi.c b/src/mlibc/stdlib/htoi.c
new file mode 100644
index 0000000..73a583b
--- /dev/null
+++ b/src/mlibc/stdlib/htoi.c
@@ -0,0 +1,22 @@
+#include <mlibc/math.h>
+#include <stddef.h>
+#include <mlibc/string.h>
+
+int htoi(char *str) {
+ size_t s_str = strlen(str);
+
+ size_t i = 0;
+ int ret = 0;
+ for (; i < s_str; i++) {
+ char c = str[i];
+ int aux = 0;
+ if (c >= '0' && c <= '9')
+ aux = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ aux = (c - 'A') + 10;
+
+ ret += aux * pow(16, (s_str - i) - 1);
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/stdlib/itoa.c b/src/mlibc/stdlib/itoa.c
new file mode 100644
index 0000000..e9c40c1
--- /dev/null
+++ b/src/mlibc/stdlib/itoa.c
@@ -0,0 +1,43 @@
+#include <mlibc/math.h>
+#include <stdint.h>
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+static const char __ITOA_TABLE[] = "0123456789";
+
+char *itoa(int n) {
+ // Special cases
+ if (!n) {
+ char *ret = kmalloc(2);
+ ret[0] = '0';
+ ret[1] = 0;
+ return ret;
+ }
+ uint8_t negative = (uint8_t) (n < 0);
+ if (negative) n *= -1;
+
+ // First get the number of digits.
+ int sz;
+ for (sz = 0; n % pow(10, sz) != n; sz++) {}
+
+ char *ret = kmalloc(sz + 1);
+
+ // Iterate all digits again.
+ for (int i = 0; i < sz; i++) {
+ int digit = (n % pow(10, i + 1)) / pow(10, i);
+ ret[i] = __ITOA_TABLE[digit];
+ }
+ ret[sz] = 0;
+
+ if (negative) {
+ char *aux = kmalloc(sz + 2);
+ strcpy(aux, ret);
+ aux[sz] = '-';
+ aux[sz + 1] = 0;
+ kfree(ret);
+ ret = aux;
+ }
+
+ strinv(ret);
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/stdlib/liballoc.c b/src/mlibc/stdlib/liballoc.c
new file mode 100644
index 0000000..f4015f2
--- /dev/null
+++ b/src/mlibc/stdlib/liballoc.c
@@ -0,0 +1,446 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <kernel/paging/paging.h>
+#include <mlibc/stdlib/liballoc.h>
+
+int liballoc_lock() {
+ // asm volatile ("cli");
+ return 0;
+}
+
+int liballoc_unlock() {
+ // asm volatile ("sti");
+ return 0;
+}
+
+void *liballoc_alloc(size_t p) {
+ uint32_t ptr = paging_alloc_pages((uint32_t) p);
+ return (void *) ptr;
+}
+
+int liballoc_free(void *ptr, size_t p) {
+ paging_set_free((uint32_t) ptr, (uint32_t) p);
+ return 0;
+}
+
+#define ALIGNMENT 16ul
+#define ALIGN_TYPE char
+#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
+#define USE_CASE1
+#define USE_CASE2
+#define USE_CASE3
+#define USE_CASE4
+#define USE_CASE5
+
+#define ALIGN(ptr) \
+ if ( ALIGNMENT > 1 ) { \
+ uintptr_t diff; \
+ ptr = (void*) ((uintptr_t) ptr + ALIGN_INFO); \
+ diff = (uintptr_t) ptr & (ALIGNMENT - 1); \
+ if (diff != 0) { \
+ diff = ALIGNMENT - diff; \
+ ptr = (void*) ((uintptr_t) ptr + diff); \
+ } \
+ *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
+ }
+
+#define UNALIGN(ptr) \
+ if (ALIGNMENT > 1) { \
+ uintptr_t diff = *((ALIGN_TYPE*) ((uintptr_t) ptr - ALIGN_INFO)); \
+ if (diff < (ALIGNMENT + ALIGN_INFO)) { \
+ ptr = (void*) ((uintptr_t) ptr - diff); \
+ } \
+ }
+
+#define LIBALLOC_MAGIC 0xc001c0de
+#define LIBALLOC_DEAD 0xdeaddead
+
+struct liballoc_major {
+ struct liballoc_major *prev;
+ struct liballoc_major *next;
+ unsigned int pages;
+ unsigned int size;
+ unsigned int usage;
+ struct liballoc_minor *first;
+};
+
+struct liballoc_minor {
+ struct liballoc_minor *prev;
+ struct liballoc_minor *next;
+ struct liballoc_major *block;
+ unsigned int magic;
+ unsigned int size;
+ unsigned int req_size;
+};
+
+static struct liballoc_major *l_memRoot = NULL;
+static struct liballoc_major *l_bestBet = NULL;
+
+static unsigned int l_pageSize = 4096;
+static unsigned int l_pageCount = 16;
+static unsigned long long l_allocated = 0;
+static unsigned long long l_inuse = 0;
+
+static long long l_warningCount = 0;
+static long long l_errorCount = 0;
+static long long l_possibleOverruns = 0;
+
+static void *liballoc_memset(void *s, int c, size_t n) {
+ unsigned int i;
+ for (i = 0; i < n; i++)
+ ((char *) s)[i] = c;
+
+ return s;
+}
+
+static void *liballoc_memcpy(void *s1, const void *s2, size_t n) {
+ char *cdest;
+ char *csrc;
+ unsigned int *ldest = (unsigned int *) s1;
+ unsigned int *lsrc = (unsigned int *) s2;
+
+ while (n >= sizeof(unsigned int)) {
+ *ldest++ = *lsrc++;
+ n -= sizeof(unsigned int);
+ }
+
+ cdest = (char *) ldest;
+ csrc = (char *) lsrc;
+
+ while (n > 0) {
+ *cdest++ = *csrc++;
+ n -= 1;
+ }
+ return s1;
+}
+
+static struct liballoc_major *allocate_new_page(unsigned int size) {
+ unsigned int st;
+ struct liballoc_major *maj;
+
+ st = size + sizeof(struct liballoc_major);
+ st += sizeof(struct liballoc_minor);
+
+ if ((st % l_pageSize) == 0)
+ st = st / (l_pageSize);
+ else
+ st = st / (l_pageSize) + 1;
+
+ if (st < l_pageCount) st = l_pageCount;
+
+ maj = (struct liballoc_major *) liballoc_alloc(st);
+
+ if (maj == NULL) {
+ l_warningCount += 1;
+ return NULL;
+ }
+
+ maj->prev = NULL;
+ maj->next = NULL;
+ maj->pages = st;
+ maj->size = st * l_pageSize;
+ maj->usage = sizeof(struct liballoc_major);
+ maj->first = NULL;
+
+ l_allocated += maj->size;
+
+ return maj;
+}
+
+void *PREFIX(malloc)(size_t req_size) {
+ int startedBet = 0;
+ unsigned long long bestSize = 0;
+ void *p = NULL;
+ uintptr_t diff;
+ struct liballoc_major *maj;
+ struct liballoc_minor *min;
+ struct liballoc_minor *new_min;
+ unsigned long size = req_size;
+
+ if (ALIGNMENT > 1) {
+ size += ALIGNMENT + ALIGN_INFO;
+ }
+
+ liballoc_lock();
+
+ if (size == 0) {
+ l_warningCount += 1;
+ liballoc_unlock();
+ return PREFIX(malloc)(1);
+ }
+
+ if (l_memRoot == NULL) {
+ l_memRoot = allocate_new_page(size);
+ if (l_memRoot == NULL) {
+ liballoc_unlock();
+ return NULL;
+ }
+ }
+
+ maj = l_memRoot;
+ startedBet = 0;
+
+ if (l_bestBet != NULL) {
+ bestSize = l_bestBet->size - l_bestBet->usage;
+
+ if (bestSize > (size + sizeof(struct liballoc_minor))) {
+ maj = l_bestBet;
+ startedBet = 1;
+ }
+ }
+
+ while (maj != NULL) {
+ diff = maj->size - maj->usage;
+ if (bestSize < diff) {
+ l_bestBet = maj;
+ bestSize = diff;
+ }
+
+#ifdef USE_CASE1
+ if (diff < (size + sizeof(struct liballoc_minor))) {
+ if (maj->next != NULL) {
+ maj = maj->next;
+ continue;
+ }
+
+ if (startedBet == 1) {
+ maj = l_memRoot;
+ startedBet = 0;
+ continue;
+ }
+
+ maj->next = allocate_new_page(size);
+ if (maj->next == NULL) break;
+ maj->next->prev = maj;
+ maj = maj->next;
+ }
+#endif
+
+#ifdef USE_CASE2
+ if (maj->first == NULL) {
+ maj->first = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major));
+
+ maj->first->magic = LIBALLOC_MAGIC;
+ maj->first->prev = NULL;
+ maj->first->next = NULL;
+ maj->first->block = maj;
+ maj->first->size = size;
+ maj->first->req_size = req_size;
+ maj->usage += size + sizeof(struct liballoc_minor);
+ l_inuse += size;
+ p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor));
+ ALIGN(p);
+ liballoc_unlock();
+ return p;
+ }
+#endif
+
+#ifdef USE_CASE3
+ diff = (uintptr_t) (maj->first);
+ diff -= (uintptr_t) maj;
+ diff -= sizeof(struct liballoc_major);
+
+ if (diff >= (size + sizeof(struct liballoc_minor))) {
+ maj->first->prev = (struct liballoc_minor *) ((uintptr_t) maj + sizeof(struct liballoc_major));
+ maj->first->prev->next = maj->first;
+ maj->first = maj->first->prev;
+ maj->first->magic = LIBALLOC_MAGIC;
+ maj->first->prev = NULL;
+ maj->first->block = maj;
+ maj->first->size = size;
+ maj->first->req_size = req_size;
+ maj->usage += size + sizeof(struct liballoc_minor);
+ l_inuse += size;
+ p = (void *) ((uintptr_t) (maj->first) + sizeof(struct liballoc_minor));
+ ALIGN(p);
+ liballoc_unlock();
+ return p;
+ }
+#endif
+
+#ifdef USE_CASE4
+ min = maj->first;
+
+ while (min != NULL) {
+ if (min->next == NULL) {
+ diff = (uintptr_t) (maj) + maj->size;
+ diff -= (uintptr_t) min;
+ diff -= sizeof(struct liballoc_minor);
+ diff -= min->size;
+ if (diff >= (size + sizeof(struct liballoc_minor))) {
+ min->next = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size);
+ min->next->prev = min;
+ min = min->next;
+ min->next = NULL;
+ min->magic = LIBALLOC_MAGIC;
+ min->block = maj;
+ min->size = size;
+ min->req_size = req_size;
+ maj->usage += size + sizeof(struct liballoc_minor);
+ l_inuse += size;
+ p = (void *) ((uintptr_t) min + sizeof(struct liballoc_minor));
+ ALIGN(p);
+ liballoc_unlock();
+ return p;
+ }
+ }
+
+ if (min->next != NULL) {
+ diff = (uintptr_t) (min->next);
+ diff -= (uintptr_t) min;
+ diff -= sizeof(struct liballoc_minor);
+ diff -= min->size;
+
+ if (diff >= (size + sizeof(struct liballoc_minor))) {
+ new_min = (struct liballoc_minor *) ((uintptr_t) min + sizeof(struct liballoc_minor) + min->size);
+ new_min->magic = LIBALLOC_MAGIC;
+ new_min->next = min->next;
+ new_min->prev = min;
+ new_min->size = size;
+ new_min->req_size = req_size;
+ new_min->block = maj;
+ min->next->prev = new_min;
+ min->next = new_min;
+ maj->usage += size + sizeof(struct liballoc_minor);
+ l_inuse += size;
+ p = (void *) ((uintptr_t) new_min + sizeof(struct liballoc_minor));
+ ALIGN(p);
+ liballoc_unlock();
+ return p;
+ }
+ }
+
+ min = min->next;
+ }
+#endif
+
+#ifdef USE_CASE5
+ if (maj->next == NULL) {
+ if (startedBet == 1) {
+ maj = l_memRoot;
+ startedBet = 0;
+ continue;
+ }
+ maj->next = allocate_new_page(size);
+ if (maj->next == NULL) break;
+ maj->next->prev = maj;
+ }
+#endif
+ maj = maj->next;
+ }
+
+ liballoc_unlock();
+
+ return NULL;
+}
+
+void PREFIX(free)(void *ptr) {
+ struct liballoc_minor *min;
+ struct liballoc_major *maj;
+
+ if (ptr == NULL) {
+ l_warningCount += 1;
+ return;
+ }
+
+ UNALIGN(ptr);
+ liballoc_lock();
+
+ min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor));
+
+ if (min->magic != LIBALLOC_MAGIC) {
+ l_errorCount += 1;
+
+ if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
+ ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
+ ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
+ l_possibleOverruns += 1;
+ }
+
+ liballoc_unlock();
+ return;
+ }
+
+ maj = min->block;
+ l_inuse -= min->size;
+ maj->usage -= (min->size + sizeof(struct liballoc_minor));
+ min->magic = LIBALLOC_DEAD;
+
+ if (min->next != NULL) min->next->prev = min->prev;
+ if (min->prev != NULL) min->prev->next = min->next;
+ if (min->prev == NULL) maj->first = min->next;
+ if (maj->first == NULL) {
+ if (l_memRoot == maj) l_memRoot = maj->next;
+ if (l_bestBet == maj) l_bestBet = NULL;
+ if (maj->prev != NULL) maj->prev->next = maj->next;
+ if (maj->next != NULL) maj->next->prev = maj->prev;
+ l_allocated -= maj->size;
+ liballoc_free(maj, maj->pages);
+ } else {
+ if (l_bestBet != NULL) {
+ int bestSize = l_bestBet->size - l_bestBet->usage;
+ int majSize = maj->size - maj->usage;
+ if (majSize > bestSize) l_bestBet = maj;
+ }
+ }
+ liballoc_unlock();
+}
+
+void *PREFIX(calloc)(size_t nobj, size_t size) {
+ int real_size;
+ void *p;
+
+ real_size = nobj * size;
+
+ p = PREFIX(malloc)(real_size);
+
+ liballoc_memset(p, 0, real_size);
+
+ return p;
+}
+
+void *PREFIX(realloc)(void *p, size_t size) {
+ void *ptr;
+ struct liballoc_minor *min;
+ unsigned int real_size;
+
+ if (size == 0) {
+ PREFIX(free)(p);
+ return NULL;
+ }
+
+ if (p == NULL) return PREFIX(malloc)(size);
+
+ ptr = p;
+ UNALIGN(ptr);
+ liballoc_lock();
+ min = (struct liballoc_minor *) ((uintptr_t) ptr - sizeof(struct liballoc_minor));
+
+ if (min->magic != LIBALLOC_MAGIC) {
+ l_errorCount += 1;
+ if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
+ ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
+ ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
+ l_possibleOverruns += 1;
+ }
+
+ liballoc_unlock();
+ return NULL;
+ }
+
+ real_size = min->req_size;
+
+ if (real_size >= size) {
+ min->req_size = size;
+ liballoc_unlock();
+ return p;
+ }
+
+ liballoc_unlock();
+
+ ptr = PREFIX(malloc)(size);
+ liballoc_memcpy(ptr, p, real_size);
+ PREFIX(free)(p);
+
+ return ptr;
+}
diff --git a/src/mlibc/stdlib/liballoc.h b/src/mlibc/stdlib/liballoc.h
new file mode 100644
index 0000000..6ed9efb
--- /dev/null
+++ b/src/mlibc/stdlib/liballoc.h
@@ -0,0 +1,24 @@
+#ifndef MELVIX_ALLOC_H
+#define MELVIX_ALLOC_H
+
+#include <stddef.h>
+
+#define PREFIX(func) k ## func
+
+int liballoc_lock();
+
+int liballoc_unlock();
+
+void *liballoc_alloc(size_t);
+
+int liballoc_free(void *, size_t);
+
+void *PREFIX(malloc)(size_t);
+
+void *PREFIX(realloc)(void *, size_t);
+
+void *PREFIX(calloc)(size_t, size_t);
+
+void PREFIX(free)(void *);
+
+#endif
diff --git a/src/mlibc/string.h b/src/mlibc/string.h
new file mode 100644
index 0000000..fe925cb
--- /dev/null
+++ b/src/mlibc/string.h
@@ -0,0 +1,22 @@
+#ifndef MELVIX_STRING_H
+#define MELVIX_STRING_H
+
+#include <stddef.h>
+
+size_t strlen(const char *str);
+
+void strcpy(char *dest, const char *orig);
+
+void strdisp(char *str, int n);
+
+void strcat(char *dest, const char *orig);
+
+void strcati(char *dest, const char *orig);
+
+char strcmp(const char *a, const char *b);
+
+char *strdup(const char *orig);
+
+void strinv(char *str);
+
+#endif
diff --git a/src/mlibc/string/strcat.c b/src/mlibc/string/strcat.c
new file mode 100644
index 0000000..3cc56f1
--- /dev/null
+++ b/src/mlibc/string/strcat.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+
+void strcat(char *dest, const char *orig) {
+ size_t s_dest = strlen(dest);
+ size_t s_orig = strlen(orig);
+
+ for (size_t i = 0; i < s_orig; i++) dest[s_dest + i] = orig[i];
+ dest[s_dest + s_orig] = 0;
+} \ No newline at end of file
diff --git a/src/mlibc/string/strcati.c b/src/mlibc/string/strcati.c
new file mode 100644
index 0000000..d925eb7
--- /dev/null
+++ b/src/mlibc/string/strcati.c
@@ -0,0 +1,7 @@
+#include <mlibc/string.h>
+
+void strcati(char *dest, const char *orig) {
+ size_t s_orig = strlen(orig);
+ strdisp(dest, (int) s_orig);
+ for (size_t i = 0; i < s_orig; i++) dest[i] = orig[i];
+} \ No newline at end of file
diff --git a/src/mlibc/string/strcmp.c b/src/mlibc/string/strcmp.c
new file mode 100644
index 0000000..cc719da
--- /dev/null
+++ b/src/mlibc/string/strcmp.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+
+char strcmp(const char *a, const char *b) {
+ if (strlen(a) != strlen(b)) return 1;
+
+ for (size_t i = 0; i < strlen(a); i++) if (a[i] != b[i]) return 1;
+
+ return 0;
+} \ No newline at end of file
diff --git a/src/mlibc/string/strcpy.c b/src/mlibc/string/strcpy.c
new file mode 100644
index 0000000..5a1ff4e
--- /dev/null
+++ b/src/mlibc/string/strcpy.c
@@ -0,0 +1,8 @@
+#include <mlibc/string.h>
+
+void strcpy(char *dest, const char *orig) {
+ size_t s_orig = strlen(orig);
+
+ for (size_t i = 0; i < s_orig; i++) dest[i] = orig[i];
+ dest[s_orig] = 0;
+} \ No newline at end of file
diff --git a/src/mlibc/string/strdisp.c b/src/mlibc/string/strdisp.c
new file mode 100644
index 0000000..6feb4ca
--- /dev/null
+++ b/src/mlibc/string/strdisp.c
@@ -0,0 +1,10 @@
+#include <mlibc/string.h>
+
+void strdisponce(char *str) {
+ for (size_t i = sizeof(str) + 2; i > 0; i--) str[i] = str[i - 1];
+ str[0] = 0;
+}
+
+void strdisp(char *str, int n) {
+ for (int i = 0; i < n; i++) strdisponce(str);
+} \ No newline at end of file
diff --git a/src/mlibc/string/strdup.c b/src/mlibc/string/strdup.c
new file mode 100644
index 0000000..0cddd79
--- /dev/null
+++ b/src/mlibc/string/strdup.c
@@ -0,0 +1,9 @@
+#include <mlibc/string.h>
+#include <mlibc/stdlib.h>
+
+char *strdup(const char *orig) {
+ size_t s_orig = strlen(orig);
+ char *ret = kmalloc(s_orig + 1);
+ strcpy(ret, orig);
+ return ret;
+} \ No newline at end of file
diff --git a/src/mlibc/string/strinv.c b/src/mlibc/string/strinv.c
new file mode 100644
index 0000000..c6dd7fd
--- /dev/null
+++ b/src/mlibc/string/strinv.c
@@ -0,0 +1,12 @@
+#include <mlibc/string.h>
+
+void strinv(char *str) {
+ size_t s_str = strlen(str);
+
+ int iterations = (int) s_str / 2;
+ for (int i = 0; i < iterations; i++) {
+ char aux = str[i];
+ str[i] = str[(s_str - i) - 1];
+ str[(s_str - i) - 1] = aux;
+ }
+} \ No newline at end of file
diff --git a/src/mlibc/string/strlen.c b/src/mlibc/string/strlen.c
new file mode 100644
index 0000000..1143683
--- /dev/null
+++ b/src/mlibc/string/strlen.c
@@ -0,0 +1,7 @@
+#include <mlibc/string.h>
+
+size_t strlen(const char *str) {
+ size_t len = 0;
+ while (str[len]) len++;
+ return len;
+} \ No newline at end of file