memobj: transform memobj lock to refcounting

We had a deadlock between:
 - free_process_memory_range (take lock) -> ihk_mc_pt_free_range ->
... -> remote_flush_tlb_array_cpumask -> "/* Wait for all cores */"
and
 - obj_list_lookup() under fileobj_list_lock that disabled irqs
and thus never ack'd the remote flush

The rework is quite big but removes the need for the big lock,
although devobj and shmobj needed a new smaller lock to be
introduced - the new locks are used much more locally and
should not cause problems.

On the bright side, refcounting being moved to memobj level means
we could remove refcounting implemented separately in all object
types and simplifies code a bit.

Change-Id: I6bc8438a98b1d8edddc91c4ac33c11b88e097ebb
This commit is contained in:
Dominique Martinet
2018-08-07 15:40:25 +09:00
parent b51886421e
commit c25fb2aa39
10 changed files with 307 additions and 403 deletions

View File

@@ -1109,7 +1109,7 @@ reserve_user_space_common(struct mcctrl_usrdata *usrdata, unsigned long start, u
struct pager {
struct list_head list;
struct inode * inode;
int ref;
uint64_t ref; /* needs same type as fileobj->sref */
struct file * rofile;
struct file * rwfile;
uintptr_t map_uaddr;
@@ -1411,14 +1411,14 @@ out:
return error;
}
static int pager_req_release(ihk_os_t os, uintptr_t handle, int unref)
static int pager_req_release(ihk_os_t os, uintptr_t handle, uint64_t sref)
{
int error;
struct pager *p;
struct pager *free_pager = NULL;
unsigned long flags;
dprintk("pager_req_relase(%p,%lx,%d)\n", os, handle, unref);
dprintk("%s(%p,%lx)\n", __func__, os, handle);
spin_lock_irqsave(&pager_lock, flags);
@@ -1426,11 +1426,11 @@ static int pager_req_release(ihk_os_t os, uintptr_t handle, int unref)
list_for_each_entry(p, &pager_list, list) {
if ((uintptr_t)p == handle) {
error = 0;
p->ref -= unref;
if (p->ref <= 0) {
list_del(&p->list);
free_pager = p;
}
p->ref -= sref;
if (p->ref > 0)
break;
list_del(&p->list);
free_pager = p;
break;
}
}
@@ -1438,7 +1438,8 @@ static int pager_req_release(ihk_os_t os, uintptr_t handle, int unref)
spin_unlock_irqrestore(&pager_lock, flags);
if (error) {
printk("pager_req_release(%p,%lx,%d):pager not found. %d\n", os, handle, unref, error);
pr_err("%s(%p,%lx):pager not found. %d\n",
__func__, os, handle, error);
goto out;
}
@@ -1454,7 +1455,7 @@ static int pager_req_release(ihk_os_t os, uintptr_t handle, int unref)
error = 0;
out:
dprintk("pager_req_release(%p,%lx,%d): %d\n", os, handle, unref, error);
dprintk("%s(%p,%lx): %d\n", __func__, os, handle, error);
return error;
}