| /** | |
| * Copyright (C) Advanced Micro Devices, Inc. All rights reserved. | |
| * | |
| * You may not use this software and documentation (if any) (collectively, the | |
| * "Materials") except in compliance with the terms and conditions of the | |
| * Software License Agreement included with the Materials or otherwise as set | |
| * forth in writing and signed by you and an authorized signatory of AMD. | |
| * | |
| * If you do not have a copy of the Software License Agreement, contact your AMD | |
| * representative for a copy. You agree that you will not reverse engineer or | |
| * decompile the Materials, in whole or in part, except as allowed by applicable | |
| * law. | |
| * | |
| * THE MATERIALS ARE DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | |
| * REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| */ | |
| #ifndef DC_MEMORY_POOL_H | |
| #define DC_MEMORY_POOL_H | |
| #include "os_types.h" | |
| /** | |
| * Non-resizable lock-free memory pool with fixed capacity. | |
| * | |
| * Custom implementation is used over Linux llist, as llist requires external | |
| * locking if more than one thread pops from the list. | |
| * | |
| * Emplace and erase operations do not use any mutexes or spinlocks, which | |
| * guarantees forward progress even if another thread | |
| * has been suspended in the middle of the call. High contention might result | |
| * in multiple internal retries, but will eventually either succeed once other | |
| * threads stop actively modifying the pool, or fail if the pool is empty. | |
| * | |
| * Implemented as Treiber stack using indexed free list and head with generation | |
| * counter to solve ABA problem, as each modification of the head increments | |
| * the generation, preventing issue of `push(A)` being indistinguishable from | |
| * `push(A); { push(B); pop(B); }` to another thread, corrupting data structure. | |
| */ | |
| struct dc_memory_pool; | |
| /** | |
| * Create dc_memory_pool. | |
| * | |
| * @param size Non-zero pool block size, all acquires will be of this size. | |
| * @param capacity Non-zero number of blocks that can be acquired from the pool. | |
| * @return Pointer to the pool if succeeded, null if failed. | |
| */ | |
| __must_check struct dc_memory_pool *dc_memory_pool_create(size_t size, | |
| size_t capacity); | |
| /** | |
| * Destroy given pool and free all allocated memory, invalidating any pointers. | |
| * | |
| * This operation is not synchronized, calling any other operation on the pool | |
| * while it is being destroyed results in Undefined Behavior. | |
| * | |
| * @param pool Can be null to support common destruction patterns. | |
| */ | |
| void dc_memory_pool_destroy(struct dc_memory_pool *pool); | |
| /** | |
| * Acquire single block from pool. | |
| * | |
| * @param pool Cannot be null. | |
| * @return Pointer to block if succeeded, null if empty. | |
| */ | |
| __must_check void *dc_memory_pool_acquire(struct dc_memory_pool *pool); | |
| /** | |
| * Release previously acquired block, freeing it for others to acquire. | |
| * | |
| * @param pool Cannot be null. | |
| * @param memory Cannot be null, has to be owned by the pool. | |
| */ | |
| void dc_memory_pool_release(struct dc_memory_pool *pool, void *memory); | |
| /** | |
| * Check if given memory is owned by the pool to facilitate arenas. | |
| * | |
| * @warning if (owns(pool, p)) release(pool, p);` pattern is not safe | |
| * if used with same `p` from multiple unsynchronized threads. | |
| * If multiple owning threads are desired, use krefs to assure single release. | |
| * | |
| * @param pool Cannot be null. | |
| * @param memory Cannot be null. | |
| * @return True if the memory was previously acquired from the pool. | |
| */ | |
| __must_check bool dc_memory_pool_owns(const struct dc_memory_pool *pool, | |
| const void *memory); | |
| /** | |
| * Get pool block size. | |
| * | |
| * @param pool Cannot be null. | |
| * @return Pool block size as given to dc_memory_pool_create(). | |
| */ | |
| __must_check size_t dc_memory_pool_size(const struct dc_memory_pool *pool); | |
| /** | |
| * Get pool block count. | |
| * | |
| * @param pool Cannot be null. | |
| * @return Pool block count as given to dc_memory_pool_create(). | |
| */ | |
| __must_check size_t dc_memory_pool_capacity(const struct dc_memory_pool *pool); | |
| #endif // Header guard |