From 544971d665b7b8d0f41edb776f289eb0a4534e2a Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 25 Nov 2015 14:27:20 +0900 Subject: [PATCH] modify for PVAS --- kernel/include/process.h | 11 ++++- kernel/mem.c | 6 +-- kernel/process.c | 88 ++++++++++++++++++++++++---------------- kernel/syscall.c | 33 ++++++++------- 4 files changed, 83 insertions(+), 55 deletions(-) diff --git a/kernel/include/process.h b/kernel/include/process.h index ac7238cc..19231a55 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -216,9 +216,14 @@ struct thread_hash { struct address_space { struct page_table *page_table; + void *opt; + void (*free_cb)(struct address_space *, void *); + ihk_atomic_t refcount; int type; #define ADDRESS_SPACE_NORMAL 1 #define ADDRESS_SPACE_PVAS 2 + cpu_set_t cpu_set; + ihk_spinlock_t cpu_set_lock; int nslots; int pids[]; }; @@ -516,6 +521,8 @@ struct process_vm { struct list_head vm_range_list; struct vm_regions region; struct process *proc; /* process that reside on the same page */ + void *opt; + void (*free_cb)(struct process_vm *, void *); ihk_spinlock_t page_table_lock; ihk_spinlock_t memory_range_lock; @@ -526,12 +533,12 @@ struct process_vm { // is protected by its own lock (see ihk/manycore/generic/page_alloc.c) ihk_atomic_t refcount; - cpu_set_t cpu_set; - ihk_spinlock_t cpu_set_lock; int exiting; }; +void hold_address_space(struct address_space *); +void release_address_space(struct address_space *); struct thread *create_thread(unsigned long user_pc); struct thread *clone_thread(struct thread *org, unsigned long pc, unsigned long sp, int clone_flags); diff --git a/kernel/mem.c b/kernel/mem.c index b1d888cb..99136ea7 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -285,9 +285,9 @@ void remote_flush_tlb_cpumask(struct process_vm *vm, /* Take a copy of the cpu set so that we don't hold the lock * all the way while interrupting other cores */ - ihk_mc_spinlock_lock_noirq(&vm->cpu_set_lock); - memcpy(&_cpu_set, &vm->cpu_set, sizeof(cpu_set_t)); - ihk_mc_spinlock_unlock_noirq(&vm->cpu_set_lock); + ihk_mc_spinlock_lock_noirq(&vm->address_space->cpu_set_lock); + memcpy(&_cpu_set, &vm->address_space->cpu_set, sizeof(cpu_set_t)); + ihk_mc_spinlock_unlock_noirq(&vm->address_space->cpu_set_lock); dkprintf("trying to aquire flush_entry->lock flush_ind: %d\n", flush_ind); diff --git a/kernel/process.c b/kernel/process.c index b10102e6..aae5e141 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -124,6 +124,7 @@ chain_thread(struct thread *thread) { struct mcs_rwlock_node_irqsave lock; struct process *proc = thread->proc; + struct process_vm *vm = thread->vm; int hash; struct thread_hash *thash; @@ -137,7 +138,7 @@ chain_thread(struct thread *thread) list_add_tail(&thread->hash_list, &thash->list[hash]); mcs_rwlock_writer_unlock(&thash->lock[hash], &lock); - ihk_atomic_inc(&proc->refcount); + ihk_atomic_inc(&vm->refcount); } struct address_space * @@ -159,12 +160,26 @@ create_address_space(struct resource_set *res, int type, int n) asp->type = type; asp->nslots = n; asp->page_table = pt; + ihk_atomic_set(&asp->refcount, 1); + memset(&asp->cpu_set, 0, sizeof(cpu_set_t)); + ihk_mc_spinlock_init(&asp->cpu_set_lock); return asp; } void -remove_address_space(struct address_space *asp) +hold_address_space(struct address_space *asp) { + ihk_atomic_inc(&asp->refcount); +} + +void +release_address_space(struct address_space *asp) +{ + if (!ihk_atomic_dec_and_test(&asp->refcount)) { + return; + } + if(asp->free_cb) + asp->free_cb(asp, asp->opt); ihk_mc_pt_destroy(asp->page_table); kfree(asp); } @@ -172,19 +187,15 @@ remove_address_space(struct address_space *asp) void detach_address_space(struct address_space *asp, int pid) { - if(asp->type == ADDRESS_SPACE_NORMAL){ - remove_address_space(asp); - } - else if(asp->type == ADDRESS_SPACE_PVAS){ - int i; + int i; - for(i = 0; i < asp->nslots; i++){ - if(asp->pids[i] == pid){ - asp->pids[i] = 0; - break; - } + for(i = 0; i < asp->nslots; i++){ + if(asp->pids[i] == pid){ + asp->pids[i] = 0; + break; } } + release_address_space(asp); } static int @@ -197,8 +208,6 @@ init_process_vm(struct process *owner, struct address_space *asp, struct process INIT_LIST_HEAD(&vm->vm_range_list); vm->address_space = asp; vm->proc = owner; - memset(&vm->cpu_set, 0, sizeof(cpu_set_t)); - ihk_mc_spinlock_init(&vm->cpu_set_lock); vm->exiting = 0; return 0; @@ -270,8 +279,8 @@ create_thread(unsigned long user_pc) goto err; } - cpu_set(ihk_mc_get_processor_id(), &thread->vm->cpu_set, - &thread->vm->cpu_set_lock); + cpu_set(ihk_mc_get_processor_id(), &thread->vm->address_space->cpu_set, + &thread->vm->address_space->cpu_set_lock); ihk_mc_spinlock_init(&thread->spin_sleep_lock); thread->spin_sleep = 0; @@ -284,7 +293,7 @@ err: if(vm) kfree(vm); if(asp) - remove_address_space(asp); + release_address_space(asp); if(thread->sigcommon) kfree(thread->sigcommon); ihk_mc_free_pages(thread, KERNEL_STACK_NR_PAGES); @@ -366,7 +375,7 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp, } proc->vm = kmalloc(sizeof(struct process_vm), IHK_MC_AP_NOWAIT); if(!proc->vm){ - remove_address_space(asp); + release_address_space(asp); kfree(proc); goto err_free_proc; } @@ -374,7 +383,7 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp, dkprintf("fork(): init_process_vm()\n"); if (init_process_vm(proc, asp, proc->vm) != 0) { - remove_address_space(asp); + release_address_space(asp); kfree(proc->vm); kfree(proc); goto err_free_proc; @@ -388,7 +397,7 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp, /* Copy user-space mappings. * TODO: do this with COW later? */ if (copy_user_ranges(proc->vm, org->vm) != 0) { - remove_address_space(asp); + release_address_space(asp); kfree(proc->vm); kfree(proc); goto err_free_proc; @@ -2034,15 +2043,11 @@ hold_process_vm(struct process_vm *vm) } void -release_process_vm(struct process_vm *vm) +free_all_process_memory_range(struct process_vm *vm) { struct vm_range *range, *next; int error; - if (!ihk_atomic_dec_and_test(&vm->refcount)) { - return; - } - ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock); list_for_each_entry_safe(range, next, &vm->vm_range_list, list) { error = free_process_memory_range(vm, range); @@ -2056,12 +2061,24 @@ release_process_vm(struct process_vm *vm) ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock); } -static void -free_process_vm(struct process_vm *vm) +void +release_process_vm(struct process_vm *vm) { + struct process *proc = vm->proc; + + if (!ihk_atomic_dec_and_test(&vm->refcount)) { + return; + } + + if(vm->free_cb) + vm->free_cb(vm, vm->opt); + + free_all_process_memory_range(vm); + detach_address_space(vm->address_space, vm->proc->pid); + proc->vm = NULL; + release_process(proc); kfree(vm); - release_process(vm->proc); } int populate_process_memory(struct process_vm *vm, void *start, size_t len) @@ -2138,7 +2155,8 @@ void destroy_thread(struct thread *thread) list_del(&thread->siblings_list); mcs_rwlock_writer_unlock(&proc->threads_lock, &lock); - cpu_clear(thread->cpu_id, &thread->vm->cpu_set, &thread->vm->cpu_set_lock); + cpu_clear(thread->cpu_id, &thread->vm->address_space->cpu_set, + &thread->vm->address_space->cpu_set_lock); list_for_each_entry_safe(pending, signext, &thread->sigpending, list){ list_del(&pending->list); kfree(pending); @@ -2165,20 +2183,16 @@ void destroy_thread(struct thread *thread) void release_thread(struct thread *thread) { struct process_vm *vm; - struct process *proc; if (!ihk_atomic_dec_and_test(&thread->refcount)) { return; } vm = thread->vm; - proc = thread->proc; destroy_thread(thread); - if(ihk_atomic_read(&vm->refcount) == 0) - free_process_vm(vm); - release_process(proc); + release_process_vm(vm); } void cpu_set(int cpu, cpu_set_t *cpu_set, ihk_spinlock_t *lock) @@ -2374,6 +2388,7 @@ void sched_init(void) idle_thread->vm->address_space = &cpu_local_var(idle_asp); idle_thread->proc = &cpu_local_var(idle_proc); init_process(idle_thread->proc, NULL); + cpu_local_var(idle_proc).nohost = 1; idle_thread->proc->vm = &cpu_local_var(idle_vm); list_add_tail(&idle_thread->siblings_list, &idle_thread->proc->children_list); @@ -2461,8 +2476,9 @@ static void do_migrate(void) v->runq_len += 1; /* update cpu_set of the VM for remote TLB invalidation */ - cpu_clear_and_set(old_cpu_id, cpu_id, &req->thread->vm->cpu_set, - &req->thread->vm->cpu_set_lock); + cpu_clear_and_set(old_cpu_id, cpu_id, + &req->thread->vm->address_space->cpu_set, + &req->thread->vm->address_space->cpu_set_lock); dkprintf("do_migrate(): migrated TID %d from CPU %d to CPU %d\n", req->thread->tid, old_cpu_id, cpu_id); diff --git a/kernel/syscall.c b/kernel/syscall.c index fd2d326e..67b2000d 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -111,6 +111,7 @@ extern int num_processors; extern unsigned long ihk_mc_get_ns_per_tsc(void); extern int ptrace_detach(int pid, int data); extern void debug_log(unsigned long); +extern void free_all_process_memory_range(struct process_vm *vm); int prepare_process_ranges_args_envs(struct thread *thread, struct program_load_desc *pn, @@ -197,15 +198,17 @@ long do_syscall(struct syscall_request *req, int cpu, int pid) int islock = 0; unsigned long irqstate; struct thread *thread = cpu_local_var(current); + struct process *proc = thread->proc; dkprintf("SC(%d)[%3d] sending syscall\n", ihk_mc_get_processor_id(), req->number); if(req->number != __NR_exit_group){ - - if(thread->proc->nohost) // host is down + if(proc->nohost && // host is down + pid == proc->pid) { return -EPIPE; + } ++thread->in_syscall_offload; } @@ -552,6 +555,7 @@ terminate(int rc, int sig) struct process *child; struct process *next; struct process *pid1 = resource_set->pid1; + struct process_vm *vm; struct mcs_rwlock_node_irqsave lock; struct mcs_rwlock_node updatelock; struct mcs_rwlock_node childlock; @@ -624,10 +628,8 @@ terminate(int rc, int sig) delete_proc_procfs_files(proc->pid); - release_process_vm(proc->vm); - while (ihk_atomic_read(&proc->vm->refcount) != 0) { - cpu_pause(); - } + vm = proc->vm; + free_all_process_memory_range(vm); if (proc->saved_cmdline) { kfree(proc->saved_cmdline); @@ -715,6 +717,7 @@ terminate(int rc, int sig) request.number = __NR_exit_group; request.args[0] = proc->exit_status; do_syscall(&request, ihk_mc_get_processor_id(), proc->pid); + proc->nohost = 1; } // Send signal to parent @@ -749,6 +752,7 @@ terminate(int rc, int sig) mythread->status = PS_EXITED; release_thread(mythread); + release_process_vm(vm); schedule(); // no return } @@ -1426,14 +1430,15 @@ SYSCALL_DECLARE(getppid) void settid(struct thread *thread, int mode, int newcpuid, int oldcpuid) { - ihk_mc_user_context_t ctx; + struct syscall_request request IHK_DMA_ALIGN; unsigned long rc; - ihk_mc_syscall_arg0(&ctx) = mode; - ihk_mc_syscall_arg1(&ctx) = thread->proc->pid; - ihk_mc_syscall_arg2(&ctx) = newcpuid; - ihk_mc_syscall_arg3(&ctx) = oldcpuid; - rc = syscall_generic_forwarding(__NR_gettid, &ctx); + request.number = __NR_gettid; + request.args[0] = mode; + request.args[1] = thread->proc->pid; + request.args[2] = newcpuid; + request.args[3] = oldcpuid; + rc = do_syscall(&request, ihk_mc_get_processor_id(), thread->proc->pid); if (mode != 2) { thread->tid = rc; } @@ -1833,10 +1838,10 @@ unsigned long do_fork(int clone_flags, unsigned long newsp, return -ENOMEM; } - cpu_set(cpuid, &new->vm->cpu_set, &new->vm->cpu_set_lock); + cpu_set(cpuid, &new->vm->address_space->cpu_set, + &new->vm->address_space->cpu_set_lock); if (clone_flags & CLONE_VM) { - new->proc->pid = cpu_local_var(current)->proc->pid; settid(new, 1, cpuid, -1); } /* fork() a new process on the host */