xref: /aosp_15_r20/external/mesa3d/src/util/u_idalloc.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker  *
3*61046927SAndroid Build Coastguard Worker  * Copyright 2017 Valve Corporation
4*61046927SAndroid Build Coastguard Worker  * All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the
8*61046927SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
9*61046927SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
10*61046927SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
11*61046927SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
12*61046927SAndroid Build Coastguard Worker  * the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
15*61046927SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
16*61046927SAndroid Build Coastguard Worker  * of the Software.
17*61046927SAndroid Build Coastguard Worker  *
18*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*61046927SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21*61046927SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
22*61046927SAndroid Build Coastguard Worker  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23*61046927SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24*61046927SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  **************************************************************************/
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker /* Allocator of IDs (e.g. OpenGL object IDs), or simply an allocator of
29*61046927SAndroid Build Coastguard Worker  * numbers.
30*61046927SAndroid Build Coastguard Worker  *
31*61046927SAndroid Build Coastguard Worker  * The allocator uses a bit array to track allocated IDs.
32*61046927SAndroid Build Coastguard Worker  */
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #ifndef U_IDALLOC_H
35*61046927SAndroid Build Coastguard Worker #define U_IDALLOC_H
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
38*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
39*61046927SAndroid Build Coastguard Worker #include "simple_mtx.h"
40*61046927SAndroid Build Coastguard Worker #include "bitscan.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
43*61046927SAndroid Build Coastguard Worker extern "C" {
44*61046927SAndroid Build Coastguard Worker #endif
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker struct util_idalloc
47*61046927SAndroid Build Coastguard Worker {
48*61046927SAndroid Build Coastguard Worker    uint32_t *data;
49*61046927SAndroid Build Coastguard Worker    unsigned num_elements;     /* number of allocated elements of "data" */
50*61046927SAndroid Build Coastguard Worker    unsigned num_set_elements; /* the last non-zero element of "data" + 1 */
51*61046927SAndroid Build Coastguard Worker    unsigned lowest_free_idx;
52*61046927SAndroid Build Coastguard Worker };
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker void
55*61046927SAndroid Build Coastguard Worker util_idalloc_init(struct util_idalloc *buf, unsigned initial_num_ids);
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker void
58*61046927SAndroid Build Coastguard Worker util_idalloc_fini(struct util_idalloc *buf);
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker unsigned
61*61046927SAndroid Build Coastguard Worker util_idalloc_alloc(struct util_idalloc *buf);
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker unsigned
64*61046927SAndroid Build Coastguard Worker util_idalloc_alloc_range(struct util_idalloc *buf, unsigned num);
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker void
67*61046927SAndroid Build Coastguard Worker util_idalloc_free(struct util_idalloc *buf, unsigned id);
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker void
70*61046927SAndroid Build Coastguard Worker util_idalloc_reserve(struct util_idalloc *buf, unsigned id);
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker #define util_idalloc_foreach(buf, id) \
73*61046927SAndroid Build Coastguard Worker    for (uint32_t _i = 0, _mask = (buf)->num_set_elements ? (buf)->data[0] : 0, id, \
74*61046927SAndroid Build Coastguard Worker                  _count = (buf)->num_used; \
75*61046927SAndroid Build Coastguard Worker         _i < _count; _mask = ++_i < _count ? (buf)->data[_i] : 0) \
76*61046927SAndroid Build Coastguard Worker       while (_mask) \
77*61046927SAndroid Build Coastguard Worker          if ((id = _i * 32 + u_bit_scan(&_mask)), true)
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker /* This allows freeing IDs while iterating, excluding ID=0. */
80*61046927SAndroid Build Coastguard Worker #define util_idalloc_foreach_no_zero_safe(buf, id) \
81*61046927SAndroid Build Coastguard Worker    for (uint32_t _i = 0, _bit, id, _count = (buf)->num_set_elements, \
82*61046927SAndroid Build Coastguard Worker          _mask = _count ? (buf)->data[0] & ~0x1 : 0; \
83*61046927SAndroid Build Coastguard Worker         _i < _count; _mask = ++_i < _count ? (buf)->data[_i] : 0) \
84*61046927SAndroid Build Coastguard Worker       while (_mask) \
85*61046927SAndroid Build Coastguard Worker          if ((_bit = u_bit_scan(&_mask), id = _i * 32 + _bit), \
86*61046927SAndroid Build Coastguard Worker              (buf)->data[_i] & BITFIELD_BIT(_bit))
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker /* Thread-safe variant. */
89*61046927SAndroid Build Coastguard Worker struct util_idalloc_mt {
90*61046927SAndroid Build Coastguard Worker    struct util_idalloc buf;
91*61046927SAndroid Build Coastguard Worker    simple_mtx_t mutex;
92*61046927SAndroid Build Coastguard Worker    bool skip_zero;
93*61046927SAndroid Build Coastguard Worker };
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker void
96*61046927SAndroid Build Coastguard Worker util_idalloc_mt_init(struct util_idalloc_mt *buf,
97*61046927SAndroid Build Coastguard Worker                      unsigned initial_num_ids, bool skip_zero);
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker void
100*61046927SAndroid Build Coastguard Worker util_idalloc_mt_init_tc(struct util_idalloc_mt *buf);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker void
103*61046927SAndroid Build Coastguard Worker util_idalloc_mt_fini(struct util_idalloc_mt *buf);
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker unsigned
106*61046927SAndroid Build Coastguard Worker util_idalloc_mt_alloc(struct util_idalloc_mt *buf);
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker void
109*61046927SAndroid Build Coastguard Worker util_idalloc_mt_free(struct util_idalloc_mt *buf, unsigned id);
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker /* util_idalloc_sparse: The 32-bit ID range is divided into separately managed
112*61046927SAndroid Build Coastguard Worker  * segments. This reduces virtual memory usage when IDs are sparse.
113*61046927SAndroid Build Coastguard Worker  * It's done by layering util_idalloc_sparse on top of util_idalloc.
114*61046927SAndroid Build Coastguard Worker  *
115*61046927SAndroid Build Coastguard Worker  * If the last ID is allocated:
116*61046927SAndroid Build Coastguard Worker  * - "util_idalloc" occupies 512 MB of virtual memory
117*61046927SAndroid Build Coastguard Worker  * - "util_idalloc_sparse" occupies only 512 KB of virtual memory
118*61046927SAndroid Build Coastguard Worker  */
119*61046927SAndroid Build Coastguard Worker struct util_idalloc_sparse {
120*61046927SAndroid Build Coastguard Worker    struct util_idalloc segment[1024];
121*61046927SAndroid Build Coastguard Worker };
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker #define UTIL_IDALLOC_MAX_IDS_PER_SEGMENT(buf) \
124*61046927SAndroid Build Coastguard Worker    ((uint32_t)(BITFIELD64_BIT(32) / ARRAY_SIZE((buf)->segment)))
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker #define UTIL_IDALLOC_MAX_ELEMS_PER_SEGMENT(buf) \
127*61046927SAndroid Build Coastguard Worker    (UTIL_IDALLOC_MAX_IDS_PER_SEGMENT(buf) / 32)
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker void
130*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_init(struct util_idalloc_sparse *buf);
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker void
133*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_fini(struct util_idalloc_sparse *buf);
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker unsigned
136*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_alloc(struct util_idalloc_sparse *buf);
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker unsigned
139*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_alloc_range(struct util_idalloc_sparse *buf, unsigned num);
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker void
142*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_free(struct util_idalloc_sparse *buf, unsigned id);
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker void
145*61046927SAndroid Build Coastguard Worker util_idalloc_sparse_reserve(struct util_idalloc_sparse *buf, unsigned id);
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker /* This allows freeing IDs while iterating, excluding ID=0. */
148*61046927SAndroid Build Coastguard Worker #define util_idalloc_sparse_foreach_no_zero_safe(buf, id) \
149*61046927SAndroid Build Coastguard Worker    for (uint32_t _s = 0; _s < ARRAY_SIZE((buf)->segment); _s++) \
150*61046927SAndroid Build Coastguard Worker       for (uint32_t _i = 0, _bit, id, _count = (buf)->segment[_s].num_set_elements, \
151*61046927SAndroid Build Coastguard Worker             _mask = _count ? (buf)->segment[_s].data[0] & ~0x1 : 0; \
152*61046927SAndroid Build Coastguard Worker            _i < _count; _mask = ++_i < _count ? (buf)->segment[_s].data[_i] : 0) \
153*61046927SAndroid Build Coastguard Worker          while (_mask) \
154*61046927SAndroid Build Coastguard Worker             if ((_bit = u_bit_scan(&_mask), id = _s * UTIL_IDALLOC_MAX_IDS_PER_SEGMENT(buf) + _i * 32 + _bit), \
155*61046927SAndroid Build Coastguard Worker                 (buf)->segment[_s].data[_i] & BITFIELD_BIT(_bit))
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker #endif
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker #endif /* U_IDALLOC_H */
162