1/**
2 * \file
3 * \brief General Numa functions
4 *
5 */
6
7/*
8 * Copyright (c) 2014, ETH Zurich.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#include <barrelfish/barrelfish.h>
17
18#include <bitmap.h>
19
20///< the bitmap data type to store the bitmap elements
21typedef uint32_t bitmap_data_t;
22
23///< helper macro for
24#define BITMAP_BITS_PER_ELEMENT (8 * sizeof(bitmap_data_t))
25
26///< helper macro for determining the number of
27#define BITMAP_DATA_SIZE(nbits) \
28     ((nbits + (BITMAP_BITS_PER_ELEMENT-1)) / BITMAP_BITS_PER_ELEMENT)
29
30
31
32/**
33 * \brief bitmap struct internal representation
34 */
35struct bitmap
36{
37    uint32_t       nbits;   ///< the number of bits this bitmap has
38    uint32_t       weight;  ///< caches the number of set bits
39    uint32_t       first;   ///< caches the position of the first bit
40    uint32_t       last;    ///< caches the number of the last bit
41    bitmap_data_t *data;    ///< stores the bit map
42};
43
44/*
45 * =============================================================================
46 * bitmap allocation and free
47 * =============================================================================
48 */
49
50/**
51 * \brief allocates a new bitmap of a given size
52 *
53 * \param nbits size of the bitmap
54 *
55 * \return pointer to the allocated bitmap on success
56 *         NULL on failure
57 */
58struct bitmap *bitmap_alloc(uint32_t nbits)
59{
60    struct bitmap *bm = calloc(1, sizeof(*bm) + BITMAP_DATA_SIZE(nbits));
61    if (bm == NULL) {
62        return 0;
63    }
64
65    bm->nbits = nbits;
66    bm->data = (bitmap_data_t *)(bm + 1);
67
68    return bm;
69}
70
71/**
72 * \brief frees the resources of a bitmap
73 *
74 * \param bm    bitmap to be freed
75 */
76void bitmap_free(struct bitmap *bm)
77{
78    if (bm) {
79        free(bm);
80    }
81}
82
83/*
84 * =============================================================================
85 * bitmap intput and output
86 * =============================================================================
87 */
88
89/**
90 * \brief formats the contents of the bitmap into the outbut buffer
91 *
92 * \param outbuf    buffer to hold the output data
93 * \param length    length of the output buffer
94 * \param bm        bitmap to format
95 * \param hex       flag to enable hexadecimal formatted output
96 *
97 * \return number of bytes written into the buffer
98 */
99size_t bitmap_format(char *outbuf, size_t length, struct bitmap *bm, uint8_t hex)
100{
101    assert(!"NYI");
102    return 0;
103}
104
105/**
106 * \brief parses an input string and stores it into the bitmap
107 *
108 * \param outbm     bitmap to store the parsed data into
109 * \param inbuf     input string buffer
110 * \param length    length of the input string buffer
111 * \param hex       parse input as hex
112 *
113 * \return number of bytes parsed from the input string
114 */
115size_t bitmap_parse(struct bitmap *outbm, char *inbuf, size_t length, uint8_t hex)
116{
117    assert(!"NYI");
118    return 0;
119}
120
121/**
122 * \brief serializes the bitmap into a buffer
123 *
124 * \param dest      buffer to store the serialized bitmap
125 * \param length    lenght ouf the buffer
126 * \param bm        bitmap to serialize
127 *
128 * \return
129 */
130errval_t bitmap_serialize(void *dest, size_t length, const struct bitmap *bm)
131{
132    assert(!"NYI");
133    return SYS_ERR_OK;
134}
135
136/**
137 * \brief deserializes a bitmap form a buffer
138 *
139 * \param bm        bitmap to store the serialized data
140 * \param src       source buffer to read the serialized data from
141 * \param length    length of the source buffer
142 *
143 * \return SYS_ERR_OK on success
144 *         errval on failure
145 */
146errval_t bitmap_deserialize(struct bitmap *bm, const void *src, size_t length)
147{
148    assert(!"NYI");
149    return SYS_ERR_OK;
150}
151
152/*
153 * =============================================================================
154 * meta information queries
155 * =============================================================================
156 */
157
158/**
159 * \brief returns the number of bytes in the bitmap data representation
160 *
161 * \param bm    bitmap to determine the bytes for
162 *
163 * \return size of the bitmap in bytes
164 */
165uint32_t bitmap_get_nbytes(const struct bitmap *bm)
166{
167    return (bitmap_bit_t)(BITMAP_DATA_SIZE(bm->nbits) * sizeof(bitmap_data_t));
168}
169
170/**
171 * \brief gets the number of bits of this bitmap
172 *
173 * \param bm    the bitmap
174 *
175 * \return size of the bitmap in bits
176 */
177uint32_t bitmap_get_nbits(const struct bitmap *bm)
178{
179    return bm->nbits;
180}
181
182/**
183 * \brief gets the weight of the bit map i.e. number of set bits
184 *
185 * \param bm    the bitmap
186 *
187 * \return number of set bits
188 */
189uint32_t bitmap_get_weight(const struct bitmap *bm)
190{
191    return bm->weight;
192}
193
194/**
195 * \brief returns a pointer to the raw bitmap
196 *
197 * \param bm    the bitmap
198 *
199 * \returns Pointer to the raw bitmap
200 */
201void *bitmap_raw(struct bitmap *bm)
202{
203    return bm->data;
204}
205
206/*
207 * =============================================================================
208 * bitmap queries
209 * =============================================================================
210 */
211
212/**
213 * \brief ckecks if a given bit is set
214 *
215 * \param bm    bitmap to check
216 * \param i     index of the bit
217 *
218 * \return TRUE iff the bit is set
219 *         FALSE otherwise (also if bit index exceeds bitmap size)
220 */
221bool bitmap_is_bit_set(const struct bitmap *bm, bitmap_bit_t i)
222{
223    if (i < bm->nbits) {
224        bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT];
225        return (data >> (i % BITMAP_BITS_PER_ELEMENT)) & 1;
226    } else {
227        return 0;
228    }
229}
230
231/**
232 * \brief ckecks if a given bit is cleare
233 *
234 * \param bm    bitmap to check
235 * \param i     index of the bit
236 *
237 * \return TRUE iff the bit is clear
238 *         FALSE otherwise
239 */
240bool bitmap_is_bit_clear(const struct bitmap *bm, bitmap_bit_t i)
241{
242    return !bitmap_is_bit_set(bm, i);
243}
244
245/**
246 * \brief checks if all bits are set
247 *
248 * \param bm    bitmap to check
249 *
250 * \return TRUE iff all bits are set
251 *         FALSE otherwise
252 */
253bool bitmap_is_all_set(const struct bitmap *bm)
254{
255    return (bm->weight == bm->nbits);
256}
257
258/**
259 * \brief checks if all bits are clear
260 *
261 * \param bm    bitmap to check
262 *
263 * \return TRUE iff all bits are clear
264 *         FALSE otherwise
265 */
266bool bitmap_is_all_clear(const struct bitmap *bm)
267{
268    return (bm->weight == 0);
269}
270
271/**
272 * \brief returns the bit number of the first set
273 *
274 * \param bm    bitmap to get the first set bit
275 *
276 * \returns index of the first bit
277 *          BITMAP_BIT_NONE if there is no bit set
278 */
279bitmap_bit_t bitmap_get_first(const struct bitmap *bm)
280{
281    if (bm->weight) {
282        return bm->first;
283    }
284    return BITMAP_BIT_NONE;
285}
286
287
288/**
289 * \brief returns the bit number of the last set
290 *
291 * \param bm    bitmap to get the last set bit
292 *
293 * \returns index of the last bit
294 *          BITMAP_BIT_NONE if there is no bit set
295 */
296bitmap_bit_t bitmap_get_last(const struct bitmap *bm)
297{
298    if (bm->weight) {
299        return bm->last;
300    }
301    return BITMAP_BIT_NONE;
302}
303
304/**
305 * \brief gets the index of the next bit set
306 *
307 * \param bm    the bitmap to check
308 * \param i     bit to start checking from (not inclusive)
309 *
310 * \return  index of the next set bit
311 *          BITMAP_BIT_NONE if none is set
312 */
313bitmap_bit_t bitmap_get_next(const struct bitmap *bm, bitmap_bit_t i)
314{
315    for (bitmap_bit_t k = i+1; k < bm->nbits; ++k) {
316        if (bitmap_is_bit_set(bm, k)) {
317            return k;
318        }
319    }
320    return BITMAP_BIT_NONE;
321}
322
323/**
324 * \brief gets the index of the previous bit set
325 *
326 * \param bm    the bitmap to check
327 * \param i     index of the bit to check
328 *
329 * \return  index of the next set bit
330 *          BITMAP_BIT_NONE if none is set
331 */
332bitmap_bit_t bitmap_get_prev(const struct bitmap *bm, bitmap_bit_t i)
333{
334    if (i < bm->nbits) {
335        for (bitmap_bit_t k = i-1; k >= 0; --k) {
336            if (bitmap_is_bit_set(bm, k)) {
337                return k;
338            }
339        }
340    }
341
342    return BITMAP_BIT_NONE;
343}
344
345/*
346 * =============================================================================
347 * Bitmap Manipulations
348 * =============================================================================
349 */
350
351/**
352 * \brief sets a bit in the bitmap
353 *
354 * \param bm    bitmap to set the bit
355 * \param i     index of the bit to set
356 */
357void bitmap_set_bit(struct bitmap *bm, bitmap_bit_t i)
358{
359    if (i < bm->nbits) {
360        bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT];
361        bitmap_data_t mask = (1UL << (i % BITMAP_BITS_PER_ELEMENT));
362        if (!(mask & data)) {
363            /* bit was cleared so set it */
364            data |= (1UL << (i % BITMAP_BITS_PER_ELEMENT));
365            bm->data[i/BITMAP_BITS_PER_ELEMENT] = data;
366            if (bm->weight) {
367                if (bm->last < i) {
368                    bm->last = i;
369                } else if (bm->first > i) {
370                    bm->first = i;
371                }
372            } else {
373                bm->first = i;
374                bm->last = i;
375            }
376            bm->weight++;
377        }
378    }
379}
380
381/**
382 * \brief clears a bit in the bitmap
383 *
384 * \param bm    bitmap to set the bit
385 * \param i     index of the bit to clear
386 */
387void bitmap_clear_bit(struct bitmap *bm, bitmap_bit_t i)
388{
389    if (i < bm->nbits) {
390        bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT];
391        bitmap_data_t mask = 1UL << (i % BITMAP_BITS_PER_ELEMENT);
392        if (data & mask) {
393            /* bit was set so clear it */
394            bm->weight--;
395            data &= ~(mask);
396            bm->data[i/BITMAP_BITS_PER_ELEMENT] = data;
397            if (bm->weight) {
398                if (bm->last == i) {
399                    bm->last = bitmap_get_prev(bm, i);
400                } else if (bm->first == i) {
401                    bm->first = bitmap_get_next(bm, i);
402                }
403            } else {
404                bm->first = BITMAP_BIT_NONE;
405                bm->last = BITMAP_BIT_NONE;
406            }
407        }
408    }
409}
410
411/**
412 * \brief sets all the bits in the bitmap
413 *
414 * \param bm    bitmap to set all bits
415 */
416void bitmap_set_all(struct bitmap *bm)
417{
418    memset(bm->data, 0xFF, bitmap_get_nbytes(bm));
419    bm->weight = bm->nbits;
420    bm->last = bm->nbits - 1;
421    bm->first = 0;
422}
423
424/**
425 * \brief clears all the bits in the bitmap
426 *
427 * \param bm    bitmap to clear all bits
428 */
429void bitmap_clear_all(struct bitmap *bm)
430{
431    memset(bm->data, 0, bitmap_get_nbytes(bm));
432    bm->weight = 0;
433    bm->first = BITMAP_BIT_NONE;
434    bm->last = BITMAP_BIT_NONE;
435}
436
437/**
438 * \brief sets a range of bits in the bitmap
439 *
440 * \param bm    bitmap to set the range
441 * \param from  start of the range (including)
442 * \param to    end of the range (including)
443 */
444void bitmap_set_range(struct bitmap *bm, bitmap_bit_t from, bitmap_bit_t to)
445{
446    if (to > bm->nbits) {
447        to = bm->nbits - 1;
448    }
449    for (bitmap_bit_t i = from; i <= to; ++i) {
450        bitmap_set_bit(bm, i);
451    }
452}
453
454/**
455 * \brief sets a range of bits in the bitmap
456 *
457 * \param bm    bitmap to set the range
458 * \param from  start of the range (including)
459 * \param to    end of the range (including)
460 */
461void bitmap_clear_range(struct bitmap *bm, bitmap_bit_t from, bitmap_bit_t to)
462{
463    if (to > bm->nbits) {
464        to = bm->nbits - 1;
465    }
466    for (bitmap_bit_t i = from; i <= to; ++i) {
467        bitmap_clear_bit(bm, i);
468    }
469}
470
471/**
472 * \brief clears the bitmap except for the given range
473 *
474 * \param bm    bitmap to set the range
475 * \param from  start of the range (including)
476 * \param to    end of the range (including)
477 */
478void bitmap_keep_range(struct bitmap *bm, uint32_t from, uint32_t to)
479{
480    if (from != 0) {
481        bitmap_clear_range(bm, 0, from - 1);
482    }
483
484    if (to != bm->nbits - 1) {
485        bitmap_clear_range(bm, to, bm->nbits);
486    }
487}
488
489/**
490 * \brief copies one bitmap onto another
491 *
492 * \param to    bitmap to copy into
493 * \param from  bitmap to copy from
494 *
495 * only the minimum number of bits in both bitmaps are copied. If the source is
496 * smaller than the destination remaining bits are cleared
497 */
498void bitmap_copy(struct bitmap *to, const struct bitmap *from)
499{
500    bitmap_clear_all(to);
501    bitmap_bit_t nbytes;
502    if (to->nbits < from->nbits) {
503        nbytes = bitmap_get_nbytes(to);
504    } else {
505        nbytes = bitmap_get_nbytes(from);
506    }
507    memcpy(to->data, from->data, nbytes);
508
509    /* TODO: set the meta information */
510    assert(!"NYI? setting meta information");
511}
512
513
514/*
515 * =============================================================================
516 * Bitmap Comparisons
517 * =============================================================================
518 */
519
520/**
521 * \brief determines if two bitmaps are equal
522 *
523 * \param bm1   the first bitmap
524 * \param bm2   the second bitmap
525 *
526 * \return TRUE if the two bitmaps are equal
527 *         FALSE otherwise
528 */
529bool bitmap_equal(const struct bitmap *bm1, const struct bitmap *bm2)
530{
531    /* the pointers are equal */
532    if (bm1 == bm2) {
533        return 1;
534    }
535    /* the sizes do not match, not equal */
536    if (bm1->nbits != bm2->nbits) {
537        return 0;
538    }
539
540    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits);
541    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits);
542
543    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
544        if (i < src_bytes) {
545            if (bm1->data[i] != bm2->data[i]) {
546                return 0;
547            }
548        }
549    }
550
551    return 1;
552}
553
554/**
555 * \brief determines if one bitmask is a subset of the other
556 *
557 * \param haystack   the original bitmap
558 * \param needle     the potential subset bitmap
559 *
560 * \return TRUE if the second bitmap is a subset of the other
561 *         FALSE otherwise
562 */
563bool bitmap_subset(const struct bitmap *haystack, const struct bitmap *needle)
564{
565    assert(!"NYI");
566    return 0;
567}
568
569/**
570 * \brief determines if two bitmaps are disjoint i.e. not sharing a set bit
571 *
572 * \param bm1   the first bitmap
573 * \param bm2   the second bitmap
574 *
575 * \return TRUE if the two bitmaps are disjoint
576 *         FALSE otherwise
577 */
578bool bitmap_disjoint(const struct bitmap *bm1, const struct bitmap *bm2)
579{
580    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits);
581    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits);
582
583    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
584        if (i < src_bytes) {
585            if (bm1->data[i] & bm2->data[i]) {
586                return 0;
587            }
588        }
589    }
590
591    return 1;
592}
593
594/**
595 * \brief determines if two bitmaps are intersecting i.e. sharing a set bit
596 *
597 * \param bm1   the first bitmap
598 * \param bm2   the second bitmap
599 *
600 * \return TRUE if the two bitmaps are equal
601 *         FALSE otherwise
602 */
603bool bitmap_intersects(const struct bitmap *bm1, const struct bitmap *bm2)
604{
605    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits);
606    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits);
607
608    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
609        if (i < src_bytes) {
610            if (bm1->data[i] & bm2->data[i]) {
611                return 1;
612            }
613        }
614    }
615
616    return 0;
617}
618
619/*
620 * =============================================================================
621 * Bitmap Operations
622 * =============================================================================
623 */
624
625/**
626 * \brief computes the complement to the bitmap
627 *
628 * \param bm the bitmap
629 */
630void bitmap_complement(struct bitmap *bm)
631{
632    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm->nbits) - 1;
633
634    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
635        bm->data[i] = ~bm->data[i];
636    }
637
638    for (bitmap_bit_t i = (dst_bytes * sizeof(bitmap_data_t)); i < bm->nbits; ++i) {
639        if (bitmap_is_bit_set(bm, i)) {
640            bitmap_clear_bit(bm, i);
641        } else {
642            bitmap_set_bit(bm, i);
643        }
644    }
645}
646
647/**
648 * \brief performs a right shift operation on the bitmap
649 *
650 * \param bm    the bitmap
651 * \param n     number of bits to shift
652 */
653void bitmap_shift_right(struct bitmap *bm, bitmap_bit_t n)
654{
655    assert(!"NYI");
656}
657
658/**
659 * \brief performs a left shift operation on the bitmap
660 *
661 * \param bm    the bitmap
662 * \param n     number of bits to shift
663 */
664void bitmap_shift_left(struct bitmap *bm, bitmap_bit_t n)
665{
666    assert(!"NYI");
667}
668
669/**
670 * \brief performs a logical AND operation between two bitmaps
671 *
672 * \param dst   destination to store the new bitmap
673 * \param src   source bitmap
674 *
675 * dst = dst AND src
676 */
677void bitmap_and(struct bitmap *dst, const struct bitmap *src)
678{
679    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits);
680    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits);
681
682    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
683        if (i < src_bytes) {
684            dst->data[i] = ~(dst->data[i] & src->data[i]);
685        } else {
686            dst->data[i] = 0;
687        }
688    }
689}
690
691/**
692 * \brief performs a logical NAND operation between two bitmaps
693 *
694 * \param dst   destination to store the new bitmap
695 * \param src   source bitmap
696 *
697 * dst = dst NAND src
698 */
699void bitmap_nand(struct bitmap *dst, const  struct bitmap *src)
700{
701    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits);
702    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits);
703
704    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
705        if (i < src_bytes) {
706            dst->data[i] = ~(dst->data[i] & src->data[i]);
707        } else {
708            dst->data[i] = ~((bitmap_data_t)0);
709        }
710    }
711}
712
713/**
714 * \brief performs a logical OR operation between two bitmaps
715 *
716 * \param dst   destination to store the new bitmap
717 * \param src   source bitmap
718 *
719 * dst = dst OR src
720 */
721void bitmap_or(struct bitmap *dst, const  struct bitmap *src)
722{
723    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits);
724    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits);
725
726    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
727        if (i < src_bytes) {
728            dst->data[i] = (dst->data[i] | src->data[i]);
729        }
730    }
731}
732
733/**
734 * \brief performs a logical AND operation between two bitmaps
735 *
736 * \param dst   destination to store the new bitmap
737 * \param src   source bitmap
738 *
739 * dst = dst XOR src
740 */
741void bitmap_xor(struct bitmap *dst, const  struct bitmap *src)
742{
743    bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits);
744    bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits);
745
746    for (bitmap_bit_t i = 0; i < dst_bytes; ++i) {
747        if (i < src_bytes) {
748            dst->data[i] = (dst->data[i] ^ src->data[i]);
749        }
750    }
751}
752
753/*
754 * =============================================================================
755 * Bitmap Debug
756 * =============================================================================
757 */
758
759void bitmap_dump(const struct bitmap *bm)
760{
761    uint8_t *data = (uint8_t *)(bm->data);
762
763    debug_printf("dumping contents of bitmap %p\n", bm);
764    debug_printf("----------------------------------\n");
765    for (uint32_t i = 0; i < bitmap_get_nbytes(bm); i += 4) {
766        debug_printf("bytes %u-%u:  [%02x] [%02x] [%02x] [%02x]\n",
767                     i, i+3, data[i], data[i+1], data[i+2], data[i+3]);
768    }
769    debug_printf("----------------------------------\n");
770}
771