Blame src/memkind.c

Packit 345191
/*
Packit 345191
 * Copyright (C) 2014 - 2019 Intel Corporation.
Packit 345191
 * All rights reserved.
Packit 345191
 *
Packit 345191
 * Redistribution and use in source and binary forms, with or without
Packit 345191
 * modification, are permitted provided that the following conditions are met:
Packit 345191
 * 1. Redistributions of source code must retain the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer.
Packit 345191
 * 2. Redistributions in binary form must reproduce the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer in the documentation
Packit 345191
 *    and/or other materials provided with the distribution.
Packit 345191
 *
Packit 345191
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
Packit 345191
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
Packit 345191
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
Packit 345191
 * EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit 345191
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 345191
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 345191
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 345191
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
Packit 345191
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Packit 345191
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 345191
 */
Packit 345191
#define MEMKIND_VERSION_MAJOR 1
Packit 345191
#define MEMKIND_VERSION_MINOR 10
Packit 345191
#define MEMKIND_VERSION_PATCH 0
Packit 345191
Packit 345191
#include <memkind.h>
Packit 345191
#include <memkind/internal/memkind_default.h>
Packit 345191
#include <memkind/internal/memkind_hugetlb.h>
Packit 345191
#include <memkind/internal/memkind_arena.h>
Packit 345191
#include <memkind/internal/memkind_hbw.h>
Packit 345191
#include <memkind/internal/memkind_regular.h>
Packit 345191
#include <memkind/internal/memkind_gbtlb.h>
Packit 345191
#include <memkind/internal/memkind_dax_kmem.h>
Packit 345191
#include <memkind/internal/memkind_pmem.h>
Packit 345191
#include <memkind/internal/memkind_interleave.h>
Packit 345191
#include <memkind/internal/memkind_private.h>
Packit 345191
#include <memkind/internal/memkind_log.h>
Packit 345191
#include <memkind/internal/tbb_wrapper.h>
Packit 345191
#include <memkind/internal/heap_manager.h>
Packit 345191
Packit 345191
#include "config.h"
Packit 345191
Packit 345191
#include <numa.h>
Packit 345191
#include <sys/param.h>
Packit 345191
#include <sys/mman.h>
Packit 345191
#include <stdint.h>
Packit 345191
#include <stdlib.h>
Packit 345191
#include <stdio.h>
Packit 345191
#include <string.h>
Packit 345191
#include <assert.h>
Packit 345191
#include <pthread.h>
Packit 345191
#include <errno.h>
Packit 345191
#include <signal.h>
Packit 345191
#include <fcntl.h>
Packit 345191
#include <unistd.h>
Packit 345191
Packit 345191
/* Clear bits in x, but only this specified in mask. */
Packit 345191
#define CLEAR_BIT(x, mask) ((x) &= (~(mask)))
Packit 345191
Packit 345191
extern struct memkind_ops MEMKIND_HBW_GBTLB_OPS;
Packit 345191
extern struct memkind_ops MEMKIND_HBW_PREFERRED_GBTLB_OPS;
Packit 345191
extern struct memkind_ops MEMKIND_GBTLB_OPS;
Packit 345191
Packit 345191
static struct memkind MEMKIND_DEFAULT_STATIC = {
Packit 345191
    .ops =  &MEMKIND_DEFAULT_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_DEFAULT,
Packit 345191
    .name = "memkind_default",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
    .arena_zero = 0,
Packit 345191
    .arena_map_len = ARENA_LIMIT_DEFAULT_KIND - 1,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HUGETLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HUGETLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HUGETLB,
Packit 345191
    .name = "memkind_hugetlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_INTERLEAVE_STATIC = {
Packit 345191
    .ops = &MEMKIND_INTERLEAVE_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_INTERLEAVE,
Packit 345191
    .name = "memkind_interleave",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW,
Packit 345191
    .name = "memkind_hbw",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_ALL_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_ALL_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_ALL,
Packit 345191
    .name = "memkind_hbw_all",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_PREFERRED_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_PREFERRED_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_PREFERRED,
Packit 345191
    .name = "memkind_hbw_preferred",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_HUGETLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_HUGETLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_HUGETLB,
Packit 345191
    .name = "memkind_hbw_hugetlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_ALL_HUGETLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_ALL_HUGETLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_ALL_HUGETLB,
Packit 345191
    .name = "memkind_hbw_all_hugetlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_PREFERRED_HUGETLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_PREFERRED_HUGETLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_PREFERRED_HUGETLB,
Packit 345191
    .name = "memkind_hbw_preferred_hugetlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_GBTLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_GBTLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_GBTLB,
Packit 345191
    .name = "memkind_hbw_gbtlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_PREFERRED_GBTLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_PREFERRED_GBTLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_PREFERRED_GBTLB,
Packit 345191
    .name = "memkind_hbw_preferred_gbtlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_GBTLB_STATIC = {
Packit 345191
    .ops = &MEMKIND_GBTLB_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_GBTLB,
Packit 345191
    .name = "memkind_gbtlb",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_HBW_INTERLEAVE_STATIC = {
Packit 345191
    .ops = &MEMKIND_HBW_INTERLEAVE_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_HBW_INTERLEAVE,
Packit 345191
    .name = "memkind_hbw_interleave",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_REGULAR_STATIC = {
Packit 345191
    .ops = &MEMKIND_REGULAR_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_REGULAR,
Packit 345191
    .name = "memkind_regular",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_DAX_KMEM_STATIC = {
Packit 345191
    .ops = &MEMKIND_DAX_KMEM_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_DAX_KMEM,
Packit 345191
    .name = "memkind_dax_kmem",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_DAX_KMEM_ALL_STATIC = {
Packit 345191
    .ops = &MEMKIND_DAX_KMEM_ALL_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_DAX_KMEM_ALL,
Packit 345191
    .name = "memkind_dax_kmem_all",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind MEMKIND_DAX_KMEM_PREFERRED_STATIC = {
Packit 345191
    .ops = &MEMKIND_DAX_KMEM_PREFERRED_OPS,
Packit 345191
    .partition = MEMKIND_PARTITION_DAX_KMEM_PREFERRED,
Packit 345191
    .name = "memkind_dax_kmem_preferred",
Packit 345191
    .init_once = PTHREAD_ONCE_INIT,
Packit 345191
};
Packit 345191
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_DEFAULT = &MEMKIND_DEFAULT_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HUGETLB = &MEMKIND_HUGETLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_INTERLEAVE = &MEMKIND_INTERLEAVE_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW = &MEMKIND_HBW_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_ALL = &MEMKIND_HBW_ALL_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_PREFERRED =
Packit 345191
        &MEMKIND_HBW_PREFERRED_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_HUGETLB =
Packit 345191
        &MEMKIND_HBW_HUGETLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_ALL_HUGETLB =
Packit 345191
        &MEMKIND_HBW_ALL_HUGETLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_PREFERRED_HUGETLB =
Packit 345191
        &MEMKIND_HBW_PREFERRED_HUGETLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_GBTLB = &MEMKIND_HBW_GBTLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_PREFERRED_GBTLB =
Packit 345191
        &MEMKIND_HBW_PREFERRED_GBTLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_GBTLB = &MEMKIND_GBTLB_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_HBW_INTERLEAVE =
Packit 345191
        &MEMKIND_HBW_INTERLEAVE_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_REGULAR = &MEMKIND_REGULAR_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_DAX_KMEM = &MEMKIND_DAX_KMEM_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_DAX_KMEM_ALL =
Packit 345191
        &MEMKIND_DAX_KMEM_ALL_STATIC;
Packit 345191
MEMKIND_EXPORT struct memkind *MEMKIND_DAX_KMEM_PREFERRED =
Packit 345191
        &MEMKIND_DAX_KMEM_PREFERRED_STATIC;
Packit 345191
Packit 345191
struct memkind_registry {
Packit 345191
    struct memkind *partition_map[MEMKIND_MAX_KIND];
Packit 345191
    int num_kind;
Packit 345191
    pthread_mutex_t lock;
Packit 345191
};
Packit 345191
Packit 345191
static struct memkind_registry memkind_registry_g = {
Packit 345191
    {
Packit 345191
        [MEMKIND_PARTITION_DEFAULT] = &MEMKIND_DEFAULT_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW] = &MEMKIND_HBW_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_PREFERRED] = &MEMKIND_HBW_PREFERRED_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_HUGETLB] = &MEMKIND_HBW_HUGETLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_PREFERRED_HUGETLB] = &MEMKIND_HBW_PREFERRED_HUGETLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HUGETLB] = &MEMKIND_HUGETLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_GBTLB] = &MEMKIND_HBW_GBTLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_PREFERRED_GBTLB] = &MEMKIND_HBW_PREFERRED_GBTLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_GBTLB] = &MEMKIND_GBTLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_INTERLEAVE] = &MEMKIND_HBW_INTERLEAVE_STATIC,
