Index: openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h =================================================================== --- openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h +++ openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.h @@ -48,16 +48,14 @@ /// Class that wraps the __tgt_async_info to simply its usage. In case the /// object is constructed without a valid __tgt_async_info, the object will use /// an internal one and will synchronize the current thread with the pending -/// operations on object destruction. +/// operations when calling AsyncInfoWrapperTy::finalize(). This latter function +/// must be called before destroying the wrapper object. struct AsyncInfoWrapperTy { - AsyncInfoWrapperTy(Error &Err, GenericDeviceTy &Device, - __tgt_async_info *AsyncInfoPtr) - : Err(Err), ErrOutParam(&Err), Device(Device), - AsyncInfoPtr(AsyncInfoPtr ? AsyncInfoPtr : &LocalAsyncInfo) {} + AsyncInfoWrapperTy(GenericDeviceTy &Device, __tgt_async_info *AsyncInfoPtr); - /// Synchronize with the __tgt_async_info's pending operations if it's the - /// internal one. - ~AsyncInfoWrapperTy(); + ~AsyncInfoWrapperTy() { + assert(!AsyncInfoPtr && "AsyncInfoWrapperTy not finalized"); + } /// Get the raw __tgt_async_info pointer. operator __tgt_async_info *() const { return AsyncInfoPtr; } @@ -72,12 +70,20 @@ /// Indicate whether there is queue. bool hasQueue() const { return (AsyncInfoPtr->Queue != nullptr); } + // Get a reference to the error associated with the asycnhronous operations + // related to the async info wrapper. + Error &getError() { return Err; } + + /// Synchronize with the __tgt_async_info's pending operations if it's the + /// internal async info and return the error associated with the async + /// operations. This function must be called before destroying the object. + Error finalize(); + private: - Error &Err; - ErrorAsOutParameter ErrOutParam; + Error Err; GenericDeviceTy &Device; __tgt_async_info LocalAsyncInfo; - __tgt_async_info *const AsyncInfoPtr; + __tgt_async_info *AsyncInfoPtr; }; /// Class wrapping a __tgt_device_image and its offload entry table on a Index: openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp =================================================================== --- openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp +++ openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp @@ -200,12 +200,29 @@ } RecordReplay; -AsyncInfoWrapperTy::~AsyncInfoWrapperTy() { +AsyncInfoWrapperTy::AsyncInfoWrapperTy(GenericDeviceTy &Device, + __tgt_async_info *AsyncInfoPtr) + : Err(Plugin::success()), Device(Device), + AsyncInfoPtr(AsyncInfoPtr ? AsyncInfoPtr : &LocalAsyncInfo) { + // Mark the success as checked. Otherwise, it would produce an error when + // re-assigned another error value. + !Err; +} + +Error AsyncInfoWrapperTy::finalize() { + assert(AsyncInfoPtr && "AsyncInfoWrapperTy already finalized"); + // If we used a local async info object we want synchronous behavior. // In that case, and assuming the current status code is OK, we will // synchronize explicitly when the object is deleted. if (AsyncInfoPtr == &LocalAsyncInfo && LocalAsyncInfo.Queue && !Err) Err = Device.synchronize(&LocalAsyncInfo); + + // Invalidate the wrapper object. + AsyncInfoPtr = nullptr; + + // Return the error associated to the async operations and the synchronize. + return std::move(Err); } Error GenericKernelTy::init(GenericDeviceTy &GenericDevice, @@ -912,35 +929,37 @@ Error GenericDeviceTy::dataSubmit(void *TgtPtr, const void *HstPtr, int64_t Size, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); + + auto &Err = AsyncInfoWrapper.getError(); Err = dataSubmitImpl(TgtPtr, HstPtr, Size, AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::dataRetrieve(void *HstPtr, const void *TgtPtr, int64_t Size, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); + + auto &Err = AsyncInfoWrapper.getError(); Err = dataRetrieveImpl(HstPtr, TgtPtr, Size, AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::dataExchange(const void *SrcPtr, GenericDeviceTy &DstDev, void *DstPtr, int64_t Size, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); + + auto &Err = AsyncInfoWrapper.getError(); Err = dataExchangeImpl(SrcPtr, DstDev, DstPtr, Size, AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs, ptrdiff_t *ArgOffsets, KernelArgsTy &KernelArgs, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); GenericKernelTy &GenericKernel = *reinterpret_cast(EntryPtr); @@ -951,6 +970,7 @@ KernelArgs.NumTeams[0], KernelArgs.ThreadLimit[0], KernelArgs.Tripcount, AsyncInfoWrapper); + auto &Err = AsyncInfoWrapper.getError(); Err = GenericKernel.launch(*this, ArgPtrs, ArgOffsets, KernelArgs, AsyncInfoWrapper); @@ -959,7 +979,7 @@ RecordReplay.saveKernelOutputInfo(GenericKernel.getName(), AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::initAsyncInfo(__tgt_async_info **AsyncInfoPtr) { @@ -967,10 +987,11 @@ *AsyncInfoPtr = new __tgt_async_info(); - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, *AsyncInfoPtr); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, *AsyncInfoPtr); + + auto &Err = AsyncInfoWrapper.getError(); Err = initAsyncInfoImpl(AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::initDeviceInfo(__tgt_device_info *DeviceInfo) { @@ -994,17 +1015,19 @@ Error GenericDeviceTy::recordEvent(void *EventPtr, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); + + auto &Err = AsyncInfoWrapper.getError(); Err = recordEventImpl(EventPtr, AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::waitEvent(void *EventPtr, __tgt_async_info *AsyncInfo) { - auto Err = Plugin::success(); - AsyncInfoWrapperTy AsyncInfoWrapper(Err, *this, AsyncInfo); + AsyncInfoWrapperTy AsyncInfoWrapper(*this, AsyncInfo); + + auto &Err = AsyncInfoWrapper.getError(); Err = waitEventImpl(EventPtr, AsyncInfoWrapper); - return Err; + return AsyncInfoWrapper.finalize(); } Error GenericDeviceTy::syncEvent(void *EventPtr) {