Loading sys/mem_area.c +32 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,38 @@ int mem_area_insert(struct process *proc, struct mem_area *area) { } int mem_area_resize(struct mem_area *area, size_t new_size, struct process *proc) { int ret = 0; size_t old_size = area->max_size; // first, call area-specific resize callback if any if(area->ops != NULL && area->ops->area_resize != NULL) ret = area->ops->area_resize(area, new_size); else area->max_size = new_size; new_size = area->max_size; // if no error occurs and decreasing the size of the area, release uneeded // pages if(ret == 0 && area->max_size < old_size) { void *old_last_page = MEM_PAGE_BEGINING(area->address + old_size); void *new_last_page = MEM_PAGE_BEGINING(area->address + new_size); union pm_page *page; for( ; new_last_page < old_last_page; new_last_page += 1024) { printk(LOG_DEBUG, "mem_area: release page @%p\n", new_last_page); page = mem_find_page(proc->dir_list, new_last_page); if(page != NULL) { mem_release_page(page); } } } return ret; } size_t mem_area_fill_partial_page(struct mem_area *area, size_t offset, void *dest) { size_t readsize = PM_PAGE_BYTES; Loading sys/mem_area.h +12 −2 Original line number Diff line number Diff line Loading @@ -88,7 +88,7 @@ struct mem_area_ops { * Any page which is out of the area after decreasing size will be removed * from the corresponding process address space by the caller. */ int (*area_resize)(struct mem_area *area, const struct mem_area *new_area); int (*area_resize)(struct mem_area *area, size_t new_size); /** Loading Loading @@ -136,7 +136,7 @@ int mem_area_insert(struct process *proc, struct mem_area *area); /** * Generic function call when a page fault occurs, inside a given area address * Generic function called when a page fault occurs, inside a given area address * range. * The implementation specific operation is called to set the corresponding page. */ Loading @@ -152,6 +152,16 @@ extern inline union pm_page mem_area_pagefault(struct mem_area *area, } } /** * Resize an area to the given new_size. * If size is decreased and some memory pages associated with corresponding * process are excluded of the given area, each one is released. * TODO the design is not so good, process should be implicit? * Return 0 for success, negative value else. */ int mem_area_resize(struct mem_area *area, size_t new_size, struct process *proc); /** * Helper for filesystem implementations, to handle MEM_AREA_PARTIAL. * Check for a given page to fill with 0 when needed, and return the number of Loading sys/memory.h +5 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,11 @@ union pm_page { ( ((uint32)(addr) >> (PM_PAGE_ORDER)) & (MEM_DIRECTORY_PAGES - 1)) // get the first byte's address of the physical page of the given address #define MEM_PAGE_BEGINING(addr) \ (void*)((uint32)(addr) & ~(PM_PAGE_BYTES-1)) /** * Process address space is managed by a linked list of "pages directory". * Each directory describe a set of sequential virtual pages, and the virtual Loading sys/process.c +4 −47 Original line number Diff line number Diff line Loading @@ -574,55 +574,12 @@ void *sys_sbrk(int incr) { // heap area exists (maybe just created) if(heap != NULL) { void *ret; ret = heap->address; void *ret = heap->address; size_t new_size; printk(LOG_DEBUG, "sbrk: incr=%d\n", incr); // 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 current_brk = heap->address + heap->max_size; incr = heap->max_size > -incr ? incr : -(heap->max_size); 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)(current_brk) % PM_PAGE_BYTES) -1) / PM_PAGE_BYTES + 1; curvm = current_brk - ((unsigned int)(current_brk) % PM_PAGE_BYTES); while(nbpages > 0) { printk(LOG_DEBUG, "sbrk: remove page @%p\n", curvm); page = mem_find_page(cur->dir_list, curvm); if(page != NULL) { mem_release_page(page); } nbpages--; curvm -= PM_PAGE_BYTES; } } // resize heap memory area heap->max_size += incr; } new_size = -incr > heap->max_size ? 0 : heap->max_size + incr; mem_area_resize(heap, new_size, cur); return ret; } Loading Loading
sys/mem_area.c +32 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,38 @@ int mem_area_insert(struct process *proc, struct mem_area *area) { } int mem_area_resize(struct mem_area *area, size_t new_size, struct process *proc) { int ret = 0; size_t old_size = area->max_size; // first, call area-specific resize callback if any if(area->ops != NULL && area->ops->area_resize != NULL) ret = area->ops->area_resize(area, new_size); else area->max_size = new_size; new_size = area->max_size; // if no error occurs and decreasing the size of the area, release uneeded // pages if(ret == 0 && area->max_size < old_size) { void *old_last_page = MEM_PAGE_BEGINING(area->address + old_size); void *new_last_page = MEM_PAGE_BEGINING(area->address + new_size); union pm_page *page; for( ; new_last_page < old_last_page; new_last_page += 1024) { printk(LOG_DEBUG, "mem_area: release page @%p\n", new_last_page); page = mem_find_page(proc->dir_list, new_last_page); if(page != NULL) { mem_release_page(page); } } } return ret; } size_t mem_area_fill_partial_page(struct mem_area *area, size_t offset, void *dest) { size_t readsize = PM_PAGE_BYTES; Loading
sys/mem_area.h +12 −2 Original line number Diff line number Diff line Loading @@ -88,7 +88,7 @@ struct mem_area_ops { * Any page which is out of the area after decreasing size will be removed * from the corresponding process address space by the caller. */ int (*area_resize)(struct mem_area *area, const struct mem_area *new_area); int (*area_resize)(struct mem_area *area, size_t new_size); /** Loading Loading @@ -136,7 +136,7 @@ int mem_area_insert(struct process *proc, struct mem_area *area); /** * Generic function call when a page fault occurs, inside a given area address * Generic function called when a page fault occurs, inside a given area address * range. * The implementation specific operation is called to set the corresponding page. */ Loading @@ -152,6 +152,16 @@ extern inline union pm_page mem_area_pagefault(struct mem_area *area, } } /** * Resize an area to the given new_size. * If size is decreased and some memory pages associated with corresponding * process are excluded of the given area, each one is released. * TODO the design is not so good, process should be implicit? * Return 0 for success, negative value else. */ int mem_area_resize(struct mem_area *area, size_t new_size, struct process *proc); /** * Helper for filesystem implementations, to handle MEM_AREA_PARTIAL. * Check for a given page to fill with 0 when needed, and return the number of Loading
sys/memory.h +5 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,11 @@ union pm_page { ( ((uint32)(addr) >> (PM_PAGE_ORDER)) & (MEM_DIRECTORY_PAGES - 1)) // get the first byte's address of the physical page of the given address #define MEM_PAGE_BEGINING(addr) \ (void*)((uint32)(addr) & ~(PM_PAGE_BYTES-1)) /** * Process address space is managed by a linked list of "pages directory". * Each directory describe a set of sequential virtual pages, and the virtual Loading
sys/process.c +4 −47 Original line number Diff line number Diff line Loading @@ -574,55 +574,12 @@ void *sys_sbrk(int incr) { // heap area exists (maybe just created) if(heap != NULL) { void *ret; ret = heap->address; void *ret = heap->address; size_t new_size; printk(LOG_DEBUG, "sbrk: incr=%d\n", incr); // 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 current_brk = heap->address + heap->max_size; incr = heap->max_size > -incr ? incr : -(heap->max_size); 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)(current_brk) % PM_PAGE_BYTES) -1) / PM_PAGE_BYTES + 1; curvm = current_brk - ((unsigned int)(current_brk) % PM_PAGE_BYTES); while(nbpages > 0) { printk(LOG_DEBUG, "sbrk: remove page @%p\n", curvm); page = mem_find_page(cur->dir_list, curvm); if(page != NULL) { mem_release_page(page); } nbpages--; curvm -= PM_PAGE_BYTES; } } // resize heap memory area heap->max_size += incr; } new_size = -incr > heap->max_size ? 0 : heap->max_size + incr; mem_area_resize(heap, new_size, cur); return ret; } Loading