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