xref: /arm-trusted-firmware/include/lib/object_pool.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef OBJECT_POOL_H
8*91f16700Schasinglulu #define OBJECT_POOL_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <stdlib.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <common/debug.h>
13*91f16700Schasinglulu #include <lib/utils_def.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu /*
16*91f16700Schasinglulu  * Pool of statically allocated objects.
17*91f16700Schasinglulu  *
18*91f16700Schasinglulu  * Objects can be reserved but not freed. This is by design and it is not a
19*91f16700Schasinglulu  * limitation. We do not want to introduce complexity induced by memory freeing,
20*91f16700Schasinglulu  * such as use-after-free bugs, memory fragmentation and so on.
21*91f16700Schasinglulu  *
22*91f16700Schasinglulu  * The object size and capacity of the pool are fixed at build time. So is the
23*91f16700Schasinglulu  * address of the objects back store.
24*91f16700Schasinglulu  */
25*91f16700Schasinglulu struct object_pool {
26*91f16700Schasinglulu 	/* Size of 1 object in the pool in byte unit. */
27*91f16700Schasinglulu 	const size_t obj_size;
28*91f16700Schasinglulu 
29*91f16700Schasinglulu 	/* Number of objects in the pool. */
30*91f16700Schasinglulu 	const size_t capacity;
31*91f16700Schasinglulu 
32*91f16700Schasinglulu 	/* Objects back store. */
33*91f16700Schasinglulu 	void *const objects;
34*91f16700Schasinglulu 
35*91f16700Schasinglulu 	/* How many objects are currently allocated. */
36*91f16700Schasinglulu 	size_t used;
37*91f16700Schasinglulu };
38*91f16700Schasinglulu 
39*91f16700Schasinglulu /* Create a static pool of objects. */
40*91f16700Schasinglulu #define OBJECT_POOL(_pool_name, _obj_backstore, _obj_size, _obj_count)	\
41*91f16700Schasinglulu 	struct object_pool _pool_name = {				\
42*91f16700Schasinglulu 		.objects = (_obj_backstore),				\
43*91f16700Schasinglulu 		.obj_size = (_obj_size),				\
44*91f16700Schasinglulu 		.capacity = (_obj_count),				\
45*91f16700Schasinglulu 		.used = 0U,						\
46*91f16700Schasinglulu 	}
47*91f16700Schasinglulu 
48*91f16700Schasinglulu /* Create a static pool of objects out of an array of pre-allocated objects. */
49*91f16700Schasinglulu #define OBJECT_POOL_ARRAY(_pool_name, _obj_array)			\
50*91f16700Schasinglulu 	OBJECT_POOL(_pool_name, (_obj_array),				\
51*91f16700Schasinglulu 		    sizeof((_obj_array)[0]), ARRAY_SIZE(_obj_array))
52*91f16700Schasinglulu 
53*91f16700Schasinglulu /*
54*91f16700Schasinglulu  * Allocate 'count' objects from a pool.
55*91f16700Schasinglulu  * Return the address of the first object. Panic on error.
56*91f16700Schasinglulu  */
57*91f16700Schasinglulu static inline void *pool_alloc_n(struct object_pool *pool, size_t count)
58*91f16700Schasinglulu {
59*91f16700Schasinglulu 	if ((pool->used + count) > pool->capacity) {
60*91f16700Schasinglulu 		ERROR("Cannot allocate %zu objects out of pool (%zu objects left).\n",
61*91f16700Schasinglulu 		      count, pool->capacity - pool->used);
62*91f16700Schasinglulu 		panic();
63*91f16700Schasinglulu 	}
64*91f16700Schasinglulu 
65*91f16700Schasinglulu 	void *obj = (char *)(pool->objects) + (pool->obj_size * pool->used);
66*91f16700Schasinglulu 	pool->used += count;
67*91f16700Schasinglulu 	return obj;
68*91f16700Schasinglulu }
69*91f16700Schasinglulu 
70*91f16700Schasinglulu /*
71*91f16700Schasinglulu  * Allocate 1 object from a pool.
72*91f16700Schasinglulu  * Return the address of the object. Panic on error.
73*91f16700Schasinglulu  */
74*91f16700Schasinglulu static inline void *pool_alloc(struct object_pool *pool)
75*91f16700Schasinglulu {
76*91f16700Schasinglulu 	return pool_alloc_n(pool, 1U);
77*91f16700Schasinglulu }
78*91f16700Schasinglulu 
79*91f16700Schasinglulu #endif /* OBJECT_POOL_H */
80