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:
@ -44,7 +44,6 @@ enum {
|
||||
MF_XPMEM = 0x10000, /* To identify XPMEM attachment pages for rusage accounting */
|
||||
MF_ZEROOBJ = 0x20000, /* To identify pages of anonymous, on-demand paging ranges for rusage accounting */
|
||||
MF_SHM = 0x40000,
|
||||
MF_HOST_RELEASED = 0x80000000,
|
||||
MF_END
|
||||
};
|
||||
|
||||
@ -56,7 +55,7 @@ struct memobj {
|
||||
uint32_t flags;
|
||||
uint32_t status;
|
||||
size_t size;
|
||||
ihk_spinlock_t lock;
|
||||
ihk_atomic_t refcnt;
|
||||
|
||||
/* For pre-mapped memobjects */
|
||||
void **pages;
|
||||
@ -64,8 +63,7 @@ struct memobj {
|
||||
char *path;
|
||||
};
|
||||
|
||||
typedef void memobj_release_func_t(struct memobj *obj);
|
||||
typedef void memobj_ref_func_t(struct memobj *obj);
|
||||
typedef void memobj_free_func_t(struct memobj *obj);
|
||||
typedef int memobj_get_page_func_t(struct memobj *obj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag, uintptr_t virt_addr);
|
||||
typedef uintptr_t memobj_copy_page_func_t(struct memobj *obj, uintptr_t orgphys, int p2align);
|
||||
typedef int memobj_flush_page_func_t(struct memobj *obj, uintptr_t phys, size_t pgsize);
|
||||
@ -73,26 +71,23 @@ typedef int memobj_invalidate_page_func_t(struct memobj *obj, uintptr_t phys, si
|
||||
typedef int memobj_lookup_page_func_t(struct memobj *obj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag);
|
||||
|
||||
struct memobj_ops {
|
||||
memobj_release_func_t * release;
|
||||
memobj_ref_func_t * ref;
|
||||
memobj_get_page_func_t * get_page;
|
||||
memobj_copy_page_func_t * copy_page;
|
||||
memobj_flush_page_func_t * flush_page;
|
||||
memobj_invalidate_page_func_t * invalidate_page;
|
||||
memobj_lookup_page_func_t * lookup_page;
|
||||
memobj_free_func_t *free;
|
||||
memobj_get_page_func_t *get_page;
|
||||
memobj_copy_page_func_t *copy_page;
|
||||
memobj_flush_page_func_t *flush_page;
|
||||
memobj_invalidate_page_func_t *invalidate_page;
|
||||
memobj_lookup_page_func_t *lookup_page;
|
||||
};
|
||||
|
||||
static inline void memobj_release(struct memobj *obj)
|
||||
static inline int memobj_ref(struct memobj *obj)
|
||||
{
|
||||
if (obj->ops->release) {
|
||||
(*obj->ops->release)(obj);
|
||||
}
|
||||
return ihk_atomic_inc_return(&obj->refcnt);
|
||||
}
|
||||
|
||||
static inline void memobj_ref(struct memobj *obj)
|
||||
static inline void memobj_unref(struct memobj *obj)
|
||||
{
|
||||
if (obj->ops->ref) {
|
||||
(*obj->ops->ref)(obj);
|
||||
if (ihk_atomic_dec_return(&obj->refcnt) == 0) {
|
||||
(*obj->ops->free)(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,16 +135,6 @@ static inline int memobj_lookup_page(struct memobj *obj, off_t off,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static inline void memobj_lock(struct memobj *obj)
|
||||
{
|
||||
ihk_mc_spinlock_lock_noirq(&obj->lock);
|
||||
}
|
||||
|
||||
static inline void memobj_unlock(struct memobj *obj)
|
||||
{
|
||||
ihk_mc_spinlock_unlock_noirq(&obj->lock);
|
||||
}
|
||||
|
||||
static inline int memobj_has_pager(struct memobj *obj)
|
||||
{
|
||||
return !!(obj->flags & MF_HAS_PAGER);
|
||||
|
||||
Reference in New Issue
Block a user