Compare commits
2 Commits
9fc8521e63
...
11a1eb52aa
| Author | SHA1 | Date | |
|---|---|---|---|
| 11a1eb52aa | |||
| a054257336 |
13
include/m/status.h
Normal file
13
include/m/status.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _M_STATUS_H
|
||||
#define _M_STATUS_H
|
||||
|
||||
#define ST_OK 0
|
||||
#define ST_SYSCALL_NOT_FOUND 1
|
||||
#define ST_UNALIGNED 2
|
||||
#define ST_OOM_ERROR 3
|
||||
#define ST_NOT_FOUND 4
|
||||
#define ST_BAD_ADDRESS_SPACE 5
|
||||
#define ST_PERMISSION_ERROR 6
|
||||
#define ST_BAD_RESOURCE 7
|
||||
|
||||
#endif // _M_STATUS_H
|
||||
@@ -13,13 +13,4 @@
|
||||
#define SYS_PROC_SPAWN_THREAD 10
|
||||
#define SYS_PROC_SCHED 11
|
||||
|
||||
#define SR_OK 0
|
||||
#define SR_SYSCALL_NOT_FOUND 1
|
||||
#define SR_UNALIGNED 2
|
||||
#define SR_OOM_ERROR 3
|
||||
#define SR_NOT_FOUND 4
|
||||
#define SR_BAD_ADDRESS_SPACE 5
|
||||
#define SR_PERMISSION_ERROR 6
|
||||
#define SR_BAD_RESOURCE 7
|
||||
|
||||
#endif // _M_SYSCALL_DEFS_H
|
||||
|
||||
19
init/init.c
19
init/init.c
@@ -1,5 +1,7 @@
|
||||
#include <alloc/liballoc.h>
|
||||
#include <limits.h>
|
||||
#include <m/proc.h>
|
||||
#include <m/status.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string/string.h>
|
||||
@@ -16,17 +18,14 @@ void mythread (void) {
|
||||
}
|
||||
}
|
||||
|
||||
void make_thread (void* fn) {
|
||||
size_t stack_pages = 256;
|
||||
size_t stack_size = PAGE_SIZE * stack_pages;
|
||||
int make_thread (void (*fn) (void)) {
|
||||
size_t stack_size = 256 * PAGE_SIZE;
|
||||
void* stack = malloc (stack_size);
|
||||
if (stack == NULL)
|
||||
return -ST_OOM_ERROR;
|
||||
|
||||
uintptr_t out_paddr;
|
||||
int mem_rid = proc_create_resource_mem (100, stack_pages, RV_PRIVATE, &out_paddr);
|
||||
proc_map (out_paddr, PROC_MAP_BASE, stack_pages, PM_PRESENT | PM_RW | PM_USER);
|
||||
memset ((void*)PROC_MAP_BASE, 0, stack_size);
|
||||
|
||||
uintptr_t vstack_top = PROC_MAP_BASE + stack_size;
|
||||
proc_spawn_thread (vstack_top, stack_size, fn);
|
||||
uintptr_t stack_top = (uintptr_t)stack + stack_size;
|
||||
return proc_spawn_thread (stack_top, stack_size, (void*)fn);
|
||||
}
|
||||
|
||||
void app_main (void) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <amd64/mm.h>
|
||||
#include <amd64/msr-index.h>
|
||||
#include <amd64/msr.h>
|
||||
#include <m/status.h>
|
||||
#include <m/syscall_defs.h>
|
||||
#include <proc/proc.h>
|
||||
#include <sys/debug.h>
|
||||
@@ -20,7 +21,7 @@ int amd64_syscall_dispatch (void* stack_ptr) {
|
||||
syscall_handler_func_t func = syscall_find_handler (syscall_num);
|
||||
|
||||
if (func == NULL)
|
||||
return -SR_SYSCALL_NOT_FOUND;
|
||||
return -ST_SYSCALL_NOT_FOUND;
|
||||
|
||||
struct proc* caller = thiscpu->proc_current;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <aux/compiler.h>
|
||||
#include <libk/std.h>
|
||||
#include <limine/requests.h>
|
||||
#include <m/status.h>
|
||||
#include <m/syscall_defs.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <proc/mutex.h>
|
||||
@@ -19,14 +20,14 @@
|
||||
/* int proc_quit (void) */
|
||||
DEFINE_SYSCALL (sys_proc_quit) {
|
||||
proc_kill (proc, regs);
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
/* int proc_test (void) */
|
||||
DEFINE_SYSCALL (sys_proc_test) {
|
||||
char c = (char)a1;
|
||||
DEBUG ("test syscall from %d! %c\n", proc->pid, c);
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
/* int proc_map (uintptr_t paddr, uintptr_t vaddr, size_t pages, uint32_t flags) */
|
||||
@@ -37,13 +38,13 @@ DEFINE_SYSCALL (sys_proc_map) {
|
||||
uint32_t flags = (uint32_t)a4;
|
||||
|
||||
if (vaddr % PAGE_SIZE != 0)
|
||||
return -SR_UNALIGNED;
|
||||
return -ST_UNALIGNED;
|
||||
|
||||
if (paddr % PAGE_SIZE != 0)
|
||||
return -SR_UNALIGNED;
|
||||
return -ST_UNALIGNED;
|
||||
|
||||
bool ok = proc_map (proc, paddr, vaddr, pages, flags);
|
||||
return ok ? SR_OK : -SR_OOM_ERROR;
|
||||
return ok ? ST_OK : -ST_OOM_ERROR;
|
||||
}
|
||||
|
||||
/* int proc_unmap (uintptr_t vaddr, size_t pages) */
|
||||
@@ -52,10 +53,10 @@ DEFINE_SYSCALL (sys_proc_unmap) {
|
||||
size_t pages = (size_t)a2;
|
||||
|
||||
if (vaddr % PAGE_SIZE != 0)
|
||||
return -SR_UNALIGNED;
|
||||
return -ST_UNALIGNED;
|
||||
|
||||
bool ok = proc_unmap (proc, vaddr, pages);
|
||||
return ok ? SR_OK : -SR_OOM_ERROR;
|
||||
return ok ? ST_OK : -ST_OOM_ERROR;
|
||||
}
|
||||
|
||||
/* int proc_create_resource_mem (int rid, size_t pages, int vis, uintptr_t* out_paddr) */
|
||||
@@ -69,7 +70,7 @@ DEFINE_SYSCALL (sys_proc_create_resource_mem) {
|
||||
uintptr_t* out_paddr_buf = (uintptr_t*)a4;
|
||||
|
||||
if (rid < 0)
|
||||
return -SR_BAD_RESOURCE;
|
||||
return -ST_BAD_RESOURCE;
|
||||
|
||||
spin_lock (&proc->pd->lock, &ctxprpd);
|
||||
|
||||
@@ -77,7 +78,7 @@ DEFINE_SYSCALL (sys_proc_create_resource_mem) {
|
||||
|
||||
if (!mm_validate_buffer (proc->pd, (uintptr_t)out_paddr_buf, sizeof (uintptr_t), 0)) {
|
||||
spin_unlock (&proc->pd->lock, &ctxprpd);
|
||||
return -SR_BAD_ADDRESS_SPACE;
|
||||
return -ST_BAD_ADDRESS_SPACE;
|
||||
}
|
||||
|
||||
spin_unlock (&proc->pd->lock, &ctxprpd);
|
||||
@@ -91,7 +92,7 @@ DEFINE_SYSCALL (sys_proc_create_resource_mem) {
|
||||
*out_paddr_buf_vaddr = r->u.mem.paddr;
|
||||
return r->rid;
|
||||
} else {
|
||||
return -SR_OOM_ERROR;
|
||||
return -ST_OOM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,13 +102,13 @@ DEFINE_SYSCALL (sys_proc_create_resource_mutex) {
|
||||
int vis = (int)a2;
|
||||
|
||||
if (rid < 0)
|
||||
return -SR_BAD_RESOURCE;
|
||||
return -ST_BAD_RESOURCE;
|
||||
|
||||
struct proc_resource* r = proc_create_resource (proc, rid, PR_MUTEX, vis, NULL);
|
||||
if (r != NULL)
|
||||
return r->rid;
|
||||
else
|
||||
return -SR_OOM_ERROR;
|
||||
return -ST_OOM_ERROR;
|
||||
}
|
||||
|
||||
/* int proc_mutex_lock (int mutex_rid) */
|
||||
@@ -122,11 +123,11 @@ DEFINE_SYSCALL (sys_proc_mutex_lock) {
|
||||
spin_unlock (&proc->lock, &ctxpr);
|
||||
|
||||
if (resource == NULL)
|
||||
return -SR_NOT_FOUND;
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
proc_mutex_lock (proc, &resource->u.mutex);
|
||||
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
DEFINE_SYSCALL (sys_proc_mutex_unlock) {
|
||||
@@ -140,15 +141,15 @@ DEFINE_SYSCALL (sys_proc_mutex_unlock) {
|
||||
spin_unlock (&proc->lock, &ctxpr);
|
||||
|
||||
if (resource == NULL)
|
||||
return -SR_NOT_FOUND;
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
int result = proc_mutex_unlock (proc, &resource->u.mutex) ? SR_OK : -SR_PERMISSION_ERROR;
|
||||
int result = proc_mutex_unlock (proc, &resource->u.mutex) ? ST_OK : -ST_PERMISSION_ERROR;
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
proc_sched (regs);
|
||||
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
/* int proc_drop_resource (int rid) */
|
||||
@@ -163,11 +164,11 @@ DEFINE_SYSCALL (sys_proc_drop_resource) {
|
||||
spin_unlock (&proc->lock, &ctxpr);
|
||||
|
||||
if (resource == NULL)
|
||||
return -SR_NOT_FOUND;
|
||||
return -ST_NOT_FOUND;
|
||||
|
||||
proc_drop_resource (proc, resource);
|
||||
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
/* int proc_spawn_thread (uintptr_t vstack_top, size_t stack_size, void* entry) */
|
||||
@@ -183,7 +184,7 @@ DEFINE_SYSCALL (sys_proc_spawn_thread) {
|
||||
DEBUG ("new=%p\n", new);
|
||||
|
||||
if (new == NULL) {
|
||||
return -SR_OOM_ERROR;
|
||||
return -ST_OOM_ERROR;
|
||||
}
|
||||
|
||||
int pid = new->pid;
|
||||
@@ -196,7 +197,7 @@ DEFINE_SYSCALL (sys_proc_spawn_thread) {
|
||||
/* int proc_sched (void) */
|
||||
DEFINE_SYSCALL (sys_proc_sched) {
|
||||
proc_sched (regs);
|
||||
return SR_OK;
|
||||
return ST_OK;
|
||||
}
|
||||
|
||||
static syscall_handler_func_t handler_table[] = {
|
||||
|
||||
1
libmsl/alloc/.gitignore
vendored
Normal file
1
libmsl/alloc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.o
|
||||
406
libmsl/alloc/liballoc.c
Normal file
406
libmsl/alloc/liballoc.c
Normal file
@@ -0,0 +1,406 @@
|
||||
/* liballoc breaks when optimized too aggressively, for eg. clang's -Oz */
|
||||
#pragma clang optimize off
|
||||
|
||||
#include <alloc/liballoc.h>
|
||||
#include <m/proc.h>
|
||||
|
||||
static int liballoc_mutex;
|
||||
static uintptr_t liballoc_map_base = PROC_MAP_BASE;
|
||||
static int mem_rid_base = 10000;
|
||||
|
||||
void liballoc_init (void) { liballoc_mutex = proc_create_resource_mutex (100, RV_PRIVATE); }
|
||||
|
||||
int liballoc_lock (void) {
|
||||
proc_mutex_lock (liballoc_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int liballoc_unlock (void) {
|
||||
proc_mutex_unlock (liballoc_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* liballoc_alloc (int pages) {
|
||||
uintptr_t current_base = liballoc_map_base;
|
||||
uintptr_t out_paddr;
|
||||
|
||||
int mem_rid = proc_create_resource_mem (mem_rid_base++, pages, RV_PRIVATE, &out_paddr);
|
||||
if (mem_rid < 0)
|
||||
return NULL;
|
||||
|
||||
proc_map (out_paddr, current_base, pages, PM_PRESENT | PM_RW | PM_USER);
|
||||
|
||||
uintptr_t old_base = current_base;
|
||||
current_base += pages * PAGE_SIZE;
|
||||
|
||||
return (void*)old_base;
|
||||
}
|
||||
|
||||
int liballoc_free (void* ptr, int pages) { return 0; }
|
||||
|
||||
/** Durand's Ridiculously Amazing Super Duper Memory functions. */
|
||||
|
||||
// #define DEBUG
|
||||
|
||||
#define LIBALLOC_MAGIC 0xc001c0de
|
||||
#define MAXCOMPLETE 5
|
||||
#define MAXEXP 32
|
||||
#define MINEXP 8
|
||||
|
||||
#define MODE_BEST 0
|
||||
#define MODE_INSTANT 1
|
||||
|
||||
#define MODE MODE_BEST
|
||||
|
||||
struct boundary_tag* l_freePages[MAXEXP]; //< Allowing for 2^MAXEXP blocks
|
||||
int l_completePages[MAXEXP]; //< Allowing for 2^MAXEXP blocks
|
||||
|
||||
static int l_initialized = 0; //< Flag to indicate initialization.
|
||||
static int l_pageSize = PAGE_SIZE; //< Individual page size
|
||||
static int l_pageCount = 16; //< Minimum number of pages to allocate.
|
||||
|
||||
// *********** HELPER FUNCTIONS *******************************
|
||||
|
||||
/** Returns the exponent required to manage 'size' amount of memory.
|
||||
*
|
||||
* Returns n where 2^n <= size < 2^(n+1)
|
||||
*/
|
||||
static inline int getexp (unsigned int size) {
|
||||
if (size < (1 << MINEXP)) {
|
||||
return -1; // Smaller than the quantum.
|
||||
}
|
||||
|
||||
int shift = MINEXP;
|
||||
|
||||
while (shift < MAXEXP) {
|
||||
if ((1 << shift) > size)
|
||||
break;
|
||||
shift += 1;
|
||||
}
|
||||
|
||||
return shift - 1;
|
||||
}
|
||||
|
||||
static void* liballoc_memset (void* s, int c, size_t n) {
|
||||
size_t 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 inline void insert_tag (struct boundary_tag* tag, int index) {
|
||||
int realIndex;
|
||||
|
||||
if (index < 0) {
|
||||
realIndex = getexp (tag->real_size - sizeof (struct boundary_tag));
|
||||
if (realIndex < MINEXP)
|
||||
realIndex = MINEXP;
|
||||
} else
|
||||
realIndex = index;
|
||||
|
||||
tag->index = realIndex;
|
||||
|
||||
if (l_freePages[realIndex] != NULL) {
|
||||
l_freePages[realIndex]->prev = tag;
|
||||
tag->next = l_freePages[realIndex];
|
||||
}
|
||||
|
||||
l_freePages[realIndex] = tag;
|
||||
}
|
||||
|
||||
static inline void remove_tag (struct boundary_tag* tag) {
|
||||
if (l_freePages[tag->index] == tag)
|
||||
l_freePages[tag->index] = tag->next;
|
||||
|
||||
if (tag->prev != NULL)
|
||||
tag->prev->next = tag->next;
|
||||
if (tag->next != NULL)
|
||||
tag->next->prev = tag->prev;
|
||||
|
||||
tag->next = NULL;
|
||||
tag->prev = NULL;
|
||||
tag->index = -1;
|
||||
}
|
||||
|
||||
static inline struct boundary_tag* melt_left (struct boundary_tag* tag) {
|
||||
struct boundary_tag* left = tag->split_left;
|
||||
|
||||
left->real_size += tag->real_size;
|
||||
left->split_right = tag->split_right;
|
||||
|
||||
if (tag->split_right != NULL)
|
||||
tag->split_right->split_left = left;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static inline struct boundary_tag* absorb_right (struct boundary_tag* tag) {
|
||||
struct boundary_tag* right = tag->split_right;
|
||||
|
||||
remove_tag (right); // Remove right from free pages.
|
||||
|
||||
tag->real_size += right->real_size;
|
||||
|
||||
tag->split_right = right->split_right;
|
||||
if (right->split_right != NULL)
|
||||
right->split_right->split_left = tag;
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static inline struct boundary_tag* split_tag (struct boundary_tag* tag) {
|
||||
unsigned int remainder = tag->real_size - sizeof (struct boundary_tag) - tag->size;
|
||||
|
||||
struct boundary_tag* new_tag =
|
||||
(struct boundary_tag*)((uintptr_t)tag + sizeof (struct boundary_tag) + tag->size);
|
||||
|
||||
new_tag->magic = LIBALLOC_MAGIC;
|
||||
new_tag->real_size = remainder;
|
||||
|
||||
new_tag->next = NULL;
|
||||
new_tag->prev = NULL;
|
||||
|
||||
new_tag->split_left = tag;
|
||||
new_tag->split_right = tag->split_right;
|
||||
|
||||
if (new_tag->split_right != NULL)
|
||||
new_tag->split_right->split_left = new_tag;
|
||||
tag->split_right = new_tag;
|
||||
|
||||
tag->real_size -= new_tag->real_size;
|
||||
|
||||
insert_tag (new_tag, -1);
|
||||
|
||||
return new_tag;
|
||||
}
|
||||
|
||||
// ***************************************************************
|
||||
|
||||
static struct boundary_tag* allocate_new_tag (unsigned int size) {
|
||||
unsigned int pages;
|
||||
unsigned int usage;
|
||||
struct boundary_tag* tag;
|
||||
|
||||
// This is how much space is required.
|
||||
usage = size + sizeof (struct boundary_tag);
|
||||
|
||||
// Perfect amount of space
|
||||
pages = usage / l_pageSize;
|
||||
if ((usage % l_pageSize) != 0)
|
||||
pages += 1;
|
||||
|
||||
// Make sure it's >= the minimum size.
|
||||
if (pages < (unsigned int)l_pageCount)
|
||||
pages = l_pageCount;
|
||||
|
||||
tag = (struct boundary_tag*)liballoc_alloc (pages);
|
||||
|
||||
if (tag == NULL)
|
||||
return NULL; // uh oh, we ran out of memory.
|
||||
|
||||
tag->magic = LIBALLOC_MAGIC;
|
||||
tag->size = size;
|
||||
tag->real_size = pages * l_pageSize;
|
||||
tag->index = -1;
|
||||
|
||||
tag->next = NULL;
|
||||
tag->prev = NULL;
|
||||
tag->split_left = NULL;
|
||||
tag->split_right = NULL;
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
void* malloc (size_t size) {
|
||||
int index;
|
||||
void* ptr;
|
||||
struct boundary_tag* tag = NULL;
|
||||
|
||||
liballoc_lock ();
|
||||
|
||||
if (l_initialized == 0) {
|
||||
for (index = 0; index < MAXEXP; index++) {
|
||||
l_freePages[index] = NULL;
|
||||
l_completePages[index] = 0;
|
||||
}
|
||||
l_initialized = 1;
|
||||
}
|
||||
|
||||
index = getexp (size) + MODE;
|
||||
if (index < MINEXP)
|
||||
index = MINEXP;
|
||||
|
||||
// Find one big enough.
|
||||
tag = l_freePages[index]; // Start at the front of the list.
|
||||
while (tag != NULL) {
|
||||
// If there's enough space in this tag.
|
||||
if ((tag->real_size - sizeof (struct boundary_tag)) >= (size + sizeof (struct boundary_tag))) {
|
||||
break;
|
||||
}
|
||||
|
||||
tag = tag->next;
|
||||
}
|
||||
|
||||
// No page found. Make one.
|
||||
if (tag == NULL) {
|
||||
if ((tag = allocate_new_tag (size)) == NULL) {
|
||||
liballoc_unlock ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index = getexp (tag->real_size - sizeof (struct boundary_tag));
|
||||
} else {
|
||||
remove_tag (tag);
|
||||
|
||||
if ((tag->split_left == NULL) && (tag->split_right == NULL))
|
||||
l_completePages[index] -= 1;
|
||||
}
|
||||
|
||||
// We have a free page. Remove it from the free pages list.
|
||||
|
||||
tag->size = size;
|
||||
|
||||
// Removed... see if we can re-use the excess space.
|
||||
|
||||
unsigned int remainder =
|
||||
tag->real_size - size - sizeof (struct boundary_tag) * 2; // Support a new tag + remainder
|
||||
|
||||
if (((int)(remainder) > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/) {
|
||||
int childIndex = getexp (remainder);
|
||||
|
||||
if (childIndex >= 0) {
|
||||
struct boundary_tag* new_tag = split_tag (tag);
|
||||
|
||||
(void)new_tag;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = (void*)((uintptr_t)tag + sizeof (struct boundary_tag));
|
||||
|
||||
liballoc_unlock ();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free (void* ptr) {
|
||||
int index;
|
||||
struct boundary_tag* tag;
|
||||
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
|
||||
liballoc_lock ();
|
||||
|
||||
tag = (struct boundary_tag*)((uintptr_t)ptr - sizeof (struct boundary_tag));
|
||||
|
||||
if (tag->magic != LIBALLOC_MAGIC) {
|
||||
liballoc_unlock (); // release the lock
|
||||
return;
|
||||
}
|
||||
|
||||
// MELT LEFT...
|
||||
while ((tag->split_left != NULL) && (tag->split_left->index >= 0)) {
|
||||
tag = melt_left (tag);
|
||||
remove_tag (tag);
|
||||
}
|
||||
|
||||
// MELT RIGHT...
|
||||
while ((tag->split_right != NULL) && (tag->split_right->index >= 0)) {
|
||||
tag = absorb_right (tag);
|
||||
}
|
||||
|
||||
// Where is it going back to?
|
||||
index = getexp (tag->real_size - sizeof (struct boundary_tag));
|
||||
if (index < MINEXP)
|
||||
index = MINEXP;
|
||||
|
||||
// A whole, empty block?
|
||||
if ((tag->split_left == NULL) && (tag->split_right == NULL)) {
|
||||
if (l_completePages[index] == MAXCOMPLETE) {
|
||||
// Too many standing by to keep. Free this one.
|
||||
unsigned int pages = tag->real_size / l_pageSize;
|
||||
|
||||
if ((tag->real_size % l_pageSize) != 0)
|
||||
pages += 1;
|
||||
if (pages < (unsigned int)l_pageCount)
|
||||
pages = l_pageCount;
|
||||
|
||||
liballoc_free (tag, pages);
|
||||
|
||||
liballoc_unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
l_completePages[index] += 1; // Increase the count of complete pages.
|
||||
}
|
||||
|
||||
// ..........
|
||||
|
||||
insert_tag (tag, index);
|
||||
|
||||
liballoc_unlock ();
|
||||
}
|
||||
|
||||
void* calloc (size_t nobj, size_t size) {
|
||||
int real_size;
|
||||
void* p;
|
||||
|
||||
real_size = nobj * size;
|
||||
|
||||
p = malloc (real_size);
|
||||
|
||||
liballoc_memset (p, 0, real_size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void* realloc (void* p, size_t size) {
|
||||
void* ptr;
|
||||
struct boundary_tag* tag;
|
||||
int real_size;
|
||||
|
||||
if (size == 0) {
|
||||
free (p);
|
||||
return NULL;
|
||||
}
|
||||
if (p == NULL)
|
||||
return malloc (size);
|
||||
|
||||
if (&liballoc_lock != NULL)
|
||||
liballoc_lock (); // lockit
|
||||
tag = (struct boundary_tag*)((uintptr_t)p - sizeof (struct boundary_tag));
|
||||
real_size = tag->size;
|
||||
if (&liballoc_unlock != NULL)
|
||||
liballoc_unlock ();
|
||||
|
||||
if ((size_t)real_size > size)
|
||||
real_size = size;
|
||||
|
||||
ptr = malloc (size);
|
||||
liballoc_memcpy (ptr, p, real_size);
|
||||
free (p);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
93
libmsl/alloc/liballoc.h
Normal file
93
libmsl/alloc/liballoc.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef _LIBALLOC_H
|
||||
#define _LIBALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define _ALLOC_SKIP_DEFINE
|
||||
|
||||
// If we are told to not define our own size_t, then we
|
||||
// skip the define.
|
||||
#ifndef _ALLOC_SKIP_DEFINE
|
||||
|
||||
#ifndef _HAVE_SIZE_T
|
||||
#define _HAVE_SIZE_T
|
||||
typedef unsigned int size_t;
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** This is a boundary tag which is prepended to the
|
||||
* page or section of a page which we have allocated. It is
|
||||
* used to identify valid memory blocks that the
|
||||
* application is trying to free.
|
||||
*/
|
||||
struct boundary_tag {
|
||||
unsigned int magic; //< It's a kind of ...
|
||||
unsigned int size; //< Requested size.
|
||||
unsigned int real_size; //< Actual size.
|
||||
int index; //< Location in the page table.
|
||||
|
||||
struct boundary_tag* split_left; //< Linked-list info for broken pages.
|
||||
struct boundary_tag* split_right; //< The same.
|
||||
|
||||
struct boundary_tag* next; //< Linked list info.
|
||||
struct boundary_tag* prev; //< Linked list info.
|
||||
};
|
||||
|
||||
/** This function is supposed to lock the memory data structures. It
|
||||
* could be as simple as disabling interrupts or acquiring a spinlock.
|
||||
* It's up to you to decide.
|
||||
*
|
||||
* \return 0 if the lock was acquired successfully. Anything else is
|
||||
* failure.
|
||||
*/
|
||||
extern int liballoc_lock (void);
|
||||
|
||||
/** This function unlocks what was previously locked by the liballoc_lock
|
||||
* function. If it disabled interrupts, it enables interrupts. If it
|
||||
* had acquiried a spinlock, it releases the spinlock. etc.
|
||||
*
|
||||
* \return 0 if the lock was successfully released.
|
||||
*/
|
||||
extern int liballoc_unlock (void);
|
||||
|
||||
/** This is the hook into the local system which allocates pages. It
|
||||
* accepts an integer parameter which is the number of pages
|
||||
* required. The page size was set up in the liballoc_init function.
|
||||
*
|
||||
* \return NULL if the pages were not allocated.
|
||||
* \return A pointer to the allocated memory.
|
||||
*/
|
||||
extern void* liballoc_alloc (int);
|
||||
|
||||
/** This frees previously allocated memory. The void* parameter passed
|
||||
* to the function is the exact same value returned from a previous
|
||||
* liballoc_alloc call.
|
||||
*
|
||||
* The integer value is the number of pages to free.
|
||||
*
|
||||
* \return 0 if the memory was successfully freed.
|
||||
*/
|
||||
extern int liballoc_free (void*, int);
|
||||
|
||||
void* malloc (size_t); //< The standard function.
|
||||
void* realloc (void*, size_t); //< The standard function.
|
||||
void* calloc (size_t, size_t); //< The standard function.
|
||||
void free (void*); //< The standard function.
|
||||
|
||||
void liballoc_init (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
3
libmsl/alloc/src.mk
Normal file
3
libmsl/alloc/src.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
c += alloc/liballoc.c
|
||||
|
||||
o += alloc/liballoc.o
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <alloc/liballoc.h>
|
||||
#include <m/proc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -15,6 +16,7 @@ static void clear_bss (void) {
|
||||
|
||||
void __premain (void) {
|
||||
clear_bss ();
|
||||
liballoc_init ();
|
||||
|
||||
app_main ();
|
||||
|
||||
|
||||
@@ -27,5 +27,6 @@ int proc_mutex_lock (int mutex_rid);
|
||||
int proc_mutex_unlock (int mutex_rid);
|
||||
int proc_spawn_thread (uintptr_t vstack_top, size_t stack_size, void* entry);
|
||||
int proc_sched (void);
|
||||
int proc_translate_resource_mem (uintptr_t vaddr);
|
||||
|
||||
#endif // _LIBMSL_M_PROC_H
|
||||
|
||||
@@ -2,3 +2,4 @@ include $(platform)/src.mk
|
||||
include init/src.mk
|
||||
include m/src.mk
|
||||
include string/src.mk
|
||||
include alloc/src.mk
|
||||
|
||||
Reference in New Issue
Block a user