88#include <assert.h>
99#include <errno.h>
1010#include <limits.h>
11-
1211#include <stddef.h>
1312#include <stdio.h>
1413#include <stdlib.h>
1514#include <string.h>
15+
16+ #if !defined(_WIN32 ) && !defined(__APPLE__ )
17+ #include <numaif.h>
18+ #include <sys/syscall.h>
19+ #endif
20+
1621#include <umf.h>
1722#include <umf/base.h>
1823#include <umf/memory_provider.h>
2429#include "ctl/ctl_internal.h"
2530#include "libumf.h"
2631#include "provider_os_memory_internal.h"
32+ #include "topology.h"
2733#include "utils_assert.h"
2834#include "utils_common.h"
2935#include "utils_concurrency.h"
3238#define CTL_PROVIDER_TYPE os_memory_provider_t
3339#include "provider_ctl_stats_impl.h"
3440
41+ #define MAX_NUMNODES 1024
3542#define NODESET_STR_BUF_LEN 1024
36-
3743#define TLS_MSG_BUF_LEN 1024
3844
3945static const char * DEFAULT_NAME = "OS" ;
@@ -152,8 +158,14 @@ static umf_result_t initialize_nodeset(os_memory_provider_t *os_provider,
152158 // Hwloc_set_area_membind fails if empty nodeset is passed so
153159 // if no node is specified, just pass all available nodes.
154160 // For modes where no node is needed, they will be ignored anyway.
161+
162+ #if defined(_WIN32 ) || defined(__APPLE__ )
155163 out_nodeset [0 ] = hwloc_bitmap_dup (
156164 hwloc_topology_get_complete_nodeset (os_provider -> topo ));
165+ #else
166+ out_nodeset [0 ] = hwloc_bitmap_dup (umfGetTopology2 ());
167+ #endif
168+
157169 if (!out_nodeset [0 ]) {
158170 goto err_free_list ;
159171 }
@@ -518,6 +530,11 @@ translate_params(const umf_os_memory_provider_params_t *in_params,
518530
519531 provider -> numa_flags =
520532 getHwlocMembindFlags (in_params -> numa_mode , is_dedicated_node_bind );
533+
534+ #if !defined(_WIN32 ) && !defined(__APPLE__ )
535+ provider -> dedicated = is_dedicated_node_bind ;
536+ #endif
537+
521538 provider -> mode = in_params -> numa_mode ;
522539 provider -> part_size = in_params -> part_size ;
523540
@@ -561,6 +578,11 @@ static umf_result_t os_initialize(const void *params, void **provider) {
561578 snprintf (os_provider -> name , sizeof (os_provider -> name ), "%s" ,
562579 in_params -> name );
563580
581+ #if defined(_WIN32 ) || defined(__APPLE__ )
582+
583+ //struct timespec ts_init_start, ts_init_end;
584+ //clock_gettime(CLOCK_MONOTONIC, &ts_init_start);
585+
564586 int r = hwloc_topology_init (& os_provider -> topo );
565587 if (r ) {
566588 LOG_ERR ("HWLOC topology init failed" );
@@ -577,6 +599,13 @@ static umf_result_t os_initialize(const void *params, void **provider) {
577599 goto err_destroy_hwloc_topology ;
578600 }
579601
602+ //clock_gettime(CLOCK_MONOTONIC, &ts_init_end);
603+ //LOG_FATAL("HWLOC topology initialized in %ld.%09ld seconds",
604+ // ts_init_end.tv_sec - ts_init_start.tv_sec,
605+ // ts_init_end.tv_nsec - ts_init_start.tv_nsec);
606+
607+ #endif // _WIN32
608+
580609 os_provider -> fd_offset_map = critnib_new (NULL , NULL );
581610 if (!os_provider -> fd_offset_map ) {
582611 LOG_ERR ("creating file descriptor offset map failed" );
@@ -625,8 +654,11 @@ static umf_result_t os_initialize(const void *params, void **provider) {
625654err_destroy_critnib :
626655 critnib_delete (os_provider -> fd_offset_map );
627656err_destroy_hwloc_topology :
657+
658+ #if defined(_WIN32 ) || defined(__APPLE__ )
628659 hwloc_topology_destroy (os_provider -> topo );
629660err_free_os_provider :
661+ #endif
630662 umf_ba_global_free (os_provider );
631663 return ret ;
632664}
@@ -649,7 +681,10 @@ static umf_result_t os_finalize(void *provider) {
649681 if (os_provider -> nodeset_str_buf ) {
650682 umf_ba_global_free (os_provider -> nodeset_str_buf );
651683 }
684+
685+ #if defined(_WIN32 ) || defined(__APPLE__ )
652686 hwloc_topology_destroy (os_provider -> topo );
687+ #endif
653688 umf_ba_global_free (os_provider );
654689 return UMF_RESULT_SUCCESS ;
655690}
@@ -1012,10 +1047,52 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment,
10121047
10131048 do {
10141049 errno = 0 ;
1050+ ret = 0 ;
1051+
1052+ #if defined(_WIN32 ) || defined(__APPLE__ )
10151053 ret = hwloc_set_area_membind (os_provider -> topo , membind .addr ,
10161054 membind .bind_size , membind .bitmap ,
10171055 os_provider -> numa_policy ,
10181056 os_provider -> numa_flags );
1057+ #else // !_WIN32 && !_APPLE__
1058+
1059+ // NOTE: could we done this
1060+
1061+ // on Linux, use mbind syscall directly instead of hwloc
1062+ unsigned long nodemask = 0 ;
1063+ int maxnode = 8 * sizeof (nodemask ); // up to 64 nodes
1064+ if (membind .bitmap ) {
1065+ for (int i = 0 ; i < maxnode ; ++ i ) {
1066+ if (hwloc_bitmap_isset (membind .bitmap , i )) {
1067+ nodemask |= (1UL << i );
1068+ }
1069+ }
1070+ }
1071+
1072+ int mbind_mode = MPOL_DEFAULT ;
1073+ if (os_provider -> mode == UMF_NUMA_MODE_INTERLEAVE &&
1074+ os_provider -> dedicated == 0 ) {
1075+ mbind_mode = MPOL_INTERLEAVE ;
1076+ } else if (os_provider -> mode == UMF_NUMA_MODE_SPLIT ) {
1077+ mbind_mode = MPOL_BIND ;
1078+ } else if (os_provider -> mode == UMF_NUMA_MODE_LOCAL ) {
1079+ mbind_mode = MPOL_LOCAL ;
1080+ nodemask = 0 ;
1081+ } else if (os_provider -> mode == UMF_NUMA_MODE_PREFERRED ) {
1082+ mbind_mode = MPOL_BIND ;
1083+ } else if (os_provider -> mode == UMF_NUMA_MODE_BIND ||
1084+ os_provider -> dedicated ) {
1085+ mbind_mode = MPOL_BIND ;
1086+ }
1087+
1088+ unsigned long mbind_flags = 0 ;
1089+ if (os_provider -> dedicated ) {
1090+ mbind_flags |= MPOL_MF_STRICT ;
1091+ }
1092+
1093+ ret = syscall (__NR_mbind , membind .addr , membind .bind_size ,
1094+ mbind_mode , & nodemask , maxnode , mbind_flags );
1095+ #endif // !_WIN32 && !_APPLE__
10191096
10201097 if (ret ) {
10211098 os_store_last_native_error (UMF_OS_RESULT_ERROR_BIND_FAILED ,
0 commit comments