diff -r 5dddd195cc86 -r b46d9f19bde2 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Mon Dec 01 23:25:24 2008 -0800 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Dec 03 14:18:57 2008 -0800 @@ -2272,7 +2272,9 @@ uncommit_memory(addr, bytes); } -void os::numa_make_global(char *addr, size_t bytes) { } +void os::numa_make_global(char *addr, size_t bytes) { + Linux::numa_interleave_memory(addr, bytes); +} void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { Linux::numa_tonode_memory(addr, bytes, lgrp_hint); @@ -2314,7 +2316,7 @@ extern "C" void numa_warn(int number, char *where, ...) { } extern "C" void numa_error(char *where) { } -void os::Linux::libnuma_init() { +bool os::Linux::libnuma_init() { // sched_getcpu() should be in libc. set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, dlsym(RTLD_DEFAULT, "sched_getcpu"))); @@ -2330,31 +2332,51 @@ dlsym(handle, "numa_available"))); set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t, dlsym(handle, "numa_tonode_memory"))); + set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t, + dlsym(handle, "numa_interleave_memory"))); + + if (numa_available() != -1) { + set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes")); // Create a cpu -> node mapping _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray(0, true); rebuild_cpu_to_node_map(); + return true; } } } + return false; } // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id. // The table is later used in get_node_by_cpu(). void os::Linux::rebuild_cpu_to_node_map() { - int cpu_num = os::active_processor_count(); + const size_t NCPUS = 32768; // Since the buffer size computation is very obscure + // in libnuma (possible values are starting from 16, + // and continuing up with every other power of 2, but less + // than the maximum number of CPUs supported by kernel), and + // is a subject to change (in libnuma version 2 the requirements + // are more reasonable) we'll just hardcode the number they use + // in the library. + const size_t BitsPerCLong = sizeof(long) * CHAR_BIT; + + size_t cpu_num = os::active_processor_count(); + size_t cpu_map_size = NCPUS / BitsPerCLong; + size_t cpu_map_valid_size = + MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size); + cpu_to_node()->clear(); cpu_to_node()->at_grow(cpu_num - 1); - int node_num = numa_get_groups_num(); - int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong; + size_t node_num = numa_get_groups_num(); + unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size); - for (int i = 0; i < node_num; i++) { + for (size_t i = 0; i < node_num; i++) { if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) { - for (int j = 0; j < cpu_map_size; j++) { + for (size_t j = 0; j < cpu_map_valid_size; j++) { if (cpu_map[j] != 0) { - for (int k = 0; k < BitsPerLong; k++) { + for (size_t k = 0; k < BitsPerCLong; k++) { if (cpu_map[j] & (1UL << k)) { - cpu_to_node()->at_put(j * BitsPerLong + k, i); + cpu_to_node()->at_put(j * BitsPerCLong + k, i); } } } @@ -2377,7 +2399,8 @@ os::Linux::numa_max_node_func_t os::Linux::_numa_max_node; os::Linux::numa_available_func_t os::Linux::_numa_available; os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory; - +os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory; +unsigned long* os::Linux::_numa_all_nodes; bool os::uncommit_memory(char* addr, size_t size) { return ::mmap(addr, size, @@ -3695,7 +3718,17 @@ } if (UseNUMA) { - Linux::libnuma_init(); + if (!Linux::libnuma_init()) { + UseNUMA = false; + } else { + if ((Linux::numa_max_node() < 1)) { + // There's only one node(they start from 0), disable NUMA. + UseNUMA = false; + } + } + if (!UseNUMA && ForceNUMA) { + UseNUMA = true; + } } if (MaxFDLimit) {