From 3fb5646d6dbd677d5dc60046c6a7f1294affb5b1 Mon Sep 17 00:00:00 2001 From: "Gainullin, Artur" Date: Thu, 18 Jun 2026 12:04:26 -0700 Subject: [PATCH 1/3] [UR] Add IPC event-sharing API to inter-process communication extension Define UR APIs for sharing event objects between processes. * Added the IPC_EVENT_SUPPORT_EXP device info query. * Extended ur_exp_event_flags_t (from the reusable events extension) with UR_EXP_EVENT_FLAG_IPC_EXP, requested via ur_exp_event_desc_t::flags at urEventCreateExp time so SYCL's enable_ipc property can be expressed. * Added urIPCGetEventHandleExp / urIPCPutEventHandleExp / urIPCOpenEventHandleExp. Sharing is bidirectional: an event opened with urIPCOpenEventHandleExp shares state with the source event, so a state change made through either event is observable through the other and either event can be signaled, waited on, or queried. Events created with profiling/timestamping enabled cannot be shared. The event returned by urIPCOpenEventHandleExp is a normal ur_event_handle_t released through urEventRelease; there is no separate IPC event close entry point. Although Level Zero exposes zeEventCounterBasedCloseIpcHandle, a dedicated UR close API would add a second public release path for the same handle and break the uniform reference-counted lifetime of UR events. The adapter instead records that the event was opened from an IPC handle and, on the final urEventRelease, selects the IPC-specific native teardown rather than the normal event cleanup path. This commit updates only the yml definitions and rst documentation. Assisted-By: Claude --- .../core/EXP-INTER-PROCESS-COMMUNICATION.rst | 59 ++++++-- .../core/exp-inter-process-communication.yml | 140 ++++++++++++++++++ 2 files changed, 188 insertions(+), 11 deletions(-) diff --git a/unified-runtime/scripts/core/EXP-INTER-PROCESS-COMMUNICATION.rst b/unified-runtime/scripts/core/EXP-INTER-PROCESS-COMMUNICATION.rst index 647f6f09ac23b..b9c0afccebfa8 100644 --- a/unified-runtime/scripts/core/EXP-INTER-PROCESS-COMMUNICATION.rst +++ b/unified-runtime/scripts/core/EXP-INTER-PROCESS-COMMUNICATION.rst @@ -23,9 +23,10 @@ Inter Process Communication Motivation -------------------------------------------------------------------------------- This extension introduces functionality for allowing processes to share common -objects, such as device USM memory allocations. Doing so lets processes actively -communicate with each other through the devices, by explicitly managing handles -that represent shareable objects for inter-process communication. +objects, such as device USM memory allocations and event objects. Doing so lets +processes actively communicate with each other through the devices, by +explicitly managing handles that represent shareable objects for inter-process +communication. API -------------------------------------------------------------------------------- @@ -34,29 +35,65 @@ Enums ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ${x}_device_info_t * ${X}_DEVICE_INFO_IPC_MEMORY_SUPPORT_EXP + * ${X}_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP +* ${x}_exp_event_flags_t + * ${X}_EXP_EVENT_FLAG_IPC_EXP Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Inter-Process Communication +* Inter-Process Communication (Memory) * ${x}IPCGetMemHandleExp * ${x}IPCPutMemHandleExp * ${x}IPCOpenMemHandleExp * ${x}IPCCloseMemHandleExp +* Inter-Process Communication (Event) + * ${x}IPCGetEventHandleExp + * ${x}IPCPutEventHandleExp + * ${x}IPCOpenEventHandleExp + +Event sharing semantics +-------------------------------------------------------------------------------- +An event must be created by ${x}EventCreateExp with the +``${X}_EXP_EVENT_FLAG_IPC_EXP`` flag set in ``${x}_exp_event_desc_t::flags`` to +be eligible for inter-process sharing. The flag cannot be enabled after the +event is created. + +An event opened with ``${x}IPCOpenEventHandleExp`` shares state with the source +event that produced the IPC handle. Either event can be signaled, waited on, or +queried, and a state change made through one event is observable through the +other. + +An event opened with ``${x}IPCOpenEventHandleExp`` is a normal +``${x}_event_handle_t`` with an initial reference count of 1. It may be passed +to entry points that accept events, retained with ``${x}EventRetain``, and must +be released with ``${x}EventRelease``. On the final release, the adapter +performs the native cleanup required for an opened IPC event. + +Events created with ``${X}_EXP_EVENT_FLAG_ENABLE_PROFILING`` cannot be shared +via IPC. Changelog -------------------------------------------------------------------------------- -+-----------+------------------------+ -| Revision | Changes | -+===========+========================+ -| 1.0 | Initial Draft | -+-----------+------------------------+ ++-----------+----------------------------------------------------------+ +| Revision | Changes | ++===========+==========================================================+ +| 1.0 | Initial Draft | ++-----------+----------------------------------------------------------+ +| 1.1 | Added IPC event sharing APIs, the | +| | ``IPC_EVENT_SUPPORT_EXP`` device info query, and the | +| | ``${X}_EXP_EVENT_FLAG_IPC_EXP`` event creation flag. | ++-----------+----------------------------------------------------------+ Support -------------------------------------------------------------------------------- -Adapters which support this experimental feature *must* return true for the new -``${X}_DEVICE_INFO_IPC_MEMORY_SUPPORT_EXP`` device info query. +Adapters which support inter-process sharing of memory allocations *must* +return true for the ``${X}_DEVICE_INFO_IPC_MEMORY_SUPPORT_EXP`` device info +query. + +Adapters which support inter-process sharing of event objects *must* return +true for the ``${X}_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP`` device info query. Contributors -------------------------------------------------------------------------------- diff --git a/unified-runtime/scripts/core/exp-inter-process-communication.yml b/unified-runtime/scripts/core/exp-inter-process-communication.yml index 71c15e6b9d71a..43827ea70cd9c 100644 --- a/unified-runtime/scripts/core/exp-inter-process-communication.yml +++ b/unified-runtime/scripts/core/exp-inter-process-communication.yml @@ -33,6 +33,30 @@ etors: value: "0x2024" desc: "[$x_bool_t] returns true if the device supports inter-process communicable physical memory handles" --- #-------------------------------------------------------------------------- +type: enum +extend: true +typed_etors: true +desc: "Extension enums to $x_device_info_t to support inter-process communicable event handles." +name: $x_device_info_t +etors: + - name: IPC_EVENT_SUPPORT_EXP + value: "0x2026" + desc: "[$x_bool_t] returns true if the device supports inter-process communicable event handles" +--- #-------------------------------------------------------------------------- +type: enum +extend: true +desc: "Extension enums to $x_exp_event_flags_t for inter-process sharing of events." +name: $x_exp_event_flags_t +etors: + - name: IPC_EXP + value: "$X_BIT(1)" + desc: > + The event can be shared with other processes through the + $xIPCGetEventHandleExp and $xIPCOpenEventHandleExp APIs. This flag + must be passed to $xEventCreateExp for any event whose IPC handle + will later be obtained; it cannot be enabled after creation. Must + not be combined with $X_EXP_EVENT_FLAG_ENABLE_PROFILING. +--- #-------------------------------------------------------------------------- type: function desc: "Gets an inter-process memory handle for a pointer to device USM memory" class: $xIPC @@ -242,3 +266,119 @@ returns: - "`NULL == hPhysMem`" - $X_RESULT_ERROR_OUT_OF_HOST_MEMORY - $X_RESULT_ERROR_OUT_OF_RESOURCES +--- #-------------------------------------------------------------------------- +type: function +desc: "Gets an inter-process event handle for an event object" +class: $xIPC +name: GetEventHandleExp +ordinal: "0" +details: + - > + The event must have been created by $xEventCreateExp with the + $X_EXP_EVENT_FLAG_IPC_EXP flag set. Events created without that flag, + and events opened with $xIPCOpenEventHandleExp, cannot be exported. + - > + On success, `ppIPCEventHandleData` receives an opaque byte buffer + allocated and owned by the implementation, and `pIPCEventHandleDataSizeRet` + receives its size. The contents of this buffer may be copied and + transferred, by the application's own means, to another process on the + same system, which passes those bytes to $xIPCOpenEventHandleExp to + obtain an event object that shares state with `hEvent`. + - > + The returned handle data must be released in the originating process + with $xIPCPutEventHandleExp once it is no longer needed. + - "Events created with $X_EXP_EVENT_FLAG_ENABLE_PROFILING cannot be exported." +params: + - type: $x_event_handle_t + name: hEvent + desc: "[in] handle of the event object" + - type: void** + name: ppIPCEventHandleData + desc: "[out] a pointer to the IPC event handle data" + - type: size_t* + name: pIPCEventHandleDataSizeRet + desc: "[out] size of the resulting IPC event handle data" +returns: + - $X_RESULT_ERROR_INVALID_NULL_HANDLE: + - "`NULL == hEvent`" + - $X_RESULT_ERROR_INVALID_NULL_POINTER: + - "`NULL == ppIPCEventHandleData`" + - "`NULL == pIPCEventHandleDataSizeRet`" + - $X_RESULT_ERROR_INVALID_EVENT: + - "`hEvent` was not created with the $X_EXP_EVENT_FLAG_IPC_EXP flag." + - "`hEvent` was obtained from $xIPCOpenEventHandleExp." + - $X_RESULT_ERROR_UNSUPPORTED_FEATURE: + - "`hEvent` has profiling or timestamping enabled." + - "The device associated with `hEvent` does not support event IPC, as reported by $X_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP." + - $X_RESULT_ERROR_OUT_OF_HOST_MEMORY + - $X_RESULT_ERROR_OUT_OF_RESOURCES +--- #-------------------------------------------------------------------------- +type: function +desc: "Releases an inter-process event handle" +class: $xIPC +name: PutEventHandleExp +ordinal: "0" +details: + - > + Releases the resources associated with IPC event handle data returned by + $xIPCGetEventHandleExp. Must be called in the same process that obtained + the handle data. This does not destroy the source event and does not + affect event objects already opened with $xIPCOpenEventHandleExp. +params: + - type: $x_context_handle_t + name: hContext + desc: "[in] handle of the context object" + - type: void* + name: pIPCEventHandleData + desc: "[in] a pointer to the IPC event handle data obtained with $xIPCGetEventHandleExp" +returns: + - $X_RESULT_ERROR_INVALID_CONTEXT + - $X_RESULT_ERROR_INVALID_NULL_HANDLE: + - "`NULL == hContext`" + - $X_RESULT_ERROR_INVALID_NULL_POINTER: + - "`NULL == pIPCEventHandleData`" + - $X_RESULT_ERROR_OUT_OF_HOST_MEMORY + - $X_RESULT_ERROR_OUT_OF_RESOURCES +--- #-------------------------------------------------------------------------- +type: function +desc: "Opens an inter-process event handle to get the corresponding event object in the current process" +class: $xIPC +name: OpenEventHandleExp +ordinal: "0" +details: + - > + Returns an event object that shares state with the event that produced + the IPC handle. Either event can be signaled, waited on, or queried, and + a state change made through one event is observable through the other. + - > + The returned event is a normal $x_event_handle_t with an initial + reference count of 1. It may be passed to entry points that accept an + event, retained with $xEventRetain, and must be released with + $xEventRelease. On the final release, the adapter performs the native + cleanup required for an opened IPC event. +params: + - type: $x_context_handle_t + name: hContext + desc: "[in] handle of the context object" + - type: const void * + name: pIPCEventHandleData + desc: "[in] the IPC event handle data" + - type: size_t + name: ipcEventHandleDataSize + desc: "[in] size of the IPC event handle data" + - type: $x_event_handle_t* + name: phEvent + desc: "[out][alloc] pointer to the handle of the event object created" +returns: + - $X_RESULT_ERROR_INVALID_CONTEXT + - $X_RESULT_ERROR_INVALID_NULL_HANDLE: + - "`NULL == hContext`" + - $X_RESULT_ERROR_INVALID_NULL_POINTER: + - "`NULL == pIPCEventHandleData`" + - "`NULL == phEvent`" + - $X_RESULT_ERROR_INVALID_VALUE: + - "`ipcEventHandleDataSize` is not the same as the size of the IPC event handle data" + - $X_RESULT_ERROR_UNSUPPORTED_FEATURE: + - "A device in `hContext` does not support event IPC, as reported by $X_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP." + - $X_RESULT_ERROR_OUT_OF_HOST_MEMORY + - $X_RESULT_ERROR_OUT_OF_RESOURCES From 935943d4f59a542021731168f10a58a8d2bfa3b5 Mon Sep 17 00:00:00 2001 From: "Gainullin, Artur" Date: Thu, 18 Jun 2026 16:05:53 -0700 Subject: [PATCH 2/3] Generate sources --- .../include/unified-runtime/ur_api.h | 168 +++++++++++++++++- .../include/unified-runtime/ur_api_funcs.def | 3 + .../include/unified-runtime/ur_ddi.h | 19 ++ .../include/unified-runtime/ur_print.h | 30 ++++ .../include/unified-runtime/ur_print.hpp | 126 +++++++++++++ unified-runtime/scripts/core/registry.yml | 11 +- .../level_zero/ur_interface_loader.cpp | 3 + .../level_zero/ur_interface_loader.hpp | 9 + .../source/adapters/mock/ur_mockddi.cpp | 149 ++++++++++++++++ .../source/adapters/opencl/common.hpp | 24 +-- .../loader/layers/tracing/ur_trcddi.cpp | 133 ++++++++++++++ .../loader/layers/validation/ur_valddi.cpp | 121 +++++++++++++ unified-runtime/source/loader/loader.def.in | 6 + unified-runtime/source/loader/loader.map.in | 6 + unified-runtime/source/loader/ur_ldrddi.cpp | 66 +++++++ unified-runtime/source/loader/ur_libapi.cpp | 150 ++++++++++++++++ unified-runtime/source/loader/ur_print.cpp | 24 +++ unified-runtime/source/ur_api.cpp | 130 ++++++++++++++ unified-runtime/tools/urinfo/urinfo.hpp | 2 + 19 files changed, 1166 insertions(+), 14 deletions(-) diff --git a/unified-runtime/include/unified-runtime/ur_api.h b/unified-runtime/include/unified-runtime/ur_api.h index ccc5c31010835..95837be5d83e3 100644 --- a/unified-runtime/include/unified-runtime/ur_api.h +++ b/unified-runtime/include/unified-runtime/ur_api.h @@ -522,6 +522,12 @@ typedef enum ur_function_t { UR_FUNCTION_IPC_CLOSE_PHYS_MEM_HANDLE_EXP = 319, /// Enumerator for ::urEventCreateExp UR_FUNCTION_EVENT_CREATE_EXP = 320, + /// Enumerator for ::urIPCGetEventHandleExp + UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP = 321, + /// Enumerator for ::urIPCPutEventHandleExp + UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP = 322, + /// Enumerator for ::urIPCOpenEventHandleExp + UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP = 323, /// @cond UR_FUNCTION_FORCE_UINT32 = 0x7fffffff /// @endcond @@ -2523,6 +2529,9 @@ typedef enum ur_device_info_t { /// created with ::urEventCreateExp and signaled by /// ::urEnqueueEventsWaitWithBarrierExt. UR_DEVICE_INFO_REUSABLE_EVENTS_SUPPORT_EXP = 0x2025, + /// [::ur_bool_t] returns true if the device supports inter-process + /// communicable event handles + UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP = 0x2026, /// [::ur_bool_t] returns true if the device supports enqueueing of /// allocations and frees. UR_DEVICE_INFO_ASYNC_USM_ALLOCATIONS_SUPPORT_EXP = 0x2050, @@ -11367,6 +11376,127 @@ UR_APIEXPORT ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( /// [in] physical memory handle opened through urIPCOpenPhysMemHandleExp ur_physical_mem_handle_t hPhysMem); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gets an inter-process event handle for an event object +/// +/// @details +/// - The event must have been created by ::urEventCreateExp with the +/// ::UR_EXP_EVENT_FLAG_IPC_EXP flag set. Events created without that +/// flag, and events opened with ::urIPCOpenEventHandleExp, cannot be +/// exported. +/// - On success, `ppIPCEventHandleData` receives an opaque byte buffer +/// allocated and owned by the implementation, and +/// `pIPCEventHandleDataSizeRet` receives its size. The contents of this +/// buffer may be copied and transferred, by the application's own means, +/// to another process on the same system, which passes those bytes to +/// ::urIPCOpenEventHandleExp to obtain an event object that shares state +/// with `hEvent`. +/// - The returned handle data must be released in the originating process +/// with ::urIPCPutEventHandleExp once it is no longer needed. +/// - Events created with ::UR_EXP_EVENT_FLAG_ENABLE_PROFILING cannot be +/// exported. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ppIPCEventHandleData` +/// + `NULL == pIPCEventHandleDataSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// + `hEvent` was not created with the ::UR_EXP_EVENT_FLAG_IPC_EXP +/// flag. +/// + `hEvent` was obtained from ::urIPCOpenEventHandleExp. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + `hEvent` has profiling or timestamping enabled. +/// + The device associated with `hEvent` does not support event IPC, as +/// reported by ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +UR_APIEXPORT ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Releases an inter-process event handle +/// +/// @details +/// - Releases the resources associated with IPC event handle data returned +/// by ::urIPCGetEventHandleExp. Must be called in the same process that +/// obtained the handle data. This does not destroy the source event and +/// does not affect event objects already opened with +/// ::urIPCOpenEventHandleExp. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +UR_APIEXPORT ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Opens an inter-process event handle to get the corresponding event +/// object in the current process +/// +/// @details +/// - Returns an event object that shares state with the event that produced +/// the IPC handle. Either event can be signaled, waited on, or queried, +/// and a state change made through one event is observable through the +/// other. +/// - The returned event is a normal ::ur_event_handle_t with an initial +/// reference count of 1. It may be passed to entry points that accept an +/// event, retained with ::urEventRetain, and must be released with +/// ::urEventRelease. On the final release, the adapter performs the +/// native cleanup required for an opened IPC event. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `ipcEventHandleDataSize` is not the same as the size of the IPC +/// event handle data +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + A device in `hContext` does not support event IPC, as reported by +/// ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +UR_APIEXPORT ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent); + #if !defined(__GNUC__) #pragma endregion #endif @@ -13794,13 +13924,19 @@ typedef enum ur_exp_event_flag_t { /// Event captures UR_PROFILING_INFO_COMMAND_START and /// UR_PROFILING_INFO_COMMAND_END timestamps when signalled. UR_EXP_EVENT_FLAG_ENABLE_PROFILING = UR_BIT(0), + /// The event can be shared with other processes through the + /// ::urIPCGetEventHandleExp and ::urIPCOpenEventHandleExp APIs. This flag + /// must be passed to ::urEventCreateExp for any event whose IPC handle + /// will later be obtained; it cannot be enabled after creation. Must not + /// be combined with ::UR_EXP_EVENT_FLAG_ENABLE_PROFILING. + UR_EXP_EVENT_FLAG_IPC_EXP = UR_BIT(1), /// @cond UR_EXP_EVENT_FLAG_FORCE_UINT32 = 0x7fffffff /// @endcond } ur_exp_event_flag_t; /// @brief Bit Mask for validating ur_exp_event_flags_t -#define UR_EXP_EVENT_FLAGS_MASK 0xfffffffe +#define UR_EXP_EVENT_FLAGS_MASK 0xfffffffc /////////////////////////////////////////////////////////////////////////////// /// @brief Descriptor type for creating reusable events. @@ -16764,6 +16900,36 @@ typedef struct ur_ipc_close_phys_mem_handle_exp_params_t { ur_physical_mem_handle_t *phPhysMem; } ur_ipc_close_phys_mem_handle_exp_params_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urIPCGetEventHandleExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_ipc_get_event_handle_exp_params_t { + ur_event_handle_t *phEvent; + void ***pppIPCEventHandleData; + size_t **ppIPCEventHandleDataSizeRet; +} ur_ipc_get_event_handle_exp_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urIPCPutEventHandleExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_ipc_put_event_handle_exp_params_t { + ur_context_handle_t *phContext; + void **ppIPCEventHandleData; +} ur_ipc_put_event_handle_exp_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urIPCOpenEventHandleExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_ipc_open_event_handle_exp_params_t { + ur_context_handle_t *phContext; + const void **ppIPCEventHandleData; + size_t *pipcEventHandleDataSize; + ur_event_handle_t **pphEvent; +} ur_ipc_open_event_handle_exp_params_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Function parameters for urMemoryExportAllocExportableMemoryExp /// @details Each entry is a pointer to the parameter passed to the function; diff --git a/unified-runtime/include/unified-runtime/ur_api_funcs.def b/unified-runtime/include/unified-runtime/ur_api_funcs.def index 23f1793e33826..5fd96396cf7a1 100644 --- a/unified-runtime/include/unified-runtime/ur_api_funcs.def +++ b/unified-runtime/include/unified-runtime/ur_api_funcs.def @@ -228,6 +228,9 @@ _UR_API(urIPCGetPhysMemHandleExp) _UR_API(urIPCPutPhysMemHandleExp) _UR_API(urIPCOpenPhysMemHandleExp) _UR_API(urIPCClosePhysMemHandleExp) +_UR_API(urIPCGetEventHandleExp) +_UR_API(urIPCPutEventHandleExp) +_UR_API(urIPCOpenEventHandleExp) _UR_API(urMemoryExportAllocExportableMemoryExp) _UR_API(urMemoryExportFreeExportableMemoryExp) _UR_API(urMemoryExportExportMemoryHandleExp) diff --git a/unified-runtime/include/unified-runtime/ur_ddi.h b/unified-runtime/include/unified-runtime/ur_ddi.h index 0b174bc636923..2b03ba7431277 100644 --- a/unified-runtime/include/unified-runtime/ur_ddi.h +++ b/unified-runtime/include/unified-runtime/ur_ddi.h @@ -2002,6 +2002,22 @@ typedef ur_result_t(UR_APICALL *ur_pfnIPCOpenPhysMemHandleExp_t)( typedef ur_result_t(UR_APICALL *ur_pfnIPCClosePhysMemHandleExp_t)( ur_context_handle_t, ur_physical_mem_handle_t); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urIPCGetEventHandleExp +typedef ur_result_t(UR_APICALL *ur_pfnIPCGetEventHandleExp_t)(ur_event_handle_t, + void **, + size_t *); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urIPCPutEventHandleExp +typedef ur_result_t(UR_APICALL *ur_pfnIPCPutEventHandleExp_t)( + ur_context_handle_t, void *); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urIPCOpenEventHandleExp +typedef ur_result_t(UR_APICALL *ur_pfnIPCOpenEventHandleExp_t)( + ur_context_handle_t, const void *, size_t, ur_event_handle_t *); + /////////////////////////////////////////////////////////////////////////////// /// @brief Table of IPCExp functions pointers typedef struct ur_ipc_exp_dditable_t { @@ -2013,6 +2029,9 @@ typedef struct ur_ipc_exp_dditable_t { ur_pfnIPCPutPhysMemHandleExp_t pfnPutPhysMemHandleExp; ur_pfnIPCOpenPhysMemHandleExp_t pfnOpenPhysMemHandleExp; ur_pfnIPCClosePhysMemHandleExp_t pfnClosePhysMemHandleExp; + ur_pfnIPCGetEventHandleExp_t pfnGetEventHandleExp; + ur_pfnIPCPutEventHandleExp_t pfnPutEventHandleExp; + ur_pfnIPCOpenEventHandleExp_t pfnOpenEventHandleExp; } ur_ipc_exp_dditable_t; /////////////////////////////////////////////////////////////////////////////// diff --git a/unified-runtime/include/unified-runtime/ur_print.h b/unified-runtime/include/unified-runtime/ur_print.h index 500b6ef34d849..f0079bc1c15bc 100644 --- a/unified-runtime/include/unified-runtime/ur_print.h +++ b/unified-runtime/include/unified-runtime/ur_print.h @@ -3855,6 +3855,36 @@ UR_APIEXPORT ur_result_t UR_APICALL urPrintIpcClosePhysMemHandleExpParams( const struct ur_ipc_close_phys_mem_handle_exp_params_t *params, char *buffer, const size_t buff_size, size_t *out_size); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_ipc_get_event_handle_exp_params_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintIpcGetEventHandleExpParams( + const struct ur_ipc_get_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_ipc_put_event_handle_exp_params_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintIpcPutEventHandleExpParams( + const struct ur_ipc_put_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_ipc_open_event_handle_exp_params_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintIpcOpenEventHandleExpParams( + const struct ur_ipc_open_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size); + /////////////////////////////////////////////////////////////////////////////// /// @brief Print ur_memory_export_alloc_exportable_memory_exp_params_t struct /// @returns diff --git a/unified-runtime/include/unified-runtime/ur_print.hpp b/unified-runtime/include/unified-runtime/ur_print.hpp index 2829e05de370d..cee4a30e34b3c 100644 --- a/unified-runtime/include/unified-runtime/ur_print.hpp +++ b/unified-runtime/include/unified-runtime/ur_print.hpp @@ -1404,6 +1404,15 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_function_t value) { case UR_FUNCTION_EVENT_CREATE_EXP: os << "UR_FUNCTION_EVENT_CREATE_EXP"; break; + case UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP: + os << "UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP"; + break; + case UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP: + os << "UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP"; + break; + case UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP: + os << "UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP"; + break; default: os << "unknown enumerator"; break; @@ -3347,6 +3356,9 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_device_info_t value) { case UR_DEVICE_INFO_REUSABLE_EVENTS_SUPPORT_EXP: os << "UR_DEVICE_INFO_REUSABLE_EVENTS_SUPPORT_EXP"; break; + case UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP: + os << "UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP"; + break; case UR_DEVICE_INFO_ASYNC_USM_ALLOCATIONS_SUPPORT_EXP: os << "UR_DEVICE_INFO_ASYNC_USM_ALLOCATIONS_SUPPORT_EXP"; break; @@ -5658,6 +5670,19 @@ inline ur_result_t printTagged(std::ostream &os, const void *ptr, os << ")"; } break; + case UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP: { + const ur_bool_t *tptr = (const ur_bool_t *)ptr; + if (sizeof(ur_bool_t) > size) { + os << "invalid size (is: " << size + << ", expected: >=" << sizeof(ur_bool_t) << ")"; + return UR_RESULT_ERROR_INVALID_SIZE; + } + os << (const void *)(tptr) << " ("; + + os << *tptr; + + os << ")"; + } break; case UR_DEVICE_INFO_ASYNC_USM_ALLOCATIONS_SUPPORT_EXP: { const ur_bool_t *tptr = (const ur_bool_t *)ptr; if (sizeof(ur_bool_t) > size) { @@ -13382,6 +13407,9 @@ inline std::ostream &operator<<(std::ostream &os, case UR_EXP_EVENT_FLAG_ENABLE_PROFILING: os << "UR_EXP_EVENT_FLAG_ENABLE_PROFILING"; break; + case UR_EXP_EVENT_FLAG_IPC_EXP: + os << "UR_EXP_EVENT_FLAG_IPC_EXP"; + break; default: os << "unknown enumerator"; break; @@ -13408,6 +13436,17 @@ inline ur_result_t printFlag(std::ostream &os, } os << UR_EXP_EVENT_FLAG_ENABLE_PROFILING; } + + if ((val & UR_EXP_EVENT_FLAG_IPC_EXP) == + (uint32_t)UR_EXP_EVENT_FLAG_IPC_EXP) { + val ^= (uint32_t)UR_EXP_EVENT_FLAG_IPC_EXP; + if (!first) { + os << " | "; + } else { + first = false; + } + os << UR_EXP_EVENT_FLAG_IPC_EXP; + } if (val != 0) { std::bitset<32> bits(val); if (!first) { @@ -22001,6 +22040,84 @@ inline std::ostream &operator<<( return os; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_ipc_get_event_handle_exp_params_t type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, + [[maybe_unused]] const struct ur_ipc_get_event_handle_exp_params_t + *params) { + + os << ".hEvent = "; + + ur::details::printPtr(os, *(params->phEvent)); + + os << ", "; + os << ".ppIPCEventHandleData = "; + + ur::details::printPtr(os, *(params->pppIPCEventHandleData)); + + os << ", "; + os << ".pIPCEventHandleDataSizeRet = "; + + ur::details::printPtr(os, *(params->ppIPCEventHandleDataSizeRet)); + + return os; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_ipc_put_event_handle_exp_params_t type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, + [[maybe_unused]] const struct ur_ipc_put_event_handle_exp_params_t + *params) { + + os << ".hContext = "; + + ur::details::printPtr(os, *(params->phContext)); + + os << ", "; + os << ".pIPCEventHandleData = "; + + ur::details::printPtr(os, *(params->ppIPCEventHandleData)); + + return os; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_ipc_open_event_handle_exp_params_t type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, + [[maybe_unused]] const struct ur_ipc_open_event_handle_exp_params_t + *params) { + + os << ".hContext = "; + + ur::details::printPtr(os, *(params->phContext)); + + os << ", "; + os << ".pIPCEventHandleData = "; + + os << *(params->ppIPCEventHandleData); + + os << ", "; + os << ".ipcEventHandleDataSize = "; + + os << *(params->pipcEventHandleDataSize); + + os << ", "; + os << ".phEvent = "; + + ur::details::printPtr(os, *(params->pphEvent)); + + return os; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Print operator for the /// ur_memory_export_alloc_exportable_memory_exp_params_t type @@ -23572,6 +23689,15 @@ inline ur_result_t UR_APICALL printFunctionParams(std::ostream &os, case UR_FUNCTION_IPC_CLOSE_PHYS_MEM_HANDLE_EXP: { os << (const struct ur_ipc_close_phys_mem_handle_exp_params_t *)params; } break; + case UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP: { + os << (const struct ur_ipc_get_event_handle_exp_params_t *)params; + } break; + case UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP: { + os << (const struct ur_ipc_put_event_handle_exp_params_t *)params; + } break; + case UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP: { + os << (const struct ur_ipc_open_event_handle_exp_params_t *)params; + } break; case UR_FUNCTION_MEMORY_EXPORT_ALLOC_EXPORTABLE_MEMORY_EXP: { os << (const struct ur_memory_export_alloc_exportable_memory_exp_params_t *) params; diff --git a/unified-runtime/scripts/core/registry.yml b/unified-runtime/scripts/core/registry.yml index b915d9f5e1ce9..4cd3da17d872c 100644 --- a/unified-runtime/scripts/core/registry.yml +++ b/unified-runtime/scripts/core/registry.yml @@ -742,7 +742,16 @@ etors: - name: EVENT_CREATE_EXP desc: Enumerator for $xEventCreateExp value: '320' -max_id: '320' +- name: IPC_GET_EVENT_HANDLE_EXP + desc: Enumerator for $xIPCGetEventHandleExp + value: '321' +- name: IPC_PUT_EVENT_HANDLE_EXP + desc: Enumerator for $xIPCPutEventHandleExp + value: '322' +- name: IPC_OPEN_EVENT_HANDLE_EXP + desc: Enumerator for $xIPCOpenEventHandleExp + value: '323' +max_id: '323' --- type: enum desc: Defines structure types diff --git a/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp b/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp index 52ef418faef59..ef21d24eab5c4 100644 --- a/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp +++ b/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp @@ -311,6 +311,9 @@ UR_APIEXPORT ur_result_t UR_APICALL urGetIPCExpProcAddrTable( ur::level_zero::urIPCOpenPhysMemHandleExp; pDdiTable->pfnClosePhysMemHandleExp = ur::level_zero::urIPCClosePhysMemHandleExp; + pDdiTable->pfnGetEventHandleExp = ur::level_zero::urIPCGetEventHandleExp; + pDdiTable->pfnPutEventHandleExp = ur::level_zero::urIPCPutEventHandleExp; + pDdiTable->pfnOpenEventHandleExp = ur::level_zero::urIPCOpenEventHandleExp; return result; } diff --git a/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp b/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp index 12c28d61e7527..dfd5194a588a4 100644 --- a/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp +++ b/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp @@ -642,6 +642,15 @@ ur_result_t urIPCOpenPhysMemHandleExp(ur_context_handle_t hContext, ur_physical_mem_handle_t *phPhysMem); ur_result_t urIPCClosePhysMemHandleExp(ur_context_handle_t hContext, ur_physical_mem_handle_t hPhysMem); +ur_result_t urIPCGetEventHandleExp(ur_event_handle_t hEvent, + void **ppIPCEventHandleData, + size_t *pIPCEventHandleDataSizeRet); +ur_result_t urIPCPutEventHandleExp(ur_context_handle_t hContext, + void *pIPCEventHandleData); +ur_result_t urIPCOpenEventHandleExp(ur_context_handle_t hContext, + const void *pIPCEventHandleData, + size_t ipcEventHandleDataSize, + ur_event_handle_t *phEvent); ur_result_t urMemoryExportAllocExportableMemoryExp( ur_context_handle_t hContext, ur_device_handle_t hDevice, size_t alignment, size_t size, ur_exp_external_mem_type_t handleTypeToExport, void **ppMem); diff --git a/unified-runtime/source/adapters/mock/ur_mockddi.cpp b/unified-runtime/source/adapters/mock/ur_mockddi.cpp index 9e2aa85d185e6..7dda578da5210 100644 --- a/unified-runtime/source/adapters/mock/ur_mockddi.cpp +++ b/unified-runtime/source/adapters/mock/ur_mockddi.cpp @@ -9855,6 +9855,149 @@ __urdlllocal ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCGetEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) try { + ur_result_t result = UR_RESULT_SUCCESS; + + ur_ipc_get_event_handle_exp_params_t params = {&hEvent, &ppIPCEventHandleData, + &pIPCEventHandleDataSizeRet}; + + auto beforeCallback = reinterpret_cast( + mock::getCallbacks().get_before_callback("urIPCGetEventHandleExp")); + if (beforeCallback) { + result = beforeCallback(¶ms); + if (result != UR_RESULT_SUCCESS) { + return result; + } + } + + auto replaceCallback = reinterpret_cast( + mock::getCallbacks().get_replace_callback("urIPCGetEventHandleExp")); + if (replaceCallback) { + result = replaceCallback(¶ms); + } else { + + result = UR_RESULT_SUCCESS; + } + + if (result != UR_RESULT_SUCCESS) { + return result; + } + + auto afterCallback = reinterpret_cast( + mock::getCallbacks().get_after_callback("urIPCGetEventHandleExp")); + if (afterCallback) { + return afterCallback(¶ms); + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCPutEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) try { + ur_result_t result = UR_RESULT_SUCCESS; + + ur_ipc_put_event_handle_exp_params_t params = {&hContext, + &pIPCEventHandleData}; + + auto beforeCallback = reinterpret_cast( + mock::getCallbacks().get_before_callback("urIPCPutEventHandleExp")); + if (beforeCallback) { + result = beforeCallback(¶ms); + if (result != UR_RESULT_SUCCESS) { + return result; + } + } + + auto replaceCallback = reinterpret_cast( + mock::getCallbacks().get_replace_callback("urIPCPutEventHandleExp")); + if (replaceCallback) { + result = replaceCallback(¶ms); + } else { + + result = UR_RESULT_SUCCESS; + } + + if (result != UR_RESULT_SUCCESS) { + return result; + } + + auto afterCallback = reinterpret_cast( + mock::getCallbacks().get_after_callback("urIPCPutEventHandleExp")); + if (afterCallback) { + return afterCallback(¶ms); + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCOpenEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) try { + ur_result_t result = UR_RESULT_SUCCESS; + + ur_ipc_open_event_handle_exp_params_t params = { + &hContext, &pIPCEventHandleData, &ipcEventHandleDataSize, &phEvent}; + + auto beforeCallback = reinterpret_cast( + mock::getCallbacks().get_before_callback("urIPCOpenEventHandleExp")); + if (beforeCallback) { + result = beforeCallback(¶ms); + if (result != UR_RESULT_SUCCESS) { + return result; + } + } + + auto replaceCallback = reinterpret_cast( + mock::getCallbacks().get_replace_callback("urIPCOpenEventHandleExp")); + if (replaceCallback) { + result = replaceCallback(¶ms); + } else { + + *phEvent = mock::createDummyHandle(); + result = UR_RESULT_SUCCESS; + } + + if (result != UR_RESULT_SUCCESS) { + return result; + } + + auto afterCallback = reinterpret_cast( + mock::getCallbacks().get_after_callback("urIPCOpenEventHandleExp")); + if (afterCallback) { + return afterCallback(¶ms); + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urMemoryExportAllocExportableMemoryExp __urdlllocal ur_result_t UR_APICALL urMemoryExportAllocExportableMemoryExp( @@ -13829,6 +13972,12 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetIPCExpProcAddrTable( pDdiTable->pfnClosePhysMemHandleExp = driver::urIPCClosePhysMemHandleExp; + pDdiTable->pfnGetEventHandleExp = driver::urIPCGetEventHandleExp; + + pDdiTable->pfnPutEventHandleExp = driver::urIPCPutEventHandleExp; + + pDdiTable->pfnOpenEventHandleExp = driver::urIPCOpenEventHandleExp; + return result; } catch (...) { return exceptionToResult(std::current_exception()); diff --git a/unified-runtime/source/adapters/opencl/common.hpp b/unified-runtime/source/adapters/opencl/common.hpp index aefea1f6c55a0..fadab9d199929 100644 --- a/unified-runtime/source/adapters/opencl/common.hpp +++ b/unified-runtime/source/adapters/opencl/common.hpp @@ -224,24 +224,24 @@ CONSTFIX char GetKernelSubGroupInfoName[] = "clGetKernelSubGroupInfoKHR"; #undef CONSTFIX using clGetDeviceFunctionPointerINTEL_fn = CL_API_ENTRY - cl_int(CL_API_CALL *)(cl_device_id device, cl_program program, - const char *FuncName, cl_ulong *ret_ptr); +cl_int(CL_API_CALL *)(cl_device_id device, cl_program program, + const char *FuncName, cl_ulong *ret_ptr); using clGetDeviceGlobalVariablePointerINTEL_fn = CL_API_ENTRY - cl_int(CL_API_CALL *)(cl_device_id device, cl_program program, - const char *globalVariableName, - size_t *globalVariableSizeRet, - void **globalVariablePointerRet); +cl_int(CL_API_CALL *)(cl_device_id device, cl_program program, + const char *globalVariableName, + size_t *globalVariableSizeRet, + void **globalVariablePointerRet); using clEnqueueWriteGlobalVariableINTEL_fn = CL_API_ENTRY - cl_int(CL_API_CALL *)(cl_command_queue, cl_program, const char *, cl_bool, - size_t, size_t, const void *, cl_uint, - const cl_event *, cl_event *); +cl_int(CL_API_CALL *)(cl_command_queue, cl_program, const char *, cl_bool, + size_t, size_t, const void *, cl_uint, const cl_event *, + cl_event *); using clEnqueueReadGlobalVariableINTEL_fn = CL_API_ENTRY - cl_int(CL_API_CALL *)(cl_command_queue, cl_program, const char *, cl_bool, - size_t, size_t, void *, cl_uint, const cl_event *, - cl_event *); +cl_int(CL_API_CALL *)(cl_command_queue, cl_program, const char *, cl_bool, + size_t, size_t, void *, cl_uint, const cl_event *, + cl_event *); using clEnqueueReadHostPipeINTEL_fn = CL_API_ENTRY cl_int(CL_API_CALL *)(cl_command_queue queue, cl_program program, diff --git a/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp b/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp index 81655c64308c4..ec1059805dde1 100644 --- a/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp +++ b/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp @@ -8331,6 +8331,130 @@ __urdlllocal ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCGetEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) { + auto pfnGetEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnGetEventHandleExp; + + if (nullptr == pfnGetEventHandleExp) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + + ur_ipc_get_event_handle_exp_params_t params = {&hEvent, &ppIPCEventHandleData, + &pIPCEventHandleDataSizeRet}; + uint64_t instance = getContext()->notify_begin( + UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP, "urIPCGetEventHandleExp", ¶ms); + + auto &logger = getContext()->logger; + UR_LOG_L(logger, INFO, " ---> urIPCGetEventHandleExp\n"); + + ur_result_t result = pfnGetEventHandleExp(hEvent, ppIPCEventHandleData, + pIPCEventHandleDataSizeRet); + + getContext()->notify_end(UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP, + "urIPCGetEventHandleExp", ¶ms, &result, + instance); + + if (logger.getLevel() <= UR_LOGGER_LEVEL_INFO) { + std::ostringstream args_str; + ur::extras::printFunctionParams( + args_str, UR_FUNCTION_IPC_GET_EVENT_HANDLE_EXP, ¶ms); + UR_LOG_L(logger, INFO, " <--- urIPCGetEventHandleExp({}) -> {};\n", + args_str.str(), result); + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCPutEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) { + auto pfnPutEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnPutEventHandleExp; + + if (nullptr == pfnPutEventHandleExp) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + + ur_ipc_put_event_handle_exp_params_t params = {&hContext, + &pIPCEventHandleData}; + uint64_t instance = getContext()->notify_begin( + UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP, "urIPCPutEventHandleExp", ¶ms); + + auto &logger = getContext()->logger; + UR_LOG_L(logger, INFO, " ---> urIPCPutEventHandleExp\n"); + + ur_result_t result = pfnPutEventHandleExp(hContext, pIPCEventHandleData); + + getContext()->notify_end(UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP, + "urIPCPutEventHandleExp", ¶ms, &result, + instance); + + if (logger.getLevel() <= UR_LOGGER_LEVEL_INFO) { + std::ostringstream args_str; + ur::extras::printFunctionParams( + args_str, UR_FUNCTION_IPC_PUT_EVENT_HANDLE_EXP, ¶ms); + UR_LOG_L(logger, INFO, " <--- urIPCPutEventHandleExp({}) -> {};\n", + args_str.str(), result); + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCOpenEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) { + auto pfnOpenEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnOpenEventHandleExp; + + if (nullptr == pfnOpenEventHandleExp) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + + ur_ipc_open_event_handle_exp_params_t params = { + &hContext, &pIPCEventHandleData, &ipcEventHandleDataSize, &phEvent}; + uint64_t instance = + getContext()->notify_begin(UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP, + "urIPCOpenEventHandleExp", ¶ms); + + auto &logger = getContext()->logger; + UR_LOG_L(logger, INFO, " ---> urIPCOpenEventHandleExp\n"); + + ur_result_t result = pfnOpenEventHandleExp(hContext, pIPCEventHandleData, + ipcEventHandleDataSize, phEvent); + + getContext()->notify_end(UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP, + "urIPCOpenEventHandleExp", ¶ms, &result, + instance); + + if (logger.getLevel() <= UR_LOGGER_LEVEL_INFO) { + std::ostringstream args_str; + ur::extras::printFunctionParams( + args_str, UR_FUNCTION_IPC_OPEN_EVENT_HANDLE_EXP, ¶ms); + UR_LOG_L(logger, INFO, " <--- urIPCOpenEventHandleExp({}) -> {};\n", + args_str.str(), result); + } + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urMemoryExportAllocExportableMemoryExp __urdlllocal ur_result_t UR_APICALL urMemoryExportAllocExportableMemoryExp( @@ -11992,6 +12116,15 @@ __urdlllocal ur_result_t UR_APICALL urGetIPCExpProcAddrTable( pDdiTable->pfnClosePhysMemHandleExp = ur_tracing_layer::urIPCClosePhysMemHandleExp; + dditable.pfnGetEventHandleExp = pDdiTable->pfnGetEventHandleExp; + pDdiTable->pfnGetEventHandleExp = ur_tracing_layer::urIPCGetEventHandleExp; + + dditable.pfnPutEventHandleExp = pDdiTable->pfnPutEventHandleExp; + pDdiTable->pfnPutEventHandleExp = ur_tracing_layer::urIPCPutEventHandleExp; + + dditable.pfnOpenEventHandleExp = pDdiTable->pfnOpenEventHandleExp; + pDdiTable->pfnOpenEventHandleExp = ur_tracing_layer::urIPCOpenEventHandleExp; + return result; } /////////////////////////////////////////////////////////////////////////////// diff --git a/unified-runtime/source/loader/layers/validation/ur_valddi.cpp b/unified-runtime/source/loader/layers/validation/ur_valddi.cpp index 99c21040f7da2..b86e2c565c249 100644 --- a/unified-runtime/source/loader/layers/validation/ur_valddi.cpp +++ b/unified-runtime/source/loader/layers/validation/ur_valddi.cpp @@ -9173,6 +9173,117 @@ __urdlllocal ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCGetEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) { + auto pfnGetEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnGetEventHandleExp; + + if (nullptr == pfnGetEventHandleExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (getContext()->enableParameterValidation) { + if (NULL == ppIPCEventHandleData) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == pIPCEventHandleDataSizeRet) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == hEvent) + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (getContext()->enableLifetimeValidation && + !getContext()->refCountContext->isReferenceValid(hEvent)) { + URLOG_CTX_INVALID_REFERENCE(hEvent); + } + + ur_result_t result = pfnGetEventHandleExp(hEvent, ppIPCEventHandleData, + pIPCEventHandleDataSizeRet); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCPutEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) { + auto pfnPutEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnPutEventHandleExp; + + if (nullptr == pfnPutEventHandleExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (getContext()->enableParameterValidation) { + if (NULL == pIPCEventHandleData) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == hContext) + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (getContext()->enableLifetimeValidation && + !getContext()->refCountContext->isReferenceValid(hContext)) { + URLOG_CTX_INVALID_REFERENCE(hContext); + } + + ur_result_t result = pfnPutEventHandleExp(hContext, pIPCEventHandleData); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCOpenEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) { + auto pfnOpenEventHandleExp = + getContext()->urDdiTable.IPCExp.pfnOpenEventHandleExp; + + if (nullptr == pfnOpenEventHandleExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (getContext()->enableParameterValidation) { + if (NULL == phEvent) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == pIPCEventHandleData) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == hContext) + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (getContext()->enableLifetimeValidation && + !getContext()->refCountContext->isReferenceValid(hContext)) { + URLOG_CTX_INVALID_REFERENCE(hContext); + } + + ur_result_t result = pfnOpenEventHandleExp(hContext, pIPCEventHandleData, + ipcEventHandleDataSize, phEvent); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urMemoryExportAllocExportableMemoryExp __urdlllocal ur_result_t UR_APICALL urMemoryExportAllocExportableMemoryExp( @@ -12772,6 +12883,16 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetIPCExpProcAddrTable( pDdiTable->pfnClosePhysMemHandleExp = ur_validation_layer::urIPCClosePhysMemHandleExp; + dditable.pfnGetEventHandleExp = pDdiTable->pfnGetEventHandleExp; + pDdiTable->pfnGetEventHandleExp = ur_validation_layer::urIPCGetEventHandleExp; + + dditable.pfnPutEventHandleExp = pDdiTable->pfnPutEventHandleExp; + pDdiTable->pfnPutEventHandleExp = ur_validation_layer::urIPCPutEventHandleExp; + + dditable.pfnOpenEventHandleExp = pDdiTable->pfnOpenEventHandleExp; + pDdiTable->pfnOpenEventHandleExp = + ur_validation_layer::urIPCOpenEventHandleExp; + return result; } diff --git a/unified-runtime/source/loader/loader.def.in b/unified-runtime/source/loader/loader.def.in index ff385140ca9f7..71f4fdc0d3a2c 100644 --- a/unified-runtime/source/loader/loader.def.in +++ b/unified-runtime/source/loader/loader.def.in @@ -150,10 +150,13 @@ EXPORTS urGraphSetDestructionCallbackExp urIPCCloseMemHandleExp urIPCClosePhysMemHandleExp + urIPCGetEventHandleExp urIPCGetMemHandleExp urIPCGetPhysMemHandleExp + urIPCOpenEventHandleExp urIPCOpenMemHandleExp urIPCOpenPhysMemHandleExp + urIPCPutEventHandleExp urIPCPutMemHandleExp urIPCPutPhysMemHandleExp urKernelCreate @@ -407,10 +410,13 @@ EXPORTS urPrintImageInfo urPrintIpcCloseMemHandleExpParams urPrintIpcClosePhysMemHandleExpParams + urPrintIpcGetEventHandleExpParams urPrintIpcGetMemHandleExpParams urPrintIpcGetPhysMemHandleExpParams + urPrintIpcOpenEventHandleExpParams urPrintIpcOpenMemHandleExpParams urPrintIpcOpenPhysMemHandleExpParams + urPrintIpcPutEventHandleExpParams urPrintIpcPutMemHandleExpParams urPrintIpcPutPhysMemHandleExpParams urPrintKernelArgLocalProperties diff --git a/unified-runtime/source/loader/loader.map.in b/unified-runtime/source/loader/loader.map.in index 2211083ca76e6..ced274e24b521 100644 --- a/unified-runtime/source/loader/loader.map.in +++ b/unified-runtime/source/loader/loader.map.in @@ -150,10 +150,13 @@ urGraphSetDestructionCallbackExp; urIPCCloseMemHandleExp; urIPCClosePhysMemHandleExp; + urIPCGetEventHandleExp; urIPCGetMemHandleExp; urIPCGetPhysMemHandleExp; + urIPCOpenEventHandleExp; urIPCOpenMemHandleExp; urIPCOpenPhysMemHandleExp; + urIPCPutEventHandleExp; urIPCPutMemHandleExp; urIPCPutPhysMemHandleExp; urKernelCreate; @@ -407,10 +410,13 @@ urPrintImageInfo; urPrintIpcCloseMemHandleExpParams; urPrintIpcClosePhysMemHandleExpParams; + urPrintIpcGetEventHandleExpParams; urPrintIpcGetMemHandleExpParams; urPrintIpcGetPhysMemHandleExpParams; + urPrintIpcOpenEventHandleExpParams; urPrintIpcOpenMemHandleExpParams; urPrintIpcOpenPhysMemHandleExpParams; + urPrintIpcPutEventHandleExpParams; urPrintIpcPutMemHandleExpParams; urPrintIpcPutPhysMemHandleExpParams; urPrintKernelArgLocalProperties; diff --git a/unified-runtime/source/loader/ur_ldrddi.cpp b/unified-runtime/source/loader/ur_ldrddi.cpp index 763f3e84cc9bd..dd410ebec353d 100644 --- a/unified-runtime/source/loader/ur_ldrddi.cpp +++ b/unified-runtime/source/loader/ur_ldrddi.cpp @@ -4729,6 +4729,69 @@ __urdlllocal ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return pfnClosePhysMemHandleExp(hContext, hPhysMem); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCGetEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) { + + auto *dditable = *reinterpret_cast(hEvent); + + auto *pfnGetEventHandleExp = dditable->IPCExp.pfnGetEventHandleExp; + if (nullptr == pfnGetEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + // forward to device-platform + return pfnGetEventHandleExp(hEvent, ppIPCEventHandleData, + pIPCEventHandleDataSizeRet); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCPutEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) { + + auto *dditable = *reinterpret_cast(hContext); + + auto *pfnPutEventHandleExp = dditable->IPCExp.pfnPutEventHandleExp; + if (nullptr == pfnPutEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + // forward to device-platform + return pfnPutEventHandleExp(hContext, pIPCEventHandleData); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urIPCOpenEventHandleExp +__urdlllocal ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) { + + auto *dditable = *reinterpret_cast(hContext); + + auto *pfnOpenEventHandleExp = dditable->IPCExp.pfnOpenEventHandleExp; + if (nullptr == pfnOpenEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + // forward to device-platform + return pfnOpenEventHandleExp(hContext, pIPCEventHandleData, + ipcEventHandleDataSize, phEvent); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urMemoryExportAllocExportableMemoryExp __urdlllocal ur_result_t UR_APICALL urMemoryExportAllocExportableMemoryExp( @@ -7068,6 +7131,9 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetIPCExpProcAddrTable( pDdiTable->pfnOpenPhysMemHandleExp = ur_loader::urIPCOpenPhysMemHandleExp; pDdiTable->pfnClosePhysMemHandleExp = ur_loader::urIPCClosePhysMemHandleExp; + pDdiTable->pfnGetEventHandleExp = ur_loader::urIPCGetEventHandleExp; + pDdiTable->pfnPutEventHandleExp = ur_loader::urIPCPutEventHandleExp; + pDdiTable->pfnOpenEventHandleExp = ur_loader::urIPCOpenEventHandleExp; } else { // return pointers directly to platform's DDIs *pDdiTable = ur_loader::getContext()->platforms.front().dditable.IPCExp; diff --git a/unified-runtime/source/loader/ur_libapi.cpp b/unified-runtime/source/loader/ur_libapi.cpp index 9ebe09146893f..a4f14b165f596 100644 --- a/unified-runtime/source/loader/ur_libapi.cpp +++ b/unified-runtime/source/loader/ur_libapi.cpp @@ -8785,6 +8785,156 @@ ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gets an inter-process event handle for an event object +/// +/// @details +/// - The event must have been created by ::urEventCreateExp with the +/// ::UR_EXP_EVENT_FLAG_IPC_EXP flag set. Events created without that +/// flag, and events opened with ::urIPCOpenEventHandleExp, cannot be +/// exported. +/// - On success, `ppIPCEventHandleData` receives an opaque byte buffer +/// allocated and owned by the implementation, and +/// `pIPCEventHandleDataSizeRet` receives its size. The contents of this +/// buffer may be copied and transferred, by the application's own means, +/// to another process on the same system, which passes those bytes to +/// ::urIPCOpenEventHandleExp to obtain an event object that shares state +/// with `hEvent`. +/// - The returned handle data must be released in the originating process +/// with ::urIPCPutEventHandleExp once it is no longer needed. +/// - Events created with ::UR_EXP_EVENT_FLAG_ENABLE_PROFILING cannot be +/// exported. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ppIPCEventHandleData` +/// + `NULL == pIPCEventHandleDataSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// + `hEvent` was not created with the ::UR_EXP_EVENT_FLAG_IPC_EXP +/// flag. +/// + `hEvent` was obtained from ::urIPCOpenEventHandleExp. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + `hEvent` has profiling or timestamping enabled. +/// + The device associated with `hEvent` does not support event IPC, as +/// reported by ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) try { + auto pfnGetEventHandleExp = + ur_lib::getContext()->urDdiTable.IPCExp.pfnGetEventHandleExp; + if (nullptr == pfnGetEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnGetEventHandleExp(hEvent, ppIPCEventHandleData, + pIPCEventHandleDataSizeRet); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Releases an inter-process event handle +/// +/// @details +/// - Releases the resources associated with IPC event handle data returned +/// by ::urIPCGetEventHandleExp. Must be called in the same process that +/// obtained the handle data. This does not destroy the source event and +/// does not affect event objects already opened with +/// ::urIPCOpenEventHandleExp. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) try { + auto pfnPutEventHandleExp = + ur_lib::getContext()->urDdiTable.IPCExp.pfnPutEventHandleExp; + if (nullptr == pfnPutEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnPutEventHandleExp(hContext, pIPCEventHandleData); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Opens an inter-process event handle to get the corresponding event +/// object in the current process +/// +/// @details +/// - Returns an event object that shares state with the event that produced +/// the IPC handle. Either event can be signaled, waited on, or queried, +/// and a state change made through one event is observable through the +/// other. +/// - The returned event is a normal ::ur_event_handle_t with an initial +/// reference count of 1. It may be passed to entry points that accept an +/// event, retained with ::urEventRetain, and must be released with +/// ::urEventRelease. On the final release, the adapter performs the +/// native cleanup required for an opened IPC event. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `ipcEventHandleDataSize` is not the same as the size of the IPC +/// event handle data +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + A device in `hContext` does not support event IPC, as reported by +/// ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) try { + auto pfnOpenEventHandleExp = + ur_lib::getContext()->urDdiTable.IPCExp.pfnOpenEventHandleExp; + if (nullptr == pfnOpenEventHandleExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnOpenEventHandleExp(hContext, pIPCEventHandleData, + ipcEventHandleDataSize, phEvent); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Allocate an exportable memory region and return a pointer to that /// allocation. diff --git a/unified-runtime/source/loader/ur_print.cpp b/unified-runtime/source/loader/ur_print.cpp index d0bc689d26c6e..43671c078686f 100644 --- a/unified-runtime/source/loader/ur_print.cpp +++ b/unified-runtime/source/loader/ur_print.cpp @@ -2259,6 +2259,30 @@ ur_result_t urPrintIpcClosePhysMemHandleExpParams( return str_copy(&ss, buffer, buff_size, out_size); } +ur_result_t urPrintIpcGetEventHandleExpParams( + const struct ur_ipc_get_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + +ur_result_t urPrintIpcPutEventHandleExpParams( + const struct ur_ipc_put_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + +ur_result_t urPrintIpcOpenEventHandleExpParams( + const struct ur_ipc_open_event_handle_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + ur_result_t urPrintKernelCreateParams(const struct ur_kernel_create_params_t *params, char *buffer, const size_t buff_size, diff --git a/unified-runtime/source/ur_api.cpp b/unified-runtime/source/ur_api.cpp index 46467c353a5a4..fb1e5c9c7961d 100644 --- a/unified-runtime/source/ur_api.cpp +++ b/unified-runtime/source/ur_api.cpp @@ -7641,6 +7641,136 @@ ur_result_t UR_APICALL urIPCClosePhysMemHandleExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gets an inter-process event handle for an event object +/// +/// @details +/// - The event must have been created by ::urEventCreateExp with the +/// ::UR_EXP_EVENT_FLAG_IPC_EXP flag set. Events created without that +/// flag, and events opened with ::urIPCOpenEventHandleExp, cannot be +/// exported. +/// - On success, `ppIPCEventHandleData` receives an opaque byte buffer +/// allocated and owned by the implementation, and +/// `pIPCEventHandleDataSizeRet` receives its size. The contents of this +/// buffer may be copied and transferred, by the application's own means, +/// to another process on the same system, which passes those bytes to +/// ::urIPCOpenEventHandleExp to obtain an event object that shares state +/// with `hEvent`. +/// - The returned handle data must be released in the originating process +/// with ::urIPCPutEventHandleExp once it is no longer needed. +/// - Events created with ::UR_EXP_EVENT_FLAG_ENABLE_PROFILING cannot be +/// exported. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hEvent` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == ppIPCEventHandleData` +/// + `NULL == pIPCEventHandleDataSizeRet` +/// - ::UR_RESULT_ERROR_INVALID_EVENT +/// + `hEvent` was not created with the ::UR_EXP_EVENT_FLAG_IPC_EXP +/// flag. +/// + `hEvent` was obtained from ::urIPCOpenEventHandleExp. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + `hEvent` has profiling or timestamping enabled. +/// + The device associated with `hEvent` does not support event IPC, as +/// reported by ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCGetEventHandleExp( + /// [in] handle of the event object + ur_event_handle_t hEvent, + /// [out] a pointer to the IPC event handle data + void **ppIPCEventHandleData, + /// [out] size of the resulting IPC event handle data + size_t *pIPCEventHandleDataSizeRet) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Releases an inter-process event handle +/// +/// @details +/// - Releases the resources associated with IPC event handle data returned +/// by ::urIPCGetEventHandleExp. Must be called in the same process that +/// obtained the handle data. This does not destroy the source event and +/// does not affect event objects already opened with +/// ::urIPCOpenEventHandleExp. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCPutEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] a pointer to the IPC event handle data obtained with + /// ::urIPCGetEventHandleExp + void *pIPCEventHandleData) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Opens an inter-process event handle to get the corresponding event +/// object in the current process +/// +/// @details +/// - Returns an event object that shares state with the event that produced +/// the IPC handle. Either event can be signaled, waited on, or queried, +/// and a state change made through one event is observable through the +/// other. +/// - The returned event is a normal ::ur_event_handle_t with an initial +/// reference count of 1. It may be passed to entry points that accept an +/// event, retained with ::urEventRetain, and must be released with +/// ::urEventRelease. On the final release, the adapter performs the +/// native cleanup required for an opened IPC event. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == phEvent` +/// + `NULL == pIPCEventHandleData` +/// - ::UR_RESULT_ERROR_INVALID_CONTEXT +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `ipcEventHandleDataSize` is not the same as the size of the IPC +/// event handle data +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + A device in `hContext` does not support event IPC, as reported by +/// ::UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP. +/// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES +ur_result_t UR_APICALL urIPCOpenEventHandleExp( + /// [in] handle of the context object + ur_context_handle_t hContext, + /// [in] the IPC event handle data + const void *pIPCEventHandleData, + /// [in] size of the IPC event handle data + size_t ipcEventHandleDataSize, + /// [out][alloc] pointer to the handle of the event object created + ur_event_handle_t *phEvent) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Allocate an exportable memory region and return a pointer to that /// allocation. diff --git a/unified-runtime/tools/urinfo/urinfo.hpp b/unified-runtime/tools/urinfo/urinfo.hpp index 416f0d85826cf..42631249e4e7a 100644 --- a/unified-runtime/tools/urinfo/urinfo.hpp +++ b/unified-runtime/tools/urinfo/urinfo.hpp @@ -472,6 +472,8 @@ inline void printDeviceInfos(ur_device_handle_t hDevice, printDeviceInfo(hDevice, UR_DEVICE_INFO_REUSABLE_EVENTS_SUPPORT_EXP); std::cout << prefix; + printDeviceInfo(hDevice, UR_DEVICE_INFO_IPC_EVENT_SUPPORT_EXP); + std::cout << prefix; printDeviceInfo(hDevice, UR_DEVICE_INFO_ASYNC_USM_ALLOCATIONS_SUPPORT_EXP); std::cout << prefix; From 6a6122e12c57613abfbf0fb1a15ca41bddeb24bc Mon Sep 17 00:00:00 2001 From: "Gainullin, Artur" Date: Thu, 18 Jun 2026 16:10:40 -0700 Subject: [PATCH 3/3] [UR][L0] Add UNSUPPORTED stubs for urIPC*EventHandleExp --- .../source/adapters/level_zero/CMakeLists.txt | 1 + .../source/adapters/level_zero/event.cpp | 18 ++++++++++ .../adapters/level_zero/v2/ipc_event.cpp | 34 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 unified-runtime/source/adapters/level_zero/v2/ipc_event.cpp diff --git a/unified-runtime/source/adapters/level_zero/CMakeLists.txt b/unified-runtime/source/adapters/level_zero/CMakeLists.txt index 6e5f29af3610f..feb8cb0a018ee 100644 --- a/unified-runtime/source/adapters/level_zero/CMakeLists.txt +++ b/unified-runtime/source/adapters/level_zero/CMakeLists.txt @@ -186,6 +186,7 @@ if(UR_BUILD_ADAPTER_L0_V2) ${CMAKE_CURRENT_SOURCE_DIR}/v2/event_provider_counter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v2/event_provider_normal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v2/event.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/v2/ipc_event.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v2/kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v2/memory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v2/queue_api.cpp diff --git a/unified-runtime/source/adapters/level_zero/event.cpp b/unified-runtime/source/adapters/level_zero/event.cpp index 9c92da0c402e4..1656c2914f381 100644 --- a/unified-runtime/source/adapters/level_zero/event.cpp +++ b/unified-runtime/source/adapters/level_zero/event.cpp @@ -1022,6 +1022,24 @@ ur_result_t urEventCreateExp(ur_context_handle_t /*hContext*/, return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } +ur_result_t urIPCGetEventHandleExp(ur_event_handle_t /*hEvent*/, + void ** /*ppIPCEventHandleData*/, + size_t * /*pIPCEventHandleDataSizeRet*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t urIPCPutEventHandleExp(ur_context_handle_t /*hContext*/, + void * /*pIPCEventHandleData*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t urIPCOpenEventHandleExp(ur_context_handle_t /*hContext*/, + const void * /*pIPCEventHandleData*/, + size_t /*ipcEventHandleDataSize*/, + ur_event_handle_t * /*phEvent*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + } // namespace ur::level_zero ur_result_t ur_event_handle_t_::getOrCreateHostVisibleEvent( diff --git a/unified-runtime/source/adapters/level_zero/v2/ipc_event.cpp b/unified-runtime/source/adapters/level_zero/v2/ipc_event.cpp new file mode 100644 index 0000000000000..a5a0cc0ec0f22 --- /dev/null +++ b/unified-runtime/source/adapters/level_zero/v2/ipc_event.cpp @@ -0,0 +1,34 @@ +//===--------- ipc_event.cpp - Level Zero Adapter -------------------------===// +// +// +// 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 + +#include "../ur_interface_loader.hpp" + +namespace ur::level_zero { + +ur_result_t urIPCGetEventHandleExp(ur_event_handle_t /*hEvent*/, + void ** /*ppIPCEventHandleData*/, + size_t * /*pIPCEventHandleDataSizeRet*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t urIPCPutEventHandleExp(ur_context_handle_t /*hContext*/, + void * /*pIPCEventHandleData*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t urIPCOpenEventHandleExp(ur_context_handle_t /*hContext*/, + const void * /*pIPCEventHandleData*/, + size_t /*ipcEventHandleDataSize*/, + ur_event_handle_t * /*phEvent*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +} // namespace ur::level_zero