Skip to content

Commit 320d0bf

Browse files
committed
Enhance AffinityLock to support dual CPU IDs and update related methods
1 parent cb44980 commit 320d0bf

File tree

12 files changed

+81
-88
lines changed

12 files changed

+81
-88
lines changed

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

Lines changed: 7 additions & 1 deletion
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
}
@@ -461,6 +463,10 @@ public int cpuId() {
461463
return cpuId;
462464
}
463465

466+
public int cpuId2() {
467+
return cpuId2;
468+
}
469+
464470
/**
465471
* @return Was a cpu found to bind this lock to.
466472
*/

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: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public static boolean isCpuFree(int cpu) {
5454
return isLockFree(cpu);
5555
}
5656

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

6161
public static boolean isProcessRunning(long pid) {
@@ -69,8 +69,8 @@ public static boolean isProcessRunning(long pid) {
6969
* stores the pid in a file, named by the core, the pid is written to the file with the date
7070
* below
7171
*/
72-
private synchronized static boolean storePid(long processID, int cpu) throws IOException {
73-
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));
7474
}
7575

7676
private synchronized static boolean isLockFree(int id) {
@@ -90,10 +90,10 @@ public static int getProcessForCpu(int core) throws IOException {
9090
return EMPTY_PID;
9191
}
9292

93-
static boolean updateCpu(int cpu) throws IOException {
93+
static boolean updateCpu(int cpu, int cpu2) throws IOException {
9494
if (!canOSSupportOperation())
9595
return true;
96-
return replacePid(cpu, getPID());
96+
return replacePid(cpu, cpu2, getPID());
9797
}
9898

9999
public static void releaseLock(int cpu) {

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

Lines changed: 5 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
}
@@ -110,7 +110,7 @@ public final synchronized void set(CpuLayout cpuLayout) {
110110
LOGGER.trace("cpu {} base={} reservable= {}", i, base, reservable);
111111
assert logicalCoreLocks != null;
112112
@SuppressWarnings("resource")
113-
AffinityLock lock = logicalCoreLocks[i] = newLock(i, base, reservable);
113+
AffinityLock lock = logicalCoreLocks[i] = newLock(i, cpuLayout.pair(i), base, reservable);
114114

115115
int layoutId = lock.cpuId();
116116
int physicalCore = toPhysicalCore(layoutId);
@@ -279,8 +279,8 @@ public final synchronized String dumpLocks() {
279279
return dumpLocks(logicalCoreLocks);
280280
}
281281

282-
protected AffinityLock newLock(int cpuId, boolean base, boolean reservable) {
283-
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);
284284
}
285285

286286
private void reset(CpuLayout cpuLayout) {
@@ -303,6 +303,6 @@ private void releaseAffinityLock(final Thread t, final AffinityLock al, final St
303303
}
304304

305305
public AffinityLock noLock() {
306-
return newLock(AffinityLock.ANY_CPU, false, false);
306+
return newLock(AffinityLock.ANY_CPU, 0, false, false);
307307
}
308308
}

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/VanillaCpuLayout.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,19 @@ public int threadId(int cpuId) {
177177
return cpuDetails.get(cpuId).threadId;
178178
}
179179

180+
@Override
181+
public int pair(int cpuId) {
182+
for (int i = 0; i < cpuDetails.size(); i++) {
183+
CpuInfo info = cpuDetails.get(i);
184+
if (info.socketId == cpuDetails.get(cpuId).socketId &&
185+
info.coreId == cpuDetails.get(cpuId).coreId &&
186+
info.threadId != cpuDetails.get(cpuId).threadId) {
187+
return i;
188+
}
189+
}
190+
return 0;
191+
}
192+
180193
@NotNull
181194
@Override
182195
public String toString() {

affinity/src/main/java/net/openhft/affinity/lockchecker/FileLockBasedLockChecker.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,25 @@ public synchronized boolean isLockFree(int id) {
9898
}
9999

100100
@Override
101-
public synchronized boolean obtainLock(int id, String metaInfo) throws IOException {
101+
public synchronized boolean obtainLock(int id, int id2, String metaInfo) throws IOException {
102102
int attempt = 0;
103103
while (attempt < MAX_LOCK_RETRIES) {
104104
try {
105105
LockReference lockReference = tryAcquireLockOnFile(id, metaInfo);
106106
if (lockReference != null) {
107-
locks[id] = lockReference;
108-
return true;
107+
if (id2 <= 0) {
108+
// no second lock to acquire, return success
109+
locks[id] = lockReference;
110+
return true;
111+
}
112+
LockReference lockReference2 = tryAcquireLockOnFile(id2, metaInfo);
113+
if (lockReference2 != null) {
114+
locks[id] = lockReference;
115+
locks[id2] = lockReference2;
116+
return true;
117+
} else {
118+
releaseLock(id);
119+
}
109120
}
110121
return false;
111122
} catch (ConcurrentLockFileDeletionException e) {

affinity/src/main/java/net/openhft/affinity/lockchecker/LockChecker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public interface LockChecker {
2626

2727
boolean isLockFree(int id);
2828

29-
boolean obtainLock(int id, String metaInfo) throws IOException;
29+
boolean obtainLock(int id, int id2, String metaInfo) throws IOException;
3030

3131
boolean releaseLock(int id);
3232

affinity/src/test/java/net/openhft/affinity/AffinityJNALoadFailureTest.java

Lines changed: 0 additions & 46 deletions
This file was deleted.

affinity/src/test/java/net/openhft/affinity/AffinityLockTest.java

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import net.openhft.affinity.impl.Utilities;
2121
import net.openhft.affinity.impl.VanillaCpuLayout;
2222
import net.openhft.affinity.testimpl.TestFileLockBasedLockChecker;
23-
import net.openhft.affinity.CpuLayout;
24-
import net.openhft.affinity.LockCheck;
2523
import org.hamcrest.MatcherAssert;
2624
import org.junit.Test;
2725
import org.slf4j.Logger;
@@ -51,14 +49,14 @@ public class AffinityLockTest extends BaseAffinityTest {
5149
public void dumpLocksI7() throws IOException {
5250
LockInventory lockInventory = new LockInventory(VanillaCpuLayout.fromCpuInfo("i7.cpuinfo"));
5351
AffinityLock[] locks = {
54-
new AffinityLock(0, true, false, lockInventory),
55-
new AffinityLock(1, false, false, lockInventory),
56-
new AffinityLock(2, false, true, lockInventory),
57-
new AffinityLock(3, false, true, lockInventory),
58-
new AffinityLock(4, true, false, lockInventory),
59-
new AffinityLock(5, false, false, lockInventory),
60-
new AffinityLock(6, false, true, lockInventory),
61-
new AffinityLock(7, false, true, lockInventory),
52+
new AffinityLock(0, 0, true, false, lockInventory),
53+
new AffinityLock(1, 5, false, false, lockInventory),
54+
new AffinityLock(2, 6, false, true, lockInventory),
55+
new AffinityLock(3, 7, false, true, lockInventory),
56+
new AffinityLock(4, 0, true, false, lockInventory),
57+
new AffinityLock(5, 1, false, false, lockInventory),
58+
new AffinityLock(6, 2, false, true, lockInventory),
59+
new AffinityLock(7, 3, false, true, lockInventory),
6260
};
6361
locks[2].assignedThread = new Thread(new InterrupedThread(), "logger");
6462
locks[2].assignedThread.start();
@@ -88,10 +86,10 @@ public void dumpLocksI7() throws IOException {
8886
public void dumpLocksI3() throws IOException {
8987
LockInventory lockInventory = new LockInventory(VanillaCpuLayout.fromCpuInfo("i3.cpuinfo"));
9088
AffinityLock[] locks = {
91-
new AffinityLock(0, true, false, lockInventory),
92-
new AffinityLock(1, false, true, lockInventory),
93-
new AffinityLock(2, true, false, lockInventory),
94-
new AffinityLock(3, false, true, lockInventory),
89+
new AffinityLock(0, 0,true, false, lockInventory),
90+
new AffinityLock(1, 3, false, true, lockInventory),
91+
new AffinityLock(2, 0, true, false, lockInventory),
92+
new AffinityLock(3, 1, false, true, lockInventory),
9593
};
9694
locks[1].assignedThread = new Thread(new InterrupedThread(), "engine");
9795
locks[1].assignedThread.start();
@@ -111,8 +109,8 @@ public void dumpLocksI3() throws IOException {
111109
public void dumpLocksCoreDuo() throws IOException {
112110
LockInventory lockInventory = new LockInventory(VanillaCpuLayout.fromCpuInfo("core.duo.cpuinfo"));
113111
AffinityLock[] locks = {
114-
new AffinityLock(0, true, false, lockInventory),
115-
new AffinityLock(1, false, true, lockInventory),
112+
new AffinityLock(0, 0,true, false, lockInventory),
113+
new AffinityLock(1, 0,false, true, lockInventory),
116114
};
117115
locks[1].assignedThread = new Thread(new InterrupedThread(), "engine");
118116
locks[1].assignedThread.start();
@@ -328,7 +326,7 @@ public void testTooHighCpuId() {
328326

329327
@Test(expected = IllegalArgumentException.class)
330328
public void testTooHighCpuId2() {
331-
AffinityLock.acquireLock(new int[] {123456});
329+
AffinityLock.acquireLock(new int[]{123456});
332330
}
333331

334332
@Test(expected = IllegalStateException.class)

affinity/src/test/java/net/openhft/affinity/FileLockLockCheckTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void before() {
4545
@Test
4646
public void test() throws IOException {
4747
Assert.assertTrue(LockCheck.isCpuFree(cpu));
48-
LockCheck.updateCpu(cpu);
48+
LockCheck.updateCpu(cpu, 0);
4949
Assert.assertEquals(LockCheck.getPID(), LockCheck.getProcessForCpu(cpu));
5050
}
5151

@@ -58,13 +58,13 @@ public void testPidOnLinux() {
5858
public void testReplace() throws IOException {
5959
cpu++;
6060
Assert.assertTrue(LockCheck.isCpuFree(cpu + 1));
61-
LockCheck.replacePid(cpu, 123L);
61+
LockCheck.replacePid(cpu, 0, 123L);
6262
Assert.assertEquals(123L, LockCheck.getProcessForCpu(cpu));
6363
}
6464

6565
@Test
6666
public void shouldNotBlowUpIfPidFileIsEmpty() throws Exception {
67-
LockCheck.updateCpu(cpu);
67+
LockCheck.updateCpu(cpu, 0);
6868

6969
final File file = lockChecker.doToFile(cpu);
7070
new RandomAccessFile(file, "rw").setLength(0);
@@ -77,7 +77,7 @@ public void lockFileDeletedWhileHeld() throws Exception {
7777
cpu++;
7878

7979
Assert.assertTrue(LockCheck.isCpuFree(cpu));
80-
LockCheck.updateCpu(cpu);
80+
LockCheck.updateCpu(cpu, 0);
8181

8282
File lockFile = lockChecker.doToFile(cpu);
8383
Assert.assertTrue(lockFile.exists());
@@ -91,7 +91,7 @@ public void lockFileDeletedWhileHeld() throws Exception {
9191
LockCheck.releaseLock(cpu);
9292

9393
Assert.assertTrue("Lock should be free after release", LockCheck.isCpuFree(cpu));
94-
LockCheck.updateCpu(cpu);
94+
LockCheck.updateCpu(cpu, 0);
9595

9696
lockFile = lockChecker.doToFile(cpu);
9797
Assert.assertTrue("Lock file should be recreated", lockFile.exists());

affinity/src/test/java/net/openhft/affinity/LockCheckTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void before() {
4646
@Test
4747
public void test() throws IOException {
4848
Assert.assertTrue(LockCheck.isCpuFree(cpu));
49-
LockCheck.updateCpu(cpu);
49+
LockCheck.updateCpu(cpu, 0);
5050
Assert.assertEquals(LockCheck.getPID(), LockCheck.getProcessForCpu(cpu));
5151
}
5252

@@ -59,13 +59,13 @@ public void testPidOnLinux() {
5959
public void testReplace() throws IOException {
6060
cpu++;
6161
Assert.assertTrue(LockCheck.isCpuFree(cpu + 1));
62-
LockCheck.replacePid(cpu, 123L);
62+
LockCheck.replacePid(cpu, 0, 123L);
6363
Assert.assertEquals(123L, LockCheck.getProcessForCpu(cpu));
6464
}
6565

6666
@Test
6767
public void shouldNotBlowUpIfPidFileIsEmpty() throws Exception {
68-
LockCheck.updateCpu(cpu);
68+
LockCheck.updateCpu(cpu, 0);
6969

7070
final File file = lockChecker.doToFile(cpu);
7171
new RandomAccessFile(file, "rw").setLength(0);
@@ -75,7 +75,7 @@ public void shouldNotBlowUpIfPidFileIsEmpty() throws Exception {
7575

7676
@Test
7777
public void shouldNotBlowUpIfPidFileIsCorrupt() throws Exception {
78-
LockCheck.updateCpu(cpu);
78+
LockCheck.updateCpu(cpu, 0);
7979

8080
final File file = lockChecker.doToFile(cpu);
8181
try (final FileWriter writer = new FileWriter(file, false)) {

0 commit comments

Comments
 (0)