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