15a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin/*
25a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * Copyright (C) 2011 The Android Open Source Project
35a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin *
45a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * Licensed under the Apache License, Version 2.0 (the "License");
55a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * you may not use this file except in compliance with the License.
65a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * You may obtain a copy of the License at
75a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin *
85a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin *      http://www.apache.org/licenses/LICENSE-2.0
95a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin *
105a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * Unless required by applicable law or agreed to in writing, software
115a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * distributed under the License is distributed on an "AS IS" BASIS,
125a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * See the License for the specific language governing permissions and
145a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin * limitations under the License.
155a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin */
165a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
175a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin#ifndef __CUTILS_BITOPS_H
185a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin#define __CUTILS_BITOPS_H
195a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
2081ec96df4f83df9781368c6f2b8160ee1b177f75Alex Ray#include <stdbool.h>
212111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#include <string.h>
222111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#include <strings.h>
235a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin#include <sys/cdefs.h>
245a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
255a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin__BEGIN_DECLS
265a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
272111bc7b28af06757fa8108bab045188d4b337fdAlex Ray/*
282111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * Bitmask Operations
292111bc7b28af06757fa8108bab045188d4b337fdAlex Ray *
302111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * Note this doesn't provide any locking/exclusion, and isn't atomic.
312111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * Additionally no bounds checking is done on the bitmask array.
322111bc7b28af06757fa8108bab045188d4b337fdAlex Ray *
332111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * Example:
342111bc7b28af06757fa8108bab045188d4b337fdAlex Ray *
352111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * int num_resources;
362111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
372111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * bitmask_init(resource_bits, num_resources);
382111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * ...
392111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * int bit = bitmask_ffz(resource_bits, num_resources);
402111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * bitmask_set(resource_bits, bit);
412111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * ...
422111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * if (bitmask_test(resource_bits, bit)) { ... }
432111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * ...
442111bc7b28af06757fa8108bab045188d4b337fdAlex Ray * bitmask_clear(resource_bits, bit);
452111bc7b28af06757fa8108bab045188d4b337fdAlex Ray *
462111bc7b28af06757fa8108bab045188d4b337fdAlex Ray */
472111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
482111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#define BITS_PER_WORD    (sizeof(unsigned int) * 8)
492111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
502111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#define BIT_IN_WORD(x)   ((x) % BITS_PER_WORD)
512111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#define BIT_WORD(x)      ((x) / BITS_PER_WORD)
522111bc7b28af06757fa8108bab045188d4b337fdAlex Ray#define BIT_MASK(x)      (1 << BIT_IN_WORD(x))
532111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
542111bc7b28af06757fa8108bab045188d4b337fdAlex Raystatic inline void bitmask_init(unsigned int *bitmask, int num_bits)
552111bc7b28af06757fa8108bab045188d4b337fdAlex Ray{
562111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
572111bc7b28af06757fa8108bab045188d4b337fdAlex Ray}
582111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
592111bc7b28af06757fa8108bab045188d4b337fdAlex Raystatic inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
602111bc7b28af06757fa8108bab045188d4b337fdAlex Ray{
612111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    int bit, result;
622111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    unsigned int i;
632111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
642111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
652111bc7b28af06757fa8108bab045188d4b337fdAlex Ray        bit = ffs(~bitmask[i]);
662111bc7b28af06757fa8108bab045188d4b337fdAlex Ray        if (bit) {
672111bc7b28af06757fa8108bab045188d4b337fdAlex Ray            // ffs is 1-indexed, return 0-indexed result
682111bc7b28af06757fa8108bab045188d4b337fdAlex Ray            bit--;
692111bc7b28af06757fa8108bab045188d4b337fdAlex Ray            result = BITS_PER_WORD * i + bit;
702111bc7b28af06757fa8108bab045188d4b337fdAlex Ray            if (result >= num_bits)
712111bc7b28af06757fa8108bab045188d4b337fdAlex Ray                return -1;
722111bc7b28af06757fa8108bab045188d4b337fdAlex Ray            return result;
732111bc7b28af06757fa8108bab045188d4b337fdAlex Ray        }
742111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    }
752111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    return -1;
762111bc7b28af06757fa8108bab045188d4b337fdAlex Ray}
772111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
78f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Raystatic inline int bitmask_weight(unsigned int *bitmask, int num_bits)
79f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray{
80f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray    int i;
81f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray    int weight = 0;
82f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray
83f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray    for (i = 0; i < BITS_TO_WORDS(num_bits); i++)
84f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray        weight += __builtin_popcount(bitmask[i]);
85f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray    return weight;
86f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray}
87f90fd9eeb32469e41c8f4207afa44929f9ec070eAlex Ray
882111bc7b28af06757fa8108bab045188d4b337fdAlex Raystatic inline void bitmask_set(unsigned int *bitmask, int bit)
892111bc7b28af06757fa8108bab045188d4b337fdAlex Ray{
902111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
912111bc7b28af06757fa8108bab045188d4b337fdAlex Ray}
922111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
932111bc7b28af06757fa8108bab045188d4b337fdAlex Raystatic inline void bitmask_clear(unsigned int *bitmask, int bit)
942111bc7b28af06757fa8108bab045188d4b337fdAlex Ray{
952111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
962111bc7b28af06757fa8108bab045188d4b337fdAlex Ray}
972111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
982111bc7b28af06757fa8108bab045188d4b337fdAlex Raystatic inline bool bitmask_test(unsigned int *bitmask, int bit)
992111bc7b28af06757fa8108bab045188d4b337fdAlex Ray{
1002111bc7b28af06757fa8108bab045188d4b337fdAlex Ray    return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
1012111bc7b28af06757fa8108bab045188d4b337fdAlex Ray}
1022111bc7b28af06757fa8108bab045188d4b337fdAlex Ray
1035a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavinstatic inline int popcount(unsigned int x)
1045a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin{
1055a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin    return __builtin_popcount(x);
1065a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin}
1075a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
1085a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavinstatic inline int popcountl(unsigned long x)
1095a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin{
1105a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin    return __builtin_popcountl(x);
1115a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin}
1125a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
1135a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavinstatic inline int popcountll(unsigned long long x)
1145a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin{
1155a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin    return __builtin_popcountll(x);
1165a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin}
1175a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
1185a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin__END_DECLS
1195a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin
1205a809b90e91d2ccf4c84181d10d175eb2c1c6bc7Dima Zavin#endif /* __CUTILS_BITOPS_H */
121