comparison src/os/linux/vm/os_linux.cpp @ 462:85f1b9537f70

6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus() Summary: In os::Linux::rebuild_cpu_to_node_map() fix the size of the CPU bitmap. Fixed arithmetic in MutableNUMASpace::adaptive_chunk_size() that could cause overflows and underflows of the chunk_size variable. Reviewed-by: apetrusenko
author iveresov
date Wed, 03 Dec 2008 14:18:57 -0800
parents 1ee8caae33af
children 24fda36852ce
comparison
equal deleted inserted replaced
457:27a80744a83b 462:85f1b9537f70
2270 2270
2271 void os::free_memory(char *addr, size_t bytes) { 2271 void os::free_memory(char *addr, size_t bytes) {
2272 uncommit_memory(addr, bytes); 2272 uncommit_memory(addr, bytes);
2273 } 2273 }
2274 2274
2275 void os::numa_make_global(char *addr, size_t bytes) { } 2275 void os::numa_make_global(char *addr, size_t bytes) {
2276 Linux::numa_interleave_memory(addr, bytes);
2277 }
2276 2278
2277 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { 2279 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
2278 Linux::numa_tonode_memory(addr, bytes, lgrp_hint); 2280 Linux::numa_tonode_memory(addr, bytes, lgrp_hint);
2279 } 2281 }
2280 2282
2312 } 2314 }
2313 2315
2314 extern "C" void numa_warn(int number, char *where, ...) { } 2316 extern "C" void numa_warn(int number, char *where, ...) { }
2315 extern "C" void numa_error(char *where) { } 2317 extern "C" void numa_error(char *where) { }
2316 2318
2317 void os::Linux::libnuma_init() { 2319 bool os::Linux::libnuma_init() {
2318 // sched_getcpu() should be in libc. 2320 // sched_getcpu() should be in libc.
2319 set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, 2321 set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
2320 dlsym(RTLD_DEFAULT, "sched_getcpu"))); 2322 dlsym(RTLD_DEFAULT, "sched_getcpu")));
2321 2323
2322 if (sched_getcpu() != -1) { // Does it work? 2324 if (sched_getcpu() != -1) { // Does it work?
2328 dlsym(handle, "numa_max_node"))); 2330 dlsym(handle, "numa_max_node")));
2329 set_numa_available(CAST_TO_FN_PTR(numa_available_func_t, 2331 set_numa_available(CAST_TO_FN_PTR(numa_available_func_t,
2330 dlsym(handle, "numa_available"))); 2332 dlsym(handle, "numa_available")));
2331 set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t, 2333 set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
2332 dlsym(handle, "numa_tonode_memory"))); 2334 dlsym(handle, "numa_tonode_memory")));
2335 set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
2336 dlsym(handle, "numa_interleave_memory")));
2337
2338
2333 if (numa_available() != -1) { 2339 if (numa_available() != -1) {
2340 set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes"));
2334 // Create a cpu -> node mapping 2341 // Create a cpu -> node mapping
2335 _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true); 2342 _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
2336 rebuild_cpu_to_node_map(); 2343 rebuild_cpu_to_node_map();
2344 return true;
2337 } 2345 }
2338 } 2346 }
2339 } 2347 }
2348 return false;
2340 } 2349 }
2341 2350
2342 // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id. 2351 // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
2343 // The table is later used in get_node_by_cpu(). 2352 // The table is later used in get_node_by_cpu().
2344 void os::Linux::rebuild_cpu_to_node_map() { 2353 void os::Linux::rebuild_cpu_to_node_map() {
2345 int cpu_num = os::active_processor_count(); 2354 const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
2355 // in libnuma (possible values are starting from 16,
2356 // and continuing up with every other power of 2, but less
2357 // than the maximum number of CPUs supported by kernel), and
2358 // is a subject to change (in libnuma version 2 the requirements
2359 // are more reasonable) we'll just hardcode the number they use
2360 // in the library.
2361 const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
2362
2363 size_t cpu_num = os::active_processor_count();
2364 size_t cpu_map_size = NCPUS / BitsPerCLong;
2365 size_t cpu_map_valid_size =
2366 MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
2367
2346 cpu_to_node()->clear(); 2368 cpu_to_node()->clear();
2347 cpu_to_node()->at_grow(cpu_num - 1); 2369 cpu_to_node()->at_grow(cpu_num - 1);
2348 int node_num = numa_get_groups_num(); 2370 size_t node_num = numa_get_groups_num();
2349 int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong; 2371
2350 unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size); 2372 unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
2351 for (int i = 0; i < node_num; i++) { 2373 for (size_t i = 0; i < node_num; i++) {
2352 if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) { 2374 if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
2353 for (int j = 0; j < cpu_map_size; j++) { 2375 for (size_t j = 0; j < cpu_map_valid_size; j++) {
2354 if (cpu_map[j] != 0) { 2376 if (cpu_map[j] != 0) {
2355 for (int k = 0; k < BitsPerLong; k++) { 2377 for (size_t k = 0; k < BitsPerCLong; k++) {
2356 if (cpu_map[j] & (1UL << k)) { 2378 if (cpu_map[j] & (1UL << k)) {
2357 cpu_to_node()->at_put(j * BitsPerLong + k, i); 2379 cpu_to_node()->at_put(j * BitsPerCLong + k, i);
2358 } 2380 }
2359 } 2381 }
2360 } 2382 }
2361 } 2383 }
2362 } 2384 }
2375 os::Linux::sched_getcpu_func_t os::Linux::_sched_getcpu; 2397 os::Linux::sched_getcpu_func_t os::Linux::_sched_getcpu;
2376 os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus; 2398 os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus;
2377 os::Linux::numa_max_node_func_t os::Linux::_numa_max_node; 2399 os::Linux::numa_max_node_func_t os::Linux::_numa_max_node;
2378 os::Linux::numa_available_func_t os::Linux::_numa_available; 2400 os::Linux::numa_available_func_t os::Linux::_numa_available;
2379 os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory; 2401 os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory;
2380 2402 os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
2403 unsigned long* os::Linux::_numa_all_nodes;
2381 2404
2382 bool os::uncommit_memory(char* addr, size_t size) { 2405 bool os::uncommit_memory(char* addr, size_t size) {
2383 return ::mmap(addr, size, 2406 return ::mmap(addr, size,
2384 PROT_READ|PROT_WRITE|PROT_EXEC, 2407 PROT_READ|PROT_WRITE|PROT_EXEC,
2385 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0) 2408 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0)
3693 Linux::glibc_version(), Linux::libpthread_version(), 3716 Linux::glibc_version(), Linux::libpthread_version(),
3694 Linux::is_floating_stack() ? "floating stack" : "fixed stack"); 3717 Linux::is_floating_stack() ? "floating stack" : "fixed stack");
3695 } 3718 }
3696 3719
3697 if (UseNUMA) { 3720 if (UseNUMA) {
3698 Linux::libnuma_init(); 3721 if (!Linux::libnuma_init()) {
3722 UseNUMA = false;
3723 } else {
3724 if ((Linux::numa_max_node() < 1)) {
3725 // There's only one node(they start from 0), disable NUMA.
3726 UseNUMA = false;
3727 }
3728 }
3729 if (!UseNUMA && ForceNUMA) {
3730 UseNUMA = true;
3731 }
3699 } 3732 }
3700 3733
3701 if (MaxFDLimit) { 3734 if (MaxFDLimit) {
3702 // set the number of file descriptors to max. print out error 3735 // set the number of file descriptors to max. print out error
3703 // if getrlimit/setrlimit fails but continue regardless. 3736 // if getrlimit/setrlimit fails but continue regardless.