diff --git a/executer/kernel/mcctrl/control.c b/executer/kernel/mcctrl/control.c index f5f19dc1..4b522dc6 100644 --- a/executer/kernel/mcctrl/control.c +++ b/executer/kernel/mcctrl/control.c @@ -969,9 +969,8 @@ void mcctrl_put_per_proc_data(struct mcctrl_per_proc_data *ppd) } ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, flags); + pager_remove_process(ppd); kfree(ppd); - - pager_remove_process(); } @@ -1464,6 +1463,9 @@ int mcexec_create_per_process_data(ihk_os_t os) rwlock_init(&ppd->per_thread_data_hash_lock[i]); } + INIT_LIST_HEAD(&ppd->devobj_pager_list); + sema_init(&ppd->devobj_pager_lock, 1); + if (mcctrl_add_per_proc_data(usrdata, ppd->pid, ppd) < 0) { printk("%s: error adding per process data\n", __FUNCTION__); kfree(ppd); diff --git a/executer/kernel/mcctrl/mcctrl.h b/executer/kernel/mcctrl/mcctrl.h index 0e75cb9b..b539e4f3 100644 --- a/executer/kernel/mcctrl/mcctrl.h +++ b/executer/kernel/mcctrl/mcctrl.h @@ -224,6 +224,9 @@ struct mcctrl_per_proc_data { cpumask_t cpu_set; int ikc_target_cpu; atomic_t refcount; + + struct list_head devobj_pager_list; + struct semaphore devobj_pager_lock; }; struct sysfsm_req { @@ -345,7 +348,7 @@ ihk_os_t osnum_to_os(int n); /* syscall.c */ void pager_add_process(void); -void pager_remove_process(void); +void pager_remove_process(struct mcctrl_per_proc_data *ppd); int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet); int mcctrl_add_per_proc_data(struct mcctrl_usrdata *ud, int pid, diff --git a/executer/kernel/mcctrl/syscall.c b/executer/kernel/mcctrl/syscall.c index 4285dcd6..e0f7bbd1 100644 --- a/executer/kernel/mcctrl/syscall.c +++ b/executer/kernel/mcctrl/syscall.c @@ -775,12 +775,35 @@ void pager_add_process(void) up(&pager_sem); } -void pager_remove_process(void) +void pager_remove_process(struct mcctrl_per_proc_data *ppd) { int error; struct pager *pager_next, *pager; - error = down_interruptible(&pager_sem); + if (in_atomic() || in_interrupt()) { + printk("%s: WARNING: shouldn't be called in IRQ context..\n", + __FUNCTION__); + return; + } + + /* Clean up device file mappings of this process */ + error = down_interruptible(&ppd->devobj_pager_lock); + if (error) { + return; + } + + list_for_each_entry_safe(pager, pager_next, + &ppd->devobj_pager_list, list) { + + dprintk("%s: devobj pager 0x%lx removed\n", __FUNCTION__, pager); + list_del(&pager->list); + kfree(pager); + } + up(&ppd->devobj_pager_lock); + + /* Clean up global pagers for regular file mappings if this + * was the last process */ + error = down_interruptible(&pager_sem); if (error) { return; } @@ -1216,8 +1239,18 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off, struct pager *pager = NULL; struct pager_map_result *resp; uintptr_t phys; + struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os); + struct mcctrl_per_proc_data *ppd = NULL; dprintk("pager_req_map(%p,%d,%lx,%lx,%lx)\n", os, fd, len, off, result_rpa); + + ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current)); + if (unlikely(!ppd)) { + kprintf("%s: ERROR: no per-process structure for PID %d??\n", + __FUNCTION__, task_tgid_vnr(current)); + return -1; + } + pager = kzalloc(sizeof(*pager), GFP_ATOMIC); if (!pager) { error = -ENOMEM; @@ -1290,8 +1323,17 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off, ihk_device_unmap_virtual(dev, resp, sizeof(*resp)); ihk_device_unmap_memory(dev, phys, sizeof(*resp)); + error = down_interruptible(&ppd->devobj_pager_lock); + if (error) { + error = -EINTR; + goto out; + } + + list_add_tail(&pager->list, &ppd->devobj_pager_list); + up(&ppd->devobj_pager_lock); + + pager = 0; error = 0; - pager = 0; /* pager should be in list? */ out: if (file) { @@ -1300,6 +1342,7 @@ out: if (pager) { kfree(pager); } + mcctrl_put_per_proc_data(ppd); dprintk("pager_req_map(%p,%d,%lx,%lx,%lx): %d\n", os, fd, len, off, result_rpa, error); return error; } @@ -1407,13 +1450,10 @@ out: return error; } -static int pager_req_unmap(ihk_os_t os, uintptr_t handle) +static int __pager_unmap(struct pager *pager) { - struct pager * const pager = (void *)handle; int error; - dprintk("pager_req_unmap(%p,%lx)\n", os, handle); - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) down_write(¤t->mm->mmap_sem); error = do_munmap(current->mm, pager->map_uaddr, pager->map_len); @@ -1423,12 +1463,42 @@ static int pager_req_unmap(ihk_os_t os, uintptr_t handle) #endif if (error) { - printk("pager_req_unmap(%p,%lx):do_munmap failed. %d\n", os, handle, error); - /* through */ + printk("%s: WARNING: munmap failed for pager 0x%lx: %d\n", + __FUNCTION__, (uintptr_t)pager, error); } + return error; +} + +static int pager_req_unmap(ihk_os_t os, uintptr_t handle) +{ + struct pager * const pager = (void *)handle; + int error; + struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os); + struct mcctrl_per_proc_data *ppd = NULL; + + dprintk("pager_req_unmap(%p,%lx)\n", os, handle); + + ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current)); + if (unlikely(!ppd)) { + kprintf("%s: ERROR: no per-process structure for PID %d??\n", + __FUNCTION__, task_tgid_vnr(current)); + return -1; + } + + error = down_interruptible(&ppd->devobj_pager_lock); + if (error) { + error = -EINTR; + goto out; + } + + list_del(&pager->list); + up(&ppd->devobj_pager_lock); + + error = __pager_unmap(pager); kfree(pager); - dprintk("pager_req_unmap(%p,%lx): %d\n", os, handle, error); + +out: return error; }