Packit 345191
        [MEMKIND_PARTITION_INTERLEAVE] = &MEMKIND_INTERLEAVE_STATIC,
Packit 345191
        [MEMKIND_PARTITION_REGULAR] = &MEMKIND_REGULAR_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_ALL] = &MEMKIND_HBW_ALL_STATIC,
Packit 345191
        [MEMKIND_PARTITION_HBW_ALL_HUGETLB] = &MEMKIND_HBW_ALL_HUGETLB_STATIC,
Packit 345191
        [MEMKIND_PARTITION_DAX_KMEM] = &MEMKIND_DAX_KMEM_STATIC,
Packit 345191
        [MEMKIND_PARTITION_DAX_KMEM_ALL] = &MEMKIND_DAX_KMEM_ALL_STATIC,
Packit 345191
        [MEMKIND_PARTITION_DAX_KMEM_PREFERRED] = &MEMKIND_DAX_KMEM_PREFERRED_STATIC,
Packit 345191
    },
Packit 345191
    MEMKIND_NUM_BASE_KIND,
Packit 345191
    PTHREAD_MUTEX_INITIALIZER
Packit 345191
};
Packit 345191
Packit 345191
void *kind_mmap(struct memkind *kind, void *addr, size_t size)
Packit 345191
{
Packit 345191
    if (MEMKIND_LIKELY(kind->ops->mmap == NULL)) {
Packit 345191
        return memkind_default_mmap(kind, addr, size);
Packit 345191
    } else {
Packit 345191
        return kind->ops->mmap(kind, addr, size);
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
Packit 345191
static int validate_memtype_bits(memkind_memtype_t memtype)
Packit 345191
{
Packit 345191
    if(memtype == 0) return -1;
Packit 345191
Packit 345191
    CLEAR_BIT(memtype, MEMKIND_MEMTYPE_DEFAULT);
Packit 345191
    CLEAR_BIT(memtype, MEMKIND_MEMTYPE_HIGH_BANDWIDTH);
Packit 345191
Packit 345191
    if(memtype != 0) return -1;
Packit 345191
    return 0;
Packit 345191
}
Packit 345191
Packit 345191
static int validate_flags_bits(memkind_bits_t flags)
Packit 345191
{
Packit 345191
    CLEAR_BIT(flags, MEMKIND_MASK_PAGE_SIZE_2MB);
Packit 345191
Packit 345191
    if(flags != 0) return -1;
Packit 345191
    return 0;
Packit 345191
}
Packit 345191
Packit 345191
static int validate_policy(memkind_policy_t policy)
Packit 345191
{
Packit 345191
    if((policy >= 0) && (policy < MEMKIND_POLICY_MAX_VALUE)) return 0;
Packit 345191
    return -1;
Packit 345191
}
Packit 345191
Packit 345191
struct create_args {
Packit 345191
    memkind_t kind;
Packit 345191
    memkind_policy_t policy;
Packit 345191
    memkind_bits_t flags;
Packit 345191
    memkind_memtype_t memtype_flags;
Packit 345191
};
Packit 345191
Packit 345191
static struct create_args supported_args[] = {
Packit 345191
Packit 345191
    {&MEMKIND_HBW_STATIC,                    MEMKIND_POLICY_BIND_LOCAL,      0,                          MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_HUGETLB_STATIC,            MEMKIND_POLICY_BIND_LOCAL,      MEMKIND_MASK_PAGE_SIZE_2MB, MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_ALL_STATIC,                MEMKIND_POLICY_BIND_ALL,        0,                          MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_ALL_HUGETLB_STATIC,        MEMKIND_POLICY_BIND_ALL,        MEMKIND_MASK_PAGE_SIZE_2MB, MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_PREFERRED_STATIC,          MEMKIND_POLICY_PREFERRED_LOCAL, 0,                          MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_PREFERRED_HUGETLB_STATIC,  MEMKIND_POLICY_PREFERRED_LOCAL, MEMKIND_MASK_PAGE_SIZE_2MB, MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_HBW_INTERLEAVE_STATIC,         MEMKIND_POLICY_INTERLEAVE_ALL,  0,                          MEMKIND_MEMTYPE_HIGH_BANDWIDTH},
Packit 345191
    {&MEMKIND_DEFAULT_STATIC,                MEMKIND_POLICY_PREFERRED_LOCAL, 0,                          MEMKIND_MEMTYPE_DEFAULT},
Packit 345191
    {&MEMKIND_HUGETLB_STATIC,                MEMKIND_POLICY_PREFERRED_LOCAL, MEMKIND_MASK_PAGE_SIZE_2MB, MEMKIND_MEMTYPE_DEFAULT},
Packit 345191
    {&MEMKIND_INTERLEAVE_STATIC,             MEMKIND_POLICY_INTERLEAVE_ALL,  0,                          MEMKIND_MEMTYPE_HIGH_BANDWIDTH | MEMKIND_MEMTYPE_DEFAULT},
Packit 345191
};
Packit 345191
Packit 345191
/* Kind creation */
Packit 345191
MEMKIND_EXPORT int memkind_create_kind(memkind_memtype_t memtype_flags,
Packit 345191
                                       memkind_policy_t policy,
Packit 345191
                                       memkind_bits_t flags,
Packit 345191
                                       memkind_t *kind)
Packit 345191
{
Packit 345191
    if(validate_memtype_bits(memtype_flags) != 0) {
Packit 345191
        log_err("Cannot create kind: incorrect memtype_flags.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    if(validate_flags_bits(flags) != 0) {
Packit 345191
        log_err("Cannot create kind: incorrect flags.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    if(validate_policy(policy) != 0) {
Packit 345191
        log_err("Cannot create kind: incorrect policy.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    if(kind == NULL) {
Packit 345191
        log_err("Cannot create kind: 'kind' is NULL pointer.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    int i, num_supported_args = sizeof(supported_args) / sizeof(struct create_args);
Packit 345191
    for(i = 0; i < num_supported_args; i++) {
Packit 345191
        if((supported_args[i].memtype_flags == memtype_flags) &&
Packit 345191
           (supported_args[i].policy == policy) &&
Packit 345191
           (supported_args[i].flags == flags)) {
Packit 345191
Packit 345191
            if(memkind_check_available(supported_args[i].kind) == 0) {
Packit 345191
                *kind = supported_args[i].kind;
Packit 345191
                return MEMKIND_SUCCESS;
Packit 345191
            } else if(policy == MEMKIND_POLICY_PREFERRED_LOCAL) {
Packit 345191
                *kind = MEMKIND_DEFAULT;
Packit 345191
                return MEMKIND_SUCCESS;
Packit 345191
            }
Packit 345191
            log_err("Cannot create kind: requested memory type is not available.");
Packit 345191
            return MEMKIND_ERROR_MEMTYPE_NOT_AVAILABLE;
Packit 345191
        }
Packit 345191
    }
Packit 345191
Packit 345191
    log_err("Cannot create kind: unsupported set of capabilities.");
Packit 345191
    return MEMKIND_ERROR_INVALID;
Packit 345191
}
Packit 345191
Packit 345191
static void memkind_destroy_dynamic_kind_from_register(unsigned int i,
Packit 345191
                                                       memkind_t kind)
Packit 345191
{
Packit 345191
    if (i >= MEMKIND_NUM_BASE_KIND) {
Packit 345191
        memkind_registry_g.partition_map[i] = NULL;
Packit 345191
        --memkind_registry_g.num_kind;
Packit 345191
        free(kind);
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
/* Kind destruction. */
Packit 345191
MEMKIND_EXPORT int memkind_destroy_kind(memkind_t kind)
Packit 345191
{
Packit 345191
    if (pthread_mutex_lock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to acquire mutex");
Packit 345191
    unsigned i;
Packit 345191
    int err = kind->ops->destroy(kind);
Packit 345191
    for (i = MEMKIND_NUM_BASE_KIND; i < MEMKIND_MAX_KIND; ++i) {
Packit 345191
        if (memkind_registry_g.partition_map[i] &&
Packit 345191
            strcmp(kind->name, memkind_registry_g.partition_map[i]->name) == 0) {
Packit 345191
            memkind_destroy_dynamic_kind_from_register(i, kind);
Packit 345191
            break;
Packit 345191
        }
Packit 345191
    }
Packit 345191
    if (pthread_mutex_unlock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to release mutex");
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT memkind_t memkind_detect_kind(void *ptr)
Packit 345191
{
Packit 345191
    return heap_manager_detect_kind(ptr);
Packit 345191
}
Packit 345191
Packit 345191
/* Declare weak symbols for allocator decorators */
Packit 345191
extern void memkind_malloc_pre(struct memkind **,
Packit 345191
                               size_t *) __attribute__((weak));
Packit 345191
extern void memkind_malloc_post(struct memkind *, size_t,
Packit 345191
                                void **) __attribute__((weak));
Packit 345191
extern void memkind_calloc_pre(struct memkind **, size_t *,
Packit 345191
                               size_t *) __attribute__((weak));
Packit 345191
extern void memkind_calloc_post(struct memkind *, size_t, size_t,
Packit 345191
                                void **) __attribute__((weak));
Packit 345191
extern void memkind_posix_memalign_pre(struct memkind **, void **, size_t *,
Packit 345191
                                       size_t *) __attribute__((weak));
Packit 345191
extern void memkind_posix_memalign_post(struct memkind *, void **, size_t,
Packit 345191
                                        size_t, int *) __attribute__((weak));
Packit 345191
extern void memkind_realloc_pre(struct memkind **, void **,
Packit 345191
                                size_t *) __attribute__((weak));
Packit 345191
extern void memkind_realloc_post(struct memkind *, void *, size_t,
Packit 345191
                                 void **) __attribute__((weak));
Packit 345191
extern void memkind_free_pre(struct memkind **, void **) __attribute__((weak));
Packit 345191
extern void memkind_free_post(struct memkind *, void *) __attribute__((weak));
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_get_version()
Packit 345191
{
Packit 345191
    return MEMKIND_VERSION_MAJOR * 1000000 + MEMKIND_VERSION_MINOR * 1000 +
Packit 345191
           MEMKIND_VERSION_PATCH;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_error_message(int err, char *msg, size_t size)
Packit 345191
{
Packit 345191
    switch (err) {
Packit 345191
        case MEMKIND_ERROR_UNAVAILABLE:
Packit 345191
            strncpy(msg, "<memkind> Requested memory kind is not available", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_MBIND:
Packit 345191
            strncpy(msg, "<memkind> Call to mbind() failed", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_MMAP:
Packit 345191
            strncpy(msg, "<memkind> Call to mmap() failed", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_MALLOC:
Packit 345191
            strncpy(msg, "<memkind> Call to malloc() failed", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_ENVIRON:
Packit 345191
            strncpy(msg, "<memkind> Error parsing environment variable (MEMKIND_*)", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_INVALID:
Packit 345191
            strncpy(msg, "<memkind> Invalid input arguments to memkind routine", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_TOOMANY:
Packit 345191
            snprintf(msg, size,
Packit 345191
                     "<memkind> Attempted to initialize more than maximum (%i) number of kinds",
Packit 345191
                     MEMKIND_MAX_KIND);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_RUNTIME:
Packit 345191
            strncpy(msg, "<memkind> Unspecified run-time error", size);
Packit 345191
            break;
Packit 345191
        case EINVAL:
Packit 345191
            strncpy(msg,
Packit 345191
                    "<memkind> Alignment must be a power of two and larger than sizeof(void *)",
Packit 345191
                    size);
Packit 345191
            break;
Packit 345191
        case ENOMEM:
Packit 345191
            strncpy(msg, "<memkind> Call to jemk_mallocx() failed", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_HUGETLB:
Packit 345191
            strncpy(msg, "<memkind> unable to allocate huge pages", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_BADOPS:
Packit 345191
            strncpy(msg,
Packit 345191
                    "<memkind> memkind_ops structure is poorly formed (missing or incorrect functions)",
Packit 345191
                    size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_MEMTYPE_NOT_AVAILABLE:
Packit 345191
            strncpy(msg, "<memkind> Requested memory type is not available", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_OPERATION_FAILED:
Packit 345191
            strncpy(msg, "<memkind> Operation failed", size);
Packit 345191
            break;
Packit 345191
        case MEMKIND_ERROR_ARENAS_CREATE:
Packit 345191
            strncpy(msg, "<memkind> Call to jemalloc's arenas.create () failed", size);
Packit 345191
            break;
Packit 345191
        default:
Packit 345191
            snprintf(msg, size, "<memkind> Undefined error number: %i", err);
Packit 345191
            break;
Packit 345191
    }
Packit 345191
    if (size > 0) {
Packit 345191
        msg[size-1] = '\0';
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
void memkind_init(memkind_t kind, bool check_numa)
Packit 345191
{
Packit 345191
    log_info("Initializing kind %s.", kind->name);
Packit 345191
    heap_manager_init(kind);
Packit 345191
    if (check_numa) {
Packit 345191
        int err = numa_available();
Packit 345191
        if (err) {
Packit 345191
            log_fatal("[%s] NUMA not available (error code:%d).", kind->name, err);
Packit 345191
            abort();
Packit 345191
        }
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
static void nop(void) {}
Packit 345191
Packit 345191
static int memkind_create(struct memkind_ops *ops, const char *name,
Packit 345191
                          struct memkind **kind)
Packit 345191
{
Packit 345191
    int err;
Packit 345191
    unsigned i;
Packit 345191
    unsigned id_kind = 0;
Packit 345191
Packit 345191
    *kind = NULL;
Packit 345191
    if (pthread_mutex_lock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to acquire mutex");
Packit 345191
Packit 345191
    if (memkind_registry_g.num_kind == MEMKIND_MAX_KIND) {
Packit 345191
        log_err("Attempted to initialize more than maximum (%i) number of kinds.",
Packit 345191
                MEMKIND_MAX_KIND);
Packit 345191
        err = MEMKIND_ERROR_TOOMANY;
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
    if (ops->create == NULL ||
Packit 345191
        ops->destroy == NULL ||
Packit 345191
        ops->malloc == NULL ||
Packit 345191
        ops->calloc == NULL ||
Packit 345191
        ops->realloc == NULL ||
Packit 345191
        ops->posix_memalign == NULL ||
Packit 345191
        ops->free == NULL ||
Packit 345191
        ops->init_once != NULL) {
Packit 345191
        err = MEMKIND_ERROR_BADOPS;
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
    for (i = 0; i < MEMKIND_MAX_KIND; ++i) {
Packit 345191
        if (memkind_registry_g.partition_map[i] == NULL) {
Packit 345191
            id_kind = i;
Packit 345191
            break;
Packit 345191
        } else if (strcmp(name, memkind_registry_g.partition_map[i]->name) == 0) {
Packit 345191
            log_err("Kind with the name %s already exists", name);
Packit 345191
            err = MEMKIND_ERROR_INVALID;
Packit 345191
            goto exit;
Packit 345191
        }
Packit 345191
    }
Packit 345191
    *kind = (struct memkind *)calloc(1, sizeof(struct memkind));
Packit 345191
    if (!*kind) {
Packit 345191
        err = MEMKIND_ERROR_MALLOC;
Packit 345191
        log_err("calloc() failed.");
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
Packit 345191
    (*kind)->partition = memkind_registry_g.num_kind;
Packit 345191
    err = ops->create(*kind, ops, name);
Packit 345191
    if (err) {
Packit 345191
        free(*kind);
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
    memkind_registry_g.partition_map[id_kind] = *kind;
Packit 345191
    ++memkind_registry_g.num_kind;
Packit 345191
Packit 345191
    (*kind)->init_once = PTHREAD_ONCE_INIT;
Packit 345191
    pthread_once(&(*kind)->init_once,
Packit 345191
                 nop); //this is done to avoid init_once for dynamic kinds
Packit 345191
exit:
Packit 345191
    if (pthread_mutex_unlock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to release mutex");
Packit 345191
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
#ifdef __GNUC__
Packit 345191
__attribute__((constructor))
Packit 345191
#endif
Packit 345191
static void memkind_construct(void)
Packit 345191
{
Packit 345191
    const char *env = secure_getenv("MEMKIND_HEAP_MANAGER");
Packit 345191
    if (env && strcmp(env, "TBB") == 0) {
Packit 345191
        load_tbb_symbols();
Packit 345191
    } else {
Packit 345191
        env = secure_getenv("MEMKIND_BACKGROUND_THREAD_LIMIT");
Packit 345191
        if (env) {
Packit 345191
            char *end;
Packit 345191
            errno = 0;
Packit 345191
            size_t thread_limit = strtoull(env, &end, 10);
Packit 345191
            if (*end != '\0' || errno != 0 ) {
Packit 345191
                log_err("Error on parsing value MEMKIND_BACKGROUND_THREAD_LIMIT");
Packit 345191
                return;
Packit 345191
            }
Packit 345191
            memkind_arena_enable_background_threads(thread_limit);
Packit 345191
        }
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
#ifdef __GNUC__
Packit 345191
__attribute__((destructor))
Packit 345191
#endif
Packit 345191
static int memkind_finalize(void)
Packit 345191
{
Packit 345191
    struct memkind *kind;
Packit 345191
    unsigned i;
Packit 345191
    int err = MEMKIND_SUCCESS;
Packit 345191
Packit 345191
    if (pthread_mutex_lock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to acquire mutex");
Packit 345191
Packit 345191
    for (i = 0; i < MEMKIND_MAX_KIND; ++i) {
Packit 345191
        kind = memkind_registry_g.partition_map[i];
Packit 345191
        if (kind && kind->ops->finalize) {
Packit 345191
            err = kind->ops->finalize(kind);
Packit 345191
            if (err) {
Packit 345191
                goto exit;
Packit 345191
            }
Packit 345191
            memkind_destroy_dynamic_kind_from_register(i, kind);
Packit 345191
        }
Packit 345191
    }
Packit 345191
    assert(memkind_registry_g.num_kind == MEMKIND_NUM_BASE_KIND);
Packit 345191
Packit 345191
exit:
Packit 345191
    if (pthread_mutex_unlock(&memkind_registry_g.lock) != 0)
Packit 345191
        assert(0 && "failed to release mutex");
Packit 345191
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_check_available(struct memkind *kind)
Packit 345191
{
Packit 345191
    int err = MEMKIND_SUCCESS;
Packit 345191
Packit 345191
    if (MEMKIND_LIKELY(kind->ops->check_available)) {
Packit 345191
        err = kind->ops->check_available(kind);
Packit 345191
    }
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT size_t memkind_malloc_usable_size(struct memkind *kind,
Packit 345191
                                                 void *ptr)
Packit 345191
{
Packit 345191
    if (!kind) {
Packit 345191
        return heap_manager_malloc_usable_size(ptr);
Packit 345191
    } else {
Packit 345191
        return kind->ops->malloc_usable_size(kind, ptr);
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void *memkind_malloc(struct memkind *kind, size_t size)
Packit 345191
{
Packit 345191
    void *result;
Packit 345191
Packit 345191
    pthread_once(&kind->init_once, kind->ops->init_once);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_malloc_pre) {
Packit 345191
        memkind_malloc_pre(&kind, &size);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    result = kind->ops->malloc(kind, size);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_malloc_post) {
Packit 345191
        memkind_malloc_post(kind, size, &result);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    return result;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void *memkind_calloc(struct memkind *kind, size_t num,
Packit 345191
                                    size_t size)
Packit 345191
{
Packit 345191
    void *result;
Packit 345191
Packit 345191
    pthread_once(&kind->init_once, kind->ops->init_once);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_calloc_pre) {
Packit 345191
        memkind_calloc_pre(&kind, &num, &size);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    result = kind->ops->calloc(kind, num, size);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_calloc_post) {
Packit 345191
        memkind_calloc_post(kind, num, size, &result);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    return result;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_posix_memalign(struct memkind *kind, void **memptr,
Packit 345191
                                          size_t alignment,
Packit 345191
                                          size_t size)
Packit 345191
{
Packit 345191
    int err;
Packit 345191
Packit 345191
    pthread_once(&kind->init_once, kind->ops->init_once);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_posix_memalign_pre) {
Packit 345191
        memkind_posix_memalign_pre(&kind, memptr, &alignment, &size);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    err = kind->ops->posix_memalign(kind, memptr, alignment, size);
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_posix_memalign_post) {
Packit 345191
        memkind_posix_memalign_post(kind, memptr, alignment, size, &err;;
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void *memkind_realloc(struct memkind *kind, void *ptr,
Packit 345191
                                     size_t size)
Packit 345191
{
Packit 345191
    void *result;
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_realloc_pre) {
Packit 345191
        memkind_realloc_pre(&kind, &ptr, &size);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    if (!kind) {
Packit 345191
        result = heap_manager_realloc(ptr, size);
Packit 345191
    } else {
Packit 345191
        pthread_once(&kind->init_once, kind->ops->init_once);
Packit 345191
        result = kind->ops->realloc(kind, ptr, size);
Packit 345191
    }
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_realloc_post) {
Packit 345191
        memkind_realloc_post(kind, ptr, size, &result);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
Packit 345191
    return result;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_free(struct memkind *kind, void *ptr)
Packit 345191
{
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_free_pre) {
Packit 345191
        memkind_free_pre(&kind, &ptr);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
    if (!kind) {
Packit 345191
        heap_manager_free(ptr);
Packit 345191
    } else {
Packit 345191
        pthread_once(&kind->init_once, kind->ops->init_once);
Packit 345191
        kind->ops->free(kind, ptr);
Packit 345191
    }
Packit 345191
Packit 345191
#ifdef MEMKIND_DECORATION_ENABLED
Packit 345191
    if (memkind_free_post) {
Packit 345191
        memkind_free_post(kind, ptr);
Packit 345191
    }
Packit 345191
#endif
Packit 345191
}
Packit 345191
Packit 345191
static int memkind_tmpfile(const char *dir, int *fd)
Packit 345191
{
Packit 345191
    static char template[] = "/memkind.XXXXXX";
Packit 345191
    int err = MEMKIND_SUCCESS;
Packit 345191
    int oerrno;
Packit 345191
    int dir_len = strlen(dir);
Packit 345191
Packit 345191
    if (dir_len > PATH_MAX) {
Packit 345191
        log_err("Could not create temporary file: too long path.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    char fullname[dir_len + sizeof (template)];
Packit 345191
    (void) strcpy(fullname, dir);
Packit 345191
    (void) strcat(fullname, template);
Packit 345191
Packit 345191
    sigset_t set, oldset;
Packit 345191
    sigfillset(&set);
Packit 345191
    (void) sigprocmask(SIG_BLOCK, &set, &oldset);
Packit 345191
Packit 345191
    if ((*fd = mkstemp(fullname)) < 0) {
Packit 345191
        log_err("Could not create temporary file: errno=%d.", errno);
Packit 345191
        err = MEMKIND_ERROR_INVALID;
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
Packit 345191
    (void) unlink(fullname);
Packit 345191
    (void) sigprocmask(SIG_SETMASK, &oldset, NULL);
Packit 345191
Packit 345191
    return err;
Packit 345191
Packit 345191
exit:
Packit 345191
    oerrno = errno;
Packit 345191
    (void) sigprocmask(SIG_SETMASK, &oldset, NULL);
Packit 345191
    if (*fd != -1) {
Packit 345191
        (void) close(*fd);
Packit 345191
    }
Packit 345191
    *fd = -1;
Packit 345191
    errno = oerrno;
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT struct memkind_config *memkind_config_new(void)
Packit 345191
{
Packit 345191
    struct memkind_config *cfg = (struct memkind_config *)malloc(sizeof(
Packit 345191
                                                                     struct memkind_config));
Packit 345191
    return cfg;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_config_delete(struct memkind_config *cfg)
Packit 345191
{
Packit 345191
    free(cfg);
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_config_set_path(struct memkind_config *cfg,
Packit 345191
                                            const char *pmem_dir)
Packit 345191
{
Packit 345191
    cfg->pmem_dir = pmem_dir;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_config_set_size(struct memkind_config *cfg,
Packit 345191
                                            size_t pmem_size)
Packit 345191
{
Packit 345191
    cfg->pmem_size = pmem_size;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void memkind_config_set_memory_usage_policy(
Packit 345191
    struct memkind_config *cfg, memkind_mem_usage_policy policy)
Packit 345191
{
Packit 345191
    cfg->policy = policy;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_create_pmem(const char *dir, size_t max_size,
Packit 345191
                                       struct memkind **kind)
Packit 345191
{
Packit 345191
    int oerrno;
Packit 345191
Packit 345191
    if (max_size && max_size < MEMKIND_PMEM_MIN_SIZE) {
Packit 345191
        log_err("Cannot create pmem: invalid size.");
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    if (max_size) {
Packit 345191
        /* round up to a multiple of jemalloc chunk size */
Packit 345191
        max_size = roundup(max_size, MEMKIND_PMEM_CHUNK_SIZE);
Packit 345191
    }
Packit 345191
Packit 345191
    int fd = -1;
Packit 345191
    char name[16];
Packit 345191
Packit 345191
    int err = memkind_tmpfile(dir, &fd;;
Packit 345191
    if (err) {
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
Packit 345191
    snprintf(name, sizeof (name), "pmem%08x", fd);
Packit 345191
Packit 345191
    err = memkind_create(&MEMKIND_PMEM_OPS, name, kind);
Packit 345191
    if (err) {
Packit 345191
        goto exit;
Packit 345191
    }
Packit 345191
Packit 345191
    struct memkind_pmem *priv = (*kind)->priv;
Packit 345191
Packit 345191
    priv->fd = fd;
Packit 345191
    priv->offset = 0;
Packit 345191
    priv->current_size = 0;
Packit 345191
    priv->max_size = max_size;
Packit 345191
Packit 345191
    return err;
Packit 345191
Packit 345191
exit:
Packit 345191
    oerrno = errno;
Packit 345191
    if (fd != -1) {
Packit 345191
        (void) close(fd);
Packit 345191
    }
Packit 345191
    errno = oerrno;
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_create_pmem_with_config(struct memkind_config *cfg,
Packit 345191
                                                   struct memkind **kind)
Packit 345191
{
Packit 345191
    int status = memkind_create_pmem(cfg->pmem_dir, cfg->pmem_size, kind);
Packit 345191
    if (MEMKIND_LIKELY(!status)) {
Packit 345191
        status = (*kind)->ops->update_memory_usage_policy(*kind, cfg->policy);
Packit 345191
    }
Packit 345191
Packit 345191
    return status;
Packit 345191
}
Packit 345191
Packit 345191
Packit 345191
static int memkind_get_kind_by_partition_internal(int partition,
Packit 345191
                                                  struct memkind **kind)
Packit 345191
{
Packit 345191
    int err = MEMKIND_SUCCESS;
Packit 345191
Packit 345191
    if (MEMKIND_LIKELY(partition >= 0 &&
Packit 345191
                       partition < MEMKIND_MAX_KIND &&
Packit 345191
                       memkind_registry_g.partition_map[partition] != NULL)) {
Packit 345191
        *kind = memkind_registry_g.partition_map[partition];
Packit 345191
    } else {
Packit 345191
        *kind = NULL;
Packit 345191
        err = MEMKIND_ERROR_UNAVAILABLE;
Packit 345191
    }
Packit 345191
    return err;
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_get_kind_by_partition(int partition,
Packit 345191
                                                 struct memkind **kind)
Packit 345191
{
Packit 345191
    return memkind_get_kind_by_partition_internal(partition, kind);
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_update_cached_stats(void)
Packit 345191
{
Packit 345191
    return heap_manager_update_cached_stats();
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT void *memkind_defrag_reallocate(memkind_t kind, void *ptr)
Packit 345191
{
Packit 345191
    if (!kind) {
Packit 345191
        return heap_manager_defrag_reallocate(ptr);
Packit 345191
    } else {
Packit 345191
        return kind->ops->defrag_reallocate(kind, ptr);
Packit 345191
    }
Packit 345191
}
Packit 345191
Packit 345191
MEMKIND_EXPORT int memkind_get_stat(memkind_t kind, memkind_stat_type stat,
Packit 345191
                                    size_t *value)
Packit 345191
{
Packit 345191
    if (MEMKIND_UNLIKELY(stat >= MEMKIND_STAT_TYPE_MAX_VALUE)) {
Packit 345191
        log_err("Unrecognized type of memory statistic %d", stat);
Packit 345191
        return MEMKIND_ERROR_INVALID;
Packit 345191
    }
Packit 345191
Packit 345191
    if (!kind) {
Packit 345191
        return heap_manager_get_stat(stat, value);
Packit 345191
    } else {
Packit 345191
        return kind->ops->get_stat(kind, stat, value);
Packit 345191
    }
Packit 345191
}