/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2006 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2007-2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2010-2018 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2014 NVIDIA Corporation. All rights reserved. * Copyright (c) 2017-2018 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "opal_config.h" #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H*/ #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #include "mpool_memkind.h" #include "opal/mca/allocator/base/base.h" #include "opal/mca/base/base.h" #include "opal/mca/mpool/base/base.h" #include "opal/util/argv.h" #include #include /* * Local functions */ static int mca_mpool_memkind_register(void); static int mca_mpool_memkind_open(void); static int mca_mpool_memkind_close(void); static int mca_mpool_memkind_query(const char *hints, int *priority, mca_mpool_base_module_t **module); mca_mpool_memkind_component_t mca_mpool_memkind_component = {{ /* First, the mca_base_component_t struct containing meta information about the component itself */ .mpool_version = {MCA_MPOOL_BASE_VERSION_3_1_0, "memkind", /* MCA component name */ MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION), .mca_open_component = mca_mpool_memkind_open, .mca_close_component = mca_mpool_memkind_close, .mca_register_component_params = mca_mpool_memkind_register}, .mpool_data = {/* The component is checkpoint ready */ MCA_BASE_METADATA_PARAM_CHECKPOINT}, .mpool_query = mca_mpool_memkind_query, }}; static void mca_mpool_memkind_module_le_destroy(mca_mpool_memkind_module_le_t *elem) { if (NULL != elem->module.kind) { memkind_destroy_kind(elem->module.kind); } } OBJ_CLASS_INSTANCE(mca_mpool_memkind_module_le_t, opal_list_item_t, NULL, mca_mpool_memkind_module_le_destroy); static mca_base_var_enum_value_t memory_types[] = { {.value = MEMKIND_MEMTYPE_DEFAULT, .string = "memkind_default"}, {.value = MEMKIND_MEMTYPE_HIGH_BANDWIDTH, .string = "memkind_hbw"}, {.string = NULL}, }; static mca_base_var_enum_value_t memory_policy[] = { {.value = MEMKIND_POLICY_BIND_LOCAL, .string = "mempolicy_bind_local"}, {.value = MEMKIND_POLICY_BIND_ALL, .string = "mempolicy_bind_all"}, {.value = MEMKIND_POLICY_PREFERRED_LOCAL, .string = "mempolicy_perferred_local"}, {.value = MEMKIND_POLICY_INTERLEAVE_LOCAL, .string = "mempolicy_interleave_local"}, {.value = MEMKIND_POLICY_INTERLEAVE_ALL, .string = "mempolicy_interleave_all"}, {.string = NULL}, }; static mca_base_var_enum_value_t memory_kind_bits[] = { {.value = 0, .string = "memkind_mask_page_size_4KB"}, {.value = MEMKIND_MASK_PAGE_SIZE_2MB, .string = "memkind_mask_page_size_2MB"}, {.string = NULL}, }; static mca_base_var_enum_t *mca_mpool_memkind_policy_enum = NULL; static mca_base_var_enum_t *mca_mpool_memkind_type_enum = NULL; static mca_base_var_enum_t *mca_mpool_memkind_kind_bits_enum = NULL; static int opal_mpool_memkind_verbose; static int mca_mpool_memkind_register(void) { int rc; /* register MEMKIND component parameters */ mca_mpool_memkind_component.default_type = memory_types[0].value; rc = mca_base_var_enum_create("memkind memory types", memory_types, &mca_mpool_memkind_type_enum); if (OPAL_SUCCESS != rc) { return rc; } (void) mca_base_component_var_register(&mca_mpool_memkind_component.super.mpool_version, "default_type", "Default memkind type to use", MCA_BASE_VAR_TYPE_INT, mca_mpool_memkind_type_enum, 0, 0, OPAL_INFO_LVL_5, MCA_BASE_VAR_SCOPE_LOCAL, &mca_mpool_memkind_component.default_type); /* * see memkind source to understand the 2 */ mca_mpool_memkind_component.default_policy = memory_policy[2].value; rc = mca_base_var_enum_create("memkind memory policy", memory_policy, &mca_mpool_memkind_policy_enum); if (OPAL_SUCCESS != rc) { return rc; } (void) mca_base_component_var_register(&mca_mpool_memkind_component.super.mpool_version, "default_policy", "Default memkind policy to use", MCA_BASE_VAR_TYPE_INT, mca_mpool_memkind_policy_enum, 0, 0, OPAL_INFO_LVL_5, MCA_BASE_VAR_SCOPE_LOCAL, &mca_mpool_memkind_component.default_policy); mca_mpool_memkind_component.default_memkind_bits = memory_kind_bits[0].value; rc = mca_base_var_enum_create("memkind memory bits", memory_kind_bits, &mca_mpool_memkind_kind_bits_enum); if (OPAL_SUCCESS != rc) { return rc; } (void) mca_base_component_var_register(&mca_mpool_memkind_component.super.mpool_version, "default_bits", "Default memkind bits to use", MCA_BASE_VAR_TYPE_INT, mca_mpool_memkind_kind_bits_enum, 0, 0, OPAL_INFO_LVL_5, MCA_BASE_VAR_SCOPE_LOCAL, &mca_mpool_memkind_component.default_memkind_bits); mca_mpool_memkind_component.priority = 10; (void) mca_base_component_var_register(&mca_mpool_memkind_component.super.mpool_version, "priority", "Default priority of the memkind component", MCA_BASE_VAR_TYPE_INT, NULL, 0, 0, OPAL_INFO_LVL_5, MCA_BASE_VAR_SCOPE_LOCAL, &mca_mpool_memkind_component.priority); opal_mpool_memkind_verbose = 0; (void) mca_base_component_var_register(&mca_mpool_memkind_component.super.mpool_version, "verbose", "Verbosity of the memkind mpool component", MCA_BASE_VAR_TYPE_INT, &mca_base_var_enum_verbose, 0, 0, OPAL_INFO_LVL_9, MCA_BASE_VAR_SCOPE_LOCAL, &opal_mpool_memkind_verbose); return OPAL_SUCCESS; } /** * component open/close/init function */ static int mca_mpool_memkind_open(void) { int rc; mca_mpool_memkind_module_le_t *item = NULL; if (opal_mpool_memkind_verbose != 0) { mca_mpool_memkind_component.output = opal_output_open(NULL); } else { mca_mpool_memkind_component.output = -1; } OBJ_CONSTRUCT(&mca_mpool_memkind_component.module_list, opal_list_t); rc = memkind_create_kind(mca_mpool_memkind_component.default_type, mca_mpool_memkind_component.default_policy, mca_mpool_memkind_component.default_memkind_bits, &mca_mpool_memkind_component.default_kind); if (MEMKIND_SUCCESS != rc) { opal_output_verbose(MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output, "memkind_create_kind default returned %d", rc); return OPAL_ERR_NOT_AVAILABLE; } item = OBJ_NEW(mca_mpool_memkind_module_le_t); item->module.type = mca_mpool_memkind_component.default_type; item->module.policy = mca_mpool_memkind_component.default_policy; item->module.memkind_bits = mca_mpool_memkind_component.default_memkind_bits; item->module.kind = mca_mpool_memkind_component.default_kind; /* * ufff, magic mask - see memkind.h in the memkind package */ if (MEMKIND_MASK_PAGE_SIZE_2MB == (item->module.memkind_bits & 0x7F)) { item->module.page_size = 2097152; } else { item->module.page_size = 4096; } opal_list_append(&mca_mpool_memkind_component.module_list, (opal_list_item_t *) item); return OPAL_SUCCESS; } static int mca_mpool_memkind_close(void) { opal_output_close(mca_mpool_memkind_component.output); mca_mpool_memkind_component.output = -1; OPAL_LIST_DESTRUCT(&mca_mpool_memkind_component.module_list); if (mca_mpool_memkind_policy_enum) { OBJ_RELEASE(mca_mpool_memkind_policy_enum); mca_mpool_memkind_policy_enum = NULL; } if (mca_mpool_memkind_type_enum) { OBJ_RELEASE(mca_mpool_memkind_type_enum); mca_mpool_memkind_type_enum = NULL; } if (mca_mpool_memkind_kind_bits_enum) { OBJ_RELEASE(mca_mpool_memkind_kind_bits_enum); mca_mpool_memkind_kind_bits_enum = NULL; } return OPAL_SUCCESS; } static int mca_mpool_memkind_query(const char *hints, int *priority_out, mca_mpool_base_module_t **module) { int my_priority = mca_mpool_memkind_component.priority; char **hint_array; char *tmp, *key, *value = NULL; int rc; memkind_memtype_t type = mca_mpool_memkind_component.default_type; memkind_policy_t policy = mca_mpool_memkind_component.default_policy; memkind_bits_t memkind_bits = mca_mpool_memkind_component.default_memkind_bits; mca_mpool_memkind_module_le_t *item = NULL; mca_mpool_base_module_t *found_module = NULL; memkind_t kind; if (NULL == hints) { if (priority_out) { *priority_out = my_priority; } return OPAL_SUCCESS; } hint_array = opal_argv_split(hints, ','); if (NULL == hint_array) { if (priority_out) { *priority_out = my_priority; } return OPAL_SUCCESS; } for (int i = 0; hint_array[i]; ++i) { key = hint_array[i]; tmp = strchr(key, '='); if (tmp) { *tmp = '\0'; value = tmp + 1; } /* * TODO: may want to emit a warning */ if (value == NULL) break; if (0 == strcasecmp(key, "mpool")) { if (0 == strcasecmp(value, "memkind")) { /* specifically selected */ my_priority = 100; } else { if (priority_out) { *priority_out = 0; } return OPAL_SUCCESS; } } else if (0 == strcasecmp(key, "policy")) { rc = mca_mpool_memkind_policy_enum->value_from_string(mca_mpool_memkind_policy_enum, value, (int *) &policy); if (OPAL_SUCCESS != rc) { opal_output_verbose(MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output, "invalid memkind policy %s specified", value); } } else if (0 == strcasecmp(key, "type")) { rc = mca_mpool_memkind_type_enum->value_from_string(mca_mpool_memkind_type_enum, value, (int *) &type); if (OPAL_SUCCESS != rc) { opal_output_verbose(MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output, "invalid memkind type %s specified", value); } } else if (0 == strcasecmp(key, "kind_bits")) { rc = mca_mpool_memkind_kind_bits_enum ->value_from_string(mca_mpool_memkind_kind_bits_enum, value, (int *) &memkind_bits); if (OPAL_SUCCESS != rc) { opal_output_verbose(MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output, "invalid memkind kind_bits %s specified", value); } } } /* * now look for an existing module with matching policy, type, memkind bits */ OPAL_LIST_FOREACH (item, &mca_mpool_memkind_component.module_list, mca_mpool_memkind_module_le_t) { if ((item->module.type == type) && (item->module.policy == policy) && (item->module.memkind_bits = memkind_bits)) { found_module = &item->module.super; break; } } /* * didn't find a matching module, try to create one */ if (NULL == found_module) { rc = memkind_create_kind(type, policy, memkind_bits, &kind); if (MEMKIND_SUCCESS == rc) { item = OBJ_NEW(mca_mpool_memkind_module_le_t); item->module.type = type; item->module.policy = policy; item->module.memkind_bits = memkind_bits; item->module.kind = kind; if (MEMKIND_MASK_PAGE_SIZE_2MB == item->module.memkind_bits) { item->module.page_size = 2097152; } else { item->module.page_size = 4096; } mca_mpool_memkind_module_init(&item->module); opal_list_append(&mca_mpool_memkind_component.module_list, (opal_list_item_t *) item); found_module = &item->module.super; } else { opal_output_verbose(MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output, "memkind_create_kind returned %d", rc); if (priority_out) { *priority_out = 0; } return OPAL_SUCCESS; } } if ((found_module) && (NULL != module)) { *module = found_module; } opal_argv_free(hint_array); if (priority_out) { *priority_out = my_priority; } return OPAL_SUCCESS; }