Skip to content

Commit c423e04

Browse files
committed
add support for IPC on L0 + Win
1 parent 3cee4a5 commit c423e04

12 files changed

+455
-93
lines changed

include/umf/providers/provider_level_zero.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
8383
umf_level_zero_memory_provider_params_handle_t hParams,
8484
umf_level_zero_memory_provider_free_policy_t policy);
8585

86+
typedef enum umf_level_zero_memory_provider_memory_exchange_policy_t {
87+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC =
88+
0, ///< Memory exchange policy based on IPC. Default.
89+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT,
90+
///< Memory exchange policy based on import/export APIs. Should be used if IPC exchange policy is not supported.
91+
} umf_level_zero_memory_provider_memory_exchange_policy_t;
92+
93+
/// @brief Set the memory exchange policy.
94+
/// @param hParams handle to the parameters of the Level Zero Memory Provider.
95+
/// @param policy memory exchange policy.
96+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
97+
umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
98+
umf_level_zero_memory_provider_params_handle_t hParams,
99+
umf_level_zero_memory_provider_memory_exchange_policy_t policy);
100+
86101
/// @brief Set the device ordinal in the parameters struct.
87102
/// @param hParams handle to the parameters of the Level Zero Memory Provider.
88103
/// @param deviceOrdinal device ordinal.

src/libumf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ EXPORTS
153153
umfGetMemoryProperty
154154
umfGetMemoryPropertySize
155155
umfJemallocPoolParamsSetName
156+
umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy
156157
umfLevelZeroMemoryProviderParamsSetName
157158
umfOsMemoryProviderParamsSetName
158159
umfPoolTrimMemory

