blob: 7f4c74e504256f6a49d4b9d9f0559e2dc5ab9344 [file] [edit]
//===--- Level Zero Target RTL Implementation -----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Level Zero Event and Event Pool abstractions.
//
//===----------------------------------------------------------------------===//
#ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H
#define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H
#include <level_zero/ze_api.h>
#include <memory>
#include <mutex>
#include "L0Defs.h"
#include "L0Trace.h"
namespace llvm::omp::target::plugin {
class L0QueueTy;
class L0EventTy {
ze_event_handle_t ZeEvent = nullptr;
bool CounterBased = false;
L0QueueTy *Queue = nullptr;
public:
L0EventTy(ze_event_handle_t ZeEvent, bool CounterBased)
: ZeEvent(ZeEvent), CounterBased(CounterBased) {}
ze_event_handle_t getZeEvent() const { return ZeEvent; }
L0QueueTy *getQueue() const { return Queue; }
Error reset() {
Queue = nullptr;
if (!CounterBased)
CALL_ZE_RET_ERROR(zeEventHostReset, ZeEvent);
return Plugin::success();
}
void setQueue(L0QueueTy &Q) { Queue = &Q; }
Error synchronize() {
CALL_ZE_RET_ERROR(zeEventHostSynchronize, ZeEvent, L0DefaultTimeout);
return Plugin::success();
}
Expected<bool> isComplete() {
ze_result_t Result;
CALL_ZE(Result, zeEventQueryStatus, ZeEvent);
if (Result == ZE_RESULT_SUCCESS)
return true;
if (Result == ZE_RESULT_NOT_READY)
return false;
return Plugin::error(ErrorCode::UNKNOWN, "failed to query event status: %s",
getZeErrorName(Result));
}
};
/// Common event pool used in the plugin. This event pool assumes all events
/// from the pool are host-visible and use the same event pool flag.
class EventPoolTy {
/// Size of L0 event pool created on demand.
size_t PoolSize = 64;
/// Context of the events.
ze_context_handle_t Context = nullptr;
/// Additional event pool flags common to this pool.
uint32_t Flags = 0;
/// Whether counter-based events are being used (don't need reset).
bool UseCounterBasedEvents = false;
/// Protection.
std::unique_ptr<std::mutex> Mtx;
/// Created L0 event pools.
llvm::SmallVector<ze_event_pool_handle_t> Pools;
/// L0 events cache.
llvm::SmallVector<ze_event_handle_t> Events;
/// L0 event objects cache.
llvm::SmallVector<L0EventTy *> EventObjects;
// Internal method to get an event from the pool. The caller must hold the
// lock.
Expected<ze_event_handle_t> getEventLocked();
public:
/// Initialize context, flags, and mutex.
Error init(ze_context_handle_t ContextIn, bool UseCounterBased,
uint32_t FlagsIn) {
Context = ContextIn;
Flags = FlagsIn;
UseCounterBasedEvents = UseCounterBased;
Mtx.reset(new std::mutex);
return Plugin::success();
}
/// Destroys L0 resources.
Error deinit() {
for (auto *EventObj : EventObjects)
delete EventObj;
for (auto E : Events)
CALL_ZE_RET_ERROR(zeEventDestroy, E);
for (auto P : Pools)
CALL_ZE_RET_ERROR(zeEventPoolDestroy, P);
return Plugin::success();
}
/// Get a L0 Event (ze_event_handle_t) from the pool.
Expected<ze_event_handle_t> getEvent() {
std::lock_guard<std::mutex> Lock(*Mtx);
return getEventLocked();
}
/// Get an L0EventTy object that wraps a ze_event_handle_t from the pool.
/// This is the preferred way to get an event unless a raw event is really
/// needed.
Expected<L0EventTy *> getEventObject();
/// Return a ze_event_handle_t to the pool.
Error releaseEvent(ze_event_handle_t Event);
/// Returns an L0EventTy object to the pool so it can be reused. This does not
/// return the underlying ze_event_handle_t to the handle pool.
Error releaseEventObject(L0EventTy *EventObj);
};
} // namespace llvm::omp::target::plugin
#endif // OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H