113 lines
2.1 KiB
C
113 lines
2.1 KiB
C
|
|
#include "liballoc.h"
|
||
|
|
|
||
|
|
#include <heap/heap.h>
|
||
|
|
#include <mango/handle.h>
|
||
|
|
#include <mango/log.h>
|
||
|
|
#include <mango/status.h>
|
||
|
|
#include <mango/task.h>
|
||
|
|
#include <mango/vm.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
#define HEAP_REGION_SIZE 0x40000000
|
||
|
|
#define HEAP_EXPAND_INCREMENT 0x100000
|
||
|
|
|
||
|
|
void *heap_alloc(heap_t *heap, size_t sz)
|
||
|
|
{
|
||
|
|
return _lbmalloc(heap, sz);
|
||
|
|
}
|
||
|
|
|
||
|
|
void *heap_realloc(heap_t *heap, void *p, size_t sz)
|
||
|
|
{
|
||
|
|
return _lbrealloc(heap, p, sz);
|
||
|
|
}
|
||
|
|
|
||
|
|
void *heap_calloc(heap_t *heap, size_t num, size_t itemsz)
|
||
|
|
{
|
||
|
|
return _lbcalloc(heap, num, itemsz);
|
||
|
|
}
|
||
|
|
|
||
|
|
void heap_free(heap_t *heap, void *p)
|
||
|
|
{
|
||
|
|
_lbfree(heap, p);
|
||
|
|
}
|
||
|
|
|
||
|
|
static kern_status_t init_heap_region(heap_t *heap)
|
||
|
|
{
|
||
|
|
kern_handle_t self, address_space;
|
||
|
|
task_self(&self);
|
||
|
|
task_get_address_space(self, &address_space);
|
||
|
|
kern_handle_close(self);
|
||
|
|
|
||
|
|
kern_status_t status = vm_region_create(
|
||
|
|
address_space,
|
||
|
|
"libc-heap",
|
||
|
|
9,
|
||
|
|
VM_REGION_ANY_OFFSET,
|
||
|
|
HEAP_REGION_SIZE,
|
||
|
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||
|
|
&heap->heap_region,
|
||
|
|
&heap->heap_base);
|
||
|
|
|
||
|
|
kern_handle_close(address_space);
|
||
|
|
|
||
|
|
if (status != KERN_OK) {
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
return KERN_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static kern_status_t expand_heap(heap_t *heap)
|
||
|
|
{
|
||
|
|
kern_handle_t vmo;
|
||
|
|
kern_status_t status = vm_object_create(
|
||
|
|
"libc-heap-data",
|
||
|
|
14,
|
||
|
|
HEAP_EXPAND_INCREMENT,
|
||
|
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||
|
|
&vmo);
|
||
|
|
if (status != KERN_OK) {
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
virt_addr_t base = 0;
|
||
|
|
|
||
|
|
status = vm_region_map_relative(
|
||
|
|
heap->heap_region,
|
||
|
|
heap->heap_sys_alloc,
|
||
|
|
vmo,
|
||
|
|
0,
|
||
|
|
HEAP_EXPAND_INCREMENT,
|
||
|
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||
|
|
&base);
|
||
|
|
|
||
|
|
kern_handle_close(vmo);
|
||
|
|
|
||
|
|
heap->heap_sys_alloc += HEAP_EXPAND_INCREMENT;
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *heap_expand(heap_t *heap, size_t size)
|
||
|
|
{
|
||
|
|
kern_status_t status = KERN_OK;
|
||
|
|
if (heap->heap_region == KERN_HANDLE_INVALID) {
|
||
|
|
status = init_heap_region(heap);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (status != KERN_OK) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
while (heap->heap_req_alloc + size > heap->heap_sys_alloc) {
|
||
|
|
status = expand_heap(heap);
|
||
|
|
if (status != KERN_OK) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void *p = (void *)(heap->heap_base + heap->heap_req_alloc);
|
||
|
|
heap->heap_req_alloc += size;
|
||
|
|
|
||
|
|
return p;
|
||
|
|
}
|