| //===-- AsyncInfo.cpp -----------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "omptarget.h" |
| |
| #include "Shared/Debug.h" |
| #include "device.h" |
| |
| #include <cassert> |
| #include <cstdint> |
| |
| using namespace llvm::omp::target::debug; |
| |
| // Temporary helper from liboffload until all usage of AsyncInfo is migrated |
| // to liboffload queues. |
| namespace llvm::offload::tmp { |
| __tgt_async_info *__ol_tgt_GetAsyncInfoFromQueue(ol_queue_handle_t Queue); |
| } // namespace llvm::offload::tmp |
| |
| AsyncInfoTy::AsyncInfoTy(DeviceTy &Device, SyncTy SyncType) |
| : Device(Device), SyncType(SyncType) { |
| if (auto Res = olCreateQueue(Device.Context, Device.DeviceHandle, &Queue)) { |
| REPORT() << "Failed to create queue for device " << Device.DeviceID << ": " |
| << Res->Details; |
| Queue = nullptr; |
| } |
| } |
| |
| AsyncInfoTy::~AsyncInfoTy() { |
| synchronize(); |
| if (Queue) { |
| if (auto Res = olDestroyQueue(Queue)) |
| REPORT() << "Failed to destroy queue " << Queue << ": " << Res->Details; |
| } |
| } |
| |
| AsyncInfoTy::operator __tgt_async_info *() { |
| return llvm::offload::tmp::__ol_tgt_GetAsyncInfoFromQueue(Queue); |
| } |
| |
| int AsyncInfoTy::synchronize() { |
| int Result = OFFLOAD_SUCCESS; |
| if (!isQueueEmpty()) { |
| switch (SyncType) { |
| case SyncTy::BLOCKING: |
| // If we have a queue we need to synchronize it now. |
| Result = Device.synchronize(*this); |
| break; |
| case SyncTy::NON_BLOCKING: |
| Result = Device.queryAsync(*this); |
| break; |
| } |
| } |
| |
| // Run any pending post-processing function registered on this async object. |
| if (Result == OFFLOAD_SUCCESS && isQueueEmpty()) { |
| ODBG(ODT_DataTransfer) |
| << "Synchronization complete, running post-processing"; |
| Result = runPostProcessing(); |
| } |
| |
| return Result; |
| } |
| |
| void *&AsyncInfoTy::getVoidPtrLocation() { |
| BufferLocations.push_back(nullptr); |
| return BufferLocations.back(); |
| } |
| |
| bool AsyncInfoTy::isDone() const { return isQueueEmpty(); } |
| |
| int32_t AsyncInfoTy::runPostProcessing() { |
| size_t Size = PostProcessingFunctions.size(); |
| for (size_t I = 0; I < Size; ++I) { |
| const int Result = PostProcessingFunctions[I](); |
| if (Result != OFFLOAD_SUCCESS) |
| return Result; |
| } |
| |
| // Clear the vector up until the last known function, since post-processing |
| // procedures might add new procedures themselves. |
| const auto *PrevBegin = PostProcessingFunctions.begin(); |
| PostProcessingFunctions.erase(PrevBegin, PrevBegin + Size); |
| |
| return OFFLOAD_SUCCESS; |
| } |
| |
| bool AsyncInfoTy::isQueueEmpty() const { |
| if (!Queue) |
| return true; |
| bool IsComplete; |
| if (auto Res = olQueryQueue(Queue, &IsComplete)) { |
| REPORT() << "Failed to query queue " << Queue << ": " << Res->Details; |
| return false; |
| } |
| return IsComplete; |
| } |