1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause 2*2d9fd380Sjfb8856606 * Copyright(c) 2019-2020 Broadcom 3*2d9fd380Sjfb8856606 * All rights reserved. 4*2d9fd380Sjfb8856606 */ 5*2d9fd380Sjfb8856606 6*2d9fd380Sjfb8856606 #ifndef _BITALLOC_H_ 7*2d9fd380Sjfb8856606 #define _BITALLOC_H_ 8*2d9fd380Sjfb8856606 9*2d9fd380Sjfb8856606 #include <stdint.h> 10*2d9fd380Sjfb8856606 11*2d9fd380Sjfb8856606 /* Bitalloc works on uint32_t as its word size */ 12*2d9fd380Sjfb8856606 typedef uint32_t bitalloc_word_t; 13*2d9fd380Sjfb8856606 14*2d9fd380Sjfb8856606 struct bitalloc { 15*2d9fd380Sjfb8856606 bitalloc_word_t size; 16*2d9fd380Sjfb8856606 bitalloc_word_t free_count; 17*2d9fd380Sjfb8856606 bitalloc_word_t storage[1]; 18*2d9fd380Sjfb8856606 }; 19*2d9fd380Sjfb8856606 20*2d9fd380Sjfb8856606 #define BA_L0(s) (((s) + 31) / 32) 21*2d9fd380Sjfb8856606 #define BA_L1(s) ((BA_L0(s) + 31) / 32) 22*2d9fd380Sjfb8856606 #define BA_L2(s) ((BA_L1(s) + 31) / 32) 23*2d9fd380Sjfb8856606 #define BA_L3(s) ((BA_L2(s) + 31) / 32) 24*2d9fd380Sjfb8856606 #define BA_L4(s) ((BA_L3(s) + 31) / 32) 25*2d9fd380Sjfb8856606 26*2d9fd380Sjfb8856606 #define BITALLOC_SIZEOF(size) \ 27*2d9fd380Sjfb8856606 (sizeof(struct bitalloc) * \ 28*2d9fd380Sjfb8856606 (((sizeof(struct bitalloc) + \ 29*2d9fd380Sjfb8856606 sizeof(struct bitalloc) - 1 + \ 30*2d9fd380Sjfb8856606 (sizeof(bitalloc_word_t) * \ 31*2d9fd380Sjfb8856606 ((BA_L0(size) - 1) + \ 32*2d9fd380Sjfb8856606 ((BA_L0(size) == 1) ? 0 : (BA_L1(size) + 1)) + \ 33*2d9fd380Sjfb8856606 ((BA_L1(size) == 1) ? 0 : (BA_L2(size) + 1)) + \ 34*2d9fd380Sjfb8856606 ((BA_L2(size) == 1) ? 0 : (BA_L3(size) + 1)) + \ 35*2d9fd380Sjfb8856606 ((BA_L3(size) == 1) ? 0 : (BA_L4(size) + 1)))))) / \ 36*2d9fd380Sjfb8856606 sizeof(struct bitalloc))) 37*2d9fd380Sjfb8856606 38*2d9fd380Sjfb8856606 #define BITALLOC_MAX_SIZE (32 * 32 * 32 * 32 * 32 * 32) 39*2d9fd380Sjfb8856606 40*2d9fd380Sjfb8856606 /* The instantiation of a bitalloc looks a bit odd. Since a 41*2d9fd380Sjfb8856606 * bit allocator has variable storage, we need a way to get a 42*2d9fd380Sjfb8856606 * a pointer to a bitalloc structure that points to the correct 43*2d9fd380Sjfb8856606 * amount of storage. We do this by creating an array of 44*2d9fd380Sjfb8856606 * bitalloc where the first element in the array is the 45*2d9fd380Sjfb8856606 * actual bitalloc base structure, and the remaining elements 46*2d9fd380Sjfb8856606 * in the array provide the storage for it. This approach allows 47*2d9fd380Sjfb8856606 * instances to be individual variables or members of larger 48*2d9fd380Sjfb8856606 * structures. 49*2d9fd380Sjfb8856606 */ 50*2d9fd380Sjfb8856606 #define BITALLOC_INST(name, size) \ 51*2d9fd380Sjfb8856606 struct bitalloc name[(BITALLOC_SIZEOF(size) / \ 52*2d9fd380Sjfb8856606 sizeof(struct bitalloc))] 53*2d9fd380Sjfb8856606 54*2d9fd380Sjfb8856606 /* Symbolic return codes */ 55*2d9fd380Sjfb8856606 #define BA_SUCCESS 0 56*2d9fd380Sjfb8856606 #define BA_FAIL -1 57*2d9fd380Sjfb8856606 #define BA_ENTRY_FREE 0 58*2d9fd380Sjfb8856606 #define BA_ENTRY_IN_USE 1 59*2d9fd380Sjfb8856606 #define BA_NO_ENTRY_FOUND -1 60*2d9fd380Sjfb8856606 61*2d9fd380Sjfb8856606 /** 62*2d9fd380Sjfb8856606 * Initializates the bitallocator 63*2d9fd380Sjfb8856606 * 64*2d9fd380Sjfb8856606 * Returns 0 on success, -1 on failure. Size is arbitrary up to 65*2d9fd380Sjfb8856606 * BITALLOC_MAX_SIZE 66*2d9fd380Sjfb8856606 */ 67*2d9fd380Sjfb8856606 int ba_init(struct bitalloc *pool, int size); 68*2d9fd380Sjfb8856606 69*2d9fd380Sjfb8856606 /** 70*2d9fd380Sjfb8856606 * Returns -1 on failure, or index of allocated entry 71*2d9fd380Sjfb8856606 */ 72*2d9fd380Sjfb8856606 int ba_alloc(struct bitalloc *pool); 73*2d9fd380Sjfb8856606 int ba_alloc_index(struct bitalloc *pool, int index); 74*2d9fd380Sjfb8856606 75*2d9fd380Sjfb8856606 /** 76*2d9fd380Sjfb8856606 * Returns -1 on failure, or index of allocated entry 77*2d9fd380Sjfb8856606 */ 78*2d9fd380Sjfb8856606 int ba_alloc_reverse(struct bitalloc *pool); 79*2d9fd380Sjfb8856606 80*2d9fd380Sjfb8856606 /** 81*2d9fd380Sjfb8856606 * Query a particular index in a pool to check if its in use. 82*2d9fd380Sjfb8856606 * 83*2d9fd380Sjfb8856606 * Returns -1 on invalid index, 1 if the index is allocated, 0 if it 84*2d9fd380Sjfb8856606 * is free 85*2d9fd380Sjfb8856606 */ 86*2d9fd380Sjfb8856606 int ba_inuse(struct bitalloc *pool, int index); 87*2d9fd380Sjfb8856606 88*2d9fd380Sjfb8856606 /** 89*2d9fd380Sjfb8856606 * Variant of ba_inuse that frees the index if it is allocated, same 90*2d9fd380Sjfb8856606 * return codes as ba_inuse 91*2d9fd380Sjfb8856606 */ 92*2d9fd380Sjfb8856606 int ba_inuse_free(struct bitalloc *pool, int index); 93*2d9fd380Sjfb8856606 94*2d9fd380Sjfb8856606 /** 95*2d9fd380Sjfb8856606 * Find next index that is in use, start checking at index 'idx' 96*2d9fd380Sjfb8856606 * 97*2d9fd380Sjfb8856606 * Returns next index that is in use on success, or 98*2d9fd380Sjfb8856606 * -1 if no in use index is found 99*2d9fd380Sjfb8856606 */ 100*2d9fd380Sjfb8856606 int ba_find_next_inuse(struct bitalloc *pool, int idx); 101*2d9fd380Sjfb8856606 102*2d9fd380Sjfb8856606 /** 103*2d9fd380Sjfb8856606 * Variant of ba_find_next_inuse that also frees the next in use index, 104*2d9fd380Sjfb8856606 * same return codes as ba_find_next_inuse 105*2d9fd380Sjfb8856606 */ 106*2d9fd380Sjfb8856606 int ba_find_next_inuse_free(struct bitalloc *pool, int idx); 107*2d9fd380Sjfb8856606 108*2d9fd380Sjfb8856606 /** 109*2d9fd380Sjfb8856606 * Multiple freeing of the same index has no negative side effects, 110*2d9fd380Sjfb8856606 * but will return -1. returns -1 on failure, 0 on success. 111*2d9fd380Sjfb8856606 */ 112*2d9fd380Sjfb8856606 int ba_free(struct bitalloc *pool, int index); 113*2d9fd380Sjfb8856606 114*2d9fd380Sjfb8856606 /** 115*2d9fd380Sjfb8856606 * Returns the pool's free count 116*2d9fd380Sjfb8856606 */ 117*2d9fd380Sjfb8856606 int ba_free_count(struct bitalloc *pool); 118*2d9fd380Sjfb8856606 119*2d9fd380Sjfb8856606 /** 120*2d9fd380Sjfb8856606 * Returns the pool's in use count 121*2d9fd380Sjfb8856606 */ 122*2d9fd380Sjfb8856606 int ba_inuse_count(struct bitalloc *pool); 123*2d9fd380Sjfb8856606 124*2d9fd380Sjfb8856606 #endif /* _BITALLOC_H_ */ 125