From 824197f886f01bcaab7aaf2866e2d909ab716da5 Mon Sep 17 00:00:00 2001
From: Howard Pritchard <howardp@lanl.gov>
Date: Thu, 22 Mar 2018 03:55:18 -0600
Subject: [PATCH] mpool/memkind: refactor to use the current API

The mpool/memkind component was using a deprecated "partitions" API.
This commit refactors the memkind component to make use of the
supported public API.

The public API uses 3 parameters to specify a mpool "kind":

- a memkind type (which for now is just default or HBM)
- a memkind policy
- a memkind_bits (partly to specify pagesize)

The MCA parameters were changed to reflect these memkind
parameters.

Add a make check test for sanity checking of the memkind component.

Signed-off-by: Howard Pritchard <howardp@lanl.gov>
---
 configure.ac                                  |   1 +
 opal/mca/mpool/memkind/configure.m4           |   7 +-
 opal/mca/mpool/memkind/mpool_memkind.h        |  31 ++-
 .../mpool/memkind/mpool_memkind_component.c   | 259 +++++++++++++-----
 opal/mca/mpool/memkind/mpool_memkind_module.c |  15 +-
 test/Makefile.am                              |   2 +-
 test/mpool/Makefile.am                        |  21 ++
 test/mpool/mpool_memkind.c                    | 160 +++++++++++
 8 files changed, 413 insertions(+), 83 deletions(-)
 create mode 100644 test/mpool/Makefile.am
 create mode 100644 test/mpool/mpool_memkind.c

