Mercurial > hg > truffle
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. |