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