19cc4651cSSandrine Bailleux /*
2*4c700c15SGovindraj Raja * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
39cc4651cSSandrine Bailleux *
49cc4651cSSandrine Bailleux * SPDX-License-Identifier: BSD-3-Clause
59cc4651cSSandrine Bailleux */
69cc4651cSSandrine Bailleux
79cc4651cSSandrine Bailleux #ifndef OBJECT_POOL_H
89cc4651cSSandrine Bailleux #define OBJECT_POOL_H
99cc4651cSSandrine Bailleux
109cc4651cSSandrine Bailleux #include <stdlib.h>
1109d40e0eSAntonio Nino Diaz
1209d40e0eSAntonio Nino Diaz #include <common/debug.h>
1309d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
149cc4651cSSandrine Bailleux
159cc4651cSSandrine Bailleux /*
169cc4651cSSandrine Bailleux * Pool of statically allocated objects.
179cc4651cSSandrine Bailleux *
189cc4651cSSandrine Bailleux * Objects can be reserved but not freed. This is by design and it is not a
199cc4651cSSandrine Bailleux * limitation. We do not want to introduce complexity induced by memory freeing,
209cc4651cSSandrine Bailleux * such as use-after-free bugs, memory fragmentation and so on.
219cc4651cSSandrine Bailleux *
229cc4651cSSandrine Bailleux * The object size and capacity of the pool are fixed at build time. So is the
239cc4651cSSandrine Bailleux * address of the objects back store.
249cc4651cSSandrine Bailleux */
259cc4651cSSandrine Bailleux struct object_pool {
269cc4651cSSandrine Bailleux /* Size of 1 object in the pool in byte unit. */
279cc4651cSSandrine Bailleux const size_t obj_size;
289cc4651cSSandrine Bailleux
299cc4651cSSandrine Bailleux /* Number of objects in the pool. */
309cc4651cSSandrine Bailleux const size_t capacity;
319cc4651cSSandrine Bailleux
329cc4651cSSandrine Bailleux /* Objects back store. */
339cc4651cSSandrine Bailleux void *const objects;
349cc4651cSSandrine Bailleux
359cc4651cSSandrine Bailleux /* How many objects are currently allocated. */
369cc4651cSSandrine Bailleux size_t used;
379cc4651cSSandrine Bailleux };
389cc4651cSSandrine Bailleux
399cc4651cSSandrine Bailleux /* Create a static pool of objects. */
409cc4651cSSandrine Bailleux #define OBJECT_POOL(_pool_name, _obj_backstore, _obj_size, _obj_count) \
419cc4651cSSandrine Bailleux struct object_pool _pool_name = { \
429cc4651cSSandrine Bailleux .objects = (_obj_backstore), \
439cc4651cSSandrine Bailleux .obj_size = (_obj_size), \
449cc4651cSSandrine Bailleux .capacity = (_obj_count), \
459cc4651cSSandrine Bailleux .used = 0U, \
469cc4651cSSandrine Bailleux }
479cc4651cSSandrine Bailleux
489cc4651cSSandrine Bailleux /* Create a static pool of objects out of an array of pre-allocated objects. */
499cc4651cSSandrine Bailleux #define OBJECT_POOL_ARRAY(_pool_name, _obj_array) \
509cc4651cSSandrine Bailleux OBJECT_POOL(_pool_name, (_obj_array), \
519cc4651cSSandrine Bailleux sizeof((_obj_array)[0]), ARRAY_SIZE(_obj_array))
529cc4651cSSandrine Bailleux
539cc4651cSSandrine Bailleux /*
549cc4651cSSandrine Bailleux * Allocate 'count' objects from a pool.
559cc4651cSSandrine Bailleux * Return the address of the first object. Panic on error.
569cc4651cSSandrine Bailleux */
pool_alloc_n(struct object_pool * pool,size_t count)579cc4651cSSandrine Bailleux static inline void *pool_alloc_n(struct object_pool *pool, size_t count)
589cc4651cSSandrine Bailleux {
59845db722SLouis Mayencourt if ((pool->used + count) > pool->capacity) {
609cc4651cSSandrine Bailleux ERROR("Cannot allocate %zu objects out of pool (%zu objects left).\n",
619cc4651cSSandrine Bailleux count, pool->capacity - pool->used);
629cc4651cSSandrine Bailleux panic();
639cc4651cSSandrine Bailleux }
649cc4651cSSandrine Bailleux
65845db722SLouis Mayencourt void *obj = (char *)(pool->objects) + (pool->obj_size * pool->used);
669cc4651cSSandrine Bailleux pool->used += count;
679cc4651cSSandrine Bailleux return obj;
689cc4651cSSandrine Bailleux }
699cc4651cSSandrine Bailleux
709cc4651cSSandrine Bailleux /*
719cc4651cSSandrine Bailleux * Allocate 1 object from a pool.
729cc4651cSSandrine Bailleux * Return the address of the object. Panic on error.
739cc4651cSSandrine Bailleux */
pool_alloc(struct object_pool * pool)749cc4651cSSandrine Bailleux static inline void *pool_alloc(struct object_pool *pool)
759cc4651cSSandrine Bailleux {
769cc4651cSSandrine Bailleux return pool_alloc_n(pool, 1U);
779cc4651cSSandrine Bailleux }
789cc4651cSSandrine Bailleux
799cc4651cSSandrine Bailleux #endif /* OBJECT_POOL_H */
80