Index: openmp/libomptarget/src/device.h =================================================================== --- openmp/libomptarget/src/device.h +++ openmp/libomptarget/src/device.h @@ -92,6 +92,14 @@ std::string refCountToStr() const { return isRefCountInf() ? "INF" : std::to_string(getRefCount()); } + + /// Should one decrement of the reference count (after resetting it if + /// \c AfterReset) remove this mapping? + bool decShouldRemove(bool AfterReset = false) const { + if (AfterReset) + return !isRefCountInf(); + return getRefCount() == 1; + } }; typedef uintptr_t HstPtrBeginTy; @@ -178,7 +186,7 @@ void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size); void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast, bool UpdateRefCount, bool &IsHostPtr, - bool MustContain = false); + bool MustContain = false, bool ForceDelete = false); int deallocTgtPtr(void *TgtPtrBegin, int64_t Size, bool ForceDelete, bool HasCloseModifier = false); int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size); Index: openmp/libomptarget/src/device.cpp =================================================================== --- openmp/libomptarget/src/device.cpp +++ openmp/libomptarget/src/device.cpp @@ -289,7 +289,7 @@ // Decrement the reference counter if called from targetDataEnd. void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast, bool UpdateRefCount, bool &IsHostPtr, - bool MustContain) { + bool MustContain, bool ForceDelete) { void *rc = NULL; IsHostPtr = false; IsLast = false; @@ -304,13 +304,21 @@ // removed the mapping in deallocTgtPtr, another thread could retrieve the // mapping, increment and decrement back to zero, and then both threads // would try to remove the mapping, resulting in a double free. - IsLast = HT.getRefCount() == 1; + IsLast = HT.decShouldRemove(ForceDelete); const char *RefCountAction; - if (!UpdateRefCount) + if (!UpdateRefCount) { RefCountAction = "update suppressed"; - else if (IsLast) + } else if (ForceDelete) { + HT.resetRefCount(); + assert(IsLast == HT.decShouldRemove() && + "expected correct IsLast prediction for reset"); + if (IsLast) + RefCountAction = "reset, deferred final decrement"; + else + RefCountAction = "reset"; + } else if (IsLast) { RefCountAction = "deferred final decrement"; - else { + } else { RefCountAction = "decremented"; HT.decRefCount(); } @@ -361,8 +369,6 @@ LookupResult lr = lookupMapping(HstPtrBegin, Size); if (lr.Flags.IsContained || lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) { auto &HT = *lr.Entry; - if (ForceDelete) - HT.resetRefCount(); if (HT.decRefCount() == 0) { DP("Deleting tgt data " DPxMOD " of size %" PRId64 "\n", DPxPTR(HT.TgtPtrBegin), Size); Index: openmp/libomptarget/src/omptarget.cpp =================================================================== --- openmp/libomptarget/src/omptarget.cpp +++ openmp/libomptarget/src/omptarget.cpp @@ -672,8 +672,9 @@ bool HasPresentModifier = ArgTypes[I] & OMP_TGT_MAPTYPE_PRESENT; // If PTR_AND_OBJ, HstPtrBegin is address of pointee - void *TgtPtrBegin = Device.getTgtPtrBegin( - HstPtrBegin, DataSize, IsLast, UpdateRef, IsHostPtr, !IsImplicit); + void *TgtPtrBegin = + Device.getTgtPtrBegin(HstPtrBegin, DataSize, IsLast, UpdateRef, + IsHostPtr, !IsImplicit, ForceDelete); if (!TgtPtrBegin && (DataSize || HasPresentModifier)) { DP("Mapping does not exist (%s)\n", (HasPresentModifier ? "'present' map type modifier" : "ignored")); @@ -712,7 +713,7 @@ if (!TgtPtrBegin) continue; - bool DelEntry = IsLast || ForceDelete; + bool DelEntry = IsLast; // If the last element from the mapper (for end transfer args comes in // reverse order), do not remove the partial entry, the parent struct still