ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
abtd_affinity.c
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 /*
7  * The Argobots affinity module parses the following grammar while it ignores
8  * all white spaces between tokens. Double-quoted symbols in the following are
9  * part of the syntax.
10  *
11  * <list> = <interval>
12  * | <list> "," <interval>
13  * <interval> = <es-id-list> ":" <num> ":" <stride>
14  * | <es-id-list> ":" <num>
15  * | <es-id-list>
16  * <es-id-list> = <id>
17  * | "{" <id-list> "}"
18  * <id-list> = <id-interval>
19  * | <id-list> "," <id-interval>
20  * <id-interval> = <id> ":" <num> ":" <stride>
21  * | <id> ":" <num>
22  * | <id>
23  * <id> = <integer>
24  * <stride> = <integer>
25  * <num> = <positive integer>
26  *
27  * An execution stream with rank n refers to the (n % N)th CPU ID list
28  * (<es-id-list>) of the whole list (<list>) that has N items. The execution
29  * stream will be scheduled on a core that has a CPU ID in its CPU ID list
30  * (<es-id-list>). If a CPU ID is smaller than zero or larger than the number
31  * of cores recognized by the system, a modulo of the number of cores is used.
32  *
33  * This grammar supports a pattern-based syntax. <id-interval> can represent
34  * multiple CPU IDs by specifying a base CPU ID (<id>), the number of CPU IDs
35  * (<num>), and a stride (<stride>) as follows:
36  * <id>, <id> + <stride>, ..., <id> + <stride> * (<num> - 1)
37  * <interval> also accepts a pattern-based syntax as follows:
38  * <es-id-list>,
39  * {<es-id-list>[0] + <stride>, <es-id-list>[1] + <stride>, ...}, ...
40  * {<es-id-list>[0] + <stride> * (<num> - 1),
41  * <es-id-list>[1] + <stride> * (<num> - 1), ...}
42  * Note that <num> and <stride> are set to 1 if they are omitted.
43  *
44  * Let us assume a 12-core machine (NOTE: "12-core" does not mean 12 physical
45  * cores but indicates 12 hardware threads on modern CPUs). Examples are as
46  * follows:
47  *
48  * Example 1: bind ES with rank n to a core that has CPU ID = n % 12
49  *
50  * | ES0 | ES1 | ES2 | ES3 | ES4 | ES5 | ES6 | ES7 | ES8 | ES9 | ES10| ES11|
51  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
52  *
53  * (1.1) ABT_SET_AFFINITY="{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}"
54  * This explicitly sets all the CPU IDs.
55  * (1.2) ABT_SET_AFFINITY="0,1,2,3,4,5,6,7,8,9,10,11"
56  * It is similar to (1.1), but it omits "{}" since "{id}" = "id".
57  * (1.3) ABT_SET_AFFINITY="{0}:12:1"
58  * This creates 12 CPU ID lists starting from {0}. The stride is specified
59  * as 1, so the created lists are {0}, {1}, {2}, ... {11}.
60  * (1.4) ABT_SET_AFFINITY="{0}:12"
61  * The default stride is 1, so it is the same as (1.3)
62  * (1.5) ABT_SET_AFFINITY="0:12"
63  * It omits "{}" in (1.4) since "{id}" = "id".
64  *
65  * Example 2: bind ES with rank n to a core that has CPU ID = (n + 6) % 12
66  *
67  * | ES6 | ES7 | ES8 | ES9 | ES10| ES11| ES0 | ES1 | ES2 | ES3 | ES4 | ES5 |
68  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
69  *
70  * (2.1) ABT_SET_AFFINITY="{6},{7},{8},{9},{10},{11},{0},{1},{2},{3},{4},{5}"
71  * This explicitly sets all the CPU IDs.
72  * (2.2) ABT_SET_AFFINITY="6,7,8,9,10,11,0,1,2,3,4,5"
73  * It is similar to (2.1), but it omits "{}" since "{id}" = "id".
74  * (2.3) ABT_SET_AFFINITY="{6}:6:1,{0}:6:1"
75  * This first creates 6 CPU ID lists starting from {6} and then 6 lists
76  * starting from {0}. The stride is "1", so the created lists are
77  * {6}, ... {11}, {0} ... {5}.
78  * (2.4) ABT_SET_AFFINITY="{6}:6,{0}:6"
79  * The default stride is 1, so it is the same as (2.3)
80  * (2.5) ABT_SET_AFFINITY="6:6,0:6"
81  * It omits "{}" in (2.4) since "{id}" = "id".
82  * (2.6) ABT_SET_AFFINITY="6:12"
83  * Affinity setting wraps around with respect to the number of cores, so
84  * this works the same as (2.5) on a 12-core machine.
85  *
86  * Example 3: bind ES with rank n to core that has CPU ID = (n * 4) % 12
87  *
88  * | ES0 | | | | ES1 | | | | ES2 | | | |
89  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
90  *
91  * (3.1) ABT_SET_AFFINITY="{0},{4},{8}"
92  * This explicitly sets all the CPU IDs.
93  * (3.2) ABT_SET_AFFINITY="0,4,8"
94  * It is similar to (3.1), but it omits "{}" since "{id}" = "id".
95  * (3.3) ABT_SET_AFFINITY="{0}:3:4"
96  * This creates 3 CPU ID lists starting from {0}. The stride is "4", so
97  * creates lists are {0}, {4}, {8}.
98  * (3.4) ABT_SET_AFFINITY="0:3:4"
99  * It omits "{}" in (3.3) since "{id}" = "id".
100  *
101  * Example 4: bind ES with rank n to core that has
102  * CPU ID = (n * 4 + (n % 12) / 3) % 12
103  *
104  * | ES0 | ES3 | ES6 | ES9 | ES1 | ES4 | ES7 | ES10| ES2 | ES5 | ES9 | ES11|
105  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
106  *
107  * (4.1) ABT_SET_AFFINITY="{0},{4},{8},{1},{5},{9},{2},{6},{10},{3},{7},{11}"
108  * This explicitly sets all the CPU IDs.
109  * (4.2) ABT_SET_AFFINITY="0,4,8,1,5,9,2,6,10,3,7,11"
110  * It is similar to (4.1), but it omits "{}" since "{id}" = "id".
111  * (4.3) ABT_SET_AFFINITY="{0}:3:4,{1}:3:4,{2}:3:4,{3}:3:4"
112  * This creates 3 CPU ID lists ({0}, {4}, {8}), then ({1}, {5}, {9}),
113  * ({2}, {6}, {10}), and ({3}, {7}, {11}).
114  * (4.4) ABT_SET_AFFINITY="0:3:4,1:3:4,2:3:4,3:3:4"
115  * It omits "{}" in (4.3) since "{id}" = "id".
116  *
117  * Example 5: bind ES with rank n to cores that have
118  * (n * 4) % 12 <= CPU ID < (n * 4) % 12 + 4
119  *
120  * | ES0 | ES1 | ES2 |
121  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
122  *
123  * (5.1) ABT_SET_AFFINITY="{0,1,2,3},{4,5,6,7},{8,9,10,11}"
124  * This explicitly sets all the CPU IDs.
125  * (5.2) ABT_SET_AFFINITY="{0,1,2,3}:3:4"
126  * This creates 3 CPU ID lists starting from {0,1,2,3}. The stride is "4",
127  * so the created lists are "{0,1,2,3}, {4,5,6,7}, {8,9,10,11}".
128  * Note that "{0,1,2,3}:3:1" (or "{0,1,2,3}:3") is wrong: they create
129  * "{0,1,2,3}, {2,3,4,5}, {3,4,5,6}" since the stride is 1.
130  * (5.3) ABT_SET_AFFINITY="{0:4:1}:3:4"
131  * "{0:4:1}" means a CPU ID list of 4 CPU IDs that starts from 0 with a
132  * stride 1, so it is the same as "{0,1,2,3}".
133  * (5.4) ABT_SET_AFFINITY="{0:4}:3:4"
134  * The default stride is 1.
135  *
136  * Example 6: bind ES with rank n to cores that have either of the following:
137  * CPU ID = (n * 2) % 6
138  * CPU ID = (n * 2) % 6 + 6
139  *
140  * | ES0 | ES1 | ES2 | ES3 | ES4 | ES5 |
141  * |CPU00|CPU06|CPU01|CPU07|CPU02|CPU08|CPU03|CPU09|CPU04|CPU10|CPU05|CPU11|
142  *
143  * (6.1) ABT_SET_AFFINITY="{0,6},{1,7},{2,8},{3,9},{4,10},{5,11}"
144  * This explicitly sets all the CPU IDs.
145  * (6.2) ABT_SET_AFFINITY="{0,6}:6:1"
146  * This creates 6 CPU ID lists starting from {0,6}. The stride is "1", so
147  * the created lists are "{0,6}, {1,7}, {2,8}, {3,9}, {4,10}, {5,11}".
148  * (6.3) ABT_SET_AFFINITY="{0,6}:6"
149  * The default stride is 1.
150  *
151  * Example 7: bind ESs to cores except for those that have CPU ID = 0 or 1
152  *
153  * | | ES0, ES1, ES2, ... |
154  * |CPU00|CPU01|CPU02|CPU03|CPU04|CPU05|CPU06|CPU07|CPU08|CPU09|CPU10|CPU11|
155  *
156  * (7.1) ABT_SET_AFFINITY="{2,3,4,5,6,7,8,9,10,11}"
157  * This explicitly sets all the CPU IDs.
158  * (7.2) ABT_SET_AFFINITY="{2:10:1}"
159  * "{2:10:1}" means a CPU ID list that has 10 CPU IDs starting from 2 with
160  * a stride 1, so it is the same as "{2,3,4,5,6,7,8,9,10,11}".
161  * (7.3) ABT_SET_AFFINITY="{2:10}"
162  * The default stride is 1.
163  */
164 
165 #include "abti.h"
166 #include <unistd.h>
167 
168 #ifdef HAVE_PTHREAD_SETAFFINITY_NP
169 #ifdef __FreeBSD__
170 
171 #include <sys/param.h>
172 #include <sys/cpuset.h>
173 #include <pthread_np.h>
174 typedef cpuset_t cpu_set_t;
175 
176 #else /* !__FreeBSD__ */
177 
178 #define _GNU_SOURCE
179 #include <sched.h>
180 
181 #endif
182 #endif /* HAVE_PTHREAD_SETAFFINITY_NP */
183 
184 typedef struct {
185  ABTD_affinity_cpuset initial_cpuset;
186  uint32_t num_cpusets;
187  ABTD_affinity_cpuset *cpusets;
189 
191 
192 static inline int int_rem(int a, unsigned int b)
193 {
194  /* Return x where a = n * b + x and 0 <= x < b */
195  /* Because of ambiguity in the C specification, it uses a branch to check if
196  * the result is positive. */
197  int int_b = b;
198  int ret = (a % int_b) + int_b;
199  return ret >= int_b ? (ret - int_b) : ret;
200 }
201 
202 ABTU_ret_err static int get_num_cores(pthread_t native_thread, int *p_num_cores)
203 {
204 #ifdef HAVE_PTHREAD_SETAFFINITY_NP
205  int i, num_cores = 0;
206  /* Check the number of available cores by counting set bits. */
207  cpu_set_t cpuset;
208  int ret = pthread_getaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
209  if (ret)
210  return ABT_ERR_SYS;
211  for (i = 0; i < CPU_SETSIZE; i++) {
212  if (CPU_ISSET(i, &cpuset)) {
213  num_cores++;
214  }
215  }
216  *p_num_cores = num_cores;
217  return ABT_SUCCESS;
218 #else
219  return ABT_ERR_FEATURE_NA;
220 #endif
221 }
222 
223 ABTU_ret_err static int create_cpuset(pthread_t native_thread,
224  ABTD_affinity_cpuset *p_cpuset)
225 {
226 #ifdef HAVE_PTHREAD_SETAFFINITY_NP
227  cpu_set_t cpuset;
228  int ret = pthread_getaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
229  if (ret)
230  return ABT_ERR_SYS;
231  int i, j, num_cpuids = 0;
232  for (i = 0; i < CPU_SETSIZE; i++) {
233  if (CPU_ISSET(i, &cpuset))
234  num_cpuids++;
235  }
236  p_cpuset->num_cpuids = num_cpuids;
237  ret = ABTU_malloc(sizeof(int) * num_cpuids, (void **)&p_cpuset->cpuids);
238  ABTI_CHECK_ERROR(ret);
239  for (i = 0, j = 0; i < CPU_SETSIZE; i++) {
240  if (CPU_ISSET(i, &cpuset))
241  p_cpuset->cpuids[j++] = i;
242  }
243  return ABT_SUCCESS;
244 #else
245  return ABT_ERR_FEATURE_NA;
246 #endif
247 }
248 
249 ABTU_ret_err static int read_cpuset(pthread_t native_thread, int max_cpuids,
250  int *cpuids, int *p_num_cpuids)
251 {
252 #ifdef HAVE_PTHREAD_SETAFFINITY_NP
253  cpu_set_t cpuset;
254  int ret = pthread_getaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
255  if (ret)
256  return ABT_ERR_SYS;
257  int i, num_cpuids = 0;
258  for (i = 0; i < CPU_SETSIZE; i++) {
259  if (CPU_ISSET(i, &cpuset)) {
260  if (num_cpuids < max_cpuids) {
261  cpuids[num_cpuids] = i;
262  }
263  num_cpuids++;
264  }
265  }
266  *p_num_cpuids = num_cpuids;
267  return ABT_SUCCESS;
268 #else
269  return ABT_ERR_FEATURE_NA;
270 #endif
271 }
272 
273 ABTU_ret_err static int apply_cpuset(pthread_t native_thread,
274  const ABTD_affinity_cpuset *p_cpuset)
275 {
276 #ifdef HAVE_PTHREAD_SETAFFINITY_NP
277  uint32_t i;
278  cpu_set_t cpuset;
279  CPU_ZERO(&cpuset);
280  if (p_cpuset->num_cpuids == 0) {
281  /* Use the initial one. */
282  for (i = 0; i < g_affinity.initial_cpuset.num_cpuids; i++)
283  CPU_SET(int_rem(g_affinity.initial_cpuset.cpuids[i], CPU_SETSIZE),
284  &cpuset);
285  } else {
286  for (i = 0; i < p_cpuset->num_cpuids; i++)
287  CPU_SET(int_rem(p_cpuset->cpuids[i], CPU_SETSIZE), &cpuset);
288  }
289  int ret = pthread_setaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
290  return ret == 0 ? ABT_SUCCESS : ABT_ERR_SYS;
291 #else
292  return ABT_ERR_FEATURE_NA;
293 #endif
294 }
295 
296 void ABTD_affinity_init(ABTI_global *p_global, const char *affinity_str)
297 {
299  g_affinity.cpusets = NULL;
300  g_affinity.initial_cpuset.cpuids = NULL;
301  pthread_t self_native_thread = pthread_self();
302  ABTD_affinity_list *p_list = NULL;
303 
304  uint32_t i;
305  int ret;
306  ret = get_num_cores(self_native_thread, &p_global->num_cores);
307  if (ret != ABT_SUCCESS || p_global->num_cores == 0)
308  goto FAILED;
309  ret = create_cpuset(self_native_thread, &g_affinity.initial_cpuset);
310  if (ret != ABT_SUCCESS || g_affinity.initial_cpuset.num_cpuids == 0)
311  goto FAILED;
312  p_global->set_affinity = ABT_TRUE;
313  ret = ABTD_affinity_list_create(affinity_str, &p_list);
314  if (ret == ABT_SUCCESS) {
315  if (p_list->num == 0) {
316  ABTD_affinity_list_free(p_list);
317  p_list = NULL;
318  }
319  }
320  if (p_list) {
321  /* Create cpusets based on the affinity list.*/
322  ret = ABTU_calloc(p_list->num, sizeof(ABTD_affinity_cpuset),
323  (void **)&g_affinity.cpusets);
324  if (ret != ABT_SUCCESS)
325  goto FAILED;
326  g_affinity.num_cpusets = p_list->num;
327  for (i = 0; i < p_list->num; i++) {
328  const ABTD_affinity_id_list *p_id_list = p_list->p_id_lists[i];
329  uint32_t j, num_cpuids = 0, len_cpuids = 8;
330  ret = ABTU_malloc(sizeof(int) * len_cpuids,
331  (void **)&g_affinity.cpusets[i].cpuids);
332  if (ret != ABT_SUCCESS)
333  goto FAILED;
334  for (j = 0; j < p_id_list->num; j++) {
335  int cpuid_i = int_rem(p_id_list->ids[j],
336  g_affinity.initial_cpuset.num_cpuids);
337  int cpuid = g_affinity.initial_cpuset.cpuids[cpuid_i];
338  /* If it is unique, add it.*/
339  uint32_t k;
340  int is_unique = 1;
341  for (k = 0; k < num_cpuids; k++) {
342  if (g_affinity.cpusets[i].cpuids[k] == cpuid) {
343  is_unique = 0;
344  break;
345  }
346  }
347  if (is_unique) {
348  if (num_cpuids == len_cpuids) {
349  ret = ABTU_realloc(sizeof(int) * len_cpuids,
350  sizeof(int) * len_cpuids * 2,
351  (void **)&g_affinity.cpusets[i]
352  .cpuids);
353  if (ret != ABT_SUCCESS)
354  goto FAILED;
355  len_cpuids *= 2;
356  }
357  g_affinity.cpusets[i].cpuids[num_cpuids] = cpuid;
358  num_cpuids++;
359  }
360  }
361  /* Adjust the size of cpuids. */
362  if (num_cpuids != len_cpuids) {
363  ret = ABTU_realloc(sizeof(int) * len_cpuids,
364  sizeof(int) * num_cpuids,
365  (void **)&g_affinity.cpusets[i].cpuids);
366  if (ret != ABT_SUCCESS)
367  goto FAILED;
368  }
369  g_affinity.cpusets[i].num_cpuids = num_cpuids;
370  }
371  ABTD_affinity_list_free(p_list);
372  } else {
373  /* Create default cpusets. */
374  ret = ABTU_calloc(g_affinity.initial_cpuset.num_cpuids,
375  sizeof(ABTD_affinity_cpuset),
376  (void **)&g_affinity.cpusets);
377  if (ret != ABT_SUCCESS)
378  goto FAILED;
380  for (i = 0; i < g_affinity.num_cpusets; i++) {
381  g_affinity.cpusets[i].num_cpuids = 1;
382  ret = ABTU_malloc(sizeof(int) * g_affinity.cpusets[i].num_cpuids,
383  (void **)&g_affinity.cpusets[i].cpuids);
384  if (ret != ABT_SUCCESS)
385  goto FAILED;
386  g_affinity.cpusets[i].cpuids[0] =
387  g_affinity.initial_cpuset.cpuids[i];
388  }
389  }
390  return;
391 FAILED:
392  if (p_list)
393  ABTD_affinity_list_free(p_list);
394  ABTD_affinity_cpuset_destroy(&g_affinity.initial_cpuset);
395  for (i = 0; i < g_affinity.num_cpusets; i++)
396  ABTD_affinity_cpuset_destroy(&g_affinity.cpusets[i]);
399  g_affinity.cpusets = NULL;
400  p_global->set_affinity = ABT_FALSE;
401  return;
402 }
403 
404 void ABTD_affinity_finalize(ABTI_global *p_global)
405 {
406  pthread_t self_native_thread = pthread_self();
407  if (p_global->set_affinity) {
408  /* Set the affinity of the main native thread to the original one. */
409  int abt_errno =
410  apply_cpuset(self_native_thread, &g_affinity.initial_cpuset);
411  /* Even if this cpuset apply fails, there is no way to handle it (e.g.,
412  * possibly the CPU affinity policy has been changed while running
413  * a user program. Let's ignore this error. */
414  (void)abt_errno;
415 
416  /* Free g_affinity. */
417  ABTD_affinity_cpuset_destroy(&g_affinity.initial_cpuset);
418  uint32_t i;
419  for (i = 0; i < g_affinity.num_cpusets; i++) {
420  ABTD_affinity_cpuset_destroy(&g_affinity.cpusets[i]);
421  }
423  g_affinity.cpusets = NULL;
425  }
426 }
427 
428 ABTU_ret_err int ABTD_affinity_cpuset_read(ABTD_xstream_context *p_ctx,
429  int max_cpuids, int *cpuids,
430  int *p_num_cpuids)
431 {
432  return read_cpuset(p_ctx->native_thread, max_cpuids, cpuids, p_num_cpuids);
433 }
434 
435 ABTU_ret_err int
436 ABTD_affinity_cpuset_apply(ABTD_xstream_context *p_ctx,
437  const ABTD_affinity_cpuset *p_cpuset)
438 {
439  return apply_cpuset(p_ctx->native_thread, p_cpuset);
440 }
441 
442 ABTU_ret_err int ABTD_affinity_cpuset_apply_default(ABTD_xstream_context *p_ctx,
443  int rank)
444 {
445  ABTD_affinity_cpuset *p_cpuset =
447  return apply_cpuset(p_ctx->native_thread, p_cpuset);
448 }
449 
450 void ABTD_affinity_cpuset_destroy(ABTD_affinity_cpuset *p_cpuset)
451 {
452  if (p_cpuset) {
453  ABTU_free(p_cpuset->cpuids);
454  p_cpuset->cpuids = NULL;
455  }
456 }
ABT_ERR_SYS
#define ABT_ERR_SYS
Error code: error related to system calls and standard libraries.
Definition: abt.h:403
ABTU_realloc
static ABTU_ret_err int ABTU_realloc(size_t old_size, size_t new_size, void **p_ptr)
Definition: abtu.h:257
get_num_cores
static ABTU_ret_err int get_num_cores(pthread_t native_thread, int *p_num_cores)
Definition: abtd_affinity.c:202
int_rem
static int int_rem(int a, unsigned int b)
Definition: abtd_affinity.c:192
abti.h
global_affinity::num_cpusets
uint32_t num_cpusets
Definition: abtd_affinity.c:186
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABTU_calloc
static ABTU_ret_err int ABTU_calloc(size_t num, size_t size, void **p_ptr)
Definition: abtu.h:244
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:155
global_affinity
Definition: abtd_affinity.c:184
g_affinity
static global_affinity g_affinity
Definition: abtd_affinity.c:190
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
apply_cpuset
static ABTU_ret_err int apply_cpuset(pthread_t native_thread, const ABTD_affinity_cpuset *p_cpuset)
Definition: abtd_affinity.c:273
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
create_cpuset
static ABTU_ret_err int create_cpuset(pthread_t native_thread, ABTD_affinity_cpuset *p_cpuset)
Definition: abtd_affinity.c:223
read_cpuset
static ABTU_ret_err int read_cpuset(pthread_t native_thread, int max_cpuids, int *cpuids, int *p_num_cpuids)
Definition: abtd_affinity.c:249
ABT_ERR_FEATURE_NA
#define ABT_ERR_FEATURE_NA
Error code: unsupported feature.
Definition: abt.h:391
global_affinity::cpusets
ABTD_affinity_cpuset * cpusets
Definition: abtd_affinity.c:187
global_affinity::initial_cpuset
ABTD_affinity_cpuset initial_cpuset
Definition: abtd_affinity.c:185