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