1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2014 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
13 * Copyright (c) 2010-2012 Oak Ridge National Labs. All rights reserved.
14 * Copyright (c) 2014 Intel, Inc. All rights reserved.
15 * Copyright (c) 2015-2017 Research Organization for Information Science
16 * and Technology (RIST). All rights reserved.
17 * $COPYRIGHT$
18 *
19 * Additional copyrights may follow
20 *
21 * $HEADER$
22 */
23
24 #include "opal_config.h"
25
26 #include <stdio.h>
27 #include <limits.h>
28
29 #include "opal/constants.h"
30 #include "opal/class/opal_bitmap.h"
31
32 /* The number of bits in the underlying type of the bitmap field
33 * in the opal_bitmap_t struct
34 */
35 #define SIZE_OF_BASE_TYPE 64
36
37 static void opal_bitmap_construct(opal_bitmap_t *bm);
38 static void opal_bitmap_destruct(opal_bitmap_t *bm);
39
40 OBJ_CLASS_INSTANCE(opal_bitmap_t, opal_object_t,
41 opal_bitmap_construct, opal_bitmap_destruct);
42
43
44 static void
opal_bitmap_construct(opal_bitmap_t * bm)45 opal_bitmap_construct(opal_bitmap_t *bm)
46 {
47 bm->bitmap = NULL;
48 bm->array_size = 0;
49 bm->max_size = INT_MAX;
50 }
51
52
53 static void
opal_bitmap_destruct(opal_bitmap_t * bm)54 opal_bitmap_destruct(opal_bitmap_t *bm)
55 {
56 if (NULL != bm->bitmap) {
57 free(bm->bitmap);
58 bm->bitmap = NULL;
59 }
60 }
61
62
opal_bitmap_set_max_size(opal_bitmap_t * bm,int max_size)63 int opal_bitmap_set_max_size (opal_bitmap_t *bm, int max_size)
64 {
65 if (NULL == bm) {
66 return OPAL_ERR_BAD_PARAM;
67 }
68
69 /*
70 * Only if the caller wants to set the maximum size,
71 * we set it (in numbers of bits!), otherwise it is
72 * set to INT_MAX in the constructor.
73 */
74 bm->max_size = (int)(((size_t)max_size + SIZE_OF_BASE_TYPE - 1) / SIZE_OF_BASE_TYPE);
75
76 return OPAL_SUCCESS;
77 }
78
79
80 int
opal_bitmap_init(opal_bitmap_t * bm,int size)81 opal_bitmap_init(opal_bitmap_t *bm, int size)
82 {
83 /*
84 * Only if the caller set the maximum size before initializing,
85 * we test here (in numbers of bits!)
86 * By default, the max size is INT_MAX, set in the constructor.
87 */
88 if ((size <= 0) || (NULL == bm) || (size > bm->max_size)) {
89 return OPAL_ERR_BAD_PARAM;
90 }
91
92 bm->array_size = (int)(((size_t)size + SIZE_OF_BASE_TYPE - 1) / SIZE_OF_BASE_TYPE);
93 if( NULL != bm->bitmap ) {
94 free(bm->bitmap);
95 if(bm->max_size < bm->array_size)
96 bm->max_size = bm->array_size;
97 }
98 bm->bitmap = (uint64_t*) malloc(bm->array_size * sizeof(uint64_t));
99 if (NULL == bm->bitmap) {
100 return OPAL_ERR_OUT_OF_RESOURCE;
101 }
102
103 opal_bitmap_clear_all_bits(bm);
104 return OPAL_SUCCESS;
105 }
106
107
108 int
opal_bitmap_set_bit(opal_bitmap_t * bm,int bit)109 opal_bitmap_set_bit(opal_bitmap_t *bm, int bit)
110 {
111 int index, offset, new_size;
112
113 if ((bit < 0) || (NULL == bm) || (bit > bm->max_size)) {
114 return OPAL_ERR_BAD_PARAM;
115 }
116
117 index = bit / SIZE_OF_BASE_TYPE;
118 offset = bit % SIZE_OF_BASE_TYPE;
119
120 if (index >= bm->array_size) {
121
122 /* We need to allocate more space for the bitmap, since we are
123 out of range. We don't throw any error here, because this is
124 valid and we simply expand the bitmap */
125
126 new_size = index + 1;
127 if( new_size > bm->max_size )
128 new_size = bm->max_size;
129
130 /* New size is just a multiple of the original size to fit in
131 the index. */
132 bm->bitmap = (uint64_t*)realloc(bm->bitmap, new_size*sizeof(uint64_t));
133 if (NULL == bm->bitmap) {
134 return OPAL_ERR_OUT_OF_RESOURCE;
135 }
136
137 /* zero out the new elements */
138 memset(&bm->bitmap[bm->array_size], 0, (new_size - bm->array_size) * sizeof(uint64_t));
139
140 /* Update the array_size */
141 bm->array_size = new_size;
142 }
143
144 /* Now set the bit */
145 bm->bitmap[index] |= (1UL << offset);
146
147 return OPAL_SUCCESS;
148 }
149
150
151 int
opal_bitmap_clear_bit(opal_bitmap_t * bm,int bit)152 opal_bitmap_clear_bit(opal_bitmap_t *bm, int bit)
153 {
154 int index, offset;
155
156 if ((bit < 0) || NULL == bm || (bit >= (bm->array_size * SIZE_OF_BASE_TYPE))) {
157 return OPAL_ERR_BAD_PARAM;
158 }
159
160 index = bit / SIZE_OF_BASE_TYPE;
161 offset = bit % SIZE_OF_BASE_TYPE;
162
163 bm->bitmap[index] &= ~(1UL << offset);
164 return OPAL_SUCCESS;
165 }
166
167
168 bool
opal_bitmap_is_set_bit(opal_bitmap_t * bm,int bit)169 opal_bitmap_is_set_bit(opal_bitmap_t *bm, int bit)
170 {
171 int index, offset;
172
173 if ((bit < 0) || NULL == bm || (bit >= (bm->array_size * SIZE_OF_BASE_TYPE))) {
174 return false;
175 }
176
177 index = bit / SIZE_OF_BASE_TYPE;
178 offset = bit % SIZE_OF_BASE_TYPE;
179
180 if (0 != (bm->bitmap[index] & (1UL << offset))) {
181 return true;
182 }
183
184 return false;
185 }
186
187
188 int
opal_bitmap_clear_all_bits(opal_bitmap_t * bm)189 opal_bitmap_clear_all_bits(opal_bitmap_t *bm)
190 {
191 if (NULL == bm) {
192 return OPAL_ERR_BAD_PARAM;
193 }
194
195 memset(bm->bitmap, 0, bm->array_size * sizeof(uint64_t));
196 return OPAL_SUCCESS;
197 }
198
199
200 int
opal_bitmap_set_all_bits(opal_bitmap_t * bm)201 opal_bitmap_set_all_bits(opal_bitmap_t *bm)
202 {
203 if (NULL == bm) {
204 return OPAL_ERR_BAD_PARAM;
205 }
206
207 memset(bm->bitmap, 0xff, bm->array_size * sizeof(uint64_t));
208
209 return OPAL_SUCCESS;
210 }
211
212
213 int
opal_bitmap_find_and_set_first_unset_bit(opal_bitmap_t * bm,int * position)214 opal_bitmap_find_and_set_first_unset_bit(opal_bitmap_t *bm, int *position)
215 {
216 int i = 0;
217 uint64_t temp, all_ones = 0xffffffffffffffffUL;
218
219 if (NULL == bm) {
220 return OPAL_ERR_BAD_PARAM;
221 }
222
223 /* Neglect all which don't have an unset bit */
224 *position = 0;
225 while((i < bm->array_size) && (bm->bitmap[i] == all_ones)) {
226 ++i;
227 }
228
229 if (i == bm->array_size) {
230 /* increase the bitmap size then */
231 *position = bm->array_size * SIZE_OF_BASE_TYPE;
232 return opal_bitmap_set_bit(bm, *position);
233 }
234
235 /* This one has an unset bit, find its bit number */
236
237 temp = bm->bitmap[i];
238 bm->bitmap[i] |= (bm->bitmap[i] + 1); /* Set the first zero bit */
239 temp ^= bm->bitmap[i]; /* Compute the change: the first unset bit in the original number */
240 while( !(temp & 0x1) ) {
241 ++(*position);
242 temp >>= 1;
243 }
244
245 (*position) += i * SIZE_OF_BASE_TYPE;
246 return OPAL_SUCCESS;
247 }
248
opal_bitmap_bitwise_and_inplace(opal_bitmap_t * dest,opal_bitmap_t * right)249 int opal_bitmap_bitwise_and_inplace(opal_bitmap_t *dest, opal_bitmap_t *right)
250 {
251 int i;
252
253 /*
254 * Sanity check
255 */
256 if( NULL == dest || NULL == right ) {
257 return OPAL_ERR_BAD_PARAM;
258 }
259 if( dest->array_size != right->array_size ) {
260 return OPAL_ERR_BAD_PARAM;
261 }
262
263 /*
264 * Bitwise AND
265 */
266 for(i = 0; i < dest->array_size; ++i) {
267 dest->bitmap[i] &= right->bitmap[i];
268 }
269
270 return OPAL_SUCCESS;
271 }
272
opal_bitmap_bitwise_or_inplace(opal_bitmap_t * dest,opal_bitmap_t * right)273 int opal_bitmap_bitwise_or_inplace(opal_bitmap_t *dest, opal_bitmap_t *right)
274 {
275 int i;
276
277 /*
278 * Sanity check
279 */
280 if( NULL == dest || NULL == right ) {
281 return OPAL_ERR_BAD_PARAM;
282 }
283 if( dest->array_size != right->array_size ) {
284 return OPAL_ERR_BAD_PARAM;
285 }
286
287 /*
288 * Bitwise OR
289 */
290 for(i = 0; i < dest->array_size; ++i) {
291 dest->bitmap[i] |= right->bitmap[i];
292 }
293
294 return OPAL_SUCCESS;
295 }
296
opal_bitmap_bitwise_xor_inplace(opal_bitmap_t * dest,opal_bitmap_t * right)297 int opal_bitmap_bitwise_xor_inplace(opal_bitmap_t *dest, opal_bitmap_t *right)
298 {
299 int i;
300
301 /*
302 * Sanity check
303 */
304 if( NULL == dest || NULL == right ) {
305 return OPAL_ERR_BAD_PARAM;
306 }
307 if( dest->array_size != right->array_size ) {
308 return OPAL_ERR_BAD_PARAM;
309 }
310
311 /*
312 * Bitwise XOR
313 */
314 for(i = 0; i < dest->array_size; ++i) {
315 dest->bitmap[i] ^= right->bitmap[i];
316 }
317
318 return OPAL_SUCCESS;
319 }
320
opal_bitmap_are_different(opal_bitmap_t * left,opal_bitmap_t * right)321 bool opal_bitmap_are_different(opal_bitmap_t *left, opal_bitmap_t *right)
322 {
323 int i;
324
325 /*
326 * Sanity check
327 */
328 if( NULL == left || NULL == right ) {
329 return OPAL_ERR_BAD_PARAM;
330 }
331
332 if( opal_bitmap_size(left) != opal_bitmap_size(right) ) {
333 return true;
334 }
335
336 /*
337 * Direct comparison
338 */
339 for(i = 0; i < left->array_size; ++i) {
340 if( left->bitmap[i] != right->bitmap[i] ) {
341 return true;
342 }
343 }
344
345 return false;
346 }
347
opal_bitmap_get_string(opal_bitmap_t * bitmap)348 char * opal_bitmap_get_string(opal_bitmap_t *bitmap)
349 {
350 int i;
351 char *bitmap_str = NULL;
352
353 if( NULL == bitmap) {
354 return NULL;
355 }
356
357 bitmap_str = malloc(bitmap->array_size * SIZE_OF_BASE_TYPE + 1);
358 if (NULL == bitmap_str) {
359 return NULL;
360 }
361 bitmap_str[bitmap->array_size * SIZE_OF_BASE_TYPE] = '\0';
362
363 for( i = 0; i < (bitmap->array_size * SIZE_OF_BASE_TYPE); ++i) {
364 if( opal_bitmap_is_set_bit(bitmap, i) ) {
365 bitmap_str[i] = 'X';
366 } else {
367 bitmap_str[i] = '_';
368 }
369 }
370
371 return bitmap_str;
372 }
373
opal_bitmap_num_unset_bits(opal_bitmap_t * bm,int len)374 int opal_bitmap_num_unset_bits(opal_bitmap_t *bm, int len)
375 {
376 return (len - opal_bitmap_num_set_bits(bm, len));
377 }
378
opal_bitmap_num_set_bits(opal_bitmap_t * bm,int len)379 int opal_bitmap_num_set_bits(opal_bitmap_t *bm, int len)
380 {
381 int i, cnt = 0;
382 uint64_t val;
383
384 #if OPAL_ENABLE_DEBUG
385 if ((len < 0) || NULL == bm || (len >= (bm->array_size * SIZE_OF_BASE_TYPE))) {
386 return 0;
387 }
388 #endif
389
390 for(i = 0; i < len; ++i) {
391 if( 0 == (val = bm->bitmap[i]) ) continue;
392 /* Peter Wegner in CACM 3 (1960), 322. This method goes through as many
393 * iterations as there are set bits. */
394 for( ; val; cnt++ ) {
395 val &= val - 1; /* clear the least significant bit set */
396 }
397 }
398
399 return cnt;
400 }
401
opal_bitmap_is_clear(opal_bitmap_t * bm)402 bool opal_bitmap_is_clear(opal_bitmap_t *bm)
403 {
404 int i;
405
406 for (i = 0; i < bm->array_size; ++i) {
407 if (0 != bm->bitmap[i]) {
408 return false;
409 }
410 }
411 return true;
412 }
413