From 4ebe778edeb4cb121bc62363e8097a8e691f7092 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Sun, 22 Mar 2015 18:04:12 +0900 Subject: [PATCH] vm->exiting: deal with exit_group() and concurrent page faults --- kernel/include/process.h | 1 + kernel/mem.c | 15 +++++++++++++++ kernel/process.c | 10 +++++++++- kernel/syscall.c | 3 ++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/kernel/include/process.h b/kernel/include/process.h index ba8052d8..ec72835d 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -431,6 +431,7 @@ struct process_vm { cpu_set_t cpu_set; ihk_spinlock_t cpu_set_lock; + int exiting; }; diff --git a/kernel/mem.c b/kernel/mem.c index 5032ad95..fbed4f43 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -370,10 +370,25 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) dkprintf("[%d]page_fault_handler(%p,%lx,%p)\n", ihk_mc_get_processor_id(), fault_addr, reason, regs); + cpu_enable_interrupt(); + error = page_fault_process_vm(proc->vm, fault_addr, reason); if (error) { struct siginfo info; + if (error == -ECANCELED) { + kprintf("process is exiting, terminate.\n"); + + ihk_mc_spinlock_lock_noirq(&proc->ftn->lock); + proc->ftn->status = PS_ZOMBIE; + ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); + release_fork_tree_node(proc->ftn->parent); + release_fork_tree_node(proc->ftn); + //release_process(proc); + + schedule(); + } + kprintf("[%d]page_fault_handler(%p,%lx,%p):" "fault vm failed. %d\n", ihk_mc_get_processor_id(), fault_addr, diff --git a/kernel/process.c b/kernel/process.c index fc4f5405..2e21de9e 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -137,7 +137,8 @@ static int init_process_vm(struct process *owner, struct process_vm *vm) vm->owner_process = owner; memset(&vm->cpu_set, 0, sizeof(cpu_set_t)); ihk_mc_spinlock_init(&vm->cpu_set_lock); - + vm->exiting = 0; + return 0; } @@ -1526,6 +1527,11 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock); + if (vm->exiting) { + error = -ECANCELED; + goto out; + } + range = lookup_process_memory_range(vm, fault_addr, fault_addr+1); if (range == NULL) { error = -EFAULT; @@ -1854,6 +1860,8 @@ void flush_process_memory(struct process *proc) dkprintf("flush_process_memory(%p)\n", proc); ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock); + /* Let concurrent page faults know the VM will be gone */ + vm->exiting = 1; list_for_each_entry_safe(range, next, &vm->vm_range_list, list) { if (range->memobj) { // XXX: temporary of temporary diff --git a/kernel/syscall.c b/kernel/syscall.c index 5686e078..85b1c009 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -3604,8 +3604,9 @@ SYSCALL_DECLARE(exit) proc->ftn->status = PS_ZOMBIE; + release_fork_tree_node(proc->ftn->parent); release_fork_tree_node(proc->ftn); - release_process(proc); + //release_process(proc); schedule();