1 /*
2 * Copyright © 2009 CNRS
3 * Copyright © 2009-2017 Inria. All rights reserved.
4 * Copyright © 2009-2011 Université Bordeaux
5 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
6 * See COPYING in top-level directory.
7 */
8
9 #include <private/autogen/config.h>
10 #include <hwloc/autogen/config.h>
11 #include <hwloc.h>
12 #include <private/misc.h>
13 #include <private/private.h>
14 #include <hwloc/bitmap.h>
15
16 #include <stdarg.h>
17 #include <stdio.h>
18 #include <assert.h>
19 #include <errno.h>
20 #include <ctype.h>
21
22 /* TODO
23 * - have a way to change the initial allocation size
24 * - preallocate inside the bitmap structure (so that the whole structure is a cacheline for instance)
25 * and allocate a dedicated array only later when reallocating larger
26 */
27
28 /* magic number */
29 #define HWLOC_BITMAP_MAGIC 0x20091007
30
31 /* actual opaque type internals */
32 struct hwloc_bitmap_s {
33 unsigned ulongs_count; /* how many ulong bitmasks are valid, >= 1 */
34 unsigned ulongs_allocated; /* how many ulong bitmasks are allocated, >= ulongs_count */
35 unsigned long *ulongs;
36 int infinite; /* set to 1 if all bits beyond ulongs are set */
37 #ifdef HWLOC_DEBUG
38 int magic;
39 #endif
40 };
41
42 /* overzealous check in debug-mode, not as powerful as valgrind but still useful */
43 #ifdef HWLOC_DEBUG
44 #define HWLOC__BITMAP_CHECK(set) do { \
45 assert((set)->magic == HWLOC_BITMAP_MAGIC); \
46 assert((set)->ulongs_count >= 1); \
47 assert((set)->ulongs_allocated >= (set)->ulongs_count); \
48 } while (0)
49 #else
50 #define HWLOC__BITMAP_CHECK(set)
51 #endif
52
53 /* extract a subset from a set using an index or a cpu */
54 #define HWLOC_SUBBITMAP_INDEX(cpu) ((cpu)/(HWLOC_BITS_PER_LONG))
55 #define HWLOC_SUBBITMAP_CPU_ULBIT(cpu) ((cpu)%(HWLOC_BITS_PER_LONG))
56 /* Read from a bitmap ulong without knowing whether x is valid.
57 * Writers should make sure that x is valid and modify set->ulongs[x] directly.
58 */
59 #define HWLOC_SUBBITMAP_READULONG(set,x) ((x) < (set)->ulongs_count ? (set)->ulongs[x] : (set)->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO)
60
61 /* predefined subset values */
62 #define HWLOC_SUBBITMAP_ZERO 0UL
63 #define HWLOC_SUBBITMAP_FULL (~0UL)
64 #define HWLOC_SUBBITMAP_ULBIT(bit) (1UL<<(bit))
65 #define HWLOC_SUBBITMAP_CPU(cpu) HWLOC_SUBBITMAP_ULBIT(HWLOC_SUBBITMAP_CPU_ULBIT(cpu))
66 #define HWLOC_SUBBITMAP_ULBIT_TO(bit) (HWLOC_SUBBITMAP_FULL>>(HWLOC_BITS_PER_LONG-1-(bit)))
67 #define HWLOC_SUBBITMAP_ULBIT_FROM(bit) (HWLOC_SUBBITMAP_FULL<<(bit))
68 #define HWLOC_SUBBITMAP_ULBIT_FROMTO(begin,end) (HWLOC_SUBBITMAP_ULBIT_TO(end) & HWLOC_SUBBITMAP_ULBIT_FROM(begin))
69
hwloc_bitmap_alloc(void)70 struct hwloc_bitmap_s * hwloc_bitmap_alloc(void)
71 {
72 struct hwloc_bitmap_s * set;
73
74 set = malloc(sizeof(struct hwloc_bitmap_s));
75 if (!set)
76 return NULL;
77
78 set->ulongs_count = 1;
79 set->ulongs_allocated = 64/sizeof(unsigned long);
80 set->ulongs = malloc(64);
81 if (!set->ulongs) {
82 free(set);
83 return NULL;
84 }
85
86 set->ulongs[0] = HWLOC_SUBBITMAP_ZERO;
87 set->infinite = 0;
88 #ifdef HWLOC_DEBUG
89 set->magic = HWLOC_BITMAP_MAGIC;
90 #endif
91 return set;
92 }
93
hwloc_bitmap_alloc_full(void)94 struct hwloc_bitmap_s * hwloc_bitmap_alloc_full(void)
95 {
96 struct hwloc_bitmap_s * set = hwloc_bitmap_alloc();
97 if (set) {
98 set->infinite = 1;
99 set->ulongs[0] = HWLOC_SUBBITMAP_FULL;
100 }
101 return set;
102 }
103
hwloc_bitmap_free(struct hwloc_bitmap_s * set)104 void hwloc_bitmap_free(struct hwloc_bitmap_s * set)
105 {
106 if (!set)
107 return;
108
109 HWLOC__BITMAP_CHECK(set);
110 #ifdef HWLOC_DEBUG
111 set->magic = 0;
112 #endif
113
114 free(set->ulongs);
115 free(set);
116 }
117
118 /* enlarge until it contains at least needed_count ulongs.
119 */
120 static void
hwloc_bitmap_enlarge_by_ulongs(struct hwloc_bitmap_s * set,unsigned needed_count)121 hwloc_bitmap_enlarge_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count)
122 {
123 unsigned tmp = 1 << hwloc_flsl((unsigned long) needed_count - 1);
124 if (tmp > set->ulongs_allocated) {
125 set->ulongs = realloc(set->ulongs, tmp * sizeof(unsigned long));
126 assert(set->ulongs);
127 set->ulongs_allocated = tmp;
128 }
129 }
130
131 /* enlarge until it contains at least needed_count ulongs,
132 * and update new ulongs according to the infinite field.
133 */
134 static void
hwloc_bitmap_realloc_by_ulongs(struct hwloc_bitmap_s * set,unsigned needed_count)135 hwloc_bitmap_realloc_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count)
136 {
137 unsigned i;
138
139 HWLOC__BITMAP_CHECK(set);
140
141 if (needed_count <= set->ulongs_count)
142 return;
143
144 /* realloc larger if needed */
145 hwloc_bitmap_enlarge_by_ulongs(set, needed_count);
146
147 /* fill the newly allocated subset depending on the infinite flag */
148 for(i=set->ulongs_count; i<needed_count; i++)
149 set->ulongs[i] = set->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
150 set->ulongs_count = needed_count;
151 }
152
153 /* realloc until it contains at least cpu+1 bits */
154 #define hwloc_bitmap_realloc_by_cpu_index(set, cpu) hwloc_bitmap_realloc_by_ulongs(set, ((cpu)/HWLOC_BITS_PER_LONG)+1)
155
156 /* reset a bitmap to exactely the needed size.
157 * the caller must reinitialize all ulongs and the infinite flag later.
158 */
159 static void
hwloc_bitmap_reset_by_ulongs(struct hwloc_bitmap_s * set,unsigned needed_count)160 hwloc_bitmap_reset_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count)
161 {
162 hwloc_bitmap_enlarge_by_ulongs(set, needed_count);
163 set->ulongs_count = needed_count;
164 }
165
166 /* reset until it contains exactly cpu+1 bits (roundup to a ulong).
167 * the caller must reinitialize all ulongs and the infinite flag later.
168 */
169 #define hwloc_bitmap_reset_by_cpu_index(set, cpu) hwloc_bitmap_reset_by_ulongs(set, ((cpu)/HWLOC_BITS_PER_LONG)+1)
170
hwloc_bitmap_dup(const struct hwloc_bitmap_s * old)171 struct hwloc_bitmap_s * hwloc_bitmap_dup(const struct hwloc_bitmap_s * old)
172 {
173 struct hwloc_bitmap_s * new;
174
175 if (!old)
176 return NULL;
177
178 HWLOC__BITMAP_CHECK(old);
179
180 new = malloc(sizeof(struct hwloc_bitmap_s));
181 if (!new)
182 return NULL;
183
184 new->ulongs = malloc(old->ulongs_allocated * sizeof(unsigned long));
185 if (!new->ulongs) {
186 free(new);
187 return NULL;
188 }
189 new->ulongs_allocated = old->ulongs_allocated;
190 new->ulongs_count = old->ulongs_count;
191 memcpy(new->ulongs, old->ulongs, new->ulongs_count * sizeof(unsigned long));
192 new->infinite = old->infinite;
193 #ifdef HWLOC_DEBUG
194 new->magic = HWLOC_BITMAP_MAGIC;
195 #endif
196 return new;
197 }
198
hwloc_bitmap_copy(struct hwloc_bitmap_s * dst,const struct hwloc_bitmap_s * src)199 void hwloc_bitmap_copy(struct hwloc_bitmap_s * dst, const struct hwloc_bitmap_s * src)
200 {
201 HWLOC__BITMAP_CHECK(dst);
202 HWLOC__BITMAP_CHECK(src);
203
204 hwloc_bitmap_reset_by_ulongs(dst, src->ulongs_count);
205
206 memcpy(dst->ulongs, src->ulongs, src->ulongs_count * sizeof(unsigned long));
207 dst->infinite = src->infinite;
208 }
209
210 /* Strings always use 32bit groups */
211 #define HWLOC_PRIxSUBBITMAP "%08lx"
212 #define HWLOC_BITMAP_SUBSTRING_SIZE 32
213 #define HWLOC_BITMAP_SUBSTRING_LENGTH (HWLOC_BITMAP_SUBSTRING_SIZE/4)
214 #define HWLOC_BITMAP_STRING_PER_LONG (HWLOC_BITS_PER_LONG/HWLOC_BITMAP_SUBSTRING_SIZE)
215
hwloc_bitmap_snprintf(char * __hwloc_restrict buf,size_t buflen,const struct hwloc_bitmap_s * __hwloc_restrict set)216 int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set)
217 {
218 ssize_t size = buflen;
219 char *tmp = buf;
220 int res, ret = 0;
221 int needcomma = 0;
222 int i;
223 unsigned long accum = 0;
224 int accumed = 0;
225 #if HWLOC_BITS_PER_LONG == HWLOC_BITMAP_SUBSTRING_SIZE
226 const unsigned long accum_mask = ~0UL;
227 #else /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
228 const unsigned long accum_mask = ((1UL << HWLOC_BITMAP_SUBSTRING_SIZE) - 1) << (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE);
229 #endif /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
230
231 HWLOC__BITMAP_CHECK(set);
232
233 /* mark the end in case we do nothing later */
234 if (buflen > 0)
235 tmp[0] = '\0';
236
237 if (set->infinite) {
238 res = hwloc_snprintf(tmp, size, "0xf...f");
239 needcomma = 1;
240 if (res < 0)
241 return -1;
242 ret += res;
243 if (res >= size)
244 res = size>0 ? (int)size - 1 : 0;
245 tmp += res;
246 size -= res;
247 }
248
249 i=set->ulongs_count-1;
250
251 if (set->infinite) {
252 /* ignore starting FULL since we have 0xf...f already */
253 while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_FULL)
254 i--;
255 } else {
256 /* ignore starting ZERO except the last one */
257 while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_ZERO)
258 i--;
259 }
260
261 while (i>=0 || accumed) {
262 /* Refill accumulator */
263 if (!accumed) {
264 accum = set->ulongs[i--];
265 accumed = HWLOC_BITS_PER_LONG;
266 }
267
268 if (accum & accum_mask) {
269 /* print the whole subset if not empty */
270 res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP,
271 (accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE));
272 needcomma = 1;
273 } else if (i == -1 && accumed == HWLOC_BITMAP_SUBSTRING_SIZE) {
274 /* print a single 0 to mark the last subset */
275 res = hwloc_snprintf(tmp, size, needcomma ? ",0x0" : "0x0");
276 } else if (needcomma) {
277 res = hwloc_snprintf(tmp, size, ",");
278 } else {
279 res = 0;
280 }
281 if (res < 0)
282 return -1;
283 ret += res;
284
285 #if HWLOC_BITS_PER_LONG == HWLOC_BITMAP_SUBSTRING_SIZE
286 accum = 0;
287 accumed = 0;
288 #else
289 accum <<= HWLOC_BITMAP_SUBSTRING_SIZE;
290 accumed -= HWLOC_BITMAP_SUBSTRING_SIZE;
291 #endif
292
293 if (res >= size)
294 res = size>0 ? (int)size - 1 : 0;
295
296 tmp += res;
297 size -= res;
298 }
299
300 /* if didn't display anything, display 0x0 */
301 if (!ret) {
302 res = hwloc_snprintf(tmp, size, "0x0");
303 if (res < 0)
304 return -1;
305 ret += res;
306 }
307
308 return ret;
309 }
310
hwloc_bitmap_asprintf(char ** strp,const struct hwloc_bitmap_s * __hwloc_restrict set)311 int hwloc_bitmap_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set)
312 {
313 int len;
314 char *buf;
315
316 HWLOC__BITMAP_CHECK(set);
317
318 len = hwloc_bitmap_snprintf(NULL, 0, set);
319 buf = malloc(len+1);
320 *strp = buf;
321 return hwloc_bitmap_snprintf(buf, len+1, set);
322 }
323
hwloc_bitmap_sscanf(struct hwloc_bitmap_s * set,const char * __hwloc_restrict string)324 int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string)
325 {
326 const char * current = string;
327 unsigned long accum = 0;
328 int count=0;
329 int infinite = 0;
330
331 /* count how many substrings there are */
332 count++;
333 while ((current = strchr(current+1, ',')) != NULL)
334 count++;
335
336 current = string;
337 if (!strncmp("0xf...f", current, 7)) {
338 current += 7;
339 if (*current != ',') {
340 /* special case for infinite/full bitmap */
341 hwloc_bitmap_fill(set);
342 return 0;
343 }
344 current++;
345 infinite = 1;
346 count--;
347 }
348
349 hwloc_bitmap_reset_by_ulongs(set, (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG);
350 set->infinite = 0;
351
352 while (*current != '\0') {
353 unsigned long val;
354 char *next;
355 val = strtoul(current, &next, 16);
356
357 assert(count > 0);
358 count--;
359
360 accum |= (val << ((count * HWLOC_BITMAP_SUBSTRING_SIZE) % HWLOC_BITS_PER_LONG));
361 if (!(count % HWLOC_BITMAP_STRING_PER_LONG)) {
362 set->ulongs[count / HWLOC_BITMAP_STRING_PER_LONG] = accum;
363 accum = 0;
364 }
365
366 if (*next != ',') {
367 if (*next || count > 0)
368 goto failed;
369 else
370 break;
371 }
372 current = (const char*) next+1;
373 }
374
375 set->infinite = infinite; /* set at the end, to avoid spurious realloc with filled new ulongs */
376
377 return 0;
378
379 failed:
380 /* failure to parse */
381 hwloc_bitmap_zero(set);
382 return -1;
383 }
384
hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf,size_t buflen,const struct hwloc_bitmap_s * __hwloc_restrict set)385 int hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set)
386 {
387 int prev = -1;
388 hwloc_bitmap_t reverse;
389 ssize_t size = buflen;
390 char *tmp = buf;
391 int res, ret = 0;
392 int needcomma = 0;
393
394 HWLOC__BITMAP_CHECK(set);
395
396 reverse = hwloc_bitmap_alloc(); /* FIXME: add hwloc_bitmap_alloc_size() + hwloc_bitmap_init_allocated() to avoid malloc? */
397 hwloc_bitmap_not(reverse, set);
398
399 /* mark the end in case we do nothing later */
400 if (buflen > 0)
401 tmp[0] = '\0';
402
403 while (1) {
404 int begin, end;
405
406 begin = hwloc_bitmap_next(set, prev);
407 if (begin == -1)
408 break;
409 end = hwloc_bitmap_next(reverse, begin);
410
411 if (end == begin+1) {
412 res = hwloc_snprintf(tmp, size, needcomma ? ",%d" : "%d", begin);
413 } else if (end == -1) {
414 res = hwloc_snprintf(tmp, size, needcomma ? ",%d-" : "%d-", begin);
415 } else {
416 res = hwloc_snprintf(tmp, size, needcomma ? ",%d-%d" : "%d-%d", begin, end-1);
417 }
418 if (res < 0) {
419 hwloc_bitmap_free(reverse);
420 return -1;
421 }
422 ret += res;
423
424 if (res >= size)
425 res = size>0 ? (int)size - 1 : 0;
426
427 tmp += res;
428 size -= res;
429 needcomma = 1;
430
431 if (end == -1)
432 break;
433 else
434 prev = end - 1;
435 }
436
437 hwloc_bitmap_free(reverse);
438
439 return ret;
440 }
441
hwloc_bitmap_list_asprintf(char ** strp,const struct hwloc_bitmap_s * __hwloc_restrict set)442 int hwloc_bitmap_list_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set)
443 {
444 int len;
445 char *buf;
446
447 HWLOC__BITMAP_CHECK(set);
448
449 len = hwloc_bitmap_list_snprintf(NULL, 0, set);
450 buf = malloc(len+1);
451 *strp = buf;
452 return hwloc_bitmap_list_snprintf(buf, len+1, set);
453 }
454
hwloc_bitmap_list_sscanf(struct hwloc_bitmap_s * set,const char * __hwloc_restrict string)455 int hwloc_bitmap_list_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string)
456 {
457 const char * current = string;
458 char *next;
459 long begin = -1, val;
460
461 hwloc_bitmap_zero(set);
462
463 while (*current != '\0') {
464
465 /* ignore empty ranges */
466 while (*current == ',')
467 current++;
468
469 val = strtoul(current, &next, 0);
470 /* make sure we got at least one digit */
471 if (next == current)
472 goto failed;
473
474 if (begin != -1) {
475 /* finishing a range */
476 hwloc_bitmap_set_range(set, begin, val);
477 begin = -1;
478
479 } else if (*next == '-') {
480 /* starting a new range */
481 if (*(next+1) == '\0') {
482 /* infinite range */
483 hwloc_bitmap_set_range(set, val, -1);
484 break;
485 } else {
486 /* normal range */
487 begin = val;
488 }
489
490 } else if (*next == ',' || *next == '\0') {
491 /* single digit */
492 hwloc_bitmap_set(set, val);
493 }
494
495 if (*next == '\0')
496 break;
497 current = next+1;
498 }
499
500 return 0;
501
502 failed:
503 /* failure to parse */
504 hwloc_bitmap_zero(set);
505 return -1;
506 }
507
hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf,size_t buflen,const struct hwloc_bitmap_s * __hwloc_restrict set)508 int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set)
509 {
510 ssize_t size = buflen;
511 char *tmp = buf;
512 int res, ret = 0;
513 int started = 0;
514 int i;
515
516 HWLOC__BITMAP_CHECK(set);
517
518 /* mark the end in case we do nothing later */
519 if (buflen > 0)
520 tmp[0] = '\0';
521
522 if (set->infinite) {
523 res = hwloc_snprintf(tmp, size, "0xf...f");
524 started = 1;
525 if (res < 0)
526 return -1;
527 ret += res;
528 if (res >= size)
529 res = size>0 ? (int)size - 1 : 0;
530 tmp += res;
531 size -= res;
532 }
533
534 i=set->ulongs_count-1;
535
536 if (set->infinite) {
537 /* ignore starting FULL since we have 0xf...f already */
538 while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_FULL)
539 i--;
540 } else {
541 /* ignore starting ZERO except the last one */
542 while (i>=1 && set->ulongs[i] == HWLOC_SUBBITMAP_ZERO)
543 i--;
544 }
545
546 while (i>=0) {
547 unsigned long val = set->ulongs[i--];
548 if (started) {
549 /* print the whole subset */
550 #if HWLOC_BITS_PER_LONG == 64
551 res = hwloc_snprintf(tmp, size, "%016lx", val);
552 #else
553 res = hwloc_snprintf(tmp, size, "%08lx", val);
554 #endif
555 } else if (val || i == -1) {
556 res = hwloc_snprintf(tmp, size, "0x%lx", val);
557 started = 1;
558 } else {
559 res = 0;
560 }
561 if (res < 0)
562 return -1;
563 ret += res;
564 if (res >= size)
565 res = size>0 ? (int)size - 1 : 0;
566 tmp += res;
567 size -= res;
568 }
569
570 /* if didn't display anything, display 0x0 */
571 if (!ret) {
572 res = hwloc_snprintf(tmp, size, "0x0");
573 if (res < 0)
574 return -1;
575 ret += res;
576 }
577
578 return ret;
579 }
580
hwloc_bitmap_taskset_asprintf(char ** strp,const struct hwloc_bitmap_s * __hwloc_restrict set)581 int hwloc_bitmap_taskset_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set)
582 {
583 int len;
584 char *buf;
585
586 HWLOC__BITMAP_CHECK(set);
587
588 len = hwloc_bitmap_taskset_snprintf(NULL, 0, set);
589 buf = malloc(len+1);
590 *strp = buf;
591 return hwloc_bitmap_taskset_snprintf(buf, len+1, set);
592 }
593
hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s * set,const char * __hwloc_restrict string)594 int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string)
595 {
596 const char * current = string;
597 int chars;
598 int count;
599 int infinite = 0;
600
601 if (!strncmp("0xf...f", current, 7)) {
602 /* infinite bitmap */
603 infinite = 1;
604 current += 7;
605 if (*current == '\0') {
606 /* special case for infinite/full bitmap */
607 hwloc_bitmap_fill(set);
608 return 0;
609 }
610 } else {
611 /* finite bitmap */
612 if (!strncmp("0x", current, 2))
613 current += 2;
614 if (*current == '\0') {
615 /* special case for empty bitmap */
616 hwloc_bitmap_zero(set);
617 return 0;
618 }
619 }
620 /* we know there are other characters now */
621
622 chars = (int)strlen(current);
623 count = (chars * 4 + HWLOC_BITS_PER_LONG - 1) / HWLOC_BITS_PER_LONG;
624
625 hwloc_bitmap_reset_by_ulongs(set, count);
626 set->infinite = 0;
627
628 while (*current != '\0') {
629 int tmpchars;
630 char ustr[17];
631 unsigned long val;
632 char *next;
633
634 tmpchars = chars % (HWLOC_BITS_PER_LONG/4);
635 if (!tmpchars)
636 tmpchars = (HWLOC_BITS_PER_LONG/4);
637
638 memcpy(ustr, current, tmpchars);
639 ustr[tmpchars] = '\0';
640 val = strtoul(ustr, &next, 16);
641 if (*next != '\0')
642 goto failed;
643
644 set->ulongs[count-1] = val;
645
646 current += tmpchars;
647 chars -= tmpchars;
648 count--;
649 }
650
651 set->infinite = infinite; /* set at the end, to avoid spurious realloc with filled new ulongs */
652
653 return 0;
654
655 failed:
656 /* failure to parse */
657 hwloc_bitmap_zero(set);
658 return -1;
659 }
660
hwloc_bitmap__zero(struct hwloc_bitmap_s * set)661 static void hwloc_bitmap__zero(struct hwloc_bitmap_s *set)
662 {
663 unsigned i;
664 for(i=0; i<set->ulongs_count; i++)
665 set->ulongs[i] = HWLOC_SUBBITMAP_ZERO;
666 set->infinite = 0;
667 }
668
hwloc_bitmap_zero(struct hwloc_bitmap_s * set)669 void hwloc_bitmap_zero(struct hwloc_bitmap_s * set)
670 {
671 HWLOC__BITMAP_CHECK(set);
672
673 hwloc_bitmap_reset_by_ulongs(set, 1);
674 hwloc_bitmap__zero(set);
675 }
676
hwloc_bitmap__fill(struct hwloc_bitmap_s * set)677 static void hwloc_bitmap__fill(struct hwloc_bitmap_s * set)
678 {
679 unsigned i;
680 for(i=0; i<set->ulongs_count; i++)
681 set->ulongs[i] = HWLOC_SUBBITMAP_FULL;
682 set->infinite = 1;
683 }
684
hwloc_bitmap_fill(struct hwloc_bitmap_s * set)685 void hwloc_bitmap_fill(struct hwloc_bitmap_s * set)
686 {
687 HWLOC__BITMAP_CHECK(set);
688
689 hwloc_bitmap_reset_by_ulongs(set, 1);
690 hwloc_bitmap__fill(set);
691 }
692
hwloc_bitmap_from_ulong(struct hwloc_bitmap_s * set,unsigned long mask)693 void hwloc_bitmap_from_ulong(struct hwloc_bitmap_s *set, unsigned long mask)
694 {
695 HWLOC__BITMAP_CHECK(set);
696
697 hwloc_bitmap_reset_by_ulongs(set, 1);
698 set->ulongs[0] = mask; /* there's always at least one ulong allocated */
699 set->infinite = 0;
700 }
701
hwloc_bitmap_from_ith_ulong(struct hwloc_bitmap_s * set,unsigned i,unsigned long mask)702 void hwloc_bitmap_from_ith_ulong(struct hwloc_bitmap_s *set, unsigned i, unsigned long mask)
703 {
704 unsigned j;
705
706 HWLOC__BITMAP_CHECK(set);
707
708 hwloc_bitmap_reset_by_ulongs(set, i+1);
709 set->ulongs[i] = mask;
710 for(j=0; j<i; j++)
711 set->ulongs[j] = HWLOC_SUBBITMAP_ZERO;
712 set->infinite = 0;
713 }
714
hwloc_bitmap_to_ulong(const struct hwloc_bitmap_s * set)715 unsigned long hwloc_bitmap_to_ulong(const struct hwloc_bitmap_s *set)
716 {
717 HWLOC__BITMAP_CHECK(set);
718
719 return set->ulongs[0]; /* there's always at least one ulong allocated */
720 }
721
hwloc_bitmap_to_ith_ulong(const struct hwloc_bitmap_s * set,unsigned i)722 unsigned long hwloc_bitmap_to_ith_ulong(const struct hwloc_bitmap_s *set, unsigned i)
723 {
724 HWLOC__BITMAP_CHECK(set);
725
726 return HWLOC_SUBBITMAP_READULONG(set, i);
727 }
728
hwloc_bitmap_only(struct hwloc_bitmap_s * set,unsigned cpu)729 void hwloc_bitmap_only(struct hwloc_bitmap_s * set, unsigned cpu)
730 {
731 unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu);
732
733 HWLOC__BITMAP_CHECK(set);
734
735 hwloc_bitmap_reset_by_cpu_index(set, cpu);
736 hwloc_bitmap__zero(set);
737 set->ulongs[index_] |= HWLOC_SUBBITMAP_CPU(cpu);
738 }
739
hwloc_bitmap_allbut(struct hwloc_bitmap_s * set,unsigned cpu)740 void hwloc_bitmap_allbut(struct hwloc_bitmap_s * set, unsigned cpu)
741 {
742 unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu);
743
744 HWLOC__BITMAP_CHECK(set);
745
746 hwloc_bitmap_reset_by_cpu_index(set, cpu);
747 hwloc_bitmap__fill(set);
748 set->ulongs[index_] &= ~HWLOC_SUBBITMAP_CPU(cpu);
749 }
750
hwloc_bitmap_set(struct hwloc_bitmap_s * set,unsigned cpu)751 void hwloc_bitmap_set(struct hwloc_bitmap_s * set, unsigned cpu)
752 {
753 unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu);
754
755 HWLOC__BITMAP_CHECK(set);
756
757 /* nothing to do if setting inside the infinite part of the bitmap */
758 if (set->infinite && cpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
759 return;
760
761 hwloc_bitmap_realloc_by_cpu_index(set, cpu);
762 set->ulongs[index_] |= HWLOC_SUBBITMAP_CPU(cpu);
763 }
764
hwloc_bitmap_set_range(struct hwloc_bitmap_s * set,unsigned begincpu,int _endcpu)765 void hwloc_bitmap_set_range(struct hwloc_bitmap_s * set, unsigned begincpu, int _endcpu)
766 {
767 unsigned i;
768 unsigned beginset,endset;
769 unsigned endcpu = (unsigned) _endcpu;
770
771 HWLOC__BITMAP_CHECK(set);
772
773 if (endcpu < begincpu)
774 return;
775 if (set->infinite && begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
776 /* setting only in the already-set infinite part, nothing to do */
777 return;
778
779 if (_endcpu == -1) {
780 /* infinite range */
781
782 /* make sure we can play with the ulong that contains begincpu */
783 hwloc_bitmap_realloc_by_cpu_index(set, begincpu);
784 /* update the ulong that contains begincpu */
785 beginset = HWLOC_SUBBITMAP_INDEX(begincpu);
786 set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu));
787 /* set ulongs after begincpu if any already allocated */
788 for(i=beginset+1; i<set->ulongs_count; i++)
789 set->ulongs[i] = HWLOC_SUBBITMAP_FULL;
790 /* mark the infinity as set */
791 set->infinite = 1;
792 } else {
793 /* finite range */
794
795 /* ignore the part of the range that overlaps with the already-set infinite part */
796 if (set->infinite && endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
797 endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1;
798 /* make sure we can play with the ulongs that contain begincpu and endcpu */
799 hwloc_bitmap_realloc_by_cpu_index(set, endcpu);
800 /* update first and last ulongs */
801 beginset = HWLOC_SUBBITMAP_INDEX(begincpu);
802 endset = HWLOC_SUBBITMAP_INDEX(endcpu);
803 if (beginset == endset) {
804 set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROMTO(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu), HWLOC_SUBBITMAP_CPU_ULBIT(endcpu));
805 } else {
806 set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu));
807 set->ulongs[endset] |= HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(endcpu));
808 }
809 /* set ulongs in the middle of the range */
810 for(i=beginset+1; i<endset; i++)
811 set->ulongs[i] = HWLOC_SUBBITMAP_FULL;
812 }
813 }
814
hwloc_bitmap_set_ith_ulong(struct hwloc_bitmap_s * set,unsigned i,unsigned long mask)815 void hwloc_bitmap_set_ith_ulong(struct hwloc_bitmap_s *set, unsigned i, unsigned long mask)
816 {
817 HWLOC__BITMAP_CHECK(set);
818
819 hwloc_bitmap_realloc_by_ulongs(set, i+1);
820 set->ulongs[i] = mask;
821 }
822
hwloc_bitmap_clr(struct hwloc_bitmap_s * set,unsigned cpu)823 void hwloc_bitmap_clr(struct hwloc_bitmap_s * set, unsigned cpu)
824 {
825 unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu);
826
827 HWLOC__BITMAP_CHECK(set);
828
829 /* nothing to do if clearing inside the infinitely-unset part of the bitmap */
830 if (!set->infinite && cpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
831 return;
832
833 hwloc_bitmap_realloc_by_cpu_index(set, cpu);
834 set->ulongs[index_] &= ~HWLOC_SUBBITMAP_CPU(cpu);
835 }
836
hwloc_bitmap_clr_range(struct hwloc_bitmap_s * set,unsigned begincpu,int _endcpu)837 void hwloc_bitmap_clr_range(struct hwloc_bitmap_s * set, unsigned begincpu, int _endcpu)
838 {
839 unsigned i;
840 unsigned beginset,endset;
841 unsigned endcpu = (unsigned) _endcpu;
842
843 HWLOC__BITMAP_CHECK(set);
844
845 if (endcpu < begincpu)
846 return;
847
848 if (!set->infinite && begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
849 /* clearing only in the already-unset infinite part, nothing to do */
850 return;
851
852 if (_endcpu == -1) {
853 /* infinite range */
854
855 /* make sure we can play with the ulong that contains begincpu */
856 hwloc_bitmap_realloc_by_cpu_index(set, begincpu);
857 /* update the ulong that contains begincpu */
858 beginset = HWLOC_SUBBITMAP_INDEX(begincpu);
859 set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu));
860 /* clear ulong after begincpu if any already allocated */
861 for(i=beginset+1; i<set->ulongs_count; i++)
862 set->ulongs[i] = HWLOC_SUBBITMAP_ZERO;
863 /* mark the infinity as unset */
864 set->infinite = 0;
865 } else {
866 /* finite range */
867
868 /* ignore the part of the range that overlaps with the already-unset infinite part */
869 if (!set->infinite && endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG)
870 endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1;
871 /* make sure we can play with the ulongs that contain begincpu and endcpu */
872 hwloc_bitmap_realloc_by_cpu_index(set, endcpu);
873 /* update first and last ulongs */
874 beginset = HWLOC_SUBBITMAP_INDEX(begincpu);
875 endset = HWLOC_SUBBITMAP_INDEX(endcpu);
876 if (beginset == endset) {
877 set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROMTO(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu), HWLOC_SUBBITMAP_CPU_ULBIT(endcpu));
878 } else {
879 set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu));
880 set->ulongs[endset] &= ~HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(endcpu));
881 }
882 /* clear ulongs in the middle of the range */
883 for(i=beginset+1; i<endset; i++)
884 set->ulongs[i] = HWLOC_SUBBITMAP_ZERO;
885 }
886 }
887
hwloc_bitmap_isset(const struct hwloc_bitmap_s * set,unsigned cpu)888 int hwloc_bitmap_isset(const struct hwloc_bitmap_s * set, unsigned cpu)
889 {
890 unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu);
891
892 HWLOC__BITMAP_CHECK(set);
893
894 return (HWLOC_SUBBITMAP_READULONG(set, index_) & HWLOC_SUBBITMAP_CPU(cpu)) != 0;
895 }
896
hwloc_bitmap_iszero(const struct hwloc_bitmap_s * set)897 int hwloc_bitmap_iszero(const struct hwloc_bitmap_s *set)
898 {
899 unsigned i;
900
901 HWLOC__BITMAP_CHECK(set);
902
903 if (set->infinite)
904 return 0;
905 for(i=0; i<set->ulongs_count; i++)
906 if (set->ulongs[i] != HWLOC_SUBBITMAP_ZERO)
907 return 0;
908 return 1;
909 }
910
hwloc_bitmap_isfull(const struct hwloc_bitmap_s * set)911 int hwloc_bitmap_isfull(const struct hwloc_bitmap_s *set)
912 {
913 unsigned i;
914
915 HWLOC__BITMAP_CHECK(set);
916
917 if (!set->infinite)
918 return 0;
919 for(i=0; i<set->ulongs_count; i++)
920 if (set->ulongs[i] != HWLOC_SUBBITMAP_FULL)
921 return 0;
922 return 1;
923 }
924
hwloc_bitmap_isequal(const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)925 int hwloc_bitmap_isequal (const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
926 {
927 unsigned count1 = set1->ulongs_count;
928 unsigned count2 = set2->ulongs_count;
929 unsigned min_count = count1 < count2 ? count1 : count2;
930 unsigned i;
931
932 HWLOC__BITMAP_CHECK(set1);
933 HWLOC__BITMAP_CHECK(set2);
934
935 for(i=0; i<min_count; i++)
936 if (set1->ulongs[i] != set2->ulongs[i])
937 return 0;
938
939 if (count1 != count2) {
940 unsigned long w1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
941 unsigned long w2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
942 for(i=min_count; i<count1; i++) {
943 if (set1->ulongs[i] != w2)
944 return 0;
945 }
946 for(i=min_count; i<count2; i++) {
947 if (set2->ulongs[i] != w1)
948 return 0;
949 }
950 }
951
952 if (set1->infinite != set2->infinite)
953 return 0;
954
955 return 1;
956 }
957
hwloc_bitmap_intersects(const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)958 int hwloc_bitmap_intersects (const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
959 {
960 unsigned count1 = set1->ulongs_count;
961 unsigned count2 = set2->ulongs_count;
962 unsigned min_count = count1 < count2 ? count1 : count2;
963 unsigned i;
964
965 HWLOC__BITMAP_CHECK(set1);
966 HWLOC__BITMAP_CHECK(set2);
967
968 for(i=0; i<min_count; i++)
969 if (set1->ulongs[i] & set2->ulongs[i])
970 return 1;
971
972 if (count1 != count2) {
973 if (set2->infinite) {
974 for(i=min_count; i<set1->ulongs_count; i++)
975 if (set1->ulongs[i])
976 return 1;
977 }
978 if (set1->infinite) {
979 for(i=min_count; i<set2->ulongs_count; i++)
980 if (set2->ulongs[i])
981 return 1;
982 }
983 }
984
985 if (set1->infinite && set2->infinite)
986 return 1;
987
988 return 0;
989 }
990
hwloc_bitmap_isincluded(const struct hwloc_bitmap_s * sub_set,const struct hwloc_bitmap_s * super_set)991 int hwloc_bitmap_isincluded (const struct hwloc_bitmap_s *sub_set, const struct hwloc_bitmap_s *super_set)
992 {
993 unsigned super_count = super_set->ulongs_count;
994 unsigned sub_count = sub_set->ulongs_count;
995 unsigned min_count = super_count < sub_count ? super_count : sub_count;
996 unsigned i;
997
998 HWLOC__BITMAP_CHECK(sub_set);
999 HWLOC__BITMAP_CHECK(super_set);
1000
1001 for(i=0; i<min_count; i++)
1002 if (super_set->ulongs[i] != (super_set->ulongs[i] | sub_set->ulongs[i]))
1003 return 0;
1004
1005 if (super_count != sub_count) {
1006 if (!super_set->infinite)
1007 for(i=min_count; i<sub_count; i++)
1008 if (sub_set->ulongs[i])
1009 return 0;
1010 if (sub_set->infinite)
1011 for(i=min_count; i<super_count; i++)
1012 if (super_set->ulongs[i] != HWLOC_SUBBITMAP_FULL)
1013 return 0;
1014 }
1015
1016 if (sub_set->infinite && !super_set->infinite)
1017 return 0;
1018
1019 return 1;
1020 }
1021
hwloc_bitmap_or(struct hwloc_bitmap_s * res,const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1022 void hwloc_bitmap_or (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
1023 {
1024 /* cache counts so that we can reset res even if it's also set1 or set2 */
1025 unsigned count1 = set1->ulongs_count;
1026 unsigned count2 = set2->ulongs_count;
1027 unsigned max_count = count1 > count2 ? count1 : count2;
1028 unsigned min_count = count1 + count2 - max_count;
1029 unsigned i;
1030
1031 HWLOC__BITMAP_CHECK(res);
1032 HWLOC__BITMAP_CHECK(set1);
1033 HWLOC__BITMAP_CHECK(set2);
1034
1035 hwloc_bitmap_reset_by_ulongs(res, max_count);
1036
1037 for(i=0; i<min_count; i++)
1038 res->ulongs[i] = set1->ulongs[i] | set2->ulongs[i];
1039
1040 if (count1 != count2) {
1041 if (min_count < count1) {
1042 if (set2->infinite) {
1043 res->ulongs_count = min_count;
1044 } else {
1045 for(i=min_count; i<max_count; i++)
1046 res->ulongs[i] = set1->ulongs[i];
1047 }
1048 } else {
1049 if (set1->infinite) {
1050 res->ulongs_count = min_count;
1051 } else {
1052 for(i=min_count; i<max_count; i++)
1053 res->ulongs[i] = set2->ulongs[i];
1054 }
1055 }
1056 }
1057
1058 res->infinite = set1->infinite || set2->infinite;
1059 }
1060
hwloc_bitmap_and(struct hwloc_bitmap_s * res,const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1061 void hwloc_bitmap_and (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
1062 {
1063 /* cache counts so that we can reset res even if it's also set1 or set2 */
1064 unsigned count1 = set1->ulongs_count;
1065 unsigned count2 = set2->ulongs_count;
1066 unsigned max_count = count1 > count2 ? count1 : count2;
1067 unsigned min_count = count1 + count2 - max_count;
1068 unsigned i;
1069
1070 HWLOC__BITMAP_CHECK(res);
1071 HWLOC__BITMAP_CHECK(set1);
1072 HWLOC__BITMAP_CHECK(set2);
1073
1074 hwloc_bitmap_reset_by_ulongs(res, max_count);
1075
1076 for(i=0; i<min_count; i++)
1077 res->ulongs[i] = set1->ulongs[i] & set2->ulongs[i];
1078
1079 if (count1 != count2) {
1080 if (min_count < count1) {
1081 if (set2->infinite) {
1082 for(i=min_count; i<max_count; i++)
1083 res->ulongs[i] = set1->ulongs[i];
1084 } else {
1085 res->ulongs_count = min_count;
1086 }
1087 } else {
1088 if (set1->infinite) {
1089 for(i=min_count; i<max_count; i++)
1090 res->ulongs[i] = set2->ulongs[i];
1091 } else {
1092 res->ulongs_count = min_count;
1093 }
1094 }
1095 }
1096
1097 res->infinite = set1->infinite && set2->infinite;
1098 }
1099
hwloc_bitmap_andnot(struct hwloc_bitmap_s * res,const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1100 void hwloc_bitmap_andnot (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
1101 {
1102 /* cache counts so that we can reset res even if it's also set1 or set2 */
1103 unsigned count1 = set1->ulongs_count;
1104 unsigned count2 = set2->ulongs_count;
1105 unsigned max_count = count1 > count2 ? count1 : count2;
1106 unsigned min_count = count1 + count2 - max_count;
1107 unsigned i;
1108
1109 HWLOC__BITMAP_CHECK(res);
1110 HWLOC__BITMAP_CHECK(set1);
1111 HWLOC__BITMAP_CHECK(set2);
1112
1113 hwloc_bitmap_reset_by_ulongs(res, max_count);
1114
1115 for(i=0; i<min_count; i++)
1116 res->ulongs[i] = set1->ulongs[i] & ~set2->ulongs[i];
1117
1118 if (count1 != count2) {
1119 if (min_count < count1) {
1120 if (!set2->infinite) {
1121 for(i=min_count; i<max_count; i++)
1122 res->ulongs[i] = set1->ulongs[i];
1123 } else {
1124 res->ulongs_count = min_count;
1125 }
1126 } else {
1127 if (set1->infinite) {
1128 for(i=min_count; i<max_count; i++)
1129 res->ulongs[i] = ~set2->ulongs[i];
1130 } else {
1131 res->ulongs_count = min_count;
1132 }
1133 }
1134 }
1135
1136 res->infinite = set1->infinite && !set2->infinite;
1137 }
1138
hwloc_bitmap_xor(struct hwloc_bitmap_s * res,const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1139 void hwloc_bitmap_xor (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2)
1140 {
1141 /* cache counts so that we can reset res even if it's also set1 or set2 */
1142 unsigned count1 = set1->ulongs_count;
1143 unsigned count2 = set2->ulongs_count;
1144 unsigned max_count = count1 > count2 ? count1 : count2;
1145 unsigned min_count = count1 + count2 - max_count;
1146 unsigned i;
1147
1148 HWLOC__BITMAP_CHECK(res);
1149 HWLOC__BITMAP_CHECK(set1);
1150 HWLOC__BITMAP_CHECK(set2);
1151
1152 hwloc_bitmap_reset_by_ulongs(res, max_count);
1153
1154 for(i=0; i<min_count; i++)
1155 res->ulongs[i] = set1->ulongs[i] ^ set2->ulongs[i];
1156
1157 if (count1 != count2) {
1158 if (min_count < count1) {
1159 unsigned long w2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
1160 for(i=min_count; i<max_count; i++)
1161 res->ulongs[i] = set1->ulongs[i] ^ w2;
1162 } else {
1163 unsigned long w1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
1164 for(i=min_count; i<max_count; i++)
1165 res->ulongs[i] = set2->ulongs[i] ^ w1;
1166 }
1167 }
1168
1169 res->infinite = (!set1->infinite) != (!set2->infinite);
1170 }
1171
hwloc_bitmap_not(struct hwloc_bitmap_s * res,const struct hwloc_bitmap_s * set)1172 void hwloc_bitmap_not (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set)
1173 {
1174 unsigned count = set->ulongs_count;
1175 unsigned i;
1176
1177 HWLOC__BITMAP_CHECK(res);
1178 HWLOC__BITMAP_CHECK(set);
1179
1180 hwloc_bitmap_reset_by_ulongs(res, count);
1181
1182 for(i=0; i<count; i++)
1183 res->ulongs[i] = ~set->ulongs[i];
1184
1185 res->infinite = !set->infinite;
1186 }
1187
hwloc_bitmap_first(const struct hwloc_bitmap_s * set)1188 int hwloc_bitmap_first(const struct hwloc_bitmap_s * set)
1189 {
1190 unsigned i;
1191
1192 HWLOC__BITMAP_CHECK(set);
1193
1194 for(i=0; i<set->ulongs_count; i++) {
1195 /* subsets are unsigned longs, use ffsl */
1196 unsigned long w = set->ulongs[i];
1197 if (w)
1198 return hwloc_ffsl(w) - 1 + HWLOC_BITS_PER_LONG*i;
1199 }
1200
1201 if (set->infinite)
1202 return set->ulongs_count * HWLOC_BITS_PER_LONG;
1203
1204 return -1;
1205 }
1206
hwloc_bitmap_last(const struct hwloc_bitmap_s * set)1207 int hwloc_bitmap_last(const struct hwloc_bitmap_s * set)
1208 {
1209 int i;
1210
1211 HWLOC__BITMAP_CHECK(set);
1212
1213 if (set->infinite)
1214 return -1;
1215
1216 for(i=set->ulongs_count-1; i>=0; i--) {
1217 /* subsets are unsigned longs, use flsl */
1218 unsigned long w = set->ulongs[i];
1219 if (w)
1220 return hwloc_flsl(w) - 1 + HWLOC_BITS_PER_LONG*i;
1221 }
1222
1223 return -1;
1224 }
1225
hwloc_bitmap_next(const struct hwloc_bitmap_s * set,int prev_cpu)1226 int hwloc_bitmap_next(const struct hwloc_bitmap_s * set, int prev_cpu)
1227 {
1228 unsigned i = HWLOC_SUBBITMAP_INDEX(prev_cpu + 1);
1229
1230 HWLOC__BITMAP_CHECK(set);
1231
1232 if (i >= set->ulongs_count) {
1233 if (set->infinite)
1234 return prev_cpu + 1;
1235 else
1236 return -1;
1237 }
1238
1239 for(; i<set->ulongs_count; i++) {
1240 /* subsets are unsigned longs, use ffsl */
1241 unsigned long w = set->ulongs[i];
1242
1243 /* if the prev cpu is in the same word as the possible next one,
1244 we need to mask out previous cpus */
1245 if (prev_cpu >= 0 && HWLOC_SUBBITMAP_INDEX((unsigned) prev_cpu) == i)
1246 w &= ~HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(prev_cpu));
1247
1248 if (w)
1249 return hwloc_ffsl(w) - 1 + HWLOC_BITS_PER_LONG*i;
1250 }
1251
1252 if (set->infinite)
1253 return set->ulongs_count * HWLOC_BITS_PER_LONG;
1254
1255 return -1;
1256 }
1257
hwloc_bitmap_singlify(struct hwloc_bitmap_s * set)1258 void hwloc_bitmap_singlify(struct hwloc_bitmap_s * set)
1259 {
1260 unsigned i;
1261 int found = 0;
1262
1263 HWLOC__BITMAP_CHECK(set);
1264
1265 for(i=0; i<set->ulongs_count; i++) {
1266 if (found) {
1267 set->ulongs[i] = HWLOC_SUBBITMAP_ZERO;
1268 continue;
1269 } else {
1270 /* subsets are unsigned longs, use ffsl */
1271 unsigned long w = set->ulongs[i];
1272 if (w) {
1273 int _ffs = hwloc_ffsl(w);
1274 set->ulongs[i] = HWLOC_SUBBITMAP_CPU(_ffs-1);
1275 found = 1;
1276 }
1277 }
1278 }
1279
1280 if (set->infinite) {
1281 if (found) {
1282 set->infinite = 0;
1283 } else {
1284 /* set the first non allocated bit */
1285 unsigned first = set->ulongs_count * HWLOC_BITS_PER_LONG;
1286 set->infinite = 0; /* do not let realloc fill the newly allocated sets */
1287 hwloc_bitmap_set(set, first);
1288 }
1289 }
1290 }
1291
hwloc_bitmap_compare_first(const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1292 int hwloc_bitmap_compare_first(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2)
1293 {
1294 unsigned count1 = set1->ulongs_count;
1295 unsigned count2 = set2->ulongs_count;
1296 unsigned max_count = count1 > count2 ? count1 : count2;
1297 unsigned min_count = count1 + count2 - max_count;
1298 unsigned i;
1299
1300 HWLOC__BITMAP_CHECK(set1);
1301 HWLOC__BITMAP_CHECK(set2);
1302
1303 for(i=0; i<min_count; i++) {
1304 unsigned long w1 = set1->ulongs[i];
1305 unsigned long w2 = set2->ulongs[i];
1306 if (w1 || w2) {
1307 int _ffs1 = hwloc_ffsl(w1);
1308 int _ffs2 = hwloc_ffsl(w2);
1309 /* if both have a bit set, compare for real */
1310 if (_ffs1 && _ffs2)
1311 return _ffs1-_ffs2;
1312 /* one is empty, and it is considered higher, so reverse-compare them */
1313 return _ffs2-_ffs1;
1314 }
1315 }
1316
1317 if (count1 != count2) {
1318 if (min_count < count2) {
1319 for(i=min_count; i<count2; i++) {
1320 unsigned long w2 = set2->ulongs[i];
1321 if (set1->infinite)
1322 return -!(w2 & 1);
1323 else if (w2)
1324 return 1;
1325 }
1326 } else {
1327 for(i=min_count; i<count1; i++) {
1328 unsigned long w1 = set1->ulongs[i];
1329 if (set2->infinite)
1330 return !(w1 & 1);
1331 else if (w1)
1332 return -1;
1333 }
1334 }
1335 }
1336
1337 return !!set1->infinite - !!set2->infinite;
1338 }
1339
hwloc_bitmap_compare(const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1340 int hwloc_bitmap_compare(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2)
1341 {
1342 unsigned count1 = set1->ulongs_count;
1343 unsigned count2 = set2->ulongs_count;
1344 unsigned max_count = count1 > count2 ? count1 : count2;
1345 unsigned min_count = count1 + count2 - max_count;
1346 int i;
1347
1348 HWLOC__BITMAP_CHECK(set1);
1349 HWLOC__BITMAP_CHECK(set2);
1350
1351 if ((!set1->infinite) != (!set2->infinite))
1352 return !!set1->infinite - !!set2->infinite;
1353
1354 if (count1 != count2) {
1355 if (min_count < count2) {
1356 unsigned long val1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
1357 for(i=max_count-1; i>=(signed) min_count; i--) {
1358 unsigned long val2 = set2->ulongs[i];
1359 if (val1 == val2)
1360 continue;
1361 return val1 < val2 ? -1 : 1;
1362 }
1363 } else {
1364 unsigned long val2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO;
1365 for(i=max_count-1; i>=(signed) min_count; i--) {
1366 unsigned long val1 = set1->ulongs[i];
1367 if (val1 == val2)
1368 continue;
1369 return val1 < val2 ? -1 : 1;
1370 }
1371 }
1372 }
1373
1374 for(i=min_count-1; i>=0; i--) {
1375 unsigned long val1 = set1->ulongs[i];
1376 unsigned long val2 = set2->ulongs[i];
1377 if (val1 == val2)
1378 continue;
1379 return val1 < val2 ? -1 : 1;
1380 }
1381
1382 return 0;
1383 }
1384
hwloc_bitmap_weight(const struct hwloc_bitmap_s * set)1385 int hwloc_bitmap_weight(const struct hwloc_bitmap_s * set)
1386 {
1387 int weight = 0;
1388 unsigned i;
1389
1390 HWLOC__BITMAP_CHECK(set);
1391
1392 if (set->infinite)
1393 return -1;
1394
1395 for(i=0; i<set->ulongs_count; i++)
1396 weight += hwloc_weight_long(set->ulongs[i]);
1397 return weight;
1398 }
1399
hwloc_bitmap_compare_inclusion(const struct hwloc_bitmap_s * set1,const struct hwloc_bitmap_s * set2)1400 int hwloc_bitmap_compare_inclusion(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2)
1401 {
1402 unsigned max_count = set1->ulongs_count > set2->ulongs_count ? set1->ulongs_count : set2->ulongs_count;
1403 int result = HWLOC_BITMAP_EQUAL; /* means empty sets return equal */
1404 int empty1 = 1;
1405 int empty2 = 1;
1406 unsigned i;
1407
1408 HWLOC__BITMAP_CHECK(set1);
1409 HWLOC__BITMAP_CHECK(set2);
1410
1411 for(i=0; i<max_count; i++) {
1412 unsigned long val1 = HWLOC_SUBBITMAP_READULONG(set1, (unsigned) i);
1413 unsigned long val2 = HWLOC_SUBBITMAP_READULONG(set2, (unsigned) i);
1414
1415 if (!val1) {
1416 if (!val2)
1417 /* both empty, no change */
1418 continue;
1419
1420 /* val1 empty, val2 not */
1421 if (result == HWLOC_BITMAP_CONTAINS) {
1422 if (!empty2)
1423 return HWLOC_BITMAP_INTERSECTS;
1424 result = HWLOC_BITMAP_DIFFERENT;
1425 } else if (result == HWLOC_BITMAP_EQUAL) {
1426 result = HWLOC_BITMAP_INCLUDED;
1427 }
1428 /* no change otherwise */
1429
1430 } else if (!val2) {
1431 /* val2 empty, val1 not */
1432 if (result == HWLOC_BITMAP_INCLUDED) {
1433 if (!empty1)
1434 return HWLOC_BITMAP_INTERSECTS;
1435 result = HWLOC_BITMAP_DIFFERENT;
1436 } else if (result == HWLOC_BITMAP_EQUAL) {
1437 result = HWLOC_BITMAP_CONTAINS;
1438 }
1439 /* no change otherwise */
1440
1441 } else if (val1 == val2) {
1442 /* equal and not empty */
1443 if (result == HWLOC_BITMAP_DIFFERENT)
1444 return HWLOC_BITMAP_INTERSECTS;
1445 /* equal/contains/included unchanged */
1446
1447 } else if ((val1 & val2) == val1) {
1448 /* included and not empty */
1449 if (result == HWLOC_BITMAP_CONTAINS || result == HWLOC_BITMAP_DIFFERENT)
1450 return HWLOC_BITMAP_INTERSECTS;
1451 /* equal/included unchanged */
1452 result = HWLOC_BITMAP_INCLUDED;
1453
1454 } else if ((val1 & val2) == val2) {
1455 /* contains and not empty */
1456 if (result == HWLOC_BITMAP_INCLUDED || result == HWLOC_BITMAP_DIFFERENT)
1457 return HWLOC_BITMAP_INTERSECTS;
1458 /* equal/contains unchanged */
1459 result = HWLOC_BITMAP_CONTAINS;
1460
1461 } else if ((val1 & val2) != 0) {
1462 /* intersects and not empty */
1463 return HWLOC_BITMAP_INTERSECTS;
1464
1465 } else {
1466 /* different and not empty */
1467
1468 /* equal/included/contains with non-empty sets means intersects */
1469 if (result == HWLOC_BITMAP_EQUAL && !empty1 /* implies !empty2 */)
1470 return HWLOC_BITMAP_INTERSECTS;
1471 if (result == HWLOC_BITMAP_INCLUDED && !empty1)
1472 return HWLOC_BITMAP_INTERSECTS;
1473 if (result == HWLOC_BITMAP_CONTAINS && !empty2)
1474 return HWLOC_BITMAP_INTERSECTS;
1475 /* otherwise means different */
1476 result = HWLOC_BITMAP_DIFFERENT;
1477 }
1478
1479 empty1 &= !val1;
1480 empty2 &= !val2;
1481 }
1482
1483 if (!set1->infinite) {
1484 if (set2->infinite) {
1485 /* set2 infinite only */
1486 if (result == HWLOC_BITMAP_CONTAINS) {
1487 if (!empty2)
1488 return HWLOC_BITMAP_INTERSECTS;
1489 result = HWLOC_BITMAP_DIFFERENT;
1490 } else if (result == HWLOC_BITMAP_EQUAL) {
1491 result = HWLOC_BITMAP_INCLUDED;
1492 }
1493 /* no change otherwise */
1494 }
1495 } else if (!set2->infinite) {
1496 /* set1 infinite only */
1497 if (result == HWLOC_BITMAP_INCLUDED) {
1498 if (!empty1)
1499 return HWLOC_BITMAP_INTERSECTS;
1500 result = HWLOC_BITMAP_DIFFERENT;
1501 } else if (result == HWLOC_BITMAP_EQUAL) {
1502 result = HWLOC_BITMAP_CONTAINS;
1503 }
1504 /* no change otherwise */
1505 } else {
1506 /* both infinite */
1507 if (result == HWLOC_BITMAP_DIFFERENT)
1508 return HWLOC_BITMAP_INTERSECTS;
1509 /* equal/contains/included unchanged */
1510 }
1511
1512 return result;
1513 }
1514