From 9cc4651c9d7098e8ef659e067e501f436f488988 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Fri, 1 Jun 2018 14:17:08 +0200 Subject: [PATCH] Introduce object pool allocator The object pool allocator provides a simplistic interface to manage allocation in a fixed-size static array. The caller creates a static "object pool" out of such an array and may then call pool_alloc() to get the next available object within the pool. There is also a variant to get multiple consecutive objects: pool_alloc_n(). Note that this interface does not provide any way to free the objects afterwards. 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. Change-Id: Iefc2e153767851fbde5841a295f92ae48adda71f Signed-off-by: Sandrine Bailleux --- include/lib/object_pool.h | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 include/lib/object_pool.h diff --git a/include/lib/object_pool.h b/include/lib/object_pool.h new file mode 100644 index 00000000..7d40b41d --- /dev/null +++ b/include/lib/object_pool.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OBJECT_POOL_H +#define OBJECT_POOL_H + +#include +#include +#include + +/* + * 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 */ -- 2.30.2