2626
2727import java .io .Closeable ;
2828import java .io .File ;
29+ import java .util .Arrays ;
2930import 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 }
0 commit comments