diff --git a/configure.ac b/configure.ac
index 64eab61b8f..35f4d4f1d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1422,6 +1422,7 @@ AC_CONFIG_FILES([
     test/datatype/Makefile
     test/dss/Makefile
     test/class/Makefile
+    test/mpool/Makefile
     test/support/Makefile
     test/threads/Makefile
     test/util/Makefile
diff --git a/opal/mca/mpool/memkind/configure.m4 b/opal/mca/mpool/memkind/configure.m4
index bc6e5a3286..95541fe100 100644
--- a/opal/mca/mpool/memkind/configure.m4
+++ b/opal/mca/mpool/memkind/configure.m4
@@ -1,6 +1,6 @@
 # -*- shell-script -*-
 #
-# Copyright (c) 2013-2014 Los Alamos National Security, LLC. All rights
+# Copyright (c) 2013-2018 Los Alamos National Security, LLC. All rights
 #                         reserved.
 # $COPYRIGHT$
 #
@@ -24,7 +24,10 @@ AC_DEFUN([MCA_opal_mpool_memkind_CONFIG],[
 	        opal_check_memkind_dir=$with_memkind
 	    fi
 
-	    OPAL_CHECK_PACKAGE([mpool_memkind], [memkind.h], [memkind], [memkind_malloc], [ -lnuma],
+            #
+            # memkind_create_kind was introduced with memkind v1.4.0 release
+            #
+            OPAL_CHECK_PACKAGE([mpool_memkind], [memkind.h], [memkind], [memkind_create_kind], [ -lnuma],
 	        [$opal_check_memkind_dir], [], [opal_mpool_memkind_happy="yes"], [])
 
 	    if test "$opal_mpool_memkind_happy" != "yes" -a -n "$with_memkind" ; then
diff --git a/opal/mca/mpool/memkind/mpool_memkind.h b/opal/mca/mpool/memkind/mpool_memkind.h
index afc0b6d8b7..2ac6c29107 100644
--- a/opal/mca/mpool/memkind/mpool_memkind.h
+++ b/opal/mca/mpool/memkind/mpool_memkind.h
@@ -12,7 +12,7 @@
  *                         All rights reserved.
  * Copyright (c) 2007      Sun Microsystems, Inc.  All rights reserved.
  * Copyright (c) 2009      Cisco Systems, Inc.  All rights reserved.
- * Copyright (c) 2010-2015 Los Alamos National Security, LLC. All rights
+ * Copyright (c) 2010-2018 Los Alamos National Security, LLC. All rights
  *                         reserved.
  * $COPYRIGHT$
  *
@@ -38,32 +38,49 @@ BEGIN_C_DECLS
 
 static const int mca_mpool_memkind_default_pagesize = 4096;
 
+
 struct mca_mpool_memkind_module_t {
     mca_mpool_base_module_t super;
     memkind_t kind;
+    memkind_memtype_t type;
+    memkind_policy_t  policy;
+    memkind_bits_t    memkind_bits;
     int page_size;
 };
+
 typedef struct mca_mpool_memkind_module_t mca_mpool_memkind_module_t;
 
+struct mca_mpool_memkind_module_le_t {
+    opal_list_item_t super;
+    mca_mpool_memkind_module_t module;
+};
+typedef struct mca_mpool_memkind_module_le_t mca_mpool_memkind_module_le_t;
+
+OBJ_CLASS_DECLARATION(mca_mpool_memkind_module_le_t);
+
 struct mca_mpool_memkind_component_t {
     mca_mpool_base_component_t super;
     int  hbw;
     int  pagesize;
     int  bind;
-    int  default_partition;
+    memkind_memtype_t default_type;
+    memkind_policy_t  default_policy;
+    memkind_bits_t    default_memkind_bits;
+    memkind_t         default_kind;
     int  priority;
-    char *memkind_file;
     int  output;
-    mca_mpool_memkind_module_t modules[MEMKIND_NUM_BASE_KIND];
+    opal_list_t module_list;
 };
+
 typedef struct mca_mpool_memkind_component_t mca_mpool_memkind_component_t;
 OPAL_MODULE_DECLSPEC extern mca_mpool_memkind_component_t mca_mpool_memkind_component;
 
-/*
+/**
  *  Initializes the mpool module.
-*/
+ */
+
+void mca_mpool_memkind_module_init(mca_mpool_memkind_module_t *mpool);
 
-void mca_mpool_memkind_module_init(mca_mpool_memkind_module_t *mpool, int partition);
 
 /**
   *  Allocate block of high bandwidth memory.
diff --git a/opal/mca/mpool/memkind/mpool_memkind_component.c b/opal/mca/mpool/memkind/mpool_memkind_component.c
index d438d0599f..41145d039c 100644
--- a/opal/mca/mpool/memkind/mpool_memkind_component.c
+++ b/opal/mca/mpool/memkind/mpool_memkind_component.c
@@ -12,7 +12,7 @@
  *                         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-2016 Los Alamos National Security, LLC. All rights
+ * Copyright (c) 2010-2018 Los Alamos National Security, LLC. All rights
  *                         reserved.
  * Copyright (c) 2014      NVIDIA Corporation.  All rights reserved.
  * Copyright (c) 2017      Research Organization for Information Science
@@ -35,6 +35,7 @@
 #include <memkind.h>
 #include "opal/mca/base/base.h"
 #include "opal/mca/allocator/base/base.h"
+#include "opal/mca/mpool/base/base.h"
 #include "opal/util/argv.h"
 #include "mpool_memkind.h"
 
@@ -77,22 +78,42 @@ mca_mpool_memkind_component_t mca_mpool_memkind_component = {
     }
 };
 
-static mca_base_var_enum_value_t memory_kinds[] = {
-  {.value = MEMKIND_PARTITION_DEFAULT, .string = "memkind_default"},
-  {.value = MEMKIND_PARTITION_HBW, .string = "memkind_hbw"},
-  {.value = MEMKIND_PARTITION_HBW_HUGETLB, .string = "memkind_hwb_hugetlb"},
-  {.value = MEMKIND_PARTITION_HBW_PREFERRED, .string = "memkind_hbw_preferred"},
-  {.value = MEMKIND_PARTITION_HBW_PREFERRED_HUGETLB, .string = "memkind_hbw_preferred_hugetlb"},
-  {.value = MEMKIND_PARTITION_HUGETLB, .string = "memkind_hugetlb"},
-  {.value = MEMKIND_PARTITION_HBW_GBTLB, .string = "memkind_hbw_gbtlb"},
-  {.value = MEMKIND_PARTITION_HBW_PREFERRED_GBTLB, .string = "memkind_hbw_preferred_gbtlb"},
-  {.value = MEMKIND_PARTITION_GBTLB, .string = "memkind_gbtlb"},
-  {.value = MEMKIND_PARTITION_HBW_INTERLEAVE, .string = "memkind_hbw_interleave"},
-  {.value = MEMKIND_PARTITION_INTERLEAVE, .string = "memkind_interleave"},
+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_t *mca_mpool_memkind_enum = 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)
@@ -100,18 +121,51 @@ static int mca_mpool_memkind_register(void)
     int rc;
 
     /* register MEMKIND component parameters */
-    mca_mpool_memkind_component.default_partition = memory_kinds[0].value;
 
-    rc = mca_base_var_enum_create ("memkind partition types", memory_kinds, &mca_mpool_memkind_enum);
+    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_partition", "Default memkind partition to use",
-                                           MCA_BASE_VAR_TYPE_INT, mca_mpool_memkind_enum, 0, 0,
+                                           "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_partition);
+                                           &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,
@@ -135,8 +189,8 @@ static int mca_mpool_memkind_register(void)
   */
 static int mca_mpool_memkind_open (void)
 {
-    memkind_t default_kind;
     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);
@@ -144,27 +198,36 @@ static int mca_mpool_memkind_open (void)
         mca_mpool_memkind_component.output = -1;
     }
 
-    rc = memkind_get_kind_by_partition (mca_mpool_memkind_component.default_partition,
-                                        &default_kind);
-    if (0 != rc) {
+    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;
     }
 
-    if (memkind_check_available (default_kind)) {
-        char *kind_string;
+    item = OBJ_NEW(mca_mpool_memkind_module_le_t);
 
-        mca_mpool_memkind_enum->string_from_value (mca_mpool_memkind_enum,
-                                                   mca_mpool_memkind_component.default_partition,
-                                                   &kind_string);
-        opal_output_verbose (MCA_BASE_VERBOSE_WARN, mca_mpool_memkind_component.output,
-                             "default kind %s not available", kind_string);
-        free (kind_string);
-        return OPAL_ERR_NOT_AVAILABLE;
+    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;
     }
 
-    for (int i = 0 ; i < MEMKIND_NUM_BASE_KIND ; ++i) {
-        mca_mpool_memkind_module_init (mca_mpool_memkind_component.modules + i, i);
-    }
+    opal_list_append(&mca_mpool_memkind_component.module_list,
+                    (opal_list_item_t *)item);
+ 
 
     return OPAL_SUCCESS;
 }
@@ -174,9 +237,21 @@ static int mca_mpool_memkind_close(void)
     opal_output_close (mca_mpool_memkind_component.output);
     mca_mpool_memkind_component.output = -1;
 
-    if (mca_mpool_memkind_enum) {
-        OBJ_RELEASE(mca_mpool_memkind_enum);
-        mca_mpool_memkind_enum = NULL;
+    OBJ_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;
@@ -186,12 +261,15 @@ 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, *partition_name;
-    int partition = -1, rc;
-
-    if (module) {
-        *module = &mca_mpool_memkind_component.modules[mca_mpool_memkind_component.default_partition].super;
-    }
+    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) {
@@ -209,7 +287,6 @@ static int mca_mpool_memkind_query (const char *hints, int *priority_out,
     }
 
     for (int i = 0 ; hint_array[i] ; ++i) {
-        char *tmp, *key, *value;
 
         key = hint_array[i];
         tmp = strchr (key, '=');
@@ -218,6 +295,11 @@ static int mca_mpool_memkind_query (const char *hints, int *priority_out,
             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 */
@@ -229,37 +311,90 @@ static int mca_mpool_memkind_query (const char *hints, int *priority_out,
                 }
                 return OPAL_SUCCESS;
             }
-        } else if (0 == strcasecmp (key, "partition")) {
-            rc = mca_mpool_memkind_enum->value_from_string (mca_mpool_memkind_enum,
-                                                            value, &partition);
+        } 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, mca_mpool_memkind_component.output,
-                                     "invalid partition %s specified", value);
+                opal_output_verbose (MCA_BASE_VERBOSE_WARN, opal_mpool_base_framework.framework_output,
+                                     "invalid memkind policy %s specified", value);
             }
 
-            partition_name = 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);
+            }
         }
     }
 
