Skip to content

Commit 87b78fb

Browse files
author
rogersimmons
committed
Extend AffinityLock.acquireLock to optionally take an explicit list of CPUs to choose from
1 parent 4c11a81 commit 87b78fb

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import java.io.Closeable;
2828
import java.io.File;
29+
import java.util.Arrays;
2930
import java.util.BitSet;
3031

3132
/**
@@ -181,6 +182,30 @@ public static AffinityLock acquireLock(int cpuId) {
181182
return acquireLock(true, cpuId, AffinityStrategies.ANY);
182183
}
183184

185+
/**
186+
* Assign a cpu which can be bound to the current thread or another thread
187+
* Caller passes in an explicit set of preferred CPUs
188+
* The first available CPU is used, and the lock returned
189+
* If all CPUs in the set are unavailable then no lock is obtained
190+
*
191+
* @param cpus the array of available CPUs to bind to
192+
* @return A handle for an affinity lock, or nolock if no available CPU in the array
193+
*/
194+
public static AffinityLock acquireLock(int[] cpus) {
195+
for( int cpu : cpus )
196+
{
197+
AffinityLock lock = tryAcquireLock(true, cpu);
198+
if(lock != null)
199+
{
200+
LOGGER.info("Acquired lock on CPU {}", cpu);
201+
return lock;
202+
}
203+
}
204+
205+
LOGGER.warn("Failed to lock any CPU in explicit list " + Arrays.toString(cpus));
206+
return LOCK_INVENTORY.noLock();
207+
}
208+
184209
/**
185210
* Allocate from the end.
186211
*
@@ -196,6 +221,7 @@ public static AffinityLock acquireLockLastMinus(int n) {
196221
* <ul>
197222
* <li>"N" being a positive integer means allocate this CPU,</li>
198223
* <li>"last" or "last-N" means allocate from the end,</li>
224+
* <li>"csv:1,2,5,6 eg means allocate first free core from the provided</li>
199225
* <li>"any" means allow any</li>
200226
* <li>"none" or null means</li>
201227
* <li>"0" is not allowed</li>
@@ -226,6 +252,14 @@ public static AffinityLock acquireLock(String desc) {
226252

227253
cpuId = PROCESSORS + lastN - 1;
228254

255+
} else if (desc.startsWith("csv:")) {
256+
String content = desc.substring(4);
257+
int[] cpus = Arrays.asList(content.split(",")).stream()
258+
.map(String::trim)
259+
.mapToInt(Integer::parseInt).toArray();
260+
261+
return acquireLock(cpus);
262+
229263
} else if (desc.equals("none")) {
230264
return LOCK_INVENTORY.noLock();
231265

@@ -263,6 +297,18 @@ private static AffinityLock acquireLock(boolean bind, int cpuId, @NotNull Affini
263297
return LOCK_INVENTORY.acquireLock(bind, cpuId, strategies);
264298
}
265299

300+
/**
301+
* Try to acquire a lock on the specified core
302+
* Returns lock if successful, or null if cpu cannot be acquired
303+
*
304+
* @param bind - if true, bind the current thread; if false, reserve a cpu which can be bound later
305+
* @param cpuId - the cpu to lock
306+
* @return - A handle to an affinity lock on success; null if failed to lock
307+
*/
308+
private static AffinityLock tryAcquireLock(boolean bind, int cpuId) {
309+
return LOCK_INVENTORY.tryAcquireLock(bind, cpuId);
310+
}
311+
266312
private static AffinityLock acquireCore(boolean bind, int cpuId, @NotNull AffinityStrategy... strategies) {
267313
return LOCK_INVENTORY.acquireCore(bind, cpuId, strategies);
268314
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,22 @@ public final synchronized AffinityLock acquireLock(boolean bind, int cpuId, Affi
131131
return noLock();
132132
}
133133

134+
public final synchronized AffinityLock tryAcquireLock(boolean bind, int cpuId) {
135+
if (getAffinityImpl() instanceof NullAffinity)
136+
return null;
137+
138+
final AffinityLock required = logicalCoreLocks[cpuId];
139+
if (required.canReserve(true)) {
140+
updateLockForCurrentThread(bind, required, false);
141+
return required;
142+
}
143+
144+
LOGGER.warn("Unable to acquire lock on CPU {} for thread {}, trying to find another CPU",
145+
cpuId, Thread.currentThread());
146+
147+
return null;
148+
}
149+
134150
public final synchronized AffinityLock acquireCore(boolean bind, int cpuId, AffinityStrategy... strategies) {
135151
for (AffinityStrategy strategy : strategies) {
136152
LOOP:

0 commit comments

Comments
 (0)