xref: /rk3399_ARM-atf/include/lib/object_pool.h (revision 72e8f2456af54b75a0a1d92aadfce0b4bcde6ba1)
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