Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions include/umf/providers/provider_level_zero.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
umf_level_zero_memory_provider_params_handle_t hParams,
umf_level_zero_memory_provider_free_policy_t policy);

typedef enum umf_level_zero_memory_provider_memory_exchange_policy_t {
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC =
0, ///< Memory exchange policy based on IPC. Default.
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT,
///< Memory exchange policy based on import/export APIs. Should be used if IPC exchange policy is not supported.
} umf_level_zero_memory_provider_memory_exchange_policy_t;

/// @brief Set the memory exchange policy.
/// @param hParams handle to the parameters of the Level Zero Memory Provider.
/// @param policy memory exchange policy.
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
umf_level_zero_memory_provider_params_handle_t hParams,
umf_level_zero_memory_provider_memory_exchange_policy_t policy);

/// @brief Set the device ordinal in the parameters struct.
/// @param hParams handle to the parameters of the Level Zero Memory Provider.
/// @param deviceOrdinal device ordinal.
Expand Down
1 change: 1 addition & 0 deletions src/libumf.def
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ EXPORTS
umfGetMemoryProperty
umfGetMemoryPropertySize
umfJemallocPoolParamsSetName
umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy
umfLevelZeroMemoryProviderParamsSetName
umfOsMemoryProviderParamsSetName
umfPoolTrimMemory
Expand Down
1 change: 1 addition & 0 deletions src/libumf.map
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ UMF_1.1 {
umfGetMemoryProperty;
umfGetMemoryPropertySize;
umfJemallocPoolParamsSetName;
umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy;
umfLevelZeroMemoryProviderParamsSetName;
umfOsMemoryProviderParamsSetName;
umfPoolTrimMemory;
Expand Down
165 changes: 136 additions & 29 deletions src/provider/provider_level_zero.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,26 @@ void fini_ze_global_state(void) {

// Level Zero Memory Provider settings struct
typedef struct umf_level_zero_memory_provider_params_t {
ze_context_handle_t
level_zero_context_handle; ///< Handle to the Level Zero context
ze_device_handle_t
level_zero_device_handle; ///< Handle to the Level Zero device
// Handle to the Level Zero context
ze_context_handle_t level_zero_context_handle;

umf_usm_memory_type_t memory_type; ///< Allocation memory type
// Handle to the Level Zero device
ze_device_handle_t level_zero_device_handle;

ze_device_handle_t *
resident_device_handles; ///< Array of devices for which the memory should be made resident
uint32_t
resident_device_count; ///< Number of devices for which the memory should be made resident
// Allocation memory type
umf_usm_memory_type_t memory_type;

umf_level_zero_memory_provider_free_policy_t
freePolicy; ///< Memory free policy
// Array of devices for which the memory should be made resident
ze_device_handle_t *resident_device_handles;

// Number of devices for which the memory should be made resident
uint32_t resident_device_count;

// Memory free policy
umf_level_zero_memory_provider_free_policy_t freePolicy;

// Memory exchange policy
umf_level_zero_memory_provider_memory_exchange_policy_t exchangePolicy;

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

ze_driver_memory_free_policy_ext_flags_t freePolicyFlags;

umf_level_zero_memory_provider_memory_exchange_policy_t exchangePolicy;

size_t min_page_size;

uint32_t device_ordinal;
Expand Down Expand Up @@ -253,6 +261,8 @@ umf_result_t umfLevelZeroMemoryProviderParamsCreate(
params->resident_device_handles = NULL;
params->resident_device_count = 0;
params->freePolicy = UMF_LEVEL_ZERO_MEMORY_PROVIDER_FREE_POLICY_DEFAULT;
params->exchangePolicy =
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC;
params->device_ordinal = 0;
strncpy(params->name, DEFAULT_NAME, sizeof(params->name) - 1);
params->name[sizeof(params->name) - 1] = '\0';
Expand Down Expand Up @@ -374,6 +384,18 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
return UMF_RESULT_SUCCESS;
}

umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
umf_level_zero_memory_provider_params_handle_t hParams,
umf_level_zero_memory_provider_memory_exchange_policy_t policy) {
if (!hParams) {
LOG_ERR("Level Zero memory provider params handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

hParams->exchangePolicy = policy;
return UMF_RESULT_SUCCESS;
}

static ze_driver_memory_free_policy_ext_flags_t
umfFreePolicyToZePolicy(umf_level_zero_memory_provider_free_policy_t policy) {
switch (policy) {
Expand Down Expand Up @@ -401,6 +423,11 @@ static ze_relaxed_allocation_limits_exp_desc_t relaxed_device_allocation_desc =
.pNext = NULL,
.flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE};

static ze_external_memory_export_desc_t memory_export_desc = {
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_DESC,
.pNext = NULL,
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32};

static umf_result_t ze_memory_provider_alloc_helper(void *provider, size_t size,
size_t alignment,
int update_stats,
Expand All @@ -421,11 +448,30 @@ static umf_result_t ze_memory_provider_alloc_helper(void *provider, size_t size,
case UMF_MEMORY_TYPE_DEVICE: {
ze_device_mem_alloc_desc_t dev_desc = {
.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC,
.pNext = use_relaxed_allocation(ze_provider, size)
? &relaxed_device_allocation_desc
: NULL,
.pNext = NULL,
.flags = 0,
.ordinal = ze_provider->device_ordinal};
void *lastNext = &dev_desc.pNext;

ze_relaxed_allocation_limits_exp_desc_t
relaxed_device_allocation_desc_copy =
relaxed_device_allocation_desc;
if (use_relaxed_allocation(ze_provider, size)) {
// add relaxed allocation desc to the pNext chain
*(uintptr_t *)lastNext =
(uintptr_t)&relaxed_device_allocation_desc_copy;
Comment on lines +461 to +462
Copy link
Preview

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using uintptr_t casting to manipulate pNext pointers is unclear and potentially unsafe. Consider using proper pointer casting like *(void **)lastNext = &relaxed_device_allocation_desc_copy; for better type safety and readability.

Copilot uses AI. Check for mistakes.

lastNext = &relaxed_device_allocation_desc_copy.pNext;
}

ze_external_memory_export_desc_t memory_export_desc_copy =
memory_export_desc;
if (ze_provider->exchangePolicy ==
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT) {
// add external memory export desc to the pNext chain
*(uintptr_t *)lastNext = (uintptr_t)&memory_export_desc_copy;
Copy link
Preview

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above - using uintptr_t casting to manipulate pNext pointers is unclear and potentially unsafe. Consider using proper pointer casting like *(void **)lastNext = &memory_export_desc_copy; for better type safety and readability.

Copilot uses AI. Check for mistakes.

lastNext = &memory_export_desc_copy.pNext;
}

ze_result = g_ze_ops.zeMemAllocDevice(ze_provider->context, &dev_desc,
size, alignment,
ze_provider->device, resultPtr);
Expand Down Expand Up @@ -599,6 +645,7 @@ static umf_result_t ze_memory_provider_initialize(const void *params,
ze_provider->memory_type = umf2ze_memory_type(ze_params->memory_type);
ze_provider->freePolicyFlags =
umfFreePolicyToZePolicy(ze_params->freePolicy);
ze_provider->exchangePolicy = ze_params->exchangePolicy;
ze_provider->min_page_size = 0;
ze_provider->device_ordinal = ze_params->device_ordinal;

Expand Down Expand Up @@ -755,6 +802,7 @@ static umf_result_t ze_memory_provider_allocation_split(void *provider,

typedef struct ze_ipc_data_t {
int pid;
size_t size;
ze_ipc_mem_handle_t ze_handle;
} ze_ipc_data_t;

Expand All @@ -770,20 +818,45 @@ static umf_result_t ze_memory_provider_get_ipc_handle(void *provider,
const void *ptr,
size_t size,
void *providerIpcData) {
(void)size;

ze_result_t ze_result;
ze_ipc_data_t *ze_ipc_data = (ze_ipc_data_t *)providerIpcData;
struct ze_memory_provider_t *ze_provider =
(struct ze_memory_provider_t *)provider;

ze_result = g_ze_ops.zeMemGetIpcHandle(ze_provider->context, ptr,
&ze_ipc_data->ze_handle);
if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemGetIpcHandle() failed.");
return ze2umf_result(ze_result);
if (ze_provider->exchangePolicy ==
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC) {
ze_result = g_ze_ops.zeMemGetIpcHandle(ze_provider->context, ptr,
&ze_ipc_data->ze_handle);

if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemGetIpcHandle() failed.");
return ze2umf_result(ze_result);
}
} else { // UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT
ze_external_memory_export_fd_t fd_desc = {
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_FD,
.pNext = NULL,
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32,
.fd = 0};

ze_memory_allocation_properties_t mem_alloc_props = {
.stype = ZE_STRUCTURE_TYPE_MEMORY_ALLOCATION_PROPERTIES,
.pNext = &fd_desc,
.type = 0,
.id = 0,
.pageSize = 0};

ze_result = g_ze_ops.zeMemGetAllocProperties(ze_provider->context, ptr,
&mem_alloc_props, NULL);
if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemGetAllocProperties() failed.");
return ze2umf_result(ze_result);
}

memcpy(&ze_ipc_data->ze_handle, &fd_desc.fd, sizeof(fd_desc.fd));
}

ze_ipc_data->size = size;
ze_ipc_data->pid = utils_getpid();

return UMF_RESULT_SUCCESS;
Expand Down Expand Up @@ -834,14 +907,40 @@ static umf_result_t ze_memory_provider_open_ipc_handle(void *provider,
memcpy(&ze_ipc_handle, &fd_local, sizeof(fd_local));
}

ze_result = g_ze_ops.zeMemOpenIpcHandle(
ze_provider->context, ze_provider->device, ze_ipc_handle, 0, ptr);
if (fd_local != -1) {
(void)utils_close_fd(fd_local);
}
if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemOpenIpcHandle() failed.");
return ze2umf_result(ze_result);
if (ze_provider->exchangePolicy ==
UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IPC) {
ze_result = g_ze_ops.zeMemOpenIpcHandle(
ze_provider->context, ze_provider->device, ze_ipc_handle, 0, ptr);
if (fd_local != -1) {
(void)utils_close_fd(fd_local);
}
if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemOpenIpcHandle() failed.");
return ze2umf_result(ze_result);
}
} else { // UMF_LEVEL_ZERO_MEMORY_PROVIDER_MEMORY_EXCHANGE_POLICY_IMPORT_EXPORT
ze_external_memory_import_fd_t import_fd = {
.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMPORT_FD,
.pNext = NULL,
.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF,
.fd = fd_local};

ze_device_mem_alloc_desc_t alloc_desc = {
.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC,
.pNext = &import_fd,
.flags = 0,
.ordinal = 0};
ze_result = g_ze_ops.zeMemAllocDevice(ze_provider->context, &alloc_desc,
ze_ipc_data->size, 0,
ze_provider->device, ptr);
if (fd_local != -1) {
(void)utils_close_fd(fd_local);
}

if (ze_result != ZE_RESULT_SUCCESS) {
LOG_ERR("zeMemAllocDevice() failed.");
return ze2umf_result(ze_result);
}
}

return UMF_RESULT_SUCCESS;
Expand Down Expand Up @@ -1027,6 +1126,14 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryExchangePolicy(
umf_level_zero_memory_provider_params_handle_t hParams,
umf_level_zero_memory_provider_memory_exchange_policy_t policy) {
(void)hParams;
(void)policy;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

umf_result_t umfLevelZeroMemoryProviderParamsSetDeviceOrdinal(
umf_level_zero_memory_provider_params_handle_t hParams,
uint32_t deviceOrdinal) {
Expand Down
45 changes: 37 additions & 8 deletions src/utils/utils_windows_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <windows.h>

#include <assert.h>
#include <handleapi.h>
#include <processenv.h>
#include <processthreadsapi.h>
#include <stdio.h>
Expand Down Expand Up @@ -47,21 +48,49 @@ int utils_getpid(void) { return GetCurrentProcessId(); }

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

int utils_close_fd(int fd) {
(void)fd; // unused
return -1;
}
int utils_close_fd(int fd) { return CloseHandle((HANDLE)(uintptr_t)fd); }

umf_result_t utils_errno_to_umf_result(int err) {
(void)err; // unused
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) {
(void)pid; // unused
(void)fd_in; // unused
(void)fd_out; // unused
return UMF_RESULT_ERROR_NOT_SUPPORTED;
umf_result_t ret = UMF_RESULT_SUCCESS;
HANDLE current_process_handle = GetCurrentProcess();
if (!current_process_handle) {
LOG_ERR("GetCurrentProcess() failed.");
return UMF_RESULT_ERROR_UNKNOWN;
}

HANDLE source_process_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
if (!source_process_handle) {
LOG_ERR("OpenProcess() failed for pid=%d.", pid);
ret = UMF_RESULT_ERROR_UNKNOWN;
goto release_current;
}

HANDLE handle_in = (HANDLE)(uintptr_t)fd_in;
HANDLE handle_out = NULL;
BOOL result = DuplicateHandle(source_process_handle, handle_in,
current_process_handle, &handle_out,
GENERIC_READ | GENERIC_WRITE, FALSE, 0);
if (!result) {
LOG_ERR("DuplicateHandle() failed for pid=%d fd_in=%d handle_in=%p",
pid, fd_in, handle_in);
ret = UMF_RESULT_ERROR_UNKNOWN;
goto release_source;
}

*fd_out = (int)(uintptr_t)handle_out;

release_source:
CloseHandle(source_process_handle);

release_current:
CloseHandle(current_process_handle);

return ret;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will always return UMF_RESULT_SUCCESS since you check error at 79.
Otherwise:

Suggested change
}
release_current:
CloseHandle(current_process_handle);
release_source:
CloseHandle(source_process_handle);
return result;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


umf_result_t utils_translate_mem_protection_flags(unsigned in_protection,
Expand Down
Loading
Loading