Skip to content

Commit

Permalink
umf providers
Browse files Browse the repository at this point in the history
  • Loading branch information
bratpiorka committed Aug 17, 2023
1 parent 33f3eef commit 5d83f45
Show file tree
Hide file tree
Showing 9 changed files with 631 additions and 3 deletions.
1 change: 1 addition & 0 deletions source/common/unified_malloc_framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(UMF_SOURCES
src/memory_provider.cpp
src/memory_tracker.cpp
src/memory_provider_get_last_failed.cpp
src/os_memory_provider.c
)

if(UMF_BUILD_SHARED_LIBRARY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ umfMemoryProvidersRegistryGet(struct umf_memory_provider_ops_t *providers,
const struct umf_memory_provider_ops_t *
umfMemoryProvidersRegistryGetOps(char *name);

bool umfMemoryProviderSupportsDevice(
const struct umf_memory_provider_ops_t *ops, const void *descr, size_t len);

///
/// \brief Allocates size bytes of uninitialized storage from memory provider
/// with specified alignment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ struct umf_memory_provider_ops_t {
/// Should be initialized using UMF_VERSION_CURRENT
uint32_t version;

void *priv;

///
/// \brief Initializes memory provider.
/// \param params provider-specific params
Expand All @@ -51,7 +53,7 @@ struct umf_memory_provider_ops_t {
enum umf_result_t (*purge_lazy)(void *provider, void *ptr, size_t size);
enum umf_result_t (*purge_force)(void *provider, void *ptr, size_t size);
const char *(*get_name)(void *provider);
bool (*supports_device)(const char *name);
bool (*supports_device)(const void* descr, size_t len);
};

#ifdef __cplusplus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ const umf_memory_provider_ops_t *umfMemoryProvidersRegistryGetOps(char *name) {
return NULL;
}

bool umfMemoryProviderSupportsDevice(const umf_memory_provider_ops_t *ops, const void* descr, size_t len)
{
return ops->supports_device(descr, len);
}

void umfMemoryProviderDestroy(umf_memory_provider_handle_t hProvider) {
hProvider->ops.finalize(hProvider->provider_priv);
free(hProvider);
Expand Down
248 changes: 248 additions & 0 deletions source/common/unified_malloc_framework/src/os_memory_provider.c
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,
};
Loading

0 comments on commit 5d83f45

Please sign in to comment.