[llvm] hosttask (PR #204173)
Ćukasz Plewa via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 17 06:26:52 PDT 2026
https://github.com/lplewa updated https://github.com/llvm/llvm-project/pull/204173
>From 63367fa45fb0e210d4ccf974b281b8c3558f2632 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Plewa?= <lukasz.plewa at intel.com>
Date: Tue, 16 Jun 2026 14:57:56 +0200
Subject: [PATCH] [offload][l0] Implement olLaunchHost function for level zero
plugin
---
.../level_zero/include/L0CmdListManager.h | 26 ++++++++++++++++++-
.../level_zero/include/L0Context.h | 6 +++++
.../level_zero/include/L0Device.h | 7 ++---
.../level_zero/include/L0Queue.h | 9 +++++++
.../level_zero/src/L0Context.cpp | 6 +++++
.../level_zero/src/L0Device.cpp | 9 +++++++
.../level_zero/src/L0Queue.cpp | 23 ++++++++++++++++
.../unittests/OffloadAPI/memory/olMemFill.cpp | 6 -----
.../OffloadAPI/queue/olLaunchHostFunction.cpp | 10 ++-----
9 files changed, 82 insertions(+), 20 deletions(-)
diff --git a/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h b/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
index f17c1149d88cb..1eed147f00456 100644
--- a/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
+++ b/offload/plugins-nextgen/level_zero/include/L0CmdListManager.h
@@ -13,6 +13,7 @@
#ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0CMDLISTMANAGER_H
#define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0CMDLISTMANAGER_H
+#include "L0Context.h"
#include "L0Defs.h"
#include "L0Trace.h"
#include <mutex>
@@ -24,11 +25,14 @@ namespace llvm::omp::target::plugin {
class L0CmdListManagerTy {
/// Underlying immediate command list.
ze_command_list_handle_t CmdList;
+ /// Owning context (provides driver-loaded extension function pointers).
+ L0ContextTy &Context;
/// Mutex to protect L0 operations that are not thread safe.
std::mutex Mtx;
public:
- L0CmdListManagerTy(ze_command_list_handle_t CmdList) : CmdList(CmdList) {}
+ L0CmdListManagerTy(ze_command_list_handle_t CmdList, L0ContextTy &Context)
+ : CmdList(CmdList), Context(Context) {}
ze_command_list_handle_t getCmdList() const { return CmdList; }
@@ -152,6 +156,26 @@ class L0CmdListManagerTy {
NumWaitEvents, WaitEvents);
return Plugin::success();
}
+
+ /// Append a host function callback. Requires the
+ /// zeCommandListAppendHostFunction extension to be available on the driver;
+ /// otherwise returns UNSUPPORTED.
+ Error appendHostFunction(void (*Callback)(void *), void *UserData,
+ ze_event_handle_t SignalEvent = nullptr,
+ uint32_t NumWaitEvents = 0,
+ ze_event_handle_t *WaitEvents = nullptr) {
+ auto zeCommandListAppendHost = Context.zeCommandListAppendHostFunction;
+ if (!zeCommandListAppendHost)
+ return Plugin::error(ErrorCode::UNSUPPORTED,
+ "zeCommandListAppendHostFunction extension is not "
+ "available on this driver");
+ std::lock_guard<std::mutex> Lock(Mtx);
+ CALL_ZE_RET_ERROR(zeCommandListAppendHost, CmdList,
+ reinterpret_cast<void *>(Callback), UserData,
+ /*pReserved*/ nullptr, SignalEvent, NumWaitEvents,
+ WaitEvents);
+ return Plugin::success();
+ }
};
} // namespace llvm::omp::target::plugin
diff --git a/offload/plugins-nextgen/level_zero/include/L0Context.h b/offload/plugins-nextgen/level_zero/include/L0Context.h
index 3ea68d8dd07a1..1bb5b76c61a84 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Context.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Context.h
@@ -141,6 +141,12 @@ class L0ContextTy {
ze_result_t(ZE_APICALL *zexKernelGetArgumentSize)(
ze_kernel_handle_t hKernel, uint32_t argIndex,
uint32_t *pArgSize) = nullptr;
+
+ /// Level Zero extension function pointer for host function callbacks.
+ ze_result_t(ZE_APICALL *zeCommandListAppendHostFunction)(
+ ze_command_list_handle_t hCommandList, void *pfnHostFunction,
+ void *pUserData, void *pReserved, ze_event_handle_t hSignalEvent,
+ uint32_t numWaitEvents, ze_event_handle_t *phWaitEvents) = nullptr;
};
} // namespace llvm::omp::target::plugin
diff --git a/offload/plugins-nextgen/level_zero/include/L0Device.h b/offload/plugins-nextgen/level_zero/include/L0Device.h
index 275182faebfd6..b70cfeeb8fd4f 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Device.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Device.h
@@ -361,7 +361,7 @@ class L0DeviceTy final : public GenericDeviceTy {
auto CmdListOrErr = createImmCmdList(InOrder);
if (!CmdListOrErr)
return CmdListOrErr.takeError();
- return new L0CmdListManagerTy(*CmdListOrErr);
+ return new L0CmdListManagerTy(*CmdListOrErr, l0Context);
}
Error releaseCmdListManager(L0CmdListManagerTy *CmndListMngr) {
@@ -522,10 +522,7 @@ class L0DeviceTy final : public GenericDeviceTy {
hasPendingWorkImpl(AsyncInfoWrapperTy &AsyncInfoWrapper) override;
Error enqueueHostCallImpl(void (*Callback)(void *), void *UserData,
- AsyncInfoWrapperTy &AsyncInfo) override {
- return Plugin::error(ErrorCode::UNIMPLEMENTED,
- "enqueueHostCallImpl not implemented yet");
- }
+ AsyncInfoWrapperTy &AsyncInfo) override;
Expected<bool> isEventCompleteImpl(void *EventPtr,
AsyncInfoWrapperTy &) override;
diff --git a/offload/plugins-nextgen/level_zero/include/L0Queue.h b/offload/plugins-nextgen/level_zero/include/L0Queue.h
index ee5b9491ca2ec..60558650b75b3 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Queue.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Queue.h
@@ -82,6 +82,10 @@ class L0QueueTy {
return launchKernelImpl(Kernel, KEnv);
}
+ Error hostCall(void (*Callback)(void *), void *UserData) {
+ return hostCallImpl(Callback, UserData);
+ }
+
Error dataFence() { return dataFenceImpl(); }
Error appendSignalEvent(L0EventTy *Event) {
@@ -126,6 +130,7 @@ class L0QueueTy {
}
virtual Error launchKernelImpl(ze_kernel_handle_t Kernel,
L0LaunchEnvTy &KEnv) = 0;
+ virtual Error hostCallImpl(void (*Callback)(void *), void *UserData) = 0;
virtual Error memoryFillImpl(void *Ptr, const void *Pattern,
size_t PatternSize, size_t Size) {
@@ -186,6 +191,7 @@ class L0AsyncQueueTy : public L0QueueTy {
Error dataSubmitImpl(void *TgtPtr, const void *HstPtr, int64_t Size) override;
Error launchKernelImpl(ze_kernel_handle_t Kernel,
L0LaunchEnvTy &KEnv) override;
+ Error hostCallImpl(void (*Callback)(void *), void *UserData) override;
Error memoryFillImpl(void *Ptr, const void *Pattern, size_t PatternSize,
size_t Size) override;
Error dataFenceImpl() override;
@@ -204,6 +210,7 @@ class L0AsyncOrderedQueueTy : public L0AsyncQueueTy {
Error synchronizeImpl() override;
std::tuple<size_t, ze_event_handle_t *> getMemCopyEvents() override;
std::tuple<size_t, ze_event_handle_t *> getLaunchKernelEvents() override;
+ Error hostCallImpl(void (*Callback)(void *), void *UserData) override;
Error dataFenceImpl() override { return Plugin::success(); }
};
@@ -222,6 +229,7 @@ class L0InorderQueueTy : public L0QueueTy {
Error memoryCopyImpl(void *Dst, const void *Src, size_t Size) override;
Error launchKernelImpl(ze_kernel_handle_t Kernel,
L0LaunchEnvTy &KEnv) override;
+ Error hostCallImpl(void (*Callback)(void *), void *UserData) override;
Error dataFenceImpl() override { return Plugin::success(); }
};
@@ -240,6 +248,7 @@ class L0SyncQueueTy : public L0InorderQueueTy {
Error memoryCopyImpl(void *Dst, const void *Src, size_t Size) override;
Error launchKernelImpl(ze_kernel_handle_t Kernel,
L0LaunchEnvTy &KEnv) override;
+ Error hostCallImpl(void (*Callback)(void *), void *UserData) override;
};
/// Simple cache for queue objects.
diff --git a/offload/plugins-nextgen/level_zero/src/L0Context.cpp b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
index 4fe0aa34ecbaf..c1556dc5b37f7 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Context.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
@@ -57,6 +57,12 @@ Error L0ContextTy::init() {
if (RC != ZE_RESULT_SUCCESS)
zexKernelGetArgumentSize = nullptr;
+ CALL_ZE(RC, zeDriverGetExtensionFunctionAddress, zeDriver,
+ "zeCommandListAppendHostFunction",
+ (void **)&zeCommandListAppendHostFunction);
+ if (RC != ZE_RESULT_SUCCESS)
+ zeCommandListAppendHostFunction = nullptr;
+
return Plugin::success();
}
diff --git a/offload/plugins-nextgen/level_zero/src/L0Device.cpp b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
index fd664f33b81e9..ac57c74ff15f0 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Device.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
@@ -387,6 +387,15 @@ Error L0DeviceTy::dataRetrieveImpl(void *HstPtr, const void *TgtPtr,
return Plugin::success();
}
+Error L0DeviceTy::enqueueHostCallImpl(void (*Callback)(void *), void *UserData,
+ AsyncInfoWrapperTy &AsyncInfoWrapper) {
+ __tgt_async_info *AsyncInfo = AsyncInfoWrapper;
+ auto QueueOrErr = getOrCreateQueue(AsyncInfo);
+ if (!QueueOrErr)
+ return QueueOrErr.takeError();
+ return (*QueueOrErr)->hostCall(Callback, UserData);
+}
+
Error L0DeviceTy::dataExchangeImpl(const void *SrcPtr, GenericDeviceTy &DstDev,
void *DstPtr, int64_t Size,
AsyncInfoWrapperTy &AsyncInfoWrapper) {
diff --git a/offload/plugins-nextgen/level_zero/src/L0Queue.cpp b/offload/plugins-nextgen/level_zero/src/L0Queue.cpp
index 1edafcd04be57..81cef7be2df48 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Queue.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Queue.cpp
@@ -247,6 +247,12 @@ Error L0AsyncQueueTy::launchKernelImpl(ze_kernel_handle_t Kernel,
return Plugin::success();
}
+Error L0AsyncQueueTy::hostCallImpl(void (*Callback)(void *), void *UserData) {
+ return Plugin::error(ErrorCode::UNIMPLEMENTED,
+ "Host function callbacks are not yet implemented for "
+ "out-of-order async queues");
+}
+
Error L0AsyncQueueTy::memoryFillImpl(void *Ptr, const void *Pattern,
size_t PatternSize, size_t Size) {
auto EventOrErr = Device.getEvent();
@@ -306,6 +312,13 @@ L0AsyncOrderedQueueTy::getLaunchKernelEvents() {
: std::make_tuple(1, &WaitEvents.back());
}
+Error L0AsyncOrderedQueueTy::hostCallImpl(void (*Callback)(void *),
+ void *UserData) {
+ return Plugin::error(ErrorCode::UNIMPLEMENTED,
+ "Host function callbacks are not yet implemented for "
+ "ordered async queues");
+}
+
// L0InorderQueueTy implementation.
Error L0InorderQueueTy::synchronizeImpl() { return CmdList->hostSynchronize(); }
@@ -323,6 +336,10 @@ Error L0InorderQueueTy::launchKernelImpl(ze_kernel_handle_t Kernel,
return dispatchLaunchKernel(Kernel, KEnv);
}
+Error L0InorderQueueTy::hostCallImpl(void (*Callback)(void *), void *UserData) {
+ return CmdList->appendHostFunction(Callback, UserData);
+}
+
// L0SyncQueueTy implementation.
Error L0SyncQueueTy::memoryCopyImpl(void *Dst, const void *Src, size_t Size) {
if (auto Err = L0InorderQueueTy::memoryCopyImpl(Dst, Src, Size))
@@ -337,6 +354,12 @@ Error L0SyncQueueTy::launchKernelImpl(ze_kernel_handle_t Kernel,
return CmdList->hostSynchronize();
}
+Error L0SyncQueueTy::hostCallImpl(void (*Callback)(void *), void *UserData) {
+ if (auto Err = L0InorderQueueTy::hostCallImpl(Callback, UserData))
+ return Err;
+ return CmdList->hostSynchronize();
+}
+
// L0QueueCache implementation.
Expected<L0QueueTy *> L0QueueCacheTy::getQueue() {
{
diff --git a/offload/unittests/OffloadAPI/memory/olMemFill.cpp b/offload/unittests/OffloadAPI/memory/olMemFill.cpp
index f314879a94394..b094c6298e16d 100644
--- a/offload/unittests/OffloadAPI/memory/olMemFill.cpp
+++ b/offload/unittests/OffloadAPI/memory/olMemFill.cpp
@@ -16,11 +16,6 @@ struct olMemFillTest : OffloadQueueTest {
template <typename PatternTy, PatternTy PatternVal, size_t Size,
bool Block = false>
void test_body() {
- if constexpr (Block) {
- // Only tests relying on olLaunchHostFunction are failing.
- SKIP_KNOWN_FAILURE(LevelZero{"unsupported feature"});
- }
-
ManuallyTriggeredTask Manual;
// Block/enqueue tests ensure that the test has been enqueued to a queue
@@ -103,7 +98,6 @@ TEST_P(olMemFillTest, SuccessLarge) {
}
TEST_P(olMemFillTest, SuccessLargeEnqueue) {
- SKIP_KNOWN_FAILURE(LevelZero{"unsupported feature"});
constexpr size_t Size = 1024;
void *Alloc;
ManuallyTriggeredTask Manual;
diff --git a/offload/unittests/OffloadAPI/queue/olLaunchHostFunction.cpp b/offload/unittests/OffloadAPI/queue/olLaunchHostFunction.cpp
index 387fb308da6d4..f3f28f82e9d30 100644
--- a/offload/unittests/OffloadAPI/queue/olLaunchHostFunction.cpp
+++ b/offload/unittests/OffloadAPI/queue/olLaunchHostFunction.cpp
@@ -12,18 +12,12 @@
#include <thread>
struct olLaunchHostFunctionTest : OffloadQueueTest {
- void SetUp() override {
- RETURN_ON_FATAL_FAILURE(OffloadQueueTest::SetUp());
- SKIP_KNOWN_FAILURE(LevelZero{"unsupported feature"});
- }
+ void SetUp() override { RETURN_ON_FATAL_FAILURE(OffloadQueueTest::SetUp()); }
};
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchHostFunctionTest);
struct olLaunchHostFunctionKernelTest : OffloadKernelTest {
- void SetUp() override {
- RETURN_ON_FATAL_FAILURE(OffloadKernelTest::SetUp());
- SKIP_KNOWN_FAILURE(LevelZero{"unsupported feature"});
- }
+ void SetUp() override { RETURN_ON_FATAL_FAILURE(OffloadKernelTest::SetUp()); }
};
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchHostFunctionKernelTest);
More information about the llvm-commits
mailing list