Skip to content

Commit

Permalink
[OpenMP][libomptarget] Do not rely on AsyncInfoWrapperTy's destructor
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinsala committed Apr 4, 2023
1 parent 273f736 commit 8dad7f4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,29 @@ struct RecordReplayTy {

} 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,
Expand Down Expand Up @@ -912,35 +929,37 @@ Error GenericDeviceTy::dataDelete(void *TgtPtr, TargetAllocTy Kind) {

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<GenericKernelTy *>(EntryPtr);
Expand All @@ -951,6 +970,7 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs,
KernelArgs.NumTeams[0], KernelArgs.ThreadLimit[0], KernelArgs.Tripcount,
AsyncInfoWrapper);

auto &Err = AsyncInfoWrapper.getError();
Err = GenericKernel.launch(*this, ArgPtrs, ArgOffsets, KernelArgs,
AsyncInfoWrapper);

Expand All @@ -959,18 +979,19 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs,
RecordReplay.saveKernelOutputInfo(GenericKernel.getName(),
AsyncInfoWrapper);

return Err;
return AsyncInfoWrapper.finalize();
}

Error GenericDeviceTy::initAsyncInfo(__tgt_async_info **AsyncInfoPtr) {
assert(AsyncInfoPtr && "Invalid async info");

*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) {
Expand All @@ -994,17 +1015,19 @@ Error GenericDeviceTy::destroyEvent(void *EventPtr) {

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,14 @@ struct GenericDeviceTy;
/// 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; }
Expand All @@ -72,12 +70,20 @@ struct AsyncInfoWrapperTy {
/// 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
Expand Down

0 comments on commit 8dad7f4

Please sign in to comment.