/* * 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 */