The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ck/include/ck_bitmap.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright 2012-2015 Samy Al Bahra.
    3  * Copyright 2012-2014 AppNexus, Inc.
    4  * Copyright 2014 Paul Khuong.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #ifndef CK_BITMAP_H
   30 #define CK_BITMAP_H
   31 
   32 #include <ck_cc.h>
   33 #include <ck_limits.h>
   34 #include <ck_pr.h>
   35 #include <ck_stdint.h>
   36 #include <ck_stdbool.h>
   37 #include <ck_stddef.h>
   38 #include <ck_stdbool.h>
   39 #include <ck_stddef.h>
   40 #include <ck_string.h>
   41 
   42 #if !defined(CK_F_PR_LOAD_UINT) || !defined(CK_F_PR_STORE_UINT) || \
   43     !defined(CK_F_PR_AND_UINT) || !defined(CK_F_PR_OR_UINT) || \
   44     !defined(CK_F_CC_CTZ)
   45 #error "ck_bitmap is not supported on your platform."
   46 #endif
   47 
   48 #define CK_BITMAP_BLOCK         (sizeof(unsigned int) * CHAR_BIT)
   49 #define CK_BITMAP_OFFSET(i)     ((i) % CK_BITMAP_BLOCK)
   50 #define CK_BITMAP_BIT(i)        (1U << CK_BITMAP_OFFSET(i))
   51 #define CK_BITMAP_PTR(x, i)     ((x) + ((i) / CK_BITMAP_BLOCK))
   52 #define CK_BITMAP_BLOCKS(n)     (((n) + CK_BITMAP_BLOCK - 1) / CK_BITMAP_BLOCK)
   53 
   54 #define CK_BITMAP_INSTANCE(n_entries)                                   \
   55         union {                                                         \
   56                 struct {                                                \
   57                         unsigned int n_bits;                            \
   58                         unsigned int map[CK_BITMAP_BLOCKS(n_entries)];  \
   59                 } content;                                              \
   60                 struct ck_bitmap bitmap;                                \
   61         }
   62 
   63 #define CK_BITMAP_ITERATOR_INIT(a, b) \
   64         ck_bitmap_iterator_init((a), &(b)->bitmap)
   65 
   66 #define CK_BITMAP_INIT(a, b, c) \
   67         ck_bitmap_init(&(a)->bitmap, (b), (c))
   68 
   69 #define CK_BITMAP_NEXT(a, b, c) \
   70         ck_bitmap_next(&(a)->bitmap, (b), (c))
   71 
   72 #define CK_BITMAP_SET(a, b) \
   73         ck_bitmap_set(&(a)->bitmap, (b))
   74 
   75 #define CK_BITMAP_BTS(a, b) \
   76         ck_bitmap_bts(&(a)->bitmap, (b))
   77 
   78 #define CK_BITMAP_RESET(a, b) \
   79         ck_bitmap_reset(&(a)->bitmap, (b))
   80 
   81 #define CK_BITMAP_TEST(a, b) \
   82         ck_bitmap_test(&(a)->bitmap, (b))
   83 
   84 #define CK_BITMAP_UNION(a, b) \
   85         ck_bitmap_union(&(a)->bitmap, &(b)->bitmap)
   86 
   87 #define CK_BITMAP_INTERSECTION(a, b) \
   88         ck_bitmap_intersection(&(a)->bitmap, &(b)->bitmap)
   89 
   90 #define CK_BITMAP_INTERSECTION_NEGATE(a, b) \
   91         ck_bitmap_intersection_negate(&(a)->bitmap, &(b)->bitmap)
   92 
   93 #define CK_BITMAP_CLEAR(a) \
   94         ck_bitmap_clear(&(a)->bitmap)
   95 
   96 #define CK_BITMAP_EMPTY(a, b) \
   97         ck_bitmap_empty(&(a)->bitmap, b)
   98 
   99 #define CK_BITMAP_FULL(a, b) \
  100         ck_bitmap_full(&(a)->bitmap, b)
  101 
  102 #define CK_BITMAP_COUNT(a, b) \
  103         ck_bitmap_count(&(a)->bitmap, b)
  104 
  105 #define CK_BITMAP_COUNT_INTERSECT(a, b, c) \
  106         ck_bitmap_count_intersect(&(a)->bitmap, b, c)
  107 
  108 #define CK_BITMAP_BITS(a) \
  109         ck_bitmap_bits(&(a)->bitmap)
  110 
  111 #define CK_BITMAP_BUFFER(a) \
  112         ck_bitmap_buffer(&(a)->bitmap)
  113 
  114 #define CK_BITMAP(a) \
  115         (&(a)->bitmap)
  116 
  117 struct ck_bitmap {
  118         unsigned int n_bits;
  119         unsigned int map[];
  120 };
  121 typedef struct ck_bitmap ck_bitmap_t;
  122 
  123 struct ck_bitmap_iterator {
  124         unsigned int cache;
  125         unsigned int n_block;
  126         unsigned int n_limit;
  127 };
  128 typedef struct ck_bitmap_iterator ck_bitmap_iterator_t;
  129 
  130 CK_CC_INLINE static unsigned int
  131 ck_bitmap_base(unsigned int n_bits)
  132 {
  133 
  134         return CK_BITMAP_BLOCKS(n_bits) * sizeof(unsigned int);
  135 }
  136 
  137 /*
  138  * Returns the required number of bytes for a ck_bitmap_t object supporting the
  139  * specified number of bits.
  140  */
  141 CK_CC_INLINE static unsigned int
  142 ck_bitmap_size(unsigned int n_bits)
  143 {
  144 
  145         return ck_bitmap_base(n_bits) + sizeof(struct ck_bitmap);
  146 }
  147 
  148 /*
  149  * Returns total number of bits in specified bitmap.
  150  */
  151 CK_CC_INLINE static unsigned int
  152 ck_bitmap_bits(const struct ck_bitmap *bitmap)
  153 {
  154 
  155         return bitmap->n_bits;
  156 }
  157 
  158 /*
  159  * Returns a pointer to the bit buffer associated
  160  * with the specified bitmap.
  161  */
  162 CK_CC_INLINE static void *
  163 ck_bitmap_buffer(struct ck_bitmap *bitmap)
  164 {
  165 
  166         return bitmap->map;
  167 }
  168 
  169 /*
  170  * Sets the bit at the offset specified in the second argument.
  171  */
  172 CK_CC_INLINE static void
  173 ck_bitmap_set(struct ck_bitmap *bitmap, unsigned int n)
  174 {
  175 
  176         ck_pr_or_uint(CK_BITMAP_PTR(bitmap->map, n), CK_BITMAP_BIT(n));
  177         return;
  178 }
  179 
  180 /*
  181  * Performs a test-and-set operation at the offset specified in the
  182  * second argument.
  183  * Returns true if the bit at the specified offset was already set,
  184  * false otherwise.
  185  */
  186 CK_CC_INLINE static bool
  187 ck_bitmap_bts(struct ck_bitmap *bitmap, unsigned int n)
  188 {
  189 
  190         return ck_pr_bts_uint(CK_BITMAP_PTR(bitmap->map, n),
  191             CK_BITMAP_OFFSET(n));
  192 }
  193 
  194 /*
  195  * Resets the bit at the offset specified in the second argument.
  196  */
  197 CK_CC_INLINE static void
  198 ck_bitmap_reset(struct ck_bitmap *bitmap, unsigned int n)
  199 {
  200 
  201         ck_pr_and_uint(CK_BITMAP_PTR(bitmap->map, n), ~CK_BITMAP_BIT(n));
  202         return;
  203 }
  204 
  205 /*
  206  * Determines whether the bit at offset specified in the
  207  * second argument is set.
  208  */
  209 CK_CC_INLINE static bool
  210 ck_bitmap_test(const struct ck_bitmap *bitmap, unsigned int n)
  211 {
  212         unsigned int block;
  213 
  214         block = ck_pr_load_uint(CK_BITMAP_PTR(bitmap->map, n));
  215         return block & CK_BITMAP_BIT(n);
  216 }
  217 
  218 /*
  219  * Combines bits from second bitmap into the first bitmap. This is not a
  220  * linearized operation with respect to the complete bitmap.
  221  */
  222 CK_CC_INLINE static void
  223 ck_bitmap_union(struct ck_bitmap *dst, const struct ck_bitmap *src)
  224 {
  225         unsigned int n;
  226         unsigned int n_buckets = dst->n_bits;
  227 
  228         if (src->n_bits < dst->n_bits)
  229                 n_buckets = src->n_bits;
  230 
  231         n_buckets = CK_BITMAP_BLOCKS(n_buckets);
  232         for (n = 0; n < n_buckets; n++) {
  233                 ck_pr_or_uint(&dst->map[n],
  234                     ck_pr_load_uint(&src->map[n]));
  235         }
  236 
  237         return;
  238 }
  239 
  240 /*
  241  * Intersects bits from second bitmap into the first bitmap. This is
  242  * not a linearized operation with respect to the complete bitmap.
  243  * Any trailing bit in dst is cleared.
  244  */
  245 CK_CC_INLINE static void
  246 ck_bitmap_intersection(struct ck_bitmap *dst, const struct ck_bitmap *src)
  247 {
  248         unsigned int n;
  249         unsigned int n_buckets = dst->n_bits;
  250         unsigned int n_intersect = n_buckets;
  251 
  252         if (src->n_bits < n_intersect)
  253                 n_intersect = src->n_bits;
  254 
  255         n_buckets = CK_BITMAP_BLOCKS(n_buckets);
  256         n_intersect = CK_BITMAP_BLOCKS(n_intersect);
  257         for (n = 0; n < n_intersect; n++) {
  258                 ck_pr_and_uint(&dst->map[n],
  259                     ck_pr_load_uint(&src->map[n]));
  260         }
  261 
  262         for (; n < n_buckets; n++)
  263                 ck_pr_store_uint(&dst->map[n], 0);
  264 
  265         return;
  266 }
  267 
  268 /*
  269  * Intersects the complement of bits from second bitmap into the first
  270  * bitmap. This is not a linearized operation with respect to the
  271  * complete bitmap.  Any trailing bit in dst is left as is.
  272  */
  273 CK_CC_INLINE static void
  274 ck_bitmap_intersection_negate(struct ck_bitmap *dst,
  275     const struct ck_bitmap *src)
  276 {
  277         unsigned int n;
  278         unsigned int n_intersect = dst->n_bits;
  279 
  280         if (src->n_bits < n_intersect)
  281                 n_intersect = src->n_bits;
  282 
  283         n_intersect = CK_BITMAP_BLOCKS(n_intersect);
  284         for (n = 0; n < n_intersect; n++) {
  285                 ck_pr_and_uint(&dst->map[n],
  286                     (~ck_pr_load_uint(&src->map[n])));
  287         }
  288 
  289         return;
  290 }
  291 
  292 /*
  293  * Resets all bits in the provided bitmap. This is not a linearized
  294  * operation in ck_bitmap.
  295  */
  296 CK_CC_INLINE static void
  297 ck_bitmap_clear(struct ck_bitmap *bitmap)
  298 {
  299         unsigned int i;
  300         unsigned int n_buckets = ck_bitmap_base(bitmap->n_bits) /
  301             sizeof(unsigned int);
  302 
  303         for (i = 0; i < n_buckets; i++)
  304                 ck_pr_store_uint(&bitmap->map[i], 0);
  305 
  306         return;
  307 }
  308 
  309 /*
  310  * Returns true if the first limit bits in bitmap are cleared.  If
  311  * limit is greater than the bitmap size, limit is truncated to that
  312  * size.
  313  */
  314 CK_CC_INLINE static bool
  315 ck_bitmap_empty(const ck_bitmap_t *bitmap, unsigned int limit)
  316 {
  317         unsigned int i, words, slop;
  318 
  319         if (limit > bitmap->n_bits)
  320                 limit = bitmap->n_bits;
  321 
  322         words = limit / CK_BITMAP_BLOCK;
  323         slop = limit % CK_BITMAP_BLOCK;
  324         for (i = 0; i < words; i++) {
  325                 if (ck_pr_load_uint(&bitmap->map[i]) != 0) {
  326                         return false;
  327                 }
  328         }
  329 
  330         if (slop > 0) {
  331                 unsigned int word;
  332 
  333                 word = ck_pr_load_uint(&bitmap->map[i]);
  334                 if ((word & ((1U << slop) - 1)) != 0)
  335                         return false;
  336         }
  337 
  338         return true;
  339 }
  340 
  341 /*
  342  * Returns true if the first limit bits in bitmap are set.  If limit
  343  * is greater than the bitmap size, limit is truncated to that size.
  344  */
  345 CK_CC_UNUSED static bool
  346 ck_bitmap_full(const ck_bitmap_t *bitmap, unsigned int limit)
  347 {
  348         unsigned int i, slop, words;
  349 
  350         if (limit > bitmap->n_bits) {
  351                 limit = bitmap->n_bits;
  352         }
  353 
  354         words = limit / CK_BITMAP_BLOCK;
  355         slop = limit % CK_BITMAP_BLOCK;
  356         for (i = 0; i < words; i++) {
  357                 if (ck_pr_load_uint(&bitmap->map[i]) != -1U)
  358                         return false;
  359         }
  360 
  361         if (slop > 0) {
  362                 unsigned int word;
  363 
  364                 word = ~ck_pr_load_uint(&bitmap->map[i]);
  365                 if ((word & ((1U << slop) - 1)) != 0)
  366                         return false;
  367         }
  368         return true;
  369 }
  370 
  371 /*
  372  * Returns the number of set bit in bitmap, upto (and excluding)
  373  * limit.  If limit is greater than the bitmap size, it is truncated
  374  * to that size.
  375  */
  376 CK_CC_INLINE static unsigned int
  377 ck_bitmap_count(const ck_bitmap_t *bitmap, unsigned int limit)
  378 {
  379         unsigned int count, i, slop, words;
  380 
  381         if (limit > bitmap->n_bits)
  382                 limit = bitmap->n_bits;
  383 
  384         words = limit / CK_BITMAP_BLOCK;
  385         slop = limit % CK_BITMAP_BLOCK;
  386         for (i = 0, count = 0; i < words; i++)
  387                 count += ck_cc_popcount(ck_pr_load_uint(&bitmap->map[i]));
  388 
  389         if (slop > 0) {
  390                 unsigned int word;
  391 
  392                 word = ck_pr_load_uint(&bitmap->map[i]);
  393                 count += ck_cc_popcount(word & ((1U << slop) - 1));
  394         }
  395         return count;
  396 }
  397 
  398 /*
  399  * Returns the number of set bit in the intersection of two bitmaps,
  400  * upto (and excluding) limit.  If limit is greater than either bitmap
  401  * size, it is truncated to the smallest.
  402  */
  403 CK_CC_INLINE static unsigned int
  404 ck_bitmap_count_intersect(const ck_bitmap_t *x, const ck_bitmap_t *y,
  405     unsigned int limit)
  406 {
  407         unsigned int count, i, slop, words;
  408 
  409         if (limit > x->n_bits)
  410                 limit = x->n_bits;
  411 
  412         if (limit > y->n_bits)
  413                 limit = y->n_bits;
  414 
  415         words = limit / CK_BITMAP_BLOCK;
  416         slop = limit % CK_BITMAP_BLOCK;
  417         for (i = 0, count = 0; i < words; i++) {
  418                 unsigned int xi, yi;
  419 
  420                 xi = ck_pr_load_uint(&x->map[i]);
  421                 yi = ck_pr_load_uint(&y->map[i]);
  422                 count += ck_cc_popcount(xi & yi);
  423         }
  424 
  425         if (slop > 0) {
  426                 unsigned int word, xi, yi;
  427 
  428                 xi = ck_pr_load_uint(&x->map[i]);
  429                 yi = ck_pr_load_uint(&y->map[i]);
  430                 word = xi & yi;
  431                 count += ck_cc_popcount(word & ((1U << slop) - 1));
  432         }
  433         return count;
  434 }
  435 
  436 /*
  437  * Initializes a ck_bitmap pointing to a region of memory with
  438  * ck_bitmap_size(n_bits) bytes. Third argument determines whether
  439  * default bit value is 1 (true) or 0 (false).
  440  */
  441 CK_CC_INLINE static void
  442 ck_bitmap_init(struct ck_bitmap *bitmap,
  443                unsigned int n_bits,
  444                bool set)
  445 {
  446         unsigned int base = ck_bitmap_base(n_bits);
  447 
  448         bitmap->n_bits = n_bits;
  449         memset(bitmap->map, -(int)set, base);
  450 
  451         if (set == true) {
  452                 unsigned int b = n_bits % CK_BITMAP_BLOCK;
  453 
  454                 if (b == 0)
  455                         return;
  456 
  457                 *CK_BITMAP_PTR(bitmap->map, n_bits - 1) &= (1U << b) - 1U;
  458         }
  459 
  460         return;
  461 }
  462 
  463 /*
  464  * Initialize iterator for use with provided bitmap.
  465  */
  466 CK_CC_INLINE static void
  467 ck_bitmap_iterator_init(struct ck_bitmap_iterator *i,
  468     const struct ck_bitmap *bitmap)
  469 {
  470 
  471         i->n_block = 0;
  472         i->n_limit = CK_BITMAP_BLOCKS(bitmap->n_bits);
  473         if (i->n_limit > 0) {
  474                 i->cache = ck_pr_load_uint(&bitmap->map[0]);
  475         } else {
  476                 i->cache = 0;
  477         }
  478         return;
  479 }
  480 
  481 /*
  482  * Iterate to next bit.
  483  */
  484 CK_CC_INLINE static bool
  485 ck_bitmap_next(const struct ck_bitmap *bitmap,
  486                struct ck_bitmap_iterator *i,
  487                unsigned int *bit)
  488 {
  489         unsigned int cache = i->cache;
  490         unsigned int n_block = i->n_block;
  491         unsigned int n_limit = i->n_limit;
  492 
  493         if (cache == 0) {
  494                 if (n_block >= n_limit)
  495                         return false;
  496 
  497                 for (n_block++; n_block < n_limit; n_block++) {
  498                         cache = ck_pr_load_uint(&bitmap->map[n_block]);
  499                         if (cache != 0)
  500                                 goto non_zero;
  501                 }
  502 
  503                 i->cache = 0;
  504                 i->n_block = n_block;
  505                 return false;
  506         }
  507 
  508 non_zero:
  509         *bit = CK_BITMAP_BLOCK * n_block + ck_cc_ctz(cache);
  510         i->cache = cache & (cache - 1);
  511         i->n_block = n_block;
  512         return true;
  513 }
  514 
  515 #endif /* CK_BITMAP_H */

Cache object: e06656b0abae60d8e4b59dcfbcdd36c1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.