-    if (-1 != partition) {
-        memkind_t kind;
+    /*
+     * now look for an existing module with matching policy, type, memkind bits
+     */
 
-        my_priority = 0;
+    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;
+        }
+    } 
 
-        if (!memkind_get_kind_by_partition (partition, &kind)) {
-            if (memkind_check_available (kind)) {
-                opal_output_verbose (MCA_BASE_VERBOSE_WARN, mca_mpool_memkind_component.output,
-                                     "kind %s not available", partition_name);
+    /*
+     * 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 {
-                my_priority = 100;
+                item->module.page_size = 4096;
             }
-        }
 
-        if (module) {
-            *module = &mca_mpool_memkind_component.modules[partition].super;
+            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) {
diff --git a/opal/mca/mpool/memkind/mpool_memkind_module.c b/opal/mca/mpool/memkind/mpool_memkind_module.c
index c61d379e3b..d53f80a27d 100644
--- a/opal/mca/mpool/memkind/mpool_memkind_module.c
+++ b/opal/mca/mpool/memkind/mpool_memkind_module.c
@@ -11,7 +11,7 @@
  * Copyright (c) 2004-2005 The Regents of the University of California.
  *                         All rights reserved.
  * Copyright (c) 2009-2018 Cisco Systems, Inc.  All rights reserved.
- * Copyright (c) 2011-2015 Los Alamos National Security, LLC. All rights
+ * Copyright (c) 2011-2018 Los Alamos National Security, LLC. All rights
  *                         reserved.
  * Copyright (c) 2011-2014 NVIDIA Corporation.  All rights reserved.
  * $COPYRIGHT$
@@ -23,32 +23,25 @@
 
 #include "opal_config.h"
 #include <string.h>
-#include "opal/mca/mpool/memkind/mpool_memkind.h"
+#include "mpool_memkind.h"
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include "opal/mca/mpool/base/base.h"
 
-size_t partition_page_sizes[MEMKIND_NUM_BASE_KIND] = {
-    4096, 4096, 2097152, 4096, 2097152, 2097152,
-    1073741824, 1073741824, 1073741824, 4096, 4096,
-};
-
 /*
  *  Initializes the mpool module.
  */
-void mca_mpool_memkind_module_init(mca_mpool_memkind_module_t *mpool, int partition)
+
+void mca_mpool_memkind_module_init(mca_mpool_memkind_module_t *mpool)
 {
     mpool->super.mpool_component = &mca_mpool_memkind_component.super;
     mpool->super.mpool_alloc = mca_mpool_memkind_alloc;
     mpool->super.mpool_realloc = mca_mpool_memkind_realloc;
     mpool->super.mpool_free = mca_mpool_memkind_free;
     mpool->super.flags = MCA_MPOOL_FLAGS_MPI_ALLOC_MEM;
-    memkind_get_kind_by_partition (partition, &mpool->kind);
-    mpool->page_size = partition_page_sizes[partition];
 }
 
-
 void* mca_mpool_memkind_alloc(
     mca_mpool_base_module_t* mpool,
     size_t size,
diff --git a/test/Makefile.am b/test/Makefile.am
index 4ed2525484..9982b94530 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -22,7 +22,7 @@
 #
 
 # support needs to be first for dependencies
-SUBDIRS = support asm class threads datatype util dss
+SUBDIRS = support asm class threads datatype util dss mpool
 if PROJECT_OMPI
 SUBDIRS += monitoring
 endif
diff --git a/test/mpool/Makefile.am b/test/mpool/Makefile.am
new file mode 100644
index 0000000000..620ed8c9a5
--- /dev/null
+++ b/test/mpool/Makefile.am
@@ -0,0 +1,21 @@
+# Copyright (c) 2018      Los Alamos National Security, LLC.  All rights reserved.
+#
+# $COPYRIGHT$
+#
+# Additional copyrights may follow
+#
+# $HEADER$
+#
+
+TESTS = mpool_memkind
+
+check_PROGRAMS = $(TESTS) $(MPI_CHECKS)
+
+mpool_memkind_SOURCES = mpool_memkind.c
+
+LDFLAGS = $(OPAL_PKG_CONFIG_LDFLAGS)
+LDADD = $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la
+
+distclean:
+	rm -rf *.dSYM .deps .libs *.log *.o *.trs $(check_PROGRAMS) Makefile
+
diff --git a/test/mpool/mpool_memkind.c b/test/mpool/mpool_memkind.c
new file mode 100644
index 0000000000..bae81fd3b5
--- /dev/null
+++ b/test/mpool/mpool_memkind.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
+ *                         University Research and Technology
+ *                         Corporation.  All rights reserved.
+ * Copyright (c) 2004-2005 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) 2016      Research Organization for Information Science
+ *                         and Technology (RIST). All rights reserved.
+ * Copyright (c) 2018      Los Alamos National Security, LLC.  All rights reserved.
+ * $COPYRIGHT$
+ *
+ * Additional copyrights may follow
+ *
+ * $HEADER$
+ */
+
+/*
+ * only do this test if we have built with memkind support
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "opal_config.h"
+#ifdef HAVE_MEMKIND_H
+#include "opal/constants.h"
+#include "opal/mca/mpool/mpool.h"
+#include "opal/include/opal/frameworks.h"
+#include "opal/runtime/opal.h"
+
+#define SIZE (2 * 1024 * 1024)
+
+const char *memory_types[] = {
+  "memkind_default",
+  "memkind_hbw",
+   NULL
+};
+
+const char *memory_policy[] = {
+   "mempolicy_bind_local",
+   "mempolicy_bind_all",
+   "mempolicy_perferred_local",
+   "mempolicy_interleave_local",
+   "mempolicy_interleave_all",
+   NULL
+};
+
+const char *memory_kind_bits[] = {
+   "memkind_mask_page_size_4KB",
+   "memkind_mask_page_size_2MB",
+   NULL
+};
+
+int main (int argc, char* argv[])
+{
+    int ret = 0;
+    void *ptr = NULL;
+    char *error = NULL;
+    char **mp_ptr = NULL;
+    char **mt_ptr = NULL;
+    char **mk_ptr = NULL;
+    const char mpool_hints[] = "mpool=memkind";
+    char hints[1024];
+
+    opal_init_util(&argc, &argv);
+
+    if (opal_frameworks == NULL){
+        error = "opal frameworks is NULL";
+        goto error;
+    }
+
+    if (OPAL_SUCCESS != (ret = mca_base_framework_open(&opal_allocator_base_framework, 0))) {
+        error = "mca_allocator_base_open() failed";
+        goto error;
+    }
+
+    if (OPAL_SUCCESS != (ret = mca_base_framework_open(&opal_mpool_base_framework, 0))) {
+        error = "mca_mpool_base_open() failed";
+        goto error;
+    }
+
+    /*
+     * first try basic allocation
+     */
+
+    ptr = mca_mpool_base_alloc(SIZE, NULL, mpool_hints);
+    if (NULL == ptr) {
+        error = "mca_mpool_base_alloc() failed";
+        goto error;
+    }
+
+    if (OPAL_SUCCESS != mca_mpool_base_free(ptr)) {
+        error = "mca_mpool_base_free() failed";
+        goto error;
+    }
+
+    /*
+     * now try policies
+     */
+
+    mp_ptr = (char **)memory_policy;
+    while (NULL != *mp_ptr) {
+
+        mt_ptr = (char **)memory_types;
+        while (NULL != *mt_ptr) {
+
+            mk_ptr = (char **)memory_kind_bits;
+            while (NULL != *mk_ptr) {
+                snprintf(hints, sizeof(hints), "%s,policy=%s,type=%s,kind=%s", 
+                         mpool_hints, *mp_ptr, *mt_ptr, *mk_ptr);
+                ptr = mca_mpool_base_alloc(SIZE, NULL, hints);
+                if (NULL == ptr) {
+                    error = "mca_mpool_base_alloc() failed";
+                    goto error;
+                }
+
+                if (OPAL_SUCCESS != mca_mpool_base_free(ptr)) {
+                    error = "mca_mpool_base_free() failed";
+                    goto error;
+                }
+                mk_ptr++;
+            }
+            mt_ptr++;
+        }
+        mp_ptr++;
+    }
+
+    if (OPAL_SUCCESS != (ret = mca_base_framework_close(&opal_mpool_base_framework))) {
+        error = "mca_mpool_base_close() failed";
+        goto error;
+    }
+
+    if (OPAL_SUCCESS != (ret = mca_base_framework_close(&opal_allocator_base_framework))) {
+        error = "mca_mpool_base_close() failed";
+        goto error;
+    }
+
+    opal_finalize();
+
+error:
+    if (NULL != error) {
+        fprintf(stderr, "mpool/memkind test failed %s\n", error);
+        ret = -1;
+    } else {
+        fprintf(stderr, "mpool/memkind test passed\n");
+    }
+
+    return ret;
+}
+#else
+int main (int argc, char* argv[])
+{
+    return 77;
+}
+#endif /* HAVE_MEMKIND_H */