xref: /aosp_15_r20/external/mesa3d/src/util/slab.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2010 Marek Olšák <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * Copyright 2016 Advanced Micro Devices, Inc.
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
6*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
7*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
8*61046927SAndroid Build Coastguard Worker  * on the rights to use, copy, modify, merge, publish, distribute, sub
9*61046927SAndroid Build Coastguard Worker  * license, and/or sell copies of the Software, and to permit persons to whom
10*61046927SAndroid Build Coastguard Worker  * the Software is furnished to do so, subject to the following conditions:
11*61046927SAndroid Build Coastguard Worker  *
12*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
13*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
14*61046927SAndroid Build Coastguard Worker  * Software.
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20*61046927SAndroid Build Coastguard Worker  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21*61046927SAndroid Build Coastguard Worker  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22*61046927SAndroid Build Coastguard Worker  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "slab.h"
25*61046927SAndroid Build Coastguard Worker #include "macros.h"
26*61046927SAndroid Build Coastguard Worker #include "u_atomic.h"
27*61046927SAndroid Build Coastguard Worker #include <stdint.h>
28*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
29*61046927SAndroid Build Coastguard Worker #include <string.h>
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #define SLAB_MAGIC_ALLOCATED 0xcafe4321
32*61046927SAndroid Build Coastguard Worker #define SLAB_MAGIC_FREE 0x7ee01234
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
35*61046927SAndroid Build Coastguard Worker #define SET_MAGIC(element, value)   (element)->magic = (value)
36*61046927SAndroid Build Coastguard Worker #define CHECK_MAGIC(element, value) assert((element)->magic == (value))
37*61046927SAndroid Build Coastguard Worker #else
38*61046927SAndroid Build Coastguard Worker #define SET_MAGIC(element, value)
39*61046927SAndroid Build Coastguard Worker #define CHECK_MAGIC(element, value)
40*61046927SAndroid Build Coastguard Worker #endif
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker /* One array element within a big buffer. */
43*61046927SAndroid Build Coastguard Worker struct slab_element_header {
44*61046927SAndroid Build Coastguard Worker    /* The next element in the free or migrated list. */
45*61046927SAndroid Build Coastguard Worker    struct slab_element_header *next;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    /* This is either
48*61046927SAndroid Build Coastguard Worker     * - a pointer to the child pool to which this element belongs, or
49*61046927SAndroid Build Coastguard Worker     * - a pointer to the orphaned page of the element, with the least
50*61046927SAndroid Build Coastguard Worker     *   significant bit set to 1.
51*61046927SAndroid Build Coastguard Worker     */
52*61046927SAndroid Build Coastguard Worker    intptr_t owner;
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
55*61046927SAndroid Build Coastguard Worker    intptr_t magic;
56*61046927SAndroid Build Coastguard Worker #endif
57*61046927SAndroid Build Coastguard Worker };
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker /* The page is an array of allocations in one block. */
60*61046927SAndroid Build Coastguard Worker struct slab_page_header {
61*61046927SAndroid Build Coastguard Worker    union {
62*61046927SAndroid Build Coastguard Worker       /* Next page in the same child pool. */
63*61046927SAndroid Build Coastguard Worker       struct slab_page_header *next;
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker       /* Number of remaining, non-freed elements (for orphaned pages). */
66*61046927SAndroid Build Coastguard Worker       unsigned num_remaining;
67*61046927SAndroid Build Coastguard Worker    } u;
68*61046927SAndroid Build Coastguard Worker    /* Memory after the last member is dedicated to the page itself.
69*61046927SAndroid Build Coastguard Worker     * The allocated size is always larger than this structure.
70*61046927SAndroid Build Coastguard Worker     */
71*61046927SAndroid Build Coastguard Worker };
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker static struct slab_element_header *
slab_get_element(struct slab_parent_pool * parent,struct slab_page_header * page,unsigned index)75*61046927SAndroid Build Coastguard Worker slab_get_element(struct slab_parent_pool *parent,
76*61046927SAndroid Build Coastguard Worker                  struct slab_page_header *page, unsigned index)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker    return (struct slab_element_header*)
79*61046927SAndroid Build Coastguard Worker           ((uint8_t*)&page[1] + (parent->element_size * index));
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker /* The given object/element belongs to an orphaned page (i.e. the owning child
83*61046927SAndroid Build Coastguard Worker  * pool has been destroyed). Mark the element as freed and free the whole page
84*61046927SAndroid Build Coastguard Worker  * when no elements are left in it.
85*61046927SAndroid Build Coastguard Worker  */
86*61046927SAndroid Build Coastguard Worker static void
slab_free_orphaned(struct slab_element_header * elt)87*61046927SAndroid Build Coastguard Worker slab_free_orphaned(struct slab_element_header *elt)
88*61046927SAndroid Build Coastguard Worker {
89*61046927SAndroid Build Coastguard Worker    struct slab_page_header *page;
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    assert(elt->owner & 1);
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    page = (struct slab_page_header *)(elt->owner & ~(intptr_t)1);
94*61046927SAndroid Build Coastguard Worker    if (!p_atomic_dec_return(&page->u.num_remaining))
95*61046927SAndroid Build Coastguard Worker       free(page);
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker /**
99*61046927SAndroid Build Coastguard Worker  * Create a parent pool for the allocation of same-sized objects.
100*61046927SAndroid Build Coastguard Worker  *
101*61046927SAndroid Build Coastguard Worker  * \param item_size     Size of one object.
102*61046927SAndroid Build Coastguard Worker  * \param num_items     Number of objects to allocate at once.
103*61046927SAndroid Build Coastguard Worker  */
104*61046927SAndroid Build Coastguard Worker void
slab_create_parent(struct slab_parent_pool * parent,unsigned item_size,unsigned num_items)105*61046927SAndroid Build Coastguard Worker slab_create_parent(struct slab_parent_pool *parent,
106*61046927SAndroid Build Coastguard Worker                    unsigned item_size,
107*61046927SAndroid Build Coastguard Worker                    unsigned num_items)
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&parent->mutex, mtx_plain);
110*61046927SAndroid Build Coastguard Worker    parent->element_size = ALIGN_POT(sizeof(struct slab_element_header) + item_size,
111*61046927SAndroid Build Coastguard Worker                                     sizeof(intptr_t));
112*61046927SAndroid Build Coastguard Worker    parent->num_elements = num_items;
113*61046927SAndroid Build Coastguard Worker    parent->item_size = item_size;
114*61046927SAndroid Build Coastguard Worker }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker void
slab_destroy_parent(struct slab_parent_pool * parent)117*61046927SAndroid Build Coastguard Worker slab_destroy_parent(struct slab_parent_pool *parent)
118*61046927SAndroid Build Coastguard Worker {
119*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&parent->mutex);
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker /**
123*61046927SAndroid Build Coastguard Worker  * Create a child pool linked to the given parent.
124*61046927SAndroid Build Coastguard Worker  */
slab_create_child(struct slab_child_pool * pool,struct slab_parent_pool * parent)125*61046927SAndroid Build Coastguard Worker void slab_create_child(struct slab_child_pool *pool,
126*61046927SAndroid Build Coastguard Worker                        struct slab_parent_pool *parent)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker    pool->parent = parent;
129*61046927SAndroid Build Coastguard Worker    pool->pages = NULL;
130*61046927SAndroid Build Coastguard Worker    pool->free = NULL;
131*61046927SAndroid Build Coastguard Worker    pool->migrated = NULL;
132*61046927SAndroid Build Coastguard Worker }
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker /**
135*61046927SAndroid Build Coastguard Worker  * Destroy the child pool.
136*61046927SAndroid Build Coastguard Worker  *
137*61046927SAndroid Build Coastguard Worker  * Pages associated to the pool will be orphaned. They are eventually freed
138*61046927SAndroid Build Coastguard Worker  * when all objects in them are freed.
139*61046927SAndroid Build Coastguard Worker  */
slab_destroy_child(struct slab_child_pool * pool)140*61046927SAndroid Build Coastguard Worker void slab_destroy_child(struct slab_child_pool *pool)
141*61046927SAndroid Build Coastguard Worker {
142*61046927SAndroid Build Coastguard Worker    if (!pool->parent)
143*61046927SAndroid Build Coastguard Worker       return; /* the slab probably wasn't even created */
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&pool->parent->mutex);
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    while (pool->pages) {
148*61046927SAndroid Build Coastguard Worker       struct slab_page_header *page = pool->pages;
149*61046927SAndroid Build Coastguard Worker       pool->pages = page->u.next;
150*61046927SAndroid Build Coastguard Worker       p_atomic_set(&page->u.num_remaining, pool->parent->num_elements);
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < pool->parent->num_elements; ++i) {
153*61046927SAndroid Build Coastguard Worker          struct slab_element_header *elt = slab_get_element(pool->parent, page, i);
154*61046927SAndroid Build Coastguard Worker          p_atomic_set(&elt->owner, (intptr_t)page | 1);
155*61046927SAndroid Build Coastguard Worker       }
156*61046927SAndroid Build Coastguard Worker    }
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker    while (pool->migrated) {
159*61046927SAndroid Build Coastguard Worker       struct slab_element_header *elt = pool->migrated;
160*61046927SAndroid Build Coastguard Worker       pool->migrated = elt->next;
161*61046927SAndroid Build Coastguard Worker       slab_free_orphaned(elt);
162*61046927SAndroid Build Coastguard Worker    }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&pool->parent->mutex);
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    while (pool->free) {
167*61046927SAndroid Build Coastguard Worker       struct slab_element_header *elt = pool->free;
168*61046927SAndroid Build Coastguard Worker       pool->free = elt->next;
169*61046927SAndroid Build Coastguard Worker       slab_free_orphaned(elt);
170*61046927SAndroid Build Coastguard Worker    }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    /* Guard against use-after-free. */
173*61046927SAndroid Build Coastguard Worker    pool->parent = NULL;
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker static bool
slab_add_new_page(struct slab_child_pool * pool)177*61046927SAndroid Build Coastguard Worker slab_add_new_page(struct slab_child_pool *pool)
178*61046927SAndroid Build Coastguard Worker {
179*61046927SAndroid Build Coastguard Worker    struct slab_page_header *page = malloc(sizeof(struct slab_page_header) +
180*61046927SAndroid Build Coastguard Worker       pool->parent->num_elements * pool->parent->element_size);
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    if (!page)
183*61046927SAndroid Build Coastguard Worker       return false;
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < pool->parent->num_elements; ++i) {
186*61046927SAndroid Build Coastguard Worker       struct slab_element_header *elt = slab_get_element(pool->parent, page, i);
187*61046927SAndroid Build Coastguard Worker       elt->owner = (intptr_t)pool;
188*61046927SAndroid Build Coastguard Worker       assert(!(elt->owner & 1));
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker       elt->next = pool->free;
191*61046927SAndroid Build Coastguard Worker       pool->free = elt;
192*61046927SAndroid Build Coastguard Worker       SET_MAGIC(elt, SLAB_MAGIC_FREE);
193*61046927SAndroid Build Coastguard Worker    }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    page->u.next = pool->pages;
196*61046927SAndroid Build Coastguard Worker    pool->pages = page;
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    return true;
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker /**
202*61046927SAndroid Build Coastguard Worker  * Allocate an object from the child pool. Single-threaded (i.e. the caller
203*61046927SAndroid Build Coastguard Worker  * must ensure that no operation happens on the same child pool in another
204*61046927SAndroid Build Coastguard Worker  * thread).
205*61046927SAndroid Build Coastguard Worker  */
206*61046927SAndroid Build Coastguard Worker void *
slab_alloc(struct slab_child_pool * pool)207*61046927SAndroid Build Coastguard Worker slab_alloc(struct slab_child_pool *pool)
208*61046927SAndroid Build Coastguard Worker {
209*61046927SAndroid Build Coastguard Worker    struct slab_element_header *elt;
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker    if (!pool->free) {
212*61046927SAndroid Build Coastguard Worker       /* First, collect elements that belong to us but were freed from a
213*61046927SAndroid Build Coastguard Worker        * different child pool.
214*61046927SAndroid Build Coastguard Worker        */
215*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&pool->parent->mutex);
216*61046927SAndroid Build Coastguard Worker       pool->free = pool->migrated;
217*61046927SAndroid Build Coastguard Worker       pool->migrated = NULL;
218*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&pool->parent->mutex);
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker       /* Now allocate a new page. */
221*61046927SAndroid Build Coastguard Worker       if (!pool->free && !slab_add_new_page(pool))
222*61046927SAndroid Build Coastguard Worker          return NULL;
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker    elt = pool->free;
226*61046927SAndroid Build Coastguard Worker    pool->free = elt->next;
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    CHECK_MAGIC(elt, SLAB_MAGIC_FREE);
229*61046927SAndroid Build Coastguard Worker    SET_MAGIC(elt, SLAB_MAGIC_ALLOCATED);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    return &elt[1];
232*61046927SAndroid Build Coastguard Worker }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker /**
235*61046927SAndroid Build Coastguard Worker  * Same as slab_alloc but memset the returned object to 0.
236*61046927SAndroid Build Coastguard Worker  */
237*61046927SAndroid Build Coastguard Worker void *
slab_zalloc(struct slab_child_pool * pool)238*61046927SAndroid Build Coastguard Worker slab_zalloc(struct slab_child_pool *pool)
239*61046927SAndroid Build Coastguard Worker {
240*61046927SAndroid Build Coastguard Worker    void *r = slab_alloc(pool);
241*61046927SAndroid Build Coastguard Worker    if (r)
242*61046927SAndroid Build Coastguard Worker       memset(r, 0, pool->parent->item_size);
243*61046927SAndroid Build Coastguard Worker    return r;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker /**
247*61046927SAndroid Build Coastguard Worker  * Free an object allocated from the slab. Single-threaded (i.e. the caller
248*61046927SAndroid Build Coastguard Worker  * must ensure that no operation happens on the same child pool in another
249*61046927SAndroid Build Coastguard Worker  * thread).
250*61046927SAndroid Build Coastguard Worker  *
251*61046927SAndroid Build Coastguard Worker  * Freeing an object in a different child pool from the one where it was
252*61046927SAndroid Build Coastguard Worker  * allocated is allowed, as long the pool belong to the same parent. No
253*61046927SAndroid Build Coastguard Worker  * additional locking is required in this case.
254*61046927SAndroid Build Coastguard Worker  */
slab_free(struct slab_child_pool * pool,void * ptr)255*61046927SAndroid Build Coastguard Worker void slab_free(struct slab_child_pool *pool, void *ptr)
256*61046927SAndroid Build Coastguard Worker {
257*61046927SAndroid Build Coastguard Worker    struct slab_element_header *elt = ((struct slab_element_header*)ptr - 1);
258*61046927SAndroid Build Coastguard Worker    intptr_t owner_int;
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    CHECK_MAGIC(elt, SLAB_MAGIC_ALLOCATED);
261*61046927SAndroid Build Coastguard Worker    SET_MAGIC(elt, SLAB_MAGIC_FREE);
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker    if (p_atomic_read(&elt->owner) == (intptr_t)pool) {
264*61046927SAndroid Build Coastguard Worker       /* This is the simple case: The caller guarantees that we can safely
265*61046927SAndroid Build Coastguard Worker        * access the free list.
266*61046927SAndroid Build Coastguard Worker        */
267*61046927SAndroid Build Coastguard Worker       elt->next = pool->free;
268*61046927SAndroid Build Coastguard Worker       pool->free = elt;
269*61046927SAndroid Build Coastguard Worker       return;
270*61046927SAndroid Build Coastguard Worker    }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    /* The slow case: migration or an orphaned page. */
273*61046927SAndroid Build Coastguard Worker    if (pool->parent)
274*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&pool->parent->mutex);
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    /* Note: we _must_ re-read elt->owner here because the owning child pool
277*61046927SAndroid Build Coastguard Worker     * may have been destroyed by another thread in the meantime.
278*61046927SAndroid Build Coastguard Worker     */
279*61046927SAndroid Build Coastguard Worker    owner_int = p_atomic_read(&elt->owner);
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker    if (!(owner_int & 1)) {
282*61046927SAndroid Build Coastguard Worker       struct slab_child_pool *owner = (struct slab_child_pool *)owner_int;
283*61046927SAndroid Build Coastguard Worker       elt->next = owner->migrated;
284*61046927SAndroid Build Coastguard Worker       owner->migrated = elt;
285*61046927SAndroid Build Coastguard Worker       if (pool->parent)
286*61046927SAndroid Build Coastguard Worker          simple_mtx_unlock(&pool->parent->mutex);
287*61046927SAndroid Build Coastguard Worker    } else {
288*61046927SAndroid Build Coastguard Worker       if (pool->parent)
289*61046927SAndroid Build Coastguard Worker          simple_mtx_unlock(&pool->parent->mutex);
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker       slab_free_orphaned(elt);
292*61046927SAndroid Build Coastguard Worker    }
293*61046927SAndroid Build Coastguard Worker }
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker /**
296*61046927SAndroid Build Coastguard Worker  * Allocate an object from the slab. Single-threaded (no mutex).
297*61046927SAndroid Build Coastguard Worker  */
298*61046927SAndroid Build Coastguard Worker void *
slab_alloc_st(struct slab_mempool * mempool)299*61046927SAndroid Build Coastguard Worker slab_alloc_st(struct slab_mempool *mempool)
300*61046927SAndroid Build Coastguard Worker {
301*61046927SAndroid Build Coastguard Worker    return slab_alloc(&mempool->child);
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker /**
305*61046927SAndroid Build Coastguard Worker  * Free an object allocated from the slab. Single-threaded (no mutex).
306*61046927SAndroid Build Coastguard Worker  */
307*61046927SAndroid Build Coastguard Worker void
slab_free_st(struct slab_mempool * mempool,void * ptr)308*61046927SAndroid Build Coastguard Worker slab_free_st(struct slab_mempool *mempool, void *ptr)
309*61046927SAndroid Build Coastguard Worker {
310*61046927SAndroid Build Coastguard Worker    slab_free(&mempool->child, ptr);
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker void
slab_destroy(struct slab_mempool * mempool)314*61046927SAndroid Build Coastguard Worker slab_destroy(struct slab_mempool *mempool)
315*61046927SAndroid Build Coastguard Worker {
316*61046927SAndroid Build Coastguard Worker    slab_destroy_child(&mempool->child);
317*61046927SAndroid Build Coastguard Worker    slab_destroy_parent(&mempool->parent);
318*61046927SAndroid Build Coastguard Worker }
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker /**
321*61046927SAndroid Build Coastguard Worker  * Create an allocator for same-sized objects.
322*61046927SAndroid Build Coastguard Worker  *
323*61046927SAndroid Build Coastguard Worker  * \param item_size     Size of one object.
324*61046927SAndroid Build Coastguard Worker  * \param num_items     Number of objects to allocate at once.
325*61046927SAndroid Build Coastguard Worker  */
326*61046927SAndroid Build Coastguard Worker void
slab_create(struct slab_mempool * mempool,unsigned item_size,unsigned num_items)327*61046927SAndroid Build Coastguard Worker slab_create(struct slab_mempool *mempool,
328*61046927SAndroid Build Coastguard Worker             unsigned item_size,
329*61046927SAndroid Build Coastguard Worker             unsigned num_items)
330*61046927SAndroid Build Coastguard Worker {
331*61046927SAndroid Build Coastguard Worker    slab_create_parent(&mempool->parent, item_size, num_items);
332*61046927SAndroid Build Coastguard Worker    slab_create_child(&mempool->child, &mempool->parent);
333*61046927SAndroid Build Coastguard Worker }
334