Skip to content

Commit 5ae00b9

Browse files
committed
Improve Linux NUMA init
- Add debug logging so that failure to initialise can be narrowed down. - Fail to initialise Linux NUMA support if a core is not mapped to a NUMA node or it is mapped to more than 1 node. - Properly handle distances of 1-9, which are reserved and have no meaning by using OSNuma#NUMA_DISTANCE_CANNOT_DETERMINE. Also, adjust OSNuma#getNumaDistance to return OSNuma#NUMA_DISTANCE_CANNOT_DETERMINE when the node numbers are out of bounds.
1 parent 0ace281 commit 5ae00b9

2 files changed

Lines changed: 34 additions & 8 deletions

File tree

src/main/java/ca/spottedleaf/concurrentutil/numa/LinuxNuma.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
import com.sun.jna.*;
44
import com.sun.jna.ptr.ByReference;
55
import com.sun.jna.ptr.IntByReference;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
68
import java.util.Arrays;
79

810
public final class LinuxNuma extends OSNuma.PreCalculatedNuma {
911

12+
private static final Logger LOGGER = LoggerFactory.getLogger(LinuxNuma.class);
13+
1014
private static final ThreadLocal<IntByReference> CURRENT_CORE_POINTER = ThreadLocal.withInitial(IntByReference::new);
1115
private static final boolean LIBRARIES_AVAILABLE;
1216
static {
@@ -19,8 +23,11 @@ public final class LinuxNuma extends OSNuma.PreCalculatedNuma {
1923

2024
if (!librariesOk) {
2125
LIBRARIES_AVAILABLE = false;
26+
LOGGER.debug("Unable to link NUMA libraries for Linux NUMA");
2227
} else {
23-
LIBRARIES_AVAILABLE = LibNuma.numa_available() >= 0;
28+
final int numaAvail = LibNuma.numa_available();
29+
LIBRARIES_AVAILABLE = numaAvail >= 0;
30+
LOGGER.debug("libnuma numa_available: " + numaAvail);
2431
}
2532
}
2633
public static final LinuxNuma INSTANCE;
@@ -34,15 +41,19 @@ public final class LinuxNuma extends OSNuma.PreCalculatedNuma {
3441
try {
3542
if (cpuMask == null) {
3643
INSTANCE = null;
44+
LOGGER.debug("Failed to create Linux NUMA CPU mapping: Failed to allocate cpu mask for libnuma");
3745
} else {
3846
final int totalCpus = LibNuma.numa_num_possible_cpus();
3947

40-
int[] coreToNuma = new int[0];
48+
int[] coreToNuma = new int[totalCpus];
49+
Arrays.fill(coreToNuma, -1);
50+
core_to_numa_setup:
4151
for (int node = 0; node < totalNumaNodes; ++node) {
4252
LibNuma.numa_bitmask_clearall(cpuMask);
4353
final int res = LibNuma.numa_node_to_cpus(node, cpuMask);
4454
if (res != 0) {
4555
// failed
56+
LOGGER.debug("Failed to create Linux NUMA CPU mapping: Failed libnuma numa_node_to_cpus(" + node + ", ...): " + res);
4657
coreToNuma = null;
4758
break;
4859
}
@@ -53,10 +64,22 @@ public final class LinuxNuma extends OSNuma.PreCalculatedNuma {
5364
// not set
5465
continue;
5566
}
67+
if (coreToNuma[cpu] != -1) {
68+
LOGGER.debug("Failed to create Linux NUMA CPU mapping: Duplicate node mapping for core " + cpu + ": " + coreToNuma[cpu] + " and " + node);
69+
coreToNuma = null;
70+
break core_to_numa_setup;
71+
}
5672
// it is set, so mark it in the core mapping
57-
if (coreToNuma.length <= cpu) {
58-
coreToNuma = Arrays.copyOf(coreToNuma, cpu + 1);
59-
coreToNuma[cpu] = node;
73+
coreToNuma[cpu] = node;
74+
}
75+
}
76+
if (coreToNuma != null) {
77+
for (int cpu = 0; cpu < coreToNuma.length; ++cpu) {
78+
final int node = coreToNuma[cpu];
79+
if (node == -1) {
80+
LOGGER.debug("Failed to create Linux NUMA CPU mapping: No node mapping for core " + cpu);
81+
coreToNuma = null;
82+
break;
6083
}
6184
}
6285
}
@@ -66,7 +89,8 @@ public final class LinuxNuma extends OSNuma.PreCalculatedNuma {
6689
for (int j = 0; j < totalNumaNodes; ++j) {
6790
final int dist = LibNuma.numa_distance(i, j);
6891
// distance is 0 when it cannot be determined
69-
costArray[i][j] = dist <= 0 ? 255 : dist;
92+
// distances 1-9 are reserved and have no meaning
93+
costArray[i][j] = dist < 10 ? OSNuma.NUMA_DISTANCE_CANNOT_DETERMINE : dist;
7094
}
7195
}
7296

src/main/java/ca/spottedleaf/concurrentutil/numa/OSNuma.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
public interface OSNuma {
77

8+
public static int NUMA_DISTANCE_CANNOT_DETERMINE = 255;
9+
810
public static OSNuma getNativeInstance() {
911
final LinuxNuma linux = LinuxNuma.INSTANCE;
1012
if (linux != null && linux.isAvailable()) {
@@ -164,12 +166,12 @@ public PreCalculatedNuma(final int[] coreToNuma, final int[][] costArray) {
164166
public int getNumaDistance(final int n1, final int n2) {
165167
if (n1 < 0 || n1 >= this.costArray.length) {
166168
// cannot determine
167-
return 0;
169+
return NUMA_DISTANCE_CANNOT_DETERMINE;
168170
}
169171
final int[] distances = this.costArray[n1];
170172
if (n2 < 0 || n2 >= distances.length) {
171173
// cannot determine
172-
return 0;
174+
return NUMA_DISTANCE_CANNOT_DETERMINE;
173175
}
174176
return distances[n2];
175177
}

0 commit comments

Comments
 (0)