forked from oneapi-src/unified-runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
33f3eef
commit 5d83f45
Showing
9 changed files
with
631 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
248 changes: 248 additions & 0 deletions
248
source/common/unified_malloc_framework/src/os_memory_provider.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/* | ||
Copyright (c) 2022 Intel Corporation | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#include <stddef.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/mman.h> | ||
#include <unistd.h> | ||
|
||
#include <umf.h> | ||
#include <umf/memory_provider_ops.h> | ||
|
||
#include "os_memory_provider.h" | ||
|
||
struct umf_os_memory_provider_config_t { | ||
int protection; | ||
enum umf_mem_visibility visibility; | ||
|
||
// NUMA config | ||
unsigned long* nodemask; | ||
unsigned long maxnode; | ||
int numa_mode; | ||
int numa_flags; | ||
}; | ||
|
||
struct umf_memory_provider_t { | ||
struct umf_memory_provider_ops_t ops; | ||
umf_os_memory_provider_config_handle_t config; | ||
}; | ||
|
||
umf_os_memory_provider_config_handle_t umfOsMemoryProviderConfigCreate() | ||
{ | ||
struct umf_os_memory_provider_config_t* config = malloc(sizeof(struct umf_os_memory_provider_config_t)); | ||
|
||
config->protection = ProtectionRead | ProtectionWrite; | ||
config->visibility = VisibilityPrivate; | ||
|
||
config->nodemask = NULL; | ||
config->maxnode = 0; | ||
config->numa_mode = NumaModeDefault; | ||
config->numa_flags = 0; | ||
|
||
return (umf_os_memory_provider_config_handle_t)config; | ||
} | ||
|
||
void umfOsMemoryProviderConfigDestroy( | ||
umf_os_memory_provider_config_handle_t hConfig) | ||
{ | ||
free(((struct umf_os_memory_provider_config_t*)hConfig)->nodemask); | ||
free(hConfig); | ||
} | ||
|
||
void umfOsMemoryProviderConfigSetMemoryProtection( | ||
umf_os_memory_provider_config_handle_t hConfig, int memoryProtection) | ||
{ | ||
hConfig->protection = memoryProtection; | ||
} | ||
|
||
void umfOsMemoryProviderConfigSetMemoryVisibility( | ||
umf_os_memory_provider_config_handle_t hConfig, | ||
enum umf_mem_visibility memoryVisibility) | ||
{ | ||
hConfig->visibility = memoryVisibility; | ||
} | ||
|
||
static enum umf_result_t copyNodeMask(const unsigned long* nodemask, | ||
unsigned long maxnode, | ||
unsigned long** outNodemask) | ||
{ | ||
if (maxnode == 0 || nodemask == NULL) { | ||
*outNodemask = NULL; | ||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
size_t nodemask_bytes = maxnode / 8; | ||
|
||
// round to the next multiple of sizeof(unsigned long) | ||
if (nodemask_bytes % sizeof(unsigned long) != 0 || nodemask_bytes == 0) { | ||
nodemask_bytes += sizeof(unsigned long) - nodemask_bytes % sizeof(unsigned long); | ||
} | ||
|
||
*outNodemask = (unsigned long*)calloc(1, nodemask_bytes); | ||
if (!*outNodemask) { | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
memcpy(*outNodemask, nodemask, nodemask_bytes); | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
enum umf_result_t umfOsMemoryProviderConfigSetNumaMemBind( | ||
umf_os_memory_provider_config_handle_t handle, | ||
const unsigned long* nodemask, unsigned long maxnode, int mode, int flags) | ||
{ | ||
|
||
enum umf_result_t ret = copyNodeMask(nodemask, maxnode, &handle->nodemask); | ||
if (ret != UMF_RESULT_SUCCESS) { | ||
return ret; | ||
} | ||
|
||
handle->maxnode = maxnode; | ||
handle->numa_mode = mode; | ||
handle->numa_flags = flags; | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
static enum umf_result_t | ||
memoryProviderConfigCreateCopy(umf_os_memory_provider_config_handle_t in, | ||
umf_os_memory_provider_config_handle_t* out) | ||
{ | ||
*out = umfOsMemoryProviderConfigCreate(); | ||
if (!*out) { | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
**out = *in; | ||
return copyNodeMask(in->nodemask, in->maxnode, &(*out)->nodemask); | ||
} | ||
|
||
enum umf_result_t os_initialize(void* params, void** pool) | ||
{ | ||
umf_os_memory_provider_config_handle_t config = NULL; | ||
umf_os_memory_provider_config_handle_t input = (umf_os_memory_provider_config_handle_t)params; | ||
enum umf_result_t ret = UMF_RESULT_SUCCESS; | ||
|
||
if (input) { | ||
ret = memoryProviderConfigCreateCopy(input, &config); | ||
} else { | ||
config = umfOsMemoryProviderConfigCreate(); | ||
} | ||
|
||
if (ret == UMF_RESULT_SUCCESS) { | ||
*pool = (void*)config; | ||
} | ||
return ret; | ||
} | ||
|
||
void os_finalize(void* pool) | ||
{ | ||
umfOsMemoryProviderConfigDestroy( | ||
(umf_os_memory_provider_config_handle_t)pool); | ||
} | ||
|
||
static enum umf_result_t os_alloc(void* provider, size_t size, size_t alignment, | ||
void** resultPtr) | ||
{ | ||
umf_os_memory_provider_config_handle_t config = (umf_os_memory_provider_config_handle_t)provider; | ||
if (alignment > sysconf(_SC_PAGE_SIZE)) { | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
int flags = MAP_ANONYMOUS | config->visibility; | ||
int protection = config->protection; | ||
|
||
if (config->visibility == VisibilityShared && config->numa_mode != NumaModeDefault) { | ||
// TODO: add support for that | ||
fprintf(stderr, "numa binding not supported for VisibilityShared"); | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
void* result = mmap(NULL, size, protection, flags, -1, 0); | ||
if (result == MAP_FAILED) { | ||
fprintf(stderr, "syscall mmap() returned: %p", result); | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
int ret = mbind(result, size, config->numa_mode, config->nodemask, | ||
config->maxnode, config->numa_flags); | ||
if (ret) { | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
*resultPtr = result; | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
static enum umf_result_t os_free(void* provider, void* ptr, size_t bytes) | ||
{ | ||
// TODO: round size to page? | ||
|
||
int ret = munmap(ptr, bytes); | ||
|
||
if (ret) { | ||
// TODO: map error | ||
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; | ||
} | ||
|
||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
void os_get_last_native_error(void* provider, const char** ppMessage, | ||
int32_t* pError) { } | ||
|
||
const char* os_get_name(void* provider) { return "OS"; } | ||
|
||
bool os_supports_device(const char* device) | ||
{ | ||
// TODO | ||
return (bool)(strcmp(device, "NUMA") == 0); | ||
} | ||
|
||
enum umf_result_t | ||
umfOsMemoryProviderCreate(umf_os_memory_provider_config_handle_t hConfig, | ||
umf_memory_provider_handle_t* out) | ||
{ | ||
struct umf_memory_provider_t* provider = malloc(sizeof(struct umf_memory_provider_t)); | ||
|
||
provider->ops = OS_MEMORY_PROVIDER_OPS; | ||
|
||
enum umf_result_t ret = memoryProviderConfigCreateCopy(hConfig, &provider->config); | ||
if (ret != UMF_RESULT_SUCCESS) { | ||
return ret; | ||
} | ||
|
||
*out = provider; | ||
return UMF_RESULT_SUCCESS; | ||
} | ||
|
||
void umfOSMemoryProviderDestroy(umf_memory_provider_handle_t hProvider) | ||
{ | ||
umfOsMemoryProviderConfigDestroy(hProvider->config); | ||
free(hProvider); | ||
} | ||
|
||
struct umf_memory_provider_ops_t OS_MEMORY_PROVIDER_OPS = { | ||
.version = UMF_VERSION_CURRENT, | ||
.initialize = os_initialize, | ||
.finalize = os_finalize, | ||
.alloc = os_alloc, | ||
.free = os_free, | ||
.get_last_native_error = os_get_last_native_error, | ||
.get_name = os_get_name, | ||
.supports_device = os_supports_device, | ||
}; |
Oops, something went wrong.