src/libumf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ UMF_1.1 {
151151
umfGetMemoryProperty;
152152
umfGetMemoryPropertySize;
153153
umfJemallocPoolParamsSetName;
154+
umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy;
154155
umfLevelZeroMemoryProviderParamsSetName;
155156
umfOsMemoryProviderParamsSetName;
156157
umfPoolTrimMemory;

src/provider/provider_level_zero.c

Lines changed: 136 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,26 @@ void fini_ze_global_state(void) {
4343

4444
// Level Zero Memory Provider settings struct
4545
typedef struct umf_level_zero_memory_provider_params_t {
46-
ze_context_handle_t
47-
level_zero_context_handle; ///< Handle to the Level Zero context
48-
ze_device_handle_t
49-
level_zero_device_handle; ///< Handle to the Level Zero device
46+
// Handle to the Level Zero context
47+
ze_context_handle_t level_zero_context_handle;
5048

51-
umf_usm_memory_type_t memory_type; ///< Allocation memory type
49+
// Handle to the Level Zero device
50+
ze_device_handle_t level_zero_device_handle;
5251

53-
ze_device_handle_t *
54-
resident_device_handles; ///< Array of devices for which the memory should be made resident
55-
uint32_t
56-
resident_device_count; ///< Number of devices for which the memory should be made resident
52+
// Allocation memory type
53+
umf_usm_memory_type_t memory_type;
5754

58-
umf_level_zero_memory_provider_free_policy_t
59-
freePolicy; ///< Memory free policy
55+
// Array of devices for which the memory should be made resident
56+
ze_device_handle_t *resident_device_handles;
57+
58+
// Number of devices for which the memory should be made resident
59+
uint32_t resident_device_count;
60+
61+
// Memory free policy
62+
umf_level_zero_memory_provider_free_policy_t freePolicy;
63+
64+
// Memory exchange policy
65+
umf_level_zero_memory_provider_memory_exchange_policy_t exchangePolicy;
6066

6167
uint32_t device_ordinal;
6268
char name[64];
@@ -74,6 +80,8 @@ typedef struct ze_memory_provider_t {
7480

7581
ze_driver_memory_free_policy_ext_flags_t freePolicyFlags;
7682

83+
umf_level_zero_memory_provider_memory_exchange_policy_t exchangePolicy;
84+
7785
size_t min_page_size;
7886

7987
uint32_t device_ordinal;
@@ -253,6 +261,8 @@ umf_result_t umfLevelZeroMemoryProviderParamsCreate(
253261
params->resident_device_handles = NULL;
254262
params->resident_device_count = 0;
255263
params->freePolicy = UMF_LEVEL_ZERO_MEMORY_PROVIDER_FREE_POLICY_DEFAULT;
264+
params->exchangePolicy =
265+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC;
256266
params->device_ordinal = 0;
257267
strncpy(params->name, DEFAULT_NAME, sizeof(params->name) - 1);
258268
params->name[sizeof(params->name) - 1] = '\0';
@@ -374,6 +384,18 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
374384
return UMF_RESULT_SUCCESS;
375385
}
376386

387+
umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
388+
umf_level_zero_memory_provider_params_handle_t hParams,
389+
umf_level_zero_memory_provider_memory_exchange_policy_t policy) {
390+
if (!hParams) {
391+
LOG_ERR("Level Zero memory provider params handle is NULL");
392+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
393+
}
394+
395+
hParams->exchangePolicy = policy;
396+
return UMF_RESULT_SUCCESS;
397+
}
398+
377399
static ze_driver_memory_free_policy_ext_flags_t
378400
umfFreePolicyToZePolicy(umf_level_zero_memory_provider_free_policy_t policy) {
379401
switch (policy) {
@@ -401,6 +423,11 @@ static ze_relaxed_allocation_limits_exp_desc_t relaxed_device_allocation_desc =
401423
.pNext = NULL,
402424
.flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE};
403425

426+
static ze_external_memory_export_desc_t memory_export_desc = {
427+
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_DESC,
428+
.pNext = NULL,
429+
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32};
430+
404431
static umf_result_t ze_memory_provider_alloc_helper(void *provider, size_t size,
405432
size_t alignment,
406433
int update_stats,
@@ -421,11 +448,30 @@ static umf_result_t ze_memory_provider_alloc_helper(void *provider, size_t size,
421448
case UMF_MEMORY_TYPE_DEVICE: {
422449
ze_device_mem_alloc_desc_t dev_desc = {
423450
.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC,
424-
.pNext = use_relaxed_allocation(ze_provider, size)
425-
? &relaxed_device_allocation_desc
426-
: NULL,
451+
.pNext = NULL,
427452
.flags = 0,
428453
.ordinal = ze_provider->device_ordinal};
454+
void *lastNext = &dev_desc.pNext;
455+
456+
ze_relaxed_allocation_limits_exp_desc_t
457+
relaxed_device_allocation_desc_copy =
458+
relaxed_device_allocation_desc;
459+
if (use_relaxed_allocation(ze_provider, size)) {
460+
// add relaxed allocation desc to the pNext chain
461+
*(uintptr_t *)lastNext =
462+
(uintptr_t)&relaxed_device_allocation_desc_copy;
463+
lastNext = &relaxed_device_allocation_desc_copy.pNext;
464+
}
465+
466+
ze_external_memory_export_desc_t memory_export_desc_copy =
467+
memory_export_desc;
468+
if (ze_provider->exchangePolicy ==
469+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT) {
470+
// add external memory export desc to the pNext chain
471+
*(uintptr_t *)lastNext = (uintptr_t)&memory_export_desc_copy;
472+
lastNext = &memory_export_desc_copy.pNext;
473+
}
474+
429475
ze_result = g_ze_ops.zeMemAllocDevice(ze_provider->context, &dev_desc,
430476
size, alignment,
431477
ze_provider->device, resultPtr);
@@ -599,6 +645,7 @@ static umf_result_t ze_memory_provider_initialize(const void *params,
599645
ze_provider->memory_type = umf2ze_memory_type(ze_params->memory_type);
600646
ze_provider->freePolicyFlags =
601647
umfFreePolicyToZePolicy(ze_params->freePolicy);
648+
ze_provider->exchangePolicy = ze_params->exchangePolicy;
602649
ze_provider->min_page_size = 0;
603650
ze_provider->device_ordinal = ze_params->device_ordinal;
604651

@@ -755,6 +802,7 @@ static umf_result_t ze_memory_provider_allocation_split(void *provider,
755802

756803
typedef struct ze_ipc_data_t {
757804
int pid;
805+
size_t size;
758806
ze_ipc_mem_handle_t ze_handle;
759807
} ze_ipc_data_t;
760808

@@ -770,20 +818,45 @@ static umf_result_t ze_memory_provider_get_ipc_handle(void *provider,
770818
const void *ptr,
771819
size_t size,
772820
void *providerIpcData) {
773-
(void)size;
774-
775821
ze_result_t ze_result;
776822
ze_ipc_data_t *ze_ipc_data = (ze_ipc_data_t *)providerIpcData;
777823
struct ze_memory_provider_t *ze_provider =
778824
(struct ze_memory_provider_t *)provider;
779825

780-
ze_result = g_ze_ops.zeMemGetIpcHandle(ze_provider->context, ptr,
781-
&ze_ipc_data->ze_handle);
782-
if (ze_result != ZE_RESULT_SUCCESS) {
783-
LOG_ERR("zeMemGetIpcHandle() failed.");
784-
return ze2umf_result(ze_result);
826+
if (ze_provider->exchangePolicy ==
827+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC) {
828+
ze_result = g_ze_ops.zeMemGetIpcHandle(ze_provider->context, ptr,
829+
&ze_ipc_data->ze_handle);
830+
831+
if (ze_result != ZE_RESULT_SUCCESS) {
832+
LOG_ERR("zeMemGetIpcHandle() failed.");
833+
return ze2umf_result(ze_result);
834+
}
835+
} else { // UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT
836+
ze_external_memory_export_fd_t fd_desc = {
837+
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_FD,
838+
.pNext = NULL,
839+
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32,
840+
.fd = 0};
841+
842+
ze_memory_allocation_properties_t mem_alloc_props = {
843+
.stype = ZE_STRUCTURE_TYPE_MEMORY_ALLOCATION_PROPERTIES,
844+
.pNext = &fd_desc,
845+
.type = 0,
846+
.id = 0,
847+
.pageSize = 0};
848+
849+
ze_result = g_ze_ops.zeMemGetAllocProperties(ze_provider->context, ptr,
850+
&mem_alloc_props, NULL);
851+
if (ze_result != ZE_RESULT_SUCCESS) {
852+
LOG_ERR("zeMemGetAllocProperties() failed.");
853+
return ze2umf_result(ze_result);
854+
}
855+
856+
memcpy(&ze_ipc_data->ze_handle, &fd_desc.fd, sizeof(fd_desc.fd));
785857
}
786858

859+
ze_ipc_data->size = size;
787860
ze_ipc_data->pid = utils_getpid();
788861

789862
return UMF_RESULT_SUCCESS;
@@ -834,14 +907,40 @@ static umf_result_t ze_memory_provider_open_ipc_handle(void *provider,
834907
memcpy(&ze_ipc_handle, &fd_local, sizeof(fd_local));
835908
}
836909

837-
ze_result = g_ze_ops.zeMemOpenIpcHandle(
838-
ze_provider->context, ze_provider->device, ze_ipc_handle, 0, ptr);
839-
if (fd_local != -1) {
840-
(void)utils_close_fd(fd_local);
841-
}
842-
if (ze_result != ZE_RESULT_SUCCESS) {
843-
LOG_ERR("zeMemOpenIpcHandle() failed.");
844-
return ze2umf_result(ze_result);
910+
if (ze_provider->exchangePolicy ==
911+
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC) {
912+
ze_result = g_ze_ops.zeMemOpenIpcHandle(
913+
ze_provider->context, ze_provider->device, ze_ipc_handle, 0, ptr);
914+
if (fd_local != -1) {
915+
(void)utils_close_fd(fd_local);
916+
}
917+
if (ze_result != ZE_RESULT_SUCCESS) {
918+
LOG_ERR("zeMemOpenIpcHandle() failed.");
919+
return ze2umf_result(ze_result);
920+
}
921+
} else { // UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT
922+
ze_external_memory_import_fd_t import_fd = {
923+
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMPORT_FD,
924+
.pNext = NULL,
925+
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF,
926+
.fd = fd_local};
927+
928+
ze_device_mem_alloc_desc_t alloc_desc = {
929+
.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC,
930+
.pNext = &import_fd,
931+
.flags = 0,
932+
.ordinal = 0};
933+
ze_result = g_ze_ops.zeMemAllocDevice(ze_provider->context, &alloc_desc,
934+
ze_ipc_data->size, 0,
935+
ze_provider->device, ptr);
936+
if (fd_local != -1) {
937+
(void)utils_close_fd(fd_local);
938+
}
939+
940+
if (ze_result != ZE_RESULT_SUCCESS) {
941+
LOG_ERR("zeMemAllocDevice() failed.");
942+
return ze2umf_result(ze_result);
943+
}
845944
}
846945

847946
return UMF_RESULT_SUCCESS;
@@ -1027,6 +1126,14 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
10271126
return UMF_RESULT_ERROR_NOT_SUPPORTED;
10281127
}
10291128

1129+
umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
1130+
umf_level_zero_memory_provider_params_handle_t hParams,
1131+
umf_level_zero_memory_provider_memory_exchange_policy_t policy) {
1132+
(void)hParams;
1133+
(void)policy;
1134+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
1135+
}
1136+
10301137
umf_result_t umfLevelZeroMemoryProviderParamsSetDeviceOrdinal(
10311138
umf_level_zero_memory_provider_params_handle_t hParams,
10321139
uint32_t deviceOrdinal) {

src/utils/utils_windows_common.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <windows.h>
1111

1212
#include <assert.h>
13+
#include <handleapi.h>
1314
#include <processenv.h>
1415
#include <processthreadsapi.h>
1516
#include <stdio.h>
@@ -47,21 +48,49 @@ int utils_getpid(void) { return GetCurrentProcessId(); }
4748

4849
int utils_gettid(void) { return GetCurrentThreadId(); }
4950

50-
int utils_close_fd(int fd) {
51-
(void)fd; // unused
52-
return -1;
53-
}
51+
int utils_close_fd(int fd) { return CloseHandle((HANDLE)(uintptr_t)fd); }
5452

5553
umf_result_t utils_errno_to_umf_result(int err) {
5654
(void)err; // unused
5755
return UMF_RESULT_ERROR_NOT_SUPPORTED;
5856
}
5957

6058
umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) {
61-
(void)pid; // unused
62-
(void)fd_in; // unused
63-
(void)fd_out; // unused
64-
return UMF_RESULT_ERROR_NOT_SUPPORTED;
59+
umf_result_t ret = UMF_RESULT_SUCCESS;
60+
HANDLE current_process_handle = GetCurrentProcess();
61+
if (!current_process_handle) {
62+
LOG_ERR("GetCurrentProcess() failed.");
63+
return UMF_RESULT_ERROR_UNKNOWN;
64+
}
65+
66+
HANDLE source_process_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
67+
if (!source_process_handle) {
68+
LOG_ERR("OpenProcess() failed for pid=%d.", pid);
69+
ret = UMF_RESULT_ERROR_UNKNOWN;
70+
goto release_current;
71+
}
72+
73+
HANDLE handle_in = (HANDLE)(uintptr_t)fd_in;
74+
HANDLE handle_out = NULL;
75+
BOOL result = DuplicateHandle(source_process_handle, handle_in,
76+
current_process_handle, &handle_out,
77+
GENERIC_READ | GENERIC_WRITE, FALSE, 0);
78+
if (!result) {
79+
LOG_ERR("DuplicateHandle() failed for pid=%d fd_in=%d handle_in=%p",
80+
pid, fd_in, handle_in);
81+
ret = UMF_RESULT_ERROR_UNKNOWN;
82+
goto release_source;
83+
}
84+
85+
*fd_out = (int)(uintptr_t)handle_out;
86+
87+
release_source:
88+
CloseHandle(source_process_handle);
89+
90+
release_current:
91+
CloseHandle(current_process_handle);
92+
93+
return ret;
6594
}
6695

6796
umf_result_t utils_translate_mem_protection_flags(unsigned in_protection,

0 commit comments

Comments
 (0)