diff --git a/openmp/libomptarget/include/device.h b/openmp/libomptarget/include/device.h --- a/openmp/libomptarget/include/device.h +++ b/openmp/libomptarget/include/device.h @@ -132,9 +132,13 @@ /// Get the event bound to this data map. void *getEvent() const { return States->Event; } - /// Add a new event, if necessary. + /// Add a new event, if necessary, and record it. /// Returns OFFLOAD_FAIL if something went wrong, OFFLOAD_SUCCESS otherwise. - int addEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const; + int recordEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const; + + /// Add a new event, if necessary, and wait for it. + /// Returns OFFLOAD_FAIL if something went wrong, OFFLOAD_SUCCESS otherwise. + int waitEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const; /// Set the event bound to this data map. void setEvent(void *Event) const { States->Event = Event; } diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp --- a/openmp/libomptarget/src/device.cpp +++ b/openmp/libomptarget/src/device.cpp @@ -20,13 +20,15 @@ #include #include -int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device, - AsyncInfoTy &AsyncInfo) const { +static int recordOrWaitForEventIfNecessary(const HostDataToTargetTy &HDTT, + DeviceTy &Device, + AsyncInfoTy &AsyncInfo, + bool Record) { // First, check if the user disabled atomic map transfer/malloc/dealloc. if (!PM->UseEventsForAtomicTransfers) return OFFLOAD_SUCCESS; - void *Event = getEvent(); + void *Event = HDTT.getEvent(); bool NeedNewEvent = Event == nullptr; if (NeedNewEvent && Device.createEvent(&Event) != OFFLOAD_SUCCESS) { REPORT("Failed to create event\n"); @@ -35,17 +37,31 @@ // We cannot assume the event should not be nullptr because we don't // know if the target support event. But if a target doesn't, - // recordEvent should always return success. - if (Device.recordEvent(Event, AsyncInfo) != OFFLOAD_SUCCESS) { - REPORT("Failed to set dependence on event " DPxMOD "\n", DPxPTR(Event)); + // recordEvent and waitEvent should always return success. + if (Record && Device.recordEvent(Event, AsyncInfo) != OFFLOAD_SUCCESS) { + REPORT("Failed to record event " DPxMOD "\n", DPxPTR(Event)); + return OFFLOAD_FAIL; + } + if (!Record && Device.waitEvent(Event, AsyncInfo) != OFFLOAD_SUCCESS) { + REPORT("Failed to wait on event " DPxMOD "\n", DPxPTR(Event)); return OFFLOAD_FAIL; } if (NeedNewEvent) - setEvent(Event); + HDTT.setEvent(Event); return OFFLOAD_SUCCESS; } +int HostDataToTargetTy::recordEventIfNecessary(DeviceTy &Device, + AsyncInfoTy &AsyncInfo) const { + return recordOrWaitForEventIfNecessary(*this, Device, AsyncInfo, + /* Record */ true); +} +int HostDataToTargetTy::waitEventIfNecessary(DeviceTy &Device, + AsyncInfoTy &AsyncInfo) const { + return recordOrWaitForEventIfNecessary(*this, Device, AsyncInfo, + /* Record */ false); +} DeviceTy::DeviceTy(RTLInfoTy *RTL) : DeviceID(-1), RTL(RTL), RTLDeviceID(-1), IsInit(false), InitFlag(), @@ -294,7 +310,8 @@ // pointer points to a corrupted memory region so it doesn't make any // sense to continue to use it. TargetPointer = nullptr; - } else if (Entry->addEventIfNecessary(*this, AsyncInfo) != OFFLOAD_SUCCESS) + } else if (Entry->recordEventIfNecessary(*this, AsyncInfo) != + OFFLOAD_SUCCESS) return {{false /* IsNewEntry */, false /* IsHostPointer */}, {} /* MapTableEntry */, nullptr /* TargetPointer */}; diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp --- a/openmp/libomptarget/src/omptarget.cpp +++ b/openmp/libomptarget/src/omptarget.cpp @@ -593,8 +593,8 @@ REPORT("Copying data to device failed.\n"); return OFFLOAD_FAIL; } - if (Pointer_TPR.MapTableEntry->addEventIfNecessary(Device, AsyncInfo) != - OFFLOAD_SUCCESS) + if (Pointer_TPR.MapTableEntry->recordEventIfNecessary( + Device, AsyncInfo) != OFFLOAD_SUCCESS) return OFFLOAD_FAIL; } else Device.ShadowMtx.unlock();