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