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