/* * Release all access permits and detach all associated attaches for the given * thread group. */ void xpmem_release_aps_of_tg(struct xpmem_thread_group *ap_tg) { struct xpmem_hashlist *hashlist; struct xpmem_access_permit *ap; int index; for (index = 0; index < XPMEM_AP_HASHTABLE_SIZE; index++) { hashlist = &ap_tg->ap_hashtable[index]; read_lock(&hashlist->lock); while (!list_empty(&hashlist->list)) { ap = list_entry((&hashlist->list)->next, struct xpmem_access_permit, ap_hashnode); xpmem_ap_ref(ap); read_unlock(&hashlist->lock); xpmem_release_ap(ap_tg, ap); xpmem_ap_deref(ap); read_lock(&hashlist->lock); } read_unlock(&hashlist->lock); } }
/* * Detach an attached XPMEM address segment. */ int xpmem_detach(vaddr_t at_vaddr) { struct xpmem_thread_group *tg; struct xpmem_access_permit *ap; struct xpmem_attachment *att; tg = xpmem_tg_ref_by_gid(current->aspace->id); if (IS_ERR(tg)) return PTR_ERR(tg); att = xpmem_att_ref_by_vaddr(tg, at_vaddr); if (IS_ERR(att)) { xpmem_tg_deref(tg); return PTR_ERR(att); } mutex_lock(&att->mutex); if (att->flags & XPMEM_FLAG_DESTROYING) { mutex_unlock(&att->mutex); xpmem_att_deref(att); xpmem_tg_deref(tg); return 0; } att->flags |= XPMEM_FLAG_DESTROYING; ap = att->ap; xpmem_ap_ref(ap); if (current->aspace->id != ap->tg->gid) { att->flags &= ~XPMEM_FLAG_DESTROYING; xpmem_ap_deref(ap); mutex_unlock(&att->mutex); xpmem_att_deref(att); return -EACCES; } __xpmem_detach_att(ap, att); mutex_unlock(&att->mutex); xpmem_att_destroyable(att); xpmem_ap_deref(ap); xpmem_att_deref(att); xpmem_tg_deref(tg); return 0; }