1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * bitmask user library implementation. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Copyright (c) 2004-2006 Silicon Graphics, Inc. All rights reserved. 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Paul Jackson <pj@sgi.com> 7f08c3bdfSopenharmony_ci */ 8f08c3bdfSopenharmony_ci 9f08c3bdfSopenharmony_ci/* 10f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 11f08c3bdfSopenharmony_ci * it under the terms of the GNU Lesser General Public License as published by 12f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2.1 of the License, or 13f08c3bdfSopenharmony_ci * (at your option) any later version. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 16f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 17f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18f08c3bdfSopenharmony_ci * GNU Lesser General Public License for more details. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * You should have received a copy of the GNU Lesser General Public License 21f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 22f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include <stdio.h> 26f08c3bdfSopenharmony_ci#include <string.h> 27f08c3bdfSopenharmony_ci#include <stdlib.h> 28f08c3bdfSopenharmony_ci#include <stdint.h> 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include "bitmask.h" 31f08c3bdfSopenharmony_ci#include "tst_minmax.h" 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistruct bitmask { 34f08c3bdfSopenharmony_ci unsigned int size; 35f08c3bdfSopenharmony_ci unsigned long *maskp; 36f08c3bdfSopenharmony_ci}; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci/* How many bits in an unsigned long */ 39f08c3bdfSopenharmony_ci#define bitsperlong (8 * sizeof(unsigned long)) 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci/* howmany(a,b) : how many elements of size b needed to hold all of a */ 42f08c3bdfSopenharmony_ci#define howmany(x,y) (((x)+((y)-1))/(y)) 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci/* How many longs in mask of n bits */ 45f08c3bdfSopenharmony_ci#define longsperbits(n) howmany(n, bitsperlong) 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci/* 48f08c3bdfSopenharmony_ci * The routines _getbit() and _setbit() are the only 49f08c3bdfSopenharmony_ci * routines that actually understand the layout of bmp->maskp[]. 50f08c3bdfSopenharmony_ci * 51f08c3bdfSopenharmony_ci * On little endian architectures, this could simply be an array of 52f08c3bdfSopenharmony_ci * bytes. But the kernel layout of bitmasks _is_ visible to userspace 53f08c3bdfSopenharmony_ci * via the sched_(set/get)affinity calls in Linux 2.6, and on big 54f08c3bdfSopenharmony_ci * endian architectures, it is painfully obvious that this is an 55f08c3bdfSopenharmony_ci * array of unsigned longs. 56f08c3bdfSopenharmony_ci */ 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci/* Return the value (0 or 1) of bit n in bitmask bmp */ 59f08c3bdfSopenharmony_cistatic unsigned int _getbit(const struct bitmask *bmp, unsigned int n) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci if (n < bmp->size) 62f08c3bdfSopenharmony_ci return (bmp->maskp[n / bitsperlong] >> (n % bitsperlong)) & 1; 63f08c3bdfSopenharmony_ci else 64f08c3bdfSopenharmony_ci return 0; 65f08c3bdfSopenharmony_ci} 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci/* Set bit n in bitmask bmp to value v (0 or 1) */ 68f08c3bdfSopenharmony_cistatic void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v) 69f08c3bdfSopenharmony_ci{ 70f08c3bdfSopenharmony_ci if (n < bmp->size) { 71f08c3bdfSopenharmony_ci if (v) 72f08c3bdfSopenharmony_ci bmp->maskp[n / bitsperlong] |= 1UL << (n % bitsperlong); 73f08c3bdfSopenharmony_ci else 74f08c3bdfSopenharmony_ci bmp->maskp[n / bitsperlong] &= 75f08c3bdfSopenharmony_ci ~(1UL << (n % bitsperlong)); 76f08c3bdfSopenharmony_ci } 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci/* 80f08c3bdfSopenharmony_ci * Allocate and free `struct bitmask *` 81f08c3bdfSopenharmony_ci */ 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci/* Allocate a new `struct bitmask` with a size of n bits */ 84f08c3bdfSopenharmony_cistruct bitmask *bitmask_alloc(unsigned int n) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci struct bitmask *bmp; 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci bmp = malloc(sizeof(*bmp)); 89f08c3bdfSopenharmony_ci if (bmp == 0) 90f08c3bdfSopenharmony_ci return 0; 91f08c3bdfSopenharmony_ci bmp->size = n; 92f08c3bdfSopenharmony_ci bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long)); 93f08c3bdfSopenharmony_ci if (bmp->maskp == 0) { 94f08c3bdfSopenharmony_ci free(bmp); 95f08c3bdfSopenharmony_ci return 0; 96f08c3bdfSopenharmony_ci } 97f08c3bdfSopenharmony_ci return bmp; 98f08c3bdfSopenharmony_ci} 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci/* Free `struct bitmask` */ 101f08c3bdfSopenharmony_civoid bitmask_free(struct bitmask *bmp) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci if (bmp == 0) 104f08c3bdfSopenharmony_ci return; 105f08c3bdfSopenharmony_ci free(bmp->maskp); 106f08c3bdfSopenharmony_ci bmp->maskp = (unsigned long *)0xdeadcdef; /* double free tripwire */ 107f08c3bdfSopenharmony_ci free(bmp); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci/* 111f08c3bdfSopenharmony_ci * Display and parse ascii string representations. 112f08c3bdfSopenharmony_ci */ 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci#define HEXCHUNKSZ 32 /* hex binary format shows 32 bits per chunk */ 115f08c3bdfSopenharmony_ci#define HEXCHARSZ 8 /* hex ascii format has up to 8 chars per chunk */ 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci/* 118f08c3bdfSopenharmony_ci * Write hex word representation of bmp to buf, 32 bits per 119f08c3bdfSopenharmony_ci * comma-separated, zero-filled hex word. Do not write more 120f08c3bdfSopenharmony_ci * than buflen chars to buf. 121f08c3bdfSopenharmony_ci * 122f08c3bdfSopenharmony_ci * Return number of chars that would have been written 123f08c3bdfSopenharmony_ci * if buf were large enough. 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ciint bitmask_displayhex(char *buf, int buflen, const struct bitmask *bmp) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci int chunk; 129f08c3bdfSopenharmony_ci int cnt = 0; 130f08c3bdfSopenharmony_ci const char *sep = ""; 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci if (buflen < 1) 133f08c3bdfSopenharmony_ci return 0; 134f08c3bdfSopenharmony_ci buf[0] = 0; 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci for (chunk = howmany(bmp->size, HEXCHUNKSZ) - 1; chunk >= 0; chunk--) { 137f08c3bdfSopenharmony_ci uint32_t val = 0; 138f08c3bdfSopenharmony_ci int bit; 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci for (bit = HEXCHUNKSZ - 1; bit >= 0; bit--) 141f08c3bdfSopenharmony_ci val = val << 1 | _getbit(bmp, chunk * HEXCHUNKSZ + bit); 142f08c3bdfSopenharmony_ci cnt += snprintf(buf + cnt, MAX(buflen - cnt, 0), "%s%0*x", 143f08c3bdfSopenharmony_ci sep, HEXCHARSZ, val); 144f08c3bdfSopenharmony_ci sep = ","; 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci return cnt; 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci/* 150f08c3bdfSopenharmony_ci * emit(buf, buflen, rbot, rtop, len) 151f08c3bdfSopenharmony_ci * 152f08c3bdfSopenharmony_ci * Helper routine for bitmask_displaylist(). Write decimal number 153f08c3bdfSopenharmony_ci * or range to buf+len, suppressing output past buf+buflen, with optional 154f08c3bdfSopenharmony_ci * comma-prefix. Return len of what would be written to buf, if it 155f08c3bdfSopenharmony_ci * all fit. 156f08c3bdfSopenharmony_ci */ 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_cistatic inline int emit(char *buf, int buflen, int rbot, int rtop, int len) 159f08c3bdfSopenharmony_ci{ 160f08c3bdfSopenharmony_ci if (len > 0) 161f08c3bdfSopenharmony_ci len += snprintf(buf + len, MAX(buflen - len, 0), ","); 162f08c3bdfSopenharmony_ci if (rbot == rtop) 163f08c3bdfSopenharmony_ci len += snprintf(buf + len, MAX(buflen - len, 0), "%d", rbot); 164f08c3bdfSopenharmony_ci else 165f08c3bdfSopenharmony_ci len += 166f08c3bdfSopenharmony_ci snprintf(buf + len, MAX(buflen - len, 0), "%d-%d", rbot, 167f08c3bdfSopenharmony_ci rtop); 168f08c3bdfSopenharmony_ci return len; 169f08c3bdfSopenharmony_ci} 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci/* 172f08c3bdfSopenharmony_ci * Write decimal list representation of bmp to buf. 173f08c3bdfSopenharmony_ci * 174f08c3bdfSopenharmony_ci * Output format is a comma-separated list of decimal numbers and 175f08c3bdfSopenharmony_ci * ranges. Consecutively set bits are shown as two hyphen-separated 176f08c3bdfSopenharmony_ci * decimal numbers, the smallest and largest bit numbers set in 177f08c3bdfSopenharmony_ci * the range. Output format is compatible with the format 178f08c3bdfSopenharmony_ci * accepted as input by bitmap_parselist(). 179f08c3bdfSopenharmony_ci * 180f08c3bdfSopenharmony_ci * The return value is the number of characters which would be 181f08c3bdfSopenharmony_ci * generated for the given input, excluding the trailing '\0', as 182f08c3bdfSopenharmony_ci * per ISO C99. 183f08c3bdfSopenharmony_ci */ 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ciint bitmask_displaylist(char *buf, int buflen, const struct bitmask *bmp) 186f08c3bdfSopenharmony_ci{ 187f08c3bdfSopenharmony_ci int len = 0; 188f08c3bdfSopenharmony_ci /* current bit is 'cur', most recently seen range is [rbot, rtop] */ 189f08c3bdfSopenharmony_ci unsigned int cur, rbot, rtop; 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci if (buflen > 0) 192f08c3bdfSopenharmony_ci *buf = 0; 193f08c3bdfSopenharmony_ci rbot = cur = bitmask_first(bmp); 194f08c3bdfSopenharmony_ci while (cur < bmp->size) { 195f08c3bdfSopenharmony_ci rtop = cur; 196f08c3bdfSopenharmony_ci cur = bitmask_next(bmp, cur + 1); 197f08c3bdfSopenharmony_ci if (cur >= bmp->size || cur > rtop + 1) { 198f08c3bdfSopenharmony_ci len = emit(buf, buflen, rbot, rtop, len); 199f08c3bdfSopenharmony_ci rbot = cur; 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci } 202f08c3bdfSopenharmony_ci return len; 203f08c3bdfSopenharmony_ci} 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_cistatic const char *nexttoken(const char *q, int sep) 206f08c3bdfSopenharmony_ci{ 207f08c3bdfSopenharmony_ci if (q) 208f08c3bdfSopenharmony_ci q = strchr(q, sep); 209f08c3bdfSopenharmony_ci if (q) 210f08c3bdfSopenharmony_ci q++; 211f08c3bdfSopenharmony_ci return q; 212f08c3bdfSopenharmony_ci} 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci/* 215f08c3bdfSopenharmony_ci * Parse hex word representation in buf to bmp. 216f08c3bdfSopenharmony_ci * 217f08c3bdfSopenharmony_ci * Returns -1 on error, leaving unspecified results in bmp. 218f08c3bdfSopenharmony_ci */ 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ciint bitmask_parsehex(const char *buf, struct bitmask *bmp) 221f08c3bdfSopenharmony_ci{ 222f08c3bdfSopenharmony_ci const char *p, *q; 223f08c3bdfSopenharmony_ci int nchunks = 0, chunk; 224f08c3bdfSopenharmony_ci unsigned int size = 0; 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci bitmask_clearall(bmp); 227f08c3bdfSopenharmony_ci size = longsperbits(bmp->size) * 8 * sizeof(unsigned long); 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci q = buf; 230f08c3bdfSopenharmony_ci while (p = q, q = nexttoken(q, ','), p) 231f08c3bdfSopenharmony_ci nchunks++; 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_ci chunk = nchunks - 1; 234f08c3bdfSopenharmony_ci q = buf; 235f08c3bdfSopenharmony_ci while (p = q, q = nexttoken(q, ','), p) { 236f08c3bdfSopenharmony_ci uint32_t val; 237f08c3bdfSopenharmony_ci int bit; 238f08c3bdfSopenharmony_ci char *endptr; 239f08c3bdfSopenharmony_ci int nchars_read, nchars_unread; 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci val = strtoul(p, &endptr, 16); 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci /* We should have consumed 1 to 8 (HEXCHARSZ) chars */ 244f08c3bdfSopenharmony_ci nchars_read = endptr - p; 245f08c3bdfSopenharmony_ci if (nchars_read < 1 || nchars_read > HEXCHARSZ) 246f08c3bdfSopenharmony_ci goto err; 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci /* We should have consumed up to next comma */ 249f08c3bdfSopenharmony_ci nchars_unread = q - endptr; 250f08c3bdfSopenharmony_ci if (q != NULL && nchars_unread != 1) 251f08c3bdfSopenharmony_ci goto err; 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_ci for (bit = HEXCHUNKSZ - 1; bit >= 0; bit--) { 254f08c3bdfSopenharmony_ci unsigned int n = chunk * HEXCHUNKSZ + bit; 255f08c3bdfSopenharmony_ci if (n >= size) 256f08c3bdfSopenharmony_ci goto err; 257f08c3bdfSopenharmony_ci _setbit(bmp, n, (val >> bit) & 1); 258f08c3bdfSopenharmony_ci } 259f08c3bdfSopenharmony_ci chunk--; 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci return 0; 262f08c3bdfSopenharmony_cierr: 263f08c3bdfSopenharmony_ci bitmask_clearall(bmp); 264f08c3bdfSopenharmony_ci return -1; 265f08c3bdfSopenharmony_ci} 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci/* 268f08c3bdfSopenharmony_ci * When parsing bitmask lists, only allow numbers, separated by one 269f08c3bdfSopenharmony_ci * of the allowed next characters. 270f08c3bdfSopenharmony_ci * 271f08c3bdfSopenharmony_ci * The parameter 'sret' is the return from a sscanf "%u%c". It is 272f08c3bdfSopenharmony_ci * -1 if the sscanf input string was empty. It is 0 if the first 273f08c3bdfSopenharmony_ci * character in the sscanf input string was not a decimal number. 274f08c3bdfSopenharmony_ci * It is 1 if the unsigned number matching the "%u" was the end of the 275f08c3bdfSopenharmony_ci * input string. It is 2 if one or more additional characters followed 276f08c3bdfSopenharmony_ci * the matched unsigned number. If it is 2, then 'nextc' is the first 277f08c3bdfSopenharmony_ci * character following the number. The parameter 'ok_next_chars' 278f08c3bdfSopenharmony_ci * is the nul-terminated list of allowed next characters. 279f08c3bdfSopenharmony_ci * 280f08c3bdfSopenharmony_ci * The mask term just scanned was ok if and only if either the numbers 281f08c3bdfSopenharmony_ci * matching the %u were all of the input or if the next character in 282f08c3bdfSopenharmony_ci * the input past the numbers was one of the allowed next characters. 283f08c3bdfSopenharmony_ci */ 284f08c3bdfSopenharmony_cistatic int scan_was_ok(int sret, char nextc, const char *ok_next_chars) 285f08c3bdfSopenharmony_ci{ 286f08c3bdfSopenharmony_ci return sret == 1 || (sret == 2 && strchr(ok_next_chars, nextc) != NULL); 287f08c3bdfSopenharmony_ci} 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci/* 290f08c3bdfSopenharmony_ci * Parses a comma-separated list of numbers and ranges of numbers, 291f08c3bdfSopenharmony_ci * with optional ':%u' strides modifying ranges, into provided bitmask. 292f08c3bdfSopenharmony_ci * Some examples of input lists and their equivalent simple list: 293f08c3bdfSopenharmony_ci * Input Equivalent to 294f08c3bdfSopenharmony_ci * 0-3 0,1,2,3 295f08c3bdfSopenharmony_ci * 0-7:2 0,2,4,6 296f08c3bdfSopenharmony_ci * 1,3,5-7 1,3,5,6,7 297f08c3bdfSopenharmony_ci * 0-3:2,8-15:4 0,2,8,12 298f08c3bdfSopenharmony_ci */ 299f08c3bdfSopenharmony_ciint bitmask_parselist(const char *buf, struct bitmask *bmp) 300f08c3bdfSopenharmony_ci{ 301f08c3bdfSopenharmony_ci const char *p, *q; 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_ci bitmask_clearall(bmp); 304f08c3bdfSopenharmony_ci 305f08c3bdfSopenharmony_ci q = buf; 306f08c3bdfSopenharmony_ci while (p = q, q = nexttoken(q, ','), p) { 307f08c3bdfSopenharmony_ci unsigned int a; /* begin of range */ 308f08c3bdfSopenharmony_ci unsigned int b; /* end of range */ 309f08c3bdfSopenharmony_ci unsigned int s; /* stride */ 310f08c3bdfSopenharmony_ci const char *c1, *c2; /* next tokens after '-' or ',' */ 311f08c3bdfSopenharmony_ci char nextc; /* char after sscanf %u match */ 312f08c3bdfSopenharmony_ci int sret; /* sscanf return (number of matches) */ 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci sret = sscanf(p, "%u%c", &a, &nextc); 315f08c3bdfSopenharmony_ci if (!scan_was_ok(sret, nextc, ",-")) 316f08c3bdfSopenharmony_ci goto err; 317f08c3bdfSopenharmony_ci b = a; 318f08c3bdfSopenharmony_ci s = 1; 319f08c3bdfSopenharmony_ci c1 = nexttoken(p, '-'); 320f08c3bdfSopenharmony_ci c2 = nexttoken(p, ','); 321f08c3bdfSopenharmony_ci if (c1 != NULL && (c2 == NULL || c1 < c2)) { 322f08c3bdfSopenharmony_ci sret = sscanf(c1, "%u%c", &b, &nextc); 323f08c3bdfSopenharmony_ci if (!scan_was_ok(sret, nextc, ",:")) 324f08c3bdfSopenharmony_ci goto err; 325f08c3bdfSopenharmony_ci c1 = nexttoken(c1, ':'); 326f08c3bdfSopenharmony_ci if (c1 != NULL && (c2 == NULL || c1 < c2)) { 327f08c3bdfSopenharmony_ci sret = sscanf(c1, "%u%c", &s, &nextc); 328f08c3bdfSopenharmony_ci if (!scan_was_ok(sret, nextc, ",")) 329f08c3bdfSopenharmony_ci goto err; 330f08c3bdfSopenharmony_ci } 331f08c3bdfSopenharmony_ci } 332f08c3bdfSopenharmony_ci if (!(a <= b)) 333f08c3bdfSopenharmony_ci goto err; 334f08c3bdfSopenharmony_ci if (b >= bmp->size) 335f08c3bdfSopenharmony_ci goto err; 336f08c3bdfSopenharmony_ci while (a <= b) { 337f08c3bdfSopenharmony_ci _setbit(bmp, a, 1); 338f08c3bdfSopenharmony_ci a += s; 339f08c3bdfSopenharmony_ci } 340f08c3bdfSopenharmony_ci } 341f08c3bdfSopenharmony_ci return 0; 342f08c3bdfSopenharmony_cierr: 343f08c3bdfSopenharmony_ci bitmask_clearall(bmp); 344f08c3bdfSopenharmony_ci return -1; 345f08c3bdfSopenharmony_ci} 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci/* 348f08c3bdfSopenharmony_ci * Basic assignment operations 349f08c3bdfSopenharmony_ci */ 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_ci/* Copy bmp2 to bmp1 */ 352f08c3bdfSopenharmony_cistruct bitmask *bitmask_copy(struct bitmask *bmp1, const struct bitmask *bmp2) 353f08c3bdfSopenharmony_ci{ 354f08c3bdfSopenharmony_ci unsigned int i; 355f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 356f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i)); 357f08c3bdfSopenharmony_ci return bmp1; 358f08c3bdfSopenharmony_ci} 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_ci/* Set all bits in bitmask: bmp = ~0 */ 361f08c3bdfSopenharmony_cistruct bitmask *bitmask_setall(struct bitmask *bmp) 362f08c3bdfSopenharmony_ci{ 363f08c3bdfSopenharmony_ci unsigned int i; 364f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 365f08c3bdfSopenharmony_ci _setbit(bmp, i, 1); 366f08c3bdfSopenharmony_ci return bmp; 367f08c3bdfSopenharmony_ci} 368f08c3bdfSopenharmony_ci 369f08c3bdfSopenharmony_ci/* Clear all bits in bitmask: bmp = 0 */ 370f08c3bdfSopenharmony_cistruct bitmask *bitmask_clearall(struct bitmask *bmp) 371f08c3bdfSopenharmony_ci{ 372f08c3bdfSopenharmony_ci unsigned int i; 373f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 374f08c3bdfSopenharmony_ci _setbit(bmp, i, 0); 375f08c3bdfSopenharmony_ci return bmp; 376f08c3bdfSopenharmony_ci} 377f08c3bdfSopenharmony_ci 378f08c3bdfSopenharmony_ci/* 379f08c3bdfSopenharmony_ci * Interface to kernel sched_setaffinity system call 380f08c3bdfSopenharmony_ci */ 381f08c3bdfSopenharmony_ci 382f08c3bdfSopenharmony_ci/* Length in bytes of mask - use as second argument to sched_setaffinity */ 383f08c3bdfSopenharmony_ciunsigned int bitmask_nbytes(struct bitmask *bmp) 384f08c3bdfSopenharmony_ci{ 385f08c3bdfSopenharmony_ci return longsperbits(bmp->size) * sizeof(unsigned long); 386f08c3bdfSopenharmony_ci} 387f08c3bdfSopenharmony_ci 388f08c3bdfSopenharmony_ci/* Direct pointer to bit mask - use as third argument to sched_setaffinty */ 389f08c3bdfSopenharmony_ciunsigned long *bitmask_mask(struct bitmask *bmp) 390f08c3bdfSopenharmony_ci{ 391f08c3bdfSopenharmony_ci return bmp->maskp; 392f08c3bdfSopenharmony_ci} 393f08c3bdfSopenharmony_ci 394f08c3bdfSopenharmony_ci/* 395f08c3bdfSopenharmony_ci * Unary numeric queries 396f08c3bdfSopenharmony_ci */ 397f08c3bdfSopenharmony_ci 398f08c3bdfSopenharmony_ci/* Size in bits of entire bitmask */ 399f08c3bdfSopenharmony_ciunsigned int bitmask_nbits(const struct bitmask *bmp) 400f08c3bdfSopenharmony_ci{ 401f08c3bdfSopenharmony_ci return bmp->size; 402f08c3bdfSopenharmony_ci} 403f08c3bdfSopenharmony_ci 404f08c3bdfSopenharmony_ci/* Hamming Weight: number of set bits */ 405f08c3bdfSopenharmony_ciunsigned int bitmask_weight(const struct bitmask *bmp) 406f08c3bdfSopenharmony_ci{ 407f08c3bdfSopenharmony_ci unsigned int i; 408f08c3bdfSopenharmony_ci unsigned int w = 0; 409f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 410f08c3bdfSopenharmony_ci if (_getbit(bmp, i)) 411f08c3bdfSopenharmony_ci w++; 412f08c3bdfSopenharmony_ci return w; 413f08c3bdfSopenharmony_ci} 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci/* 416f08c3bdfSopenharmony_ci * Unary Boolean queries 417f08c3bdfSopenharmony_ci */ 418f08c3bdfSopenharmony_ci 419f08c3bdfSopenharmony_ci/* True if specified bit i is set */ 420f08c3bdfSopenharmony_ciint bitmask_isbitset(const struct bitmask *bmp, unsigned int i) 421f08c3bdfSopenharmony_ci{ 422f08c3bdfSopenharmony_ci return _getbit(bmp, i); 423f08c3bdfSopenharmony_ci} 424f08c3bdfSopenharmony_ci 425f08c3bdfSopenharmony_ci/* True if specified bit i is clear */ 426f08c3bdfSopenharmony_ciint bitmask_isbitclear(const struct bitmask *bmp, unsigned int i) 427f08c3bdfSopenharmony_ci{ 428f08c3bdfSopenharmony_ci return !_getbit(bmp, i); 429f08c3bdfSopenharmony_ci} 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci/* True if all bits are set */ 432f08c3bdfSopenharmony_ciint bitmask_isallset(const struct bitmask *bmp) 433f08c3bdfSopenharmony_ci{ 434f08c3bdfSopenharmony_ci unsigned int i; 435f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 436f08c3bdfSopenharmony_ci if (!_getbit(bmp, i)) 437f08c3bdfSopenharmony_ci return 0; 438f08c3bdfSopenharmony_ci return 1; 439f08c3bdfSopenharmony_ci} 440f08c3bdfSopenharmony_ci 441f08c3bdfSopenharmony_ci/* True if all bits are clear */ 442f08c3bdfSopenharmony_ciint bitmask_isallclear(const struct bitmask *bmp) 443f08c3bdfSopenharmony_ci{ 444f08c3bdfSopenharmony_ci unsigned int i; 445f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 446f08c3bdfSopenharmony_ci if (_getbit(bmp, i)) 447f08c3bdfSopenharmony_ci return 0; 448f08c3bdfSopenharmony_ci return 1; 449f08c3bdfSopenharmony_ci} 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ci/* 452f08c3bdfSopenharmony_ci * Single bit operations 453f08c3bdfSopenharmony_ci */ 454f08c3bdfSopenharmony_ci 455f08c3bdfSopenharmony_ci/* Set a single bit i in bitmask */ 456f08c3bdfSopenharmony_cistruct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i) 457f08c3bdfSopenharmony_ci{ 458f08c3bdfSopenharmony_ci _setbit(bmp, i, 1); 459f08c3bdfSopenharmony_ci return bmp; 460f08c3bdfSopenharmony_ci} 461f08c3bdfSopenharmony_ci 462f08c3bdfSopenharmony_ci/* Clear a single bit i in bitmask */ 463f08c3bdfSopenharmony_cistruct bitmask *bitmask_clearbit(struct bitmask *bmp, unsigned int i) 464f08c3bdfSopenharmony_ci{ 465f08c3bdfSopenharmony_ci _setbit(bmp, i, 0); 466f08c3bdfSopenharmony_ci return bmp; 467f08c3bdfSopenharmony_ci} 468f08c3bdfSopenharmony_ci 469f08c3bdfSopenharmony_ci/* 470f08c3bdfSopenharmony_ci * Binary Boolean operations: bmp1 op? bmp2 471f08c3bdfSopenharmony_ci */ 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci/* True if two bitmasks are equal */ 474f08c3bdfSopenharmony_ciint bitmask_equal(const struct bitmask *bmp1, const struct bitmask *bmp2) 475f08c3bdfSopenharmony_ci{ 476f08c3bdfSopenharmony_ci unsigned int i; 477f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size || i < bmp2->size; i++) 478f08c3bdfSopenharmony_ci if (_getbit(bmp1, i) != _getbit(bmp2, i)) 479f08c3bdfSopenharmony_ci return 0; 480f08c3bdfSopenharmony_ci return 1; 481f08c3bdfSopenharmony_ci} 482f08c3bdfSopenharmony_ci 483f08c3bdfSopenharmony_ci/* True if first bitmask is subset of second */ 484f08c3bdfSopenharmony_ciint bitmask_subset(const struct bitmask *bmp1, const struct bitmask *bmp2) 485f08c3bdfSopenharmony_ci{ 486f08c3bdfSopenharmony_ci unsigned int i; 487f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 488f08c3bdfSopenharmony_ci if (_getbit(bmp1, i) > _getbit(bmp2, i)) 489f08c3bdfSopenharmony_ci return 0; 490f08c3bdfSopenharmony_ci return 1; 491f08c3bdfSopenharmony_ci} 492f08c3bdfSopenharmony_ci 493f08c3bdfSopenharmony_ci/* True if two bitmasks don't overlap */ 494f08c3bdfSopenharmony_ciint bitmask_disjoint(const struct bitmask *bmp1, const struct bitmask *bmp2) 495f08c3bdfSopenharmony_ci{ 496f08c3bdfSopenharmony_ci unsigned int i; 497f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 498f08c3bdfSopenharmony_ci if (_getbit(bmp1, i) & _getbit(bmp2, i)) 499f08c3bdfSopenharmony_ci return 0; 500f08c3bdfSopenharmony_ci return 1; 501f08c3bdfSopenharmony_ci} 502f08c3bdfSopenharmony_ci 503f08c3bdfSopenharmony_ci/* True if two bitmasks do overlap */ 504f08c3bdfSopenharmony_ciint bitmask_intersects(const struct bitmask *bmp1, const struct bitmask *bmp2) 505f08c3bdfSopenharmony_ci{ 506f08c3bdfSopenharmony_ci unsigned int i; 507f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 508f08c3bdfSopenharmony_ci if (_getbit(bmp1, i) & _getbit(bmp2, i)) 509f08c3bdfSopenharmony_ci return 1; 510f08c3bdfSopenharmony_ci return 0; 511f08c3bdfSopenharmony_ci} 512f08c3bdfSopenharmony_ci 513f08c3bdfSopenharmony_ci/* 514f08c3bdfSopenharmony_ci * Range operations 515f08c3bdfSopenharmony_ci */ 516f08c3bdfSopenharmony_ci 517f08c3bdfSopenharmony_ci/* Set bits of bitmask in specified range [i, j) */ 518f08c3bdfSopenharmony_cistruct bitmask *bitmask_setrange(struct bitmask *bmp, 519f08c3bdfSopenharmony_ci unsigned int i, unsigned int j) 520f08c3bdfSopenharmony_ci{ 521f08c3bdfSopenharmony_ci unsigned int n; 522f08c3bdfSopenharmony_ci for (n = i; n < j; n++) 523f08c3bdfSopenharmony_ci _setbit(bmp, n, 1); 524f08c3bdfSopenharmony_ci return bmp; 525f08c3bdfSopenharmony_ci} 526f08c3bdfSopenharmony_ci 527f08c3bdfSopenharmony_ci/* Clear bits of bitmask in specified range */ 528f08c3bdfSopenharmony_cistruct bitmask *bitmask_clearrange(struct bitmask *bmp, 529f08c3bdfSopenharmony_ci unsigned int i, unsigned int j) 530f08c3bdfSopenharmony_ci{ 531f08c3bdfSopenharmony_ci unsigned int n; 532f08c3bdfSopenharmony_ci for (n = i; n < j; n++) 533f08c3bdfSopenharmony_ci _setbit(bmp, n, 0); 534f08c3bdfSopenharmony_ci return bmp; 535f08c3bdfSopenharmony_ci} 536f08c3bdfSopenharmony_ci 537f08c3bdfSopenharmony_ci/* Clear all but specified range */ 538f08c3bdfSopenharmony_cistruct bitmask *bitmask_keeprange(struct bitmask *bmp, 539f08c3bdfSopenharmony_ci unsigned int i, unsigned int j) 540f08c3bdfSopenharmony_ci{ 541f08c3bdfSopenharmony_ci bitmask_clearrange(bmp, 0, i); 542f08c3bdfSopenharmony_ci bitmask_clearrange(bmp, j, bmp->size); 543f08c3bdfSopenharmony_ci return bmp; 544f08c3bdfSopenharmony_ci} 545f08c3bdfSopenharmony_ci 546f08c3bdfSopenharmony_ci/* 547f08c3bdfSopenharmony_ci * Unary operations: bmp1 = op(struct bitmask *bmp2) 548f08c3bdfSopenharmony_ci */ 549f08c3bdfSopenharmony_ci 550f08c3bdfSopenharmony_ci/* Complement: bmp1 = ~bmp2 */ 551f08c3bdfSopenharmony_cistruct bitmask *bitmask_complement(struct bitmask *bmp1, 552f08c3bdfSopenharmony_ci const struct bitmask *bmp2) 553f08c3bdfSopenharmony_ci{ 554f08c3bdfSopenharmony_ci unsigned int i; 555f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 556f08c3bdfSopenharmony_ci _setbit(bmp1, i, !_getbit(bmp2, i)); 557f08c3bdfSopenharmony_ci return bmp1; 558f08c3bdfSopenharmony_ci} 559f08c3bdfSopenharmony_ci 560f08c3bdfSopenharmony_ci/* Right shift: bmp1 = bmp2 >> n */ 561f08c3bdfSopenharmony_cistruct bitmask *bitmask_shiftright(struct bitmask *bmp1, 562f08c3bdfSopenharmony_ci const struct bitmask *bmp2, unsigned int n) 563f08c3bdfSopenharmony_ci{ 564f08c3bdfSopenharmony_ci unsigned int i; 565f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 566f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i + n)); 567f08c3bdfSopenharmony_ci return bmp1; 568f08c3bdfSopenharmony_ci} 569f08c3bdfSopenharmony_ci 570f08c3bdfSopenharmony_ci/* Left shift: bmp1 = bmp2 << n */ 571f08c3bdfSopenharmony_cistruct bitmask *bitmask_shiftleft(struct bitmask *bmp1, 572f08c3bdfSopenharmony_ci const struct bitmask *bmp2, unsigned int n) 573f08c3bdfSopenharmony_ci{ 574f08c3bdfSopenharmony_ci int i; 575f08c3bdfSopenharmony_ci for (i = bmp1->size - 1; i >= 0; i--) 576f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i - n)); 577f08c3bdfSopenharmony_ci return bmp1; 578f08c3bdfSopenharmony_ci} 579f08c3bdfSopenharmony_ci 580f08c3bdfSopenharmony_ci/* 581f08c3bdfSopenharmony_ci * Binary operations: bmp1 = bmp2 op bmp3 582f08c3bdfSopenharmony_ci */ 583f08c3bdfSopenharmony_ci 584f08c3bdfSopenharmony_ci/* Logical `and` of two bitmasks: bmp1 = bmp2 & bmp3 */ 585f08c3bdfSopenharmony_cistruct bitmask *bitmask_and(struct bitmask *bmp1, const struct bitmask *bmp2, 586f08c3bdfSopenharmony_ci const struct bitmask *bmp3) 587f08c3bdfSopenharmony_ci{ 588f08c3bdfSopenharmony_ci unsigned int i; 589f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 590f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i) & _getbit(bmp3, i)); 591f08c3bdfSopenharmony_ci return bmp1; 592f08c3bdfSopenharmony_ci} 593f08c3bdfSopenharmony_ci 594f08c3bdfSopenharmony_ci/* Logical `andnot` of two bitmasks: bmp1 = bmp2 & ~bmp3 */ 595f08c3bdfSopenharmony_cistruct bitmask *bitmask_andnot(struct bitmask *bmp1, const struct bitmask *bmp2, 596f08c3bdfSopenharmony_ci const struct bitmask *bmp3) 597f08c3bdfSopenharmony_ci{ 598f08c3bdfSopenharmony_ci unsigned int i; 599f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 600f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i) & ~_getbit(bmp3, i)); 601f08c3bdfSopenharmony_ci return bmp1; 602f08c3bdfSopenharmony_ci} 603f08c3bdfSopenharmony_ci 604f08c3bdfSopenharmony_ci/* Logical `or` of two bitmasks: bmp1 = bmp2 | bmp3 */ 605f08c3bdfSopenharmony_cistruct bitmask *bitmask_or(struct bitmask *bmp1, const struct bitmask *bmp2, 606f08c3bdfSopenharmony_ci const struct bitmask *bmp3) 607f08c3bdfSopenharmony_ci{ 608f08c3bdfSopenharmony_ci unsigned int i; 609f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 610f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i) | _getbit(bmp3, i)); 611f08c3bdfSopenharmony_ci return bmp1; 612f08c3bdfSopenharmony_ci} 613f08c3bdfSopenharmony_ci 614f08c3bdfSopenharmony_ci/* Logical `eor` of two bitmasks: bmp1 = bmp2 ^ bmp3 */ 615f08c3bdfSopenharmony_cistruct bitmask *bitmask_eor(struct bitmask *bmp1, const struct bitmask *bmp2, 616f08c3bdfSopenharmony_ci const struct bitmask *bmp3) 617f08c3bdfSopenharmony_ci{ 618f08c3bdfSopenharmony_ci unsigned int i; 619f08c3bdfSopenharmony_ci for (i = 0; i < bmp1->size; i++) 620f08c3bdfSopenharmony_ci _setbit(bmp1, i, _getbit(bmp2, i) ^ _getbit(bmp3, i)); 621f08c3bdfSopenharmony_ci return bmp1; 622f08c3bdfSopenharmony_ci} 623f08c3bdfSopenharmony_ci 624f08c3bdfSopenharmony_ci/* 625f08c3bdfSopenharmony_ci * Iteration operators 626f08c3bdfSopenharmony_ci */ 627f08c3bdfSopenharmony_ci 628f08c3bdfSopenharmony_ci/* Number of lowest set bit (min) */ 629f08c3bdfSopenharmony_ciunsigned int bitmask_first(const struct bitmask *bmp) 630f08c3bdfSopenharmony_ci{ 631f08c3bdfSopenharmony_ci return bitmask_next(bmp, 0); 632f08c3bdfSopenharmony_ci} 633f08c3bdfSopenharmony_ci 634f08c3bdfSopenharmony_ci/* Number of next set bit at or above given bit i */ 635f08c3bdfSopenharmony_ciunsigned int bitmask_next(const struct bitmask *bmp, unsigned int i) 636f08c3bdfSopenharmony_ci{ 637f08c3bdfSopenharmony_ci unsigned int n; 638f08c3bdfSopenharmony_ci for (n = i; n < bmp->size; n++) 639f08c3bdfSopenharmony_ci if (_getbit(bmp, n)) 640f08c3bdfSopenharmony_ci break; 641f08c3bdfSopenharmony_ci return n; 642f08c3bdfSopenharmony_ci} 643f08c3bdfSopenharmony_ci 644f08c3bdfSopenharmony_ci/* Absolute position of nth set bit */ 645f08c3bdfSopenharmony_ciunsigned int bitmask_rel_to_abs_pos(const struct bitmask *bmp, unsigned int n) 646f08c3bdfSopenharmony_ci{ 647f08c3bdfSopenharmony_ci unsigned int i; 648f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 649f08c3bdfSopenharmony_ci if (_getbit(bmp, i)) 650f08c3bdfSopenharmony_ci if (n-- == 0) 651f08c3bdfSopenharmony_ci break; 652f08c3bdfSopenharmony_ci return i; 653f08c3bdfSopenharmony_ci} 654f08c3bdfSopenharmony_ci 655f08c3bdfSopenharmony_ci/* Relative position amongst set bits of bit n */ 656f08c3bdfSopenharmony_ciunsigned int bitmask_abs_to_rel_pos(const struct bitmask *bmp, unsigned int n) 657f08c3bdfSopenharmony_ci{ 658f08c3bdfSopenharmony_ci unsigned int i; 659f08c3bdfSopenharmony_ci unsigned int w = 0; 660f08c3bdfSopenharmony_ci 661f08c3bdfSopenharmony_ci if (!_getbit(bmp, n)) 662f08c3bdfSopenharmony_ci return bmp->size; 663f08c3bdfSopenharmony_ci /* Add in number bits set before bit n */ 664f08c3bdfSopenharmony_ci for (i = 0; i < n; i++) 665f08c3bdfSopenharmony_ci if (_getbit(bmp, i)) 666f08c3bdfSopenharmony_ci w++; 667f08c3bdfSopenharmony_ci return w; 668f08c3bdfSopenharmony_ci} 669f08c3bdfSopenharmony_ci 670f08c3bdfSopenharmony_ci/* Number of highest set bit (max) */ 671f08c3bdfSopenharmony_ciunsigned int bitmask_last(const struct bitmask *bmp) 672f08c3bdfSopenharmony_ci{ 673f08c3bdfSopenharmony_ci unsigned int i; 674f08c3bdfSopenharmony_ci unsigned int m = bmp->size; 675f08c3bdfSopenharmony_ci for (i = 0; i < bmp->size; i++) 676f08c3bdfSopenharmony_ci if (_getbit(bmp, i)) 677f08c3bdfSopenharmony_ci m = i; 678f08c3bdfSopenharmony_ci return m; 679f08c3bdfSopenharmony_ci} 680