Commit e6d5a6cb authored by Léo Grange's avatar Léo Grange

sbrk() now use memory areas to implement heap

parent 3e6b70c5
......@@ -145,7 +145,6 @@ int elfloader_load_all(struct file *filep, void *offset, struct process *dest,
if(flags & ELF_LOAD_SET_BRK) {
dest->initial_brk = cur_brk;
dest->current_brk = cur_brk;
}
}
}
......
......@@ -125,7 +125,7 @@ struct process *process_alloc() {
proc->kticks = 0;
proc->initial_brk = NULL;
proc->current_brk = NULL;
proc->heap_area = NULL;
#ifdef CONFIG_ELF_SHARED
proc->shared.file = NULL;
......@@ -289,6 +289,11 @@ pid_t sys_fork() {
new_area = mem_area_alloc();
*new_area = *old_area;
mem_area_insert(newproc, new_area);
// check for heap, and translate to corresponding area
if(old_area == cur->heap_area) {
newproc->heap_area = new_area;
}
}
// copy each memory page with same virtual addresses
......@@ -305,6 +310,7 @@ pid_t sys_fork() {
// TODO shared pages
}
}
newproc->initial_brk = cur->initial_brk;
// copy signal info
sigemptyset(& newproc->sig_pending);
......@@ -537,70 +543,64 @@ int sys_execve(const char *filename, char *const argv[], char *const envp[]) {
void *sys_sbrk(int incr) {
// current implementation is pretty simple (no check for stack/shared area)
struct process *cur;
struct mem_area *heap;
cur = process_get_current();
if(cur->initial_brk != NULL) {
void *ret;
heap = cur->heap_area;
if(cur->current_brk == NULL)
cur->current_brk = cur->initial_brk;
ret = cur->current_brk;
// TODO remove initial_brk and dynamical find a good area to set heap
if(heap == NULL && cur->initial_brk != NULL) {
void *real_brk;
size_t brk_align;
printk(LOG_DEBUG, "sbrk: incr=%d\n", incr);
heap = mem_area_alloc();
// add or remove the given size
if(incr > 0) {
// add pages to process if needed
unsigned int curalign;
void *lastpos;
lastpos = cur->current_brk - 1;
curalign = (((unsigned int) lastpos)) % PM_PAGE_BYTES;
if(curalign + incr >= PM_PAGE_BYTES) {
union pm_page page;
void *curvm;
int relincr;
// create heap area, using initial location rounded to page align
brk_align = ((size_t)cur->initial_brk) % PM_PAGE_BYTES;
real_brk = brk_align == 0 ? cur->initial_brk
: cur->initial_brk + (PM_PAGE_BYTES - brk_align);
mem_area_set_anon(heap, real_brk, 0);
mem_area_insert(cur, heap);
relincr = incr - (PM_PAGE_BYTES - curalign);
curvm = lastpos + (PM_PAGE_BYTES - curalign);
cur->heap_area = heap;
page.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID | MEM_PAGE_CACHED;
while(relincr >= 0) {
void *pageaddr;
printk(LOG_DEBUG, "sbrk: created heap memory area\n");
}
// heap area exists (maybe just created)
if(heap != NULL) {
void *ret;
printk(LOG_DEBUG, "sbrk: add page @%p\n", curvm);
pageaddr = arch_pm_get_free_page(MEM_PM_CACHED);
if(pageaddr == NULL) {
// FIXME clean before return
return (void*)-1;
}
ret = heap->address;
page.private.ppn = PM_PHYSICAL_PAGE(pageaddr);
mem_insert_page(& cur->dir_list , &page, curvm);
printk(LOG_DEBUG, "sbrk: incr=%d\n", incr);
relincr -= PM_PAGE_BYTES;
curvm += PM_PAGE_BYTES;
}
}
// add or remove the given size
if(incr > 0) {
// just resize the heap area, allocation is done on page fault
// FIXME need a check to ensure no area are overlayed by the heap!
heap->max_size += incr;
}
else if(incr < 0) {
// remove pages if possible
int curalign;
void *current_brk;
// impossible to reduce the size beyond the original heap begin addr
incr = cur->current_brk + incr <= cur->initial_brk ?
cur->initial_brk - cur->current_brk : incr ;
current_brk = heap->address + heap->max_size;
incr = heap->max_size > -incr ? incr : -(heap->max_size);
curalign = (((unsigned int) cur->current_brk) - 1) % PM_PAGE_BYTES;
curalign = (((unsigned int) current_brk) - 1) % PM_PAGE_BYTES;
if(curalign + incr < 0 ) {
union pm_page *page;
void *curvm;
int nbpages;
nbpages = (-incr - ((unsigned int)(cur->current_brk) % PM_PAGE_BYTES)
nbpages = (-incr - ((unsigned int)(current_brk) % PM_PAGE_BYTES)
-1) / PM_PAGE_BYTES + 1;
curvm = cur->current_brk - ((unsigned int)(cur->current_brk)
curvm = current_brk - ((unsigned int)(current_brk)
% PM_PAGE_BYTES);
while(nbpages > 0) {
......@@ -615,9 +615,11 @@ void *sys_sbrk(int incr) {
curvm -= PM_PAGE_BYTES;
}
}
// resize heap memory area
heap->max_size += incr;
}
cur->current_brk += incr;
return ret;
}
return (void*)-1;
......
......@@ -56,6 +56,7 @@ struct elf_shared_lib {
#define PROCESS_DEFAULT_STACK_SIZE (64*1024)
struct tty;
struct mem_area;
struct process {
// address on the kernel stack of the process, or NULL if running out of any
......@@ -102,9 +103,9 @@ struct process {
// initial data break address (end of static .data/.bss)
void *initial_brk;
// the current_brk is the current address of the top of the heap (changed
// by sbrk() )
void *current_brk;
// this is the pointer to the main heap memory area (manipulated by sbrk())
// be careful : this area *should* exists in process mem_areas list!
struct mem_area *heap_area;
// for process cpu load (should not be used directly, see cpu_load.h)
uint8 load_cursamp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment