after process termination, the PGD and its PGTs will be freed

This commit is contained in:
Stefan Lankes 2011-02-24 18:32:58 +01:00
parent 6f23361bf5
commit 54d636d25c
8 changed files with 77 additions and 12 deletions

View file

@ -110,6 +110,11 @@ int get_kernel_pgd(task_t* task);
*/
int get_user_pgd(task_t* task);
/*
* Delete page directory and its page tables
*/
int drop_pgd(void);
/*
* Change the page permission in the page tables of the current task
*/

View file

@ -116,6 +116,31 @@ int get_user_pgd(task_t* task)
return 0;
}
int drop_pgd(void)
{
uint32_t i;
page_dir_t* pgd = per_core(current_task)->pgd;
size_t phy_pgd = virt_to_phys((size_t) pgd);
if (BUILTIN_EXPECT(pgd == &boot_pgd, 0))
return -EINVAL;
spinlock_lock(per_core(current_task)->pgd_lock);
for(i=KERNEL_SPACE/(1024*PAGE_SIZE); i<1024; i++)
if (pgd->entries[i] & 0xFFFFF000)
put_page(pgd->entries[i] & 0xFFFFF000);
// freeing the page directory
put_page(phy_pgd);
per_core(current_task)->pgd = NULL;
spinlock_unlock(per_core(current_task)->pgd_lock);
return 0;
}
size_t virt_to_phys(size_t viraddr)
{
task_t* task = per_core(current_task);

View file

@ -34,6 +34,8 @@ extern atomic_int32_t total_available_pages;
int mmu_init(void);
size_t get_pages(uint32_t no_pages);
static inline size_t get_page(void) { return get_pages(1); }
int put_page(size_t phyaddr);
#ifdef __cplusplus
}

View file

@ -64,9 +64,12 @@ void NORETURN leave_kernel_task(void);
/* by leaving user level task, this function will be called */
void NORETURN leave_user_task(void);
/* system call to terminate a user level task */
/* system call to terminate a user level process */
void NORETURN sys_exit(int);
/* system call to create a new child process */
int sys_fork(void);
#ifdef __cplusplus
}
#endif

View file

@ -68,10 +68,12 @@ int syscall_handler(uint32_t sys_nr, ...)
ret = per_core(current_task)->id;
break;
case __NR_fork:
ret = sys_fork();
break;
case __NR_fstat:
default:
kputs("invalid system call\n");
ret = -EINVAL;
ret = -ENOSYS;
break;
};

View file

@ -38,8 +38,7 @@ static spinlock_t table_lock = SPINLOCK_INIT;
/*
* helper function for the assembly code to determine the current task
*/
task_t* get_current_task(void)
{
task_t* get_current_task(void) {
return per_core(current_task);
}
@ -83,6 +82,8 @@ static void NORETURN do_exit(int arg) {
kprintf("Terminate task: %u, return value %d\n", per_core(current_task)->id, arg);
wakeup_blocked_tasks(arg);
//vma_dump(per_core(current_task));
spinlock_lock(&(per_core(current_task)->vma_lock));
@ -95,7 +96,8 @@ static void NORETURN do_exit(int arg) {
spinlock_unlock(&(per_core(current_task)->vma_lock));
wakeup_blocked_tasks(arg);
drop_pgd(); // delete page directory and its page tables
if (atomic_int32_read(&per_core(current_task)->mem_usage))
kprintf("Memory leak! Task %d did not release %d pages\n", per_core(current_task)->id, atomic_int32_read(&per_core(current_task)->mem_usage));
per_core(current_task)->status = TASK_FINISHED;
@ -114,8 +116,7 @@ void NORETURN leave_kernel_task(void) {
do_exit(result);
}
void NORETURN sys_exit(int arg)
{
void NORETURN sys_exit(int arg) {
do_exit(arg);
}
@ -135,10 +136,14 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, int user)
for(i=0; i<MAX_TASKS; i++) {
if (task_table[i].status == TASK_INVALID) {
if (!user)
if (!user) {
ret = get_kernel_pgd(task_table+i);
else
atomic_int32_set(&task_table[i].mem_usage, 0);
} else {
ret = get_user_pgd(task_table+i);
// user-level pgd needs already a page
atomic_int32_set(&task_table[i].mem_usage, 1);
}
if (ret != 0) {
ret = -ENOMEM;
@ -147,7 +152,6 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, int user)
task_table[i].id = i;
task_table[i].status = TASK_READY;
atomic_int32_set(&task_table[i].mem_usage, 0);
spinlock_init(&task_table[i].vma_lock);
task_table[i].vma_list = NULL;
memset(task_table[i].mbox, 0x00, sizeof(mailbox_int32_t*)*MAX_TASKS);
@ -313,6 +317,11 @@ int create_user_task(tid_t* id, size_t sz, const char* fname, int argc, char** a
return create_task(id, user_entry, node, 1);
}
int sys_fork(void)
{
return -EINVAL;
}
int join_task(tid_t id, int* result)
{
int32_t tmp;

View file

@ -104,7 +104,7 @@ int test_init(void)
sem_init(&consuming, 0);
mailbox_int32_init(&mbox);
create_kernel_task(NULL, foo, "Hello from foo1\n");
//create_kernel_task(NULL, foo, "Hello from foo1\n");
//create_kernel_task(NULL, join_test, NULL);
//create_kernel_task(NULL, producer, NULL);
//create_kernel_task(NULL, consumer, NULL);

View file

@ -25,6 +25,7 @@
#include <metalsvm/time.h>
#include <metalsvm/processor.h>
#include <metalsvm/page.h>
#include <metalsvm/errno.h>
#ifdef CONFIG_MULTIBOOT
#include <asm/multiboot.h>
#endif
@ -235,6 +236,25 @@ oom:
return ret;
}
int put_page(size_t phyaddr)
{
uint32_t index = phyaddr / PAGE_SIZE;
task_t* task = per_core(current_task);
if (BUILTIN_EXPECT(!phyaddr, 0))
return -EINVAL;
spinlock_lock(&bitmap_lock);
page_clear_mark(index);
spinlock_unlock(&bitmap_lock);
atomic_int32_sub(&total_allocated_pages, 1);
atomic_int32_add(&total_available_pages, 1);
atomic_int32_sub(&(task->mem_usage), 1);
return 0;
}
void* mem_allocation(size_t sz, uint32_t flags)
{
size_t phyaddr, viraddr;
@ -273,7 +293,6 @@ void kfree(void* addr, size_t sz)
if (sz % PAGE_SIZE)
npages++;
spinlock_lock(&bitmap_lock);
for(i=0; i<npages; i++) {
phyaddr = virt_to_phys((size_t) addr+i*PAGE_SIZE);