void* mmap_1g(void* addr /* = nullptr */, int node /* = -1 */) { #ifdef __linux__ if (s_num1GPages >= kMaxNum1GPages) return nullptr; if (get_huge1g_info(node).free_hugepages <= 0) return nullptr; if (node >= 0 && !numa_node_allowed(node)) return nullptr; #ifdef HAVE_NUMA bitmask* memMask = nullptr; bitmask* interleaveMask = nullptr; if (node >= 0 && numa_num_nodes > 1) { memMask = numa_get_membind(); interleaveMask = numa_get_interleave_mask(); bitmask* mask = numa_allocate_nodemask(); numa_bitmask_setbit(mask, node); numa_set_membind(mask); numa_bitmask_free(mask); } #endif void* ret = mmap_1g_impl(addr); if (ret != nullptr) { s_1GPages[s_num1GPages++] = ret; } #ifdef HAVE_NUMA if (memMask) { assert(interleaveMask); numa_set_membind(memMask); numa_set_interleave_mask(interleaveMask); numa_bitmask_free(memMask); numa_bitmask_free(interleaveMask); } #endif return ret; #else return nullptr; #endif }
static int memkind_regular_finalize(memkind_t kind) { if(regular_nodes_mask) numa_bitmask_free(regular_nodes_mask); return memkind_arena_finalize(kind); }
/** * mem_alloc_pages_onnode - allocates pages on a given numa node * @nr: the number of pages * @size: the page size (4KB, 2MB, or 1GB) * @numa_node: the numa node to allocate the pages from * @numa_policy: how strictly to take @numa_node * * Returns a pointer (virtual address) to a page or NULL if fail. */ void *mem_alloc_pages_onnode(int nr, int size, int node, int numa_policy) { void *vaddr; struct bitmask *mask = numa_allocate_nodemask(); numa_bitmask_setbit(mask, node); vaddr = mem_alloc_pages(nr, size, mask, numa_policy); numa_bitmask_free(mask); return vaddr; }
void *__mem_alloc_pages_onnode(void *base, int nr, int size, int node) { void *vaddr; struct bitmask *mask = numa_allocate_nodemask(); numa_bitmask_setbit(mask, node); vaddr = __mem_alloc_pages(base, nr, size, mask, MPOL_BIND); numa_bitmask_free(mask); return vaddr; }
///This function tries to fill bandwidth array based on knowledge about known CPU models static int fill_bandwidth_values_heuristically(int* bandwidth, int bandwidth_len) { int ret = MEMKIND_ERROR_UNAVAILABLE; // Default error returned if heuristic aproach fails int i, nodes_num, memory_only_nodes_num = 0; struct bitmask *memory_only_nodes, *node_cpus; if (is_cpu_xeon_phi_x200() == 0) { log_info("Known CPU model detected: Intel(R) Xeon Phi(TM) x200."); nodes_num = numa_num_configured_nodes(); // Check if number of numa-nodes meets expectations for // supported configurations of Intel Xeon Phi x200 if( nodes_num != 2 && nodes_num != 4 && nodes_num!= 8 ) { return ret; } memory_only_nodes = numa_allocate_nodemask(); node_cpus = numa_allocate_cpumask(); for(i=0; i<nodes_num; i++) { numa_node_to_cpus(i, node_cpus); if(numa_bitmask_weight(node_cpus) == 0) { memory_only_nodes_num++; numa_bitmask_setbit(memory_only_nodes, i); } } // Check if number of memory-only nodes is equal number of memory+cpu nodes // If it passes change ret to 0 (success) and fill bw table if ( memory_only_nodes_num == (nodes_num - memory_only_nodes_num) ) { ret = 0; assign_arbitrary_bandwidth_values(bandwidth, bandwidth_len, memory_only_nodes); } numa_bitmask_free(memory_only_nodes); numa_bitmask_free(node_cpus); } return ret; }
static void regular_nodes_init(void) { int i, node = 0, nodes_num = numa_num_configured_nodes(); struct bitmask *node_cpus = numa_allocate_cpumask(); regular_nodes_mask = numa_allocate_nodemask(); for (i = 0; i < nodes_num; i++) { numa_node_to_cpus(node, node_cpus); if (numa_bitmask_weight(node_cpus)) numa_bitmask_setbit(regular_nodes_mask, i); } numa_bitmask_free(node_cpus); }
void* mmap_2m(void* addr, int prot, int node /* = -1 */, bool map_shared /* = false */, bool map_fixed /* = false */) { #ifdef __linux__ if (get_huge2m_info(node).free_hugepages <= 0) return nullptr; #ifdef HAVE_NUMA bitmask* memMask = nullptr; bitmask* interleaveMask = nullptr; if (node >= 0 && numa_num_nodes > 1) { assert(numa_node_set != 0); if ((numa_node_set & (1u << node)) == 0) { // Numa policy forbids allocation on the node. return nullptr; } memMask = numa_get_membind(); interleaveMask = numa_get_interleave_mask(); bitmask* mask = numa_allocate_nodemask(); numa_bitmask_setbit(mask, node); numa_set_membind(mask); numa_bitmask_free(mask); } #endif void* ret = mmap_2m_impl(addr, prot, map_shared, map_fixed); s_num2MPages += !!ret; #ifdef HAVE_NUMA if (memMask) { numa_set_membind(memMask); numa_set_interleave_mask(interleaveMask); numa_bitmask_free(memMask); numa_bitmask_free(interleaveMask); } #endif return ret; #else // not linux return nullptr; #endif }
static int fill_bandwidth_values_from_enviroment(int* bandwidth, int bandwidth_len, char *hbw_nodes_env) { struct bitmask *hbw_nodes_bm = numa_parse_nodestring(hbw_nodes_env); if (!hbw_nodes_bm) { log_err("Wrong MEMKIND_HBW_NODES environment value."); return MEMKIND_ERROR_ENVIRON; } else { assign_arbitrary_bandwidth_values(bandwidth, bandwidth_len, hbw_nodes_bm); numa_bitmask_free(hbw_nodes_bm); } return 0; }
int bind_cpu(int cpu) { cpu_set_t *cmask; struct bitmask *bmask; size_t ncpu, setsize; int ret; ncpu = get_num_cpus(); if (cpu < 0 || cpu >= (int)ncpu) { errno = -EINVAL; return -1; } cmask = CPU_ALLOC(ncpu); if (cmask == NULL) return -1; setsize = CPU_ALLOC_SIZE(ncpu); CPU_ZERO_S(setsize, cmask); CPU_SET_S(cpu, setsize, cmask); ret = sched_setaffinity(0, ncpu, cmask); CPU_FREE(cmask); /* skip NUMA stuff for UMA systems */ if (numa_max_node() == 0) return ret; bmask = numa_bitmask_alloc(16); assert(bmask); numa_bitmask_setbit(bmask, cpu % 2); numa_set_membind(bmask); numa_bitmask_free(bmask); return ret; }
int fire_worker_init(fire_worker_context_t *context) { buffer[context->queue_id] = (char *)malloc(buf_size); /* init worker struct */ fire_worker_t *cc = &(workers[context->queue_id]); cc->total_packets = 0; cc->total_bytes = 0; /* nids init */ nids_init(context->core_id); #if !defined(AFFINITY_NO) /* set schedule affinity */ unsigned long mask = 1 << context->core_id; if (sched_setaffinity(0, sizeof(unsigned long), (cpu_set_t *)&mask) < 0) { assert(0); } /* set schedule policy */ struct sched_param param; param.sched_priority = 99; pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); #endif if (numa_max_node() == 0) return 0; struct bitmask *bmask; bmask = numa_bitmask_alloc(16); assert(bmask); numa_bitmask_setbit(bmask, context->core_id % 2); numa_set_membind(bmask); numa_bitmask_free(bmask); return 0; }
void myhbwmalloc_init(void) { /* set to NULL before trying to initialize. if we return before * successful creation of the mspace, then it will still be NULL, * and we can use that in subsequent library calls to determine * that the library failed to initialize. */ myhbwmalloc_mspace = NULL; /* verbose printout? */ myhbwmalloc_verbose = 0; { char * env_char = getenv("HBWMALLOC_VERBOSE"); if (env_char != NULL) { myhbwmalloc_verbose = 1; printf("hbwmalloc: HBWMALLOC_VERBOSE set\n"); } } /* fail hard or soft? */ myhbwmalloc_hardfail = 1; { char * env_char = getenv("HBWMALLOC_SOFTFAIL"); if (env_char != NULL) { myhbwmalloc_hardfail = 0; printf("hbwmalloc: HBWMALLOC_SOFTFAIL set\n"); } } /* set the atexit handler that will destroy the mspace and free the numa allocation */ atexit(myhbwmalloc_final); /* detect and configure use of NUMA memory nodes */ { int max_possible_node = numa_max_possible_node(); int num_possible_nodes = numa_num_possible_nodes(); int max_numa_nodes = numa_max_node(); int num_configured_nodes = numa_num_configured_nodes(); int num_configured_cpus = numa_num_configured_cpus(); if (myhbwmalloc_verbose) { printf("hbwmalloc: numa_max_possible_node() = %d\n", max_possible_node); printf("hbwmalloc: numa_num_possible_nodes() = %d\n", num_possible_nodes); printf("hbwmalloc: numa_max_node() = %d\n", max_numa_nodes); printf("hbwmalloc: numa_num_configured_nodes() = %d\n", num_configured_nodes); printf("hbwmalloc: numa_num_configured_cpus() = %d\n", num_configured_cpus); } /* FIXME this is a hack. assumes HBW is only numa node 1. */ if (num_configured_nodes <= 2) { myhbwmalloc_numa_node = num_configured_nodes-1; } else { fprintf(stderr,"hbwmalloc: we support only 2 numa nodes, not %d\n", num_configured_nodes); } if (myhbwmalloc_verbose) { for (int i=0; i<num_configured_nodes; i++) { unsigned max_numa_cpus = numa_num_configured_cpus(); struct bitmask * mask = numa_bitmask_alloc( max_numa_cpus ); int rc = numa_node_to_cpus(i, mask); if (rc != 0) { fprintf(stderr, "hbwmalloc: numa_node_to_cpus failed\n"); } else { printf("hbwmalloc: numa node %d cpu mask:", i); for (unsigned j=0; j<max_numa_cpus; j++) { int bit = numa_bitmask_isbitset(mask,j); printf(" %d", bit); } printf("\n"); } numa_bitmask_free(mask); } fflush(stdout); } } #if 0 /* unused */ /* see if the user specifies a slab size */ size_t slab_size_requested = 0; { char * env_char = getenv("HBWMALLOC_BYTES"); if (env_char!=NULL) { long units = 1L; if ( NULL != strstr(env_char,"G") ) units = 1000000000L; else if ( NULL != strstr(env_char,"M") ) units = 1000000L; else if ( NULL != strstr(env_char,"K") ) units = 1000L; else units = 1L; int num_count = strspn(env_char, "0123456789"); memset( &env_char[num_count], ' ', strlen(env_char)-num_count); slab_size_requested = units * atol(env_char); } if (myhbwmalloc_verbose) { printf("hbwmalloc: requested slab_size_requested = %zu\n", slab_size_requested); } } #endif /* see what libnuma says is available */ size_t myhbwmalloc_slab_size; { int node = myhbwmalloc_numa_node; long long freemem; long long maxmem = numa_node_size64(node, &freemem); if (myhbwmalloc_verbose) { printf("hbwmalloc: numa_node_size64 says maxmem=%lld freemem=%lld for numa node %d\n", maxmem, freemem, node); } myhbwmalloc_slab_size = freemem; } /* assume threads, disable if MPI knows otherwise, then allow user to override. */ int multithreaded = 1; #ifdef HAVE_MPI int nprocs; { int is_init, is_final; MPI_Initialized(&is_init); MPI_Finalized(&is_final); if (is_init && !is_final) { MPI_Comm_size(MPI_COMM_WORLD, &nprocs); } /* give equal portion to every MPI process */ myhbwmalloc_slab_size /= nprocs; /* if the user initializes MPI with MPI_Init or * MPI_Init_thread(MPI_THREAD_SINGLE), they assert there * are no threads at all, which means we can skip the * malloc mspace lock. * * if the user lies to MPI, they deserve any bad thing * that comes of it. */ int provided; MPI_Query_thread(&provided); if (provided==MPI_THREAD_SINGLE) { multithreaded = 0; } else { multithreaded = 1; } if (myhbwmalloc_verbose) { printf("hbwmalloc: MPI processes = %d (threaded = %d)\n", nprocs, multithreaded); printf("hbwmalloc: myhbwmalloc_slab_size = %d\n", myhbwmalloc_slab_size); } } #endif /* user can assert that hbwmalloc and friends need not be thread-safe */ { char * env_char = getenv("HBWMALLOC_LOCKLESS"); if (env_char != NULL) { multithreaded = 0; if (myhbwmalloc_verbose) { printf("hbwmalloc: user has disabled locking in mspaces by setting HBWMALLOC_LOCKLESS\n"); } } } myhbwmalloc_slab = numa_alloc_onnode( myhbwmalloc_slab_size, myhbwmalloc_numa_node); if (myhbwmalloc_slab==NULL) { fprintf(stderr, "hbwmalloc: numa_alloc_onnode returned NULL for size = %zu\n", myhbwmalloc_slab_size); return; } else { if (myhbwmalloc_verbose) { printf("hbwmalloc: numa_alloc_onnode succeeded for size %zu\n", myhbwmalloc_slab_size); } /* part (less than 128*sizeof(size_t) bytes) of this space is used for bookkeeping, * so the capacity must be at least this large */ if (myhbwmalloc_slab_size < 128*sizeof(size_t)) { fprintf(stderr, "hbwmalloc: not enough space for mspace bookkeeping\n"); return; } /* see above regarding if the user lies to MPI. */ int locked = multithreaded; myhbwmalloc_mspace = create_mspace_with_base( myhbwmalloc_slab, myhbwmalloc_slab_size, locked); if (myhbwmalloc_mspace == NULL) { fprintf(stderr, "hbwmalloc: create_mspace_with_base returned NULL\n"); return; } else if (myhbwmalloc_verbose) { printf("hbwmalloc: create_mspace_with_base succeeded for size %zu\n", myhbwmalloc_slab_size); } } }
int main(int argc, const char **argv) { int num_cpus = numa_num_task_cpus(); printf("num cpus: %d\n", num_cpus); printf("numa available: %d\n", numa_available()); numa_set_localalloc(); struct bitmask *bm = numa_bitmask_alloc(num_cpus); for (int i=0; i<=numa_max_node(); ++i) { numa_node_to_cpus(i, bm); printf("numa node %d ", i); print_bitmask(bm); printf(" - %g GiB\n", numa_node_size(i, 0) / (1024.*1024*1024.)); } numa_bitmask_free(bm); puts(""); char *x; const size_t cache_line_size = 64; const size_t array_size = 100*1000*1000; size_t ntrips = 2; #pragma omp parallel { assert(omp_get_num_threads() == num_cpus); int tid = omp_get_thread_num(); pin_to_core(tid); if(tid == 0) x = (char *) numa_alloc_local(array_size); // {{{ single access #pragma omp barrier for (size_t i = 0; i<num_cpus; ++i) { if (tid == i) { double t = measure_access(x, array_size, ntrips); printf("sequential core %d -> core 0 : BW %g MB/s\n", i, array_size*ntrips*cache_line_size / t / 1e6); } #pragma omp barrier } // }}} // {{{ everybody contends for one { if (tid == 0) puts(""); #pragma omp barrier double t = measure_access(x, array_size, ntrips); #pragma omp barrier for (size_t i = 0; i<num_cpus; ++i) { if (tid == i) printf("all-contention core %d -> core 0 : BW %g MB/s\n", tid, array_size*ntrips*cache_line_size / t / 1e6); #pragma omp barrier } } // }}} // {{{ zero and someone else contending if (tid == 0) puts(""); #pragma omp barrier for (size_t i = 1; i<num_cpus; ++i) { double t; if (tid == i || tid == 0) t = measure_access(x, array_size, ntrips); #pragma omp barrier if (tid == 0) { printf("two-contention core %d -> core 0 : BW %g MB/s\n", tid, array_size*ntrips*cache_line_size / t / 1e6); } #pragma omp barrier if (tid == i) { printf("two-contention core %d -> core 0 : BW %g MB/s\n\n", tid, array_size*ntrips*cache_line_size / t / 1e6); } #pragma omp barrier } } numa_free(x, array_size); return 0; }
int main(int ac, char **av) { int c, i, nnodes=0; long node=-1; char *end; char shortopts[array_len(opts)*2 + 1]; struct bitmask *mask = NULL; get_short_opts(opts,shortopts); while ((c = getopt_long(ac, av, shortopts, opts, NULL)) != -1) { switch (c) { case 's': /* --show */ show(); exit(0); case 'H': /* --hardware */ nopolicy(); hardware(); exit(0); case 'i': /* --interleave */ checknuma(); mask = numactl_parse_nodestring(optarg); if (!mask) { printf ("<%s> is invalid\n", optarg); usage(); } errno = 0; setpolicy(MPOL_INTERLEAVE); if (shmfd >= 0) numa_interleave_memory(shmptr, shmlen, mask); else numa_set_interleave_mask(mask); checkerror("setting interleave mask"); break; case 'N': /* --cpunodebind */ case 'c': /* --cpubind */ dontshm("-c/--cpubind/--cpunodebind"); checknuma(); mask = numactl_parse_nodestring(optarg); if (!mask) { printf ("<%s> is invalid\n", optarg); usage(); } errno = 0; check_cpubind(do_shm); did_cpubind = 1; numa_run_on_node_mask(mask); checkerror("sched_setaffinity"); break; case 'C': /* --physcpubind */ { struct bitmask *cpubuf; dontshm("-C/--physcpubind"); cpubuf = numa_parse_cpustring(optarg); if (!cpubuf) { printf ("<%s> is invalid\n", optarg); usage(); } errno = 0; check_cpubind(do_shm); did_cpubind = 1; numa_sched_setaffinity(0, cpubuf); checkerror("sched_setaffinity"); free(cpubuf); break; } case 'm': /* --membind */ checknuma(); setpolicy(MPOL_BIND); mask = numactl_parse_nodestring(optarg); if (!mask) { printf ("<%s> is invalid\n", optarg); usage(); } errno = 0; numa_set_bind_policy(1); if (shmfd >= 0) { numa_tonodemask_memory(shmptr, shmlen, mask); } else { numa_set_membind(mask); } numa_set_bind_policy(0); checkerror("setting membind"); break; case 'p': /* --preferred */ checknuma(); setpolicy(MPOL_PREFERRED); mask = numactl_parse_nodestring(optarg); if (!mask) { printf ("<%s> is invalid\n", optarg); usage(); } for (i=0; i<mask->size; i++) { if (numa_bitmask_isbitset(mask, i)) { node = i; nnodes++; } } if (nnodes != 1) usage(); numa_bitmask_free(mask); errno = 0; numa_set_bind_policy(0); if (shmfd >= 0) numa_tonode_memory(shmptr, shmlen, node); else numa_set_preferred(node); checkerror("setting preferred node"); break; case 'l': /* --local */ checknuma(); setpolicy(MPOL_DEFAULT); errno = 0; if (shmfd >= 0) numa_setlocal_memory(shmptr, shmlen); else numa_set_localalloc(); checkerror("local allocation"); break; case 'S': /* --shm */ check_cpubind(did_cpubind); nopolicy(); attach_sysvshm(optarg, "--shm"); shmattached = 1; break; case 'f': /* --file */ check_cpubind(did_cpubind); nopolicy(); attach_shared(optarg, "--file"); shmattached = 1; break; case 'L': /* --length */ noshm("--length"); shmlen = memsize(optarg); break; case 'M': /* --shmmode */ noshm("--shmmode"); shmmode = strtoul(optarg, &end, 8); if (end == optarg || *end) usage(); break; case 'd': /* --dump */ if (shmfd < 0) complain( "Cannot do --dump without shared memory.\n"); dump_shm(); do_dump = 1; break; case 'D': /* --dump-nodes */ if (shmfd < 0) complain( "Cannot do --dump-nodes without shared memory.\n"); dump_shm_nodes(); do_dump = 1; break; case 't': /* --strict */ did_strict = 1; numa_set_strict(1); break; case 'I': /* --shmid */ shmid = strtoul(optarg, &end, 0); if (end == optarg || *end) usage(); break; case 'u': /* --huge */ noshm("--huge"); shmflags |= SHM_HUGETLB; break; case 'o': /* --offset */ noshm("--offset"); shmoffset = memsize(optarg); break; case 'T': /* --touch */ needshm("--touch"); check_shmbeyond("--touch"); numa_police_memory(shmptr, shmlen); break; case 'V': /* --verify */ needshm("--verify"); if (set_policy < 0) complain("Need a policy first to verify"); check_shmbeyond("--verify"); numa_police_memory(shmptr, shmlen); if (!mask) complain("Need a mask to verify"); else verify_shm(set_policy, mask); break; default: usage(); } } av += optind; ac -= optind; if (shmfd >= 0) { if (*av) usage(); exit(exitcode); } if (did_strict) fprintf(stderr, "numactl: warning. Strict flag for process ignored.\n"); if (do_dump) usage_msg("cannot do --dump|--dump-shm for process"); if (shmoption) usage_msg("shm related option %s for process", shmoption); if (*av == NULL) usage(); execvp(*av, av); complain("execution of `%s': %s\n", av[0], strerror(errno)); return 0; /* not reached */ }
void CPU_FreeSet(CPU_Set_t *cs) { numa_bitmask_free(cs); }
size_t remap_interleaved_2m_pages(void* addr, size_t pages, int prot, bool shared /* = false */) { #ifdef __linux__ assert(reinterpret_cast<uintptr_t>(addr) % size2m == 0); assert(addr != nullptr); if (pages == 0) return 0; #ifdef HAVE_NUMA const int maxNode = numa_max_node(); bitmask* memMask = nullptr; bitmask* interleaveMask = nullptr; bitmask* mask = nullptr; if (maxNode > 0) { memMask = numa_get_membind(); interleaveMask = numa_get_interleave_mask(); mask = numa_allocate_nodemask(); } #else constexpr int maxNode = 0; #endif int node = -1; int failed = 0; // consecutive failure count int mapped_count = 0; do { #ifdef HAVE_NUMA if (maxNode > 0) { if (++node > maxNode) node = 0; if (!numa_node_allowed(node)) { // Numa policy forbids allocation on node if (++failed > maxNode) break; continue; } numa_bitmask_setbit(mask, node); numa_set_membind(mask); numa_bitmask_clearbit(mask, node); } #endif // Fail early if we don't have huge pages reserved. if (get_huge2m_info(node).free_hugepages > 0 && mmap_2m_impl(addr, prot, shared, true /* MAP_FIXED */)) { addr = (char*)addr + size2m; ++mapped_count; failed = 0; continue; } // We failed on node, give up if we have failed on all nodes if (++failed > maxNode) break; } while (mapped_count < pages); #ifdef HAVE_NUMA if (mask) { numa_set_membind(memMask); numa_set_interleave_mask(interleaveMask); numa_bitmask_free(mask); numa_bitmask_free(interleaveMask); numa_bitmask_free(memMask); } #endif return mapped_count; #else // not linux return 0; #endif }
static void memkind_hbw_closest_numanode_init(void) { struct memkind_hbw_closest_numanode_t *g = &memkind_hbw_closest_numanode_g; int *bandwidth = NULL; int num_unique = 0; int high_bandwidth = 0; int node; struct bandwidth_nodes_t *bandwidth_nodes = NULL; char *hbw_nodes_env; struct bitmask *hbw_nodes_bm; g->num_cpu = numa_num_configured_cpus(); g->closest_numanode = (int *)je_malloc(sizeof(int) * g->num_cpu); bandwidth = (int *)je_malloc(sizeof(int) * NUMA_NUM_NODES); if (!(g->closest_numanode && bandwidth)) { g->init_err = MEMKIND_ERROR_MALLOC; } if (!g->init_err) { hbw_nodes_env = getenv("MEMKIND_HBW_NODES"); if (hbw_nodes_env) { hbw_nodes_bm = numa_parse_nodestring(hbw_nodes_env); if (!hbw_nodes_bm) { g->init_err = MEMKIND_ERROR_ENVIRON; } else { for (node = 0; node < NUMA_NUM_NODES; ++node) { if (numa_bitmask_isbitset(hbw_nodes_bm, node)) { bandwidth[node] = 2; } else { bandwidth[node] = 1; } } numa_bitmask_free(hbw_nodes_bm); } } else { g->init_err = parse_node_bandwidth(NUMA_NUM_NODES, bandwidth, MEMKIND_BANDWIDTH_PATH); } } if (!g->init_err) { g->init_err = create_bandwidth_nodes(NUMA_NUM_NODES, bandwidth, &num_unique, &bandwidth_nodes); } if (!g->init_err) { if (num_unique == 1) { g->init_err = MEMKIND_ERROR_UNAVAILABLE; } } if (!g->init_err) { high_bandwidth = bandwidth_nodes[num_unique-1].bandwidth; g->init_err = set_closest_numanode(num_unique, bandwidth_nodes, high_bandwidth, g->num_cpu, g->closest_numanode); } if (bandwidth_nodes) { je_free(bandwidth_nodes); } if (bandwidth) { je_free(bandwidth); } if (g->init_err) { if (g->closest_numanode) { je_free(g->closest_numanode); g->closest_numanode = NULL; } } }
/*----------------------------------------------------------------------------*/ int mtcp_core_affinitize(int cpu) { #ifndef DISABLE_NUMA struct bitmask *bmask; #endif /* DISABLE_NUMA */ cpu_set_t cpus; FILE *fp; char sysfname[MAX_FILE_NAME]; int phy_id; size_t n; int ret; n = GetNumCPUs(); if (cpu < 0 || cpu >= (int) n) { errno = -EINVAL; return -1; } CPU_ZERO(&cpus); CPU_SET((unsigned)cpu, &cpus); ret = sched_setaffinity(Gettid(), sizeof(cpus), &cpus); #ifndef DISABLE_NUMA if (numa_max_node() == 0) return ret; bmask = numa_bitmask_alloc(n); assert(bmask); #endif /* DISABLE_NUMA */ /* read physical id of the core from sys information */ snprintf(sysfname, MAX_FILE_NAME - 1, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); fp = fopen(sysfname, "r"); if (!fp) { perror(sysfname); errno = EFAULT; return -1; } ret = fscanf(fp, "%d", &phy_id); if (ret != 1) { perror("Fail to read core id"); errno = EFAULT; return -1; } #ifndef DISABLE_NUMA numa_bitmask_setbit(bmask, phy_id); numa_set_membind(bmask); numa_bitmask_free(bmask); #endif /* DISABLE_NUMA */ fclose(fp); return ret; }