Skip to content

Commit 422fcfc

Browse files
authored
Merge pull request OpenHFT#180 from OpenHFT/acquireCore-fix
AffinityLock.acquireCore should lock/unlock all cpus ie 2 when hypert…
2 parents cf3383a + 61dda34 commit 422fcfc

20 files changed

+305
-75
lines changed

affinity/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@
110110
<profile>
111111
<id>make-c</id>
112112
<activation>
113+
<os>
114+
<family>linux</family>
115+
<arch>!arm</arch>
116+
</os>
113117
<property>
114118
<name>!dontMake</name>
115119
</property>

affinity/src/main/java/net/openhft/affinity/AffinityLock.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public class AffinityLock implements Closeable {
6969
* Logical ID of the CPU to which this lock belongs to.
7070
*/
7171
private final int cpuId;
72+
private final int cpuId2;
7273
/**
7374
* CPU to which this lock belongs to is of general use.
7475
*/
@@ -88,9 +89,10 @@ public class AffinityLock implements Closeable {
8889
Throwable boundHere;
8990
private boolean resetAffinity = true;
9091

91-
AffinityLock(int cpuId, boolean base, boolean reservable, LockInventory lockInventory) {
92+
AffinityLock(int cpuId, int cpuId2, boolean base, boolean reservable, LockInventory lockInventory) {
9293
this.lockInventory = lockInventory;
9394
this.cpuId = cpuId;
95+
this.cpuId2 = cpuId2;
9496
this.base = base;
9597
this.reservable = reservable;
9698
}
@@ -133,7 +135,7 @@ private static BitSet getReservedAffinity0() {
133135
int end = reservedAffinity.length();
134136
for (int i = 0; i < longs.length; i++) {
135137
int begin = Math.max(0, end - 16);
136-
longs[i] = Long.parseLong(reservedAffinity.substring(begin, end), 16);
138+
longs[i] = Long.parseUnsignedLong(reservedAffinity.substring(begin, end), 16);
137139
end = begin;
138140
}
139141
return BitSet.valueOf(longs);
@@ -183,7 +185,7 @@ public static AffinityLock acquireLock(boolean bind) {
183185
* for defining your thread layout centrally and passing the handle via dependency injection.
184186
*
185187
* @param cpuId the CPU id to bind to
186-
* @return A handle for an affinity lock.
188+
* @return A handle for an affinity lock, or no lock if no available CPU in the array
187189
*/
188190
public static AffinityLock acquireLock(int cpuId) {
189191
if (isInvalidCpuId(cpuId))
@@ -474,6 +476,10 @@ public int cpuId() {
474476
return cpuId;
475477
}
476478

479+
public int cpuId2() {
480+
return cpuId2;
481+
}
482+
477483
/**
478484
* @return Was a cpu found to bind this lock to.
479485
*/

affinity/src/main/java/net/openhft/affinity/BootClassPath.java

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
2323

24+
import java.io.File;
2425
import java.io.IOException;
26+
import java.net.URI;
2527
import java.nio.file.*;
2628
import java.nio.file.attribute.BasicFileAttributes;
2729
import java.util.Collections;
@@ -39,21 +41,56 @@ enum BootClassPath {
3941
private static Set<String> getResourcesOnBootClasspath() {
4042
final Logger logger = LoggerFactory.getLogger(BootClassPath.class);
4143
final Set<String> resources = new HashSet<>();
44+
4245
final String bootClassPath = System.getProperty("sun.boot.class.path", "");
43-
logger.trace("Boot class-path is: {}", bootClassPath);
46+
if (!bootClassPath.isEmpty()) {
47+
logger.trace("Boot class-path is: {}", bootClassPath);
4448

45-
final String pathSeparator = System.getProperty("path.separator");
46-
logger.trace("Path separator is: '{}'", pathSeparator);
49+
final String pathSeparator = File.pathSeparator;
50+
logger.trace("Path separator is: '{}'", pathSeparator);
4751

48-
final String[] pathElements = bootClassPath.split(pathSeparator);
52+
final String[] pathElements = bootClassPath.split(pathSeparator);
4953

50-
for (final String pathElement : pathElements) {
51-
resources.addAll(findResources(Paths.get(pathElement), logger));
54+
for (final String pathElement : pathElements) {
55+
resources.addAll(findResources(Paths.get(pathElement), logger));
56+
}
57+
} else {
58+
resources.addAll(findResourcesInJrt(logger));
5259
}
5360

5461
return resources;
5562
}
5663

64+
private static Set<String> findResourcesInJrt(final Logger logger) {
65+
final Set<String> jrtResources = new HashSet<>();
66+
try {
67+
FileSystem fs;
68+
try {
69+
fs = FileSystems.getFileSystem(URI.create("jrt:/"));
70+
} catch (FileSystemNotFoundException | ProviderNotFoundException e) {
71+
fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap());
72+
}
73+
final Path modules = fs.getPath("/modules");
74+
Files.walkFileTree(modules, new SimpleFileVisitor<Path>() {
75+
@Override
76+
public @NotNull FileVisitResult visitFile(final @NotNull Path file,
77+
final @NotNull BasicFileAttributes attrs) throws IOException {
78+
if (file.getFileName().toString().endsWith(".class")) {
79+
Path relative = modules.relativize(file);
80+
if (relative.getNameCount() > 1) {
81+
Path classPath = relative.subpath(1, relative.getNameCount());
82+
jrtResources.add(classPath.toString());
83+
}
84+
}
85+
return FileVisitResult.CONTINUE;
86+
}
87+
});
88+
} catch (IOException e) {
89+
logger.warn("Error walking jrt filesystem", e);
90+
}
91+
return jrtResources;
92+
}
93+
5794
private static Set<String> findResources(final Path path, final Logger logger) {
5895
if (!Files.exists(path)) {
5996
return Collections.emptySet();

affinity/src/main/java/net/openhft/affinity/CpuLayout.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,10 @@ public interface CpuLayout {
4949
* @return which thread on a core this cpu is on.
5050
*/
5151
int threadId(int cpuId);
52+
53+
/**
54+
* @param cpuId the logical processor number
55+
* @return the hyperthreaded pair number or 0 if not hyperthreaded.
56+
*/
57+
int pair(int cpuId);
5258
}

affinity/src/main/java/net/openhft/affinity/LockCheck.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package net.openhft.affinity;
1919

20+
import net.openhft.affinity.impl.Utilities;
2021
import net.openhft.affinity.lockchecker.FileLockBasedLockChecker;
2122
import net.openhft.affinity.lockchecker.LockChecker;
2223
import org.slf4j.Logger;
@@ -39,9 +40,7 @@ public enum LockCheck {
3940
private static final LockChecker lockChecker = FileLockBasedLockChecker.getInstance();
4041

4142
public static long getPID() {
42-
String processName =
43-
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
44-
return Long.parseLong(processName.split("@")[0]);
43+
return Utilities.currentProcessId();
4544
}
4645

4746
static boolean canOSSupportOperation() {
@@ -55,8 +54,8 @@ public static boolean isCpuFree(int cpu) {
5554
return isLockFree(cpu);
5655
}
5756

58-
static boolean replacePid(int cpu, long processID) throws IOException {
59-
return storePid(processID, cpu);
57+
static boolean replacePid(int cpu, int cpu2, long processID) throws IOException {
58+
return storePid(processID, cpu, cpu2);
6059
}
6160

6261
public static boolean isProcessRunning(long pid) {
@@ -70,15 +69,18 @@ public static boolean isProcessRunning(long pid) {
7069
* stores the pid in a file, named by the core, the pid is written to the file with the date
7170
* below
7271
*/
73-
private synchronized static boolean storePid(long processID, int cpu) throws IOException {
74-
return lockChecker.obtainLock(cpu, Long.toString(processID));
72+
private synchronized static boolean storePid(long processID, int cpu, int cpu2) throws IOException {
73+
return lockChecker.obtainLock(cpu, cpu2, Long.toString(processID));
7574
}
7675

7776
private synchronized static boolean isLockFree(int id) {
7877
return lockChecker.isLockFree(id);
7978
}
8079

8180
public static int getProcessForCpu(int core) throws IOException {
81+
if (!canOSSupportOperation())
82+
return EMPTY_PID;
83+
8284
String meta = lockChecker.getMetaInfo(core);
8385

8486
if (meta != null && !meta.isEmpty()) {
@@ -91,10 +93,10 @@ public static int getProcessForCpu(int core) throws IOException {
9193
return EMPTY_PID;
9294
}
9395

94-
static boolean updateCpu(int cpu) throws IOException {
96+
static boolean updateCpu(int cpu, int cpu2) throws IOException {
9597
if (!canOSSupportOperation())
9698
return true;
97-
return replacePid(cpu, getPID());
99+
return replacePid(cpu, cpu2, getPID());
98100
}
99101

100102
public static void releaseLock(int cpu) {

affinity/src/main/java/net/openhft/affinity/LockInventory.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private static boolean isAnyCpu(final int cpuId) {
8282
*/
8383
private static boolean updateLockForCurrentThread(final boolean bind, final AffinityLock al, final boolean wholeCore) throws ClosedByInterruptException {
8484
try {
85-
if (LockCheck.updateCpu(al.cpuId())) {
85+
if (LockCheck.updateCpu(al.cpuId(), wholeCore ? al.cpuId2() : 0)) {
8686
al.assignCurrentThread(bind, wholeCore);
8787
return true;
8888
}
@@ -108,7 +108,9 @@ public final synchronized void set(CpuLayout cpuLayout) {
108108
final boolean base = AffinityLock.BASE_AFFINITY.get(i);
109109
final boolean reservable = AffinityLock.RESERVED_AFFINITY.get(i);
110110
LOGGER.trace("cpu {} base={} reservable= {}", i, base, reservable);
111-
AffinityLock lock = logicalCoreLocks[i] = newLock(i, base, reservable);
111+
assert logicalCoreLocks != null;
112+
@SuppressWarnings("resource")
113+
AffinityLock lock = logicalCoreLocks[i] = newLock(i, cpuLayout.pair(i), base, reservable);
112114

113115
int layoutId = lock.cpuId();
114116
int physicalCore = toPhysicalCore(layoutId);
@@ -277,8 +279,8 @@ public final synchronized String dumpLocks() {
277279
return dumpLocks(logicalCoreLocks);
278280
}
279281

280-
protected AffinityLock newLock(int cpuId, boolean base, boolean reservable) {
281-
return new AffinityLock(cpuId, base, reservable, this);
282+
protected AffinityLock newLock(int cpuId, int cpuId2, boolean base, boolean reservable) {
283+
return new AffinityLock(cpuId, cpuId2, base, reservable, this);
282284
}
283285

284286
private void reset(CpuLayout cpuLayout) {
@@ -301,6 +303,6 @@ private void releaseAffinityLock(final Thread t, final AffinityLock al, final St
301303
}
302304

303305
public AffinityLock noLock() {
304-
return newLock(AffinityLock.ANY_CPU, false, false);
306+
return newLock(AffinityLock.ANY_CPU, 0, false, false);
305307
}
306308
}

affinity/src/main/java/net/openhft/affinity/impl/NoCpuLayout.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,9 @@ public int coreId(int cpuId) {
6464
public int threadId(int cpuId) {
6565
return 0;
6666
}
67+
68+
@Override
69+
public int pair(int cpuId) {
70+
return 0;
71+
}
6772
}

affinity/src/main/java/net/openhft/affinity/impl/NullAffinity.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
2323

24-
import java.lang.management.ManagementFactory;
2524
import java.util.BitSet;
2625

2726
/**
@@ -48,8 +47,7 @@ public int getCpu() {
4847

4948
@Override
5049
public int getProcessId() {
51-
final String name = ManagementFactory.getRuntimeMXBean().getName();
52-
return Integer.parseInt(name.split("@")[0]);
50+
return Utilities.currentProcessId();
5351
}
5452

5553
@Override

affinity/src/main/java/net/openhft/affinity/impl/OSXJNAAffinity.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
2626

27-
import java.lang.management.ManagementFactory;
2827
import java.util.BitSet;
2928

3029
/**
@@ -55,8 +54,7 @@ public int getCpu() {
5554

5655
@Override
5756
public int getProcessId() {
58-
final String name = ManagementFactory.getRuntimeMXBean().getName();
59-
return Integer.parseInt(name.split("@")[0]);
57+
return Utilities.currentProcessId();
6058
}
6159

6260
@Override

affinity/src/main/java/net/openhft/affinity/impl/SolarisJNAAffinity.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
2626

27-
import java.lang.management.ManagementFactory;
2827
import java.util.BitSet;
2928

3029
/**
@@ -55,8 +54,7 @@ public int getCpu() {
5554

5655
@Override
5756
public int getProcessId() {
58-
final String name = ManagementFactory.getRuntimeMXBean().getName();
59-
return Integer.parseInt(name.split("@")[0]);
57+
return Utilities.currentProcessId();
6058
}
6159

6260
@Override

0 commit comments

Comments
 (0)