mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
568 lines
18 KiB
568 lines
18 KiB
/* |
|
Copyright (c) 2012, Broadcom Europe Ltd |
|
All rights reserved. |
|
|
|
Redistribution and use in source and binary forms, with or without |
|
modification, are permitted provided that the following conditions are met: |
|
* Redistributions of source code must retain the above copyright |
|
notice, this list of conditions and the following disclaimer. |
|
* Redistributions in binary form must reproduce the above copyright |
|
notice, this list of conditions and the following disclaimer in the |
|
documentation and/or other materials provided with the distribution. |
|
* Neither the name of the copyright holder nor the |
|
names of its contributors may be used to endorse or promote products |
|
derived from this software without specific prior written permission. |
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
|
|
|
#define VCOS_LOG_CATEGORY (&vcos_blockpool_log) |
|
|
|
#include <stddef.h> |
|
#include <string.h> |
|
#include "interface/vcos/vcos.h" |
|
#include "interface/vcos/generic/vcos_generic_blockpool.h" |
|
|
|
#define VCOS_BLOCKPOOL_FOURCC(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24)) |
|
#define VCOS_BLOCKPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 'b', 'p', 'l') |
|
#define VCOS_BLOCKPOOL_SUBPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 's', 'p', 'l') |
|
|
|
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE (0) |
|
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM (1 << 0) |
|
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION (1 << 1) |
|
|
|
/* Uncomment to enable really verbose debug messages */ |
|
/* #define VCOS_BLOCKPOOL_DEBUGGING */ |
|
/* Whether to overwrite freed blocks with 0xBD */ |
|
#ifdef VCOS_BLOCKPOOL_DEBUGGING |
|
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1 |
|
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (UINT32_MAX) |
|
#else |
|
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 0 |
|
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (2 * 1024 * 1024) |
|
#endif |
|
|
|
#ifdef VCOS_BLOCKPOOL_DEBUGGING |
|
#define VCOS_BLOCKPOOL_ASSERT vcos_demand |
|
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_TRACE |
|
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, __VA_ARGS__) |
|
#undef VCOS_BLOCKPOOL_OVERWRITE_ON_FREE |
|
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1 |
|
#else |
|
#define VCOS_BLOCKPOOL_ASSERT vcos_demand |
|
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_ERROR |
|
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...) |
|
#endif |
|
|
|
#define ASSERT_POOL(p) \ |
|
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_MAGIC); |
|
|
|
#define ASSERT_SUBPOOL(p) \ |
|
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC && \ |
|
p->start >= p->mem); |
|
|
|
#if defined(VCOS_LOGGING_ENABLED) |
|
static VCOS_LOG_CAT_T vcos_blockpool_log = |
|
VCOS_LOG_INIT("vcos_blockpool", VCOS_BLOCKPOOL_TRACE_LEVEL); |
|
#endif |
|
|
|
static void vcos_generic_blockpool_subpool_init( |
|
VCOS_BLOCKPOOL_T *pool, VCOS_BLOCKPOOL_SUBPOOL_T *subpool, |
|
void *mem, size_t pool_size, VCOS_UNSIGNED num_blocks, int align, |
|
uint32_t flags) |
|
{ |
|
VCOS_BLOCKPOOL_HEADER_T *block; |
|
VCOS_BLOCKPOOL_HEADER_T *end; |
|
|
|
vcos_unused(flags); |
|
|
|
vcos_log_trace( |
|
"%s: pool %p subpool %p mem %p pool_size %d " \ |
|
"num_blocks %d align %d flags %x", |
|
VCOS_FUNCTION, |
|
pool, subpool, mem, (uint32_t) pool_size, |
|
num_blocks, align, flags); |
|
|
|
subpool->magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC; |
|
subpool->mem = mem; |
|
|
|
/* The block data pointers must be aligned according to align and the |
|
* block header pre-preceeds the first block data. |
|
* For large alignments there may be wasted space between subpool->mem |
|
* and the first block header. |
|
*/ |
|
subpool->start = (char *) subpool->mem + sizeof(VCOS_BLOCKPOOL_HEADER_T); |
|
subpool->start = (void*) |
|
VCOS_BLOCKPOOL_ROUND_UP((unsigned long) subpool->start, align); |
|
subpool->start = (char *) subpool->start - sizeof(VCOS_BLOCKPOOL_HEADER_T); |
|
|
|
vcos_assert(subpool->start >= subpool->mem); |
|
|
|
vcos_log_trace("%s: mem %p subpool->start %p" \ |
|
" pool->block_size %d pool->block_data_size %d", |
|
VCOS_FUNCTION, mem, subpool->start, |
|
(int) pool->block_size, (int) pool->block_data_size); |
|
|
|
subpool->num_blocks = num_blocks; |
|
subpool->available_blocks = num_blocks; |
|
subpool->free_list = NULL; |
|
subpool->owner = pool; |
|
|
|
/* Initialise to a predictable bit pattern unless the pool is so big |
|
* that the delay would be noticeable. */ |
|
if (pool_size < VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE) |
|
memset(subpool->mem, 0xBC, pool_size); /* For debugging */ |
|
|
|
block = (VCOS_BLOCKPOOL_HEADER_T*) subpool->start; |
|
end = (VCOS_BLOCKPOOL_HEADER_T*) |
|
((char *) subpool->start + (pool->block_size * num_blocks)); |
|
subpool->end = end; |
|
|
|
/* Initialise the free list for this subpool */ |
|
while (block < end) |
|
{ |
|
block->owner.next = subpool->free_list; |
|
subpool->free_list = block; |
|
block = (VCOS_BLOCKPOOL_HEADER_T*)((char*) block + pool->block_size); |
|
} |
|
|
|
} |
|
|
|
VCOS_STATUS_T vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool, |
|
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size, |
|
void *start, VCOS_UNSIGNED pool_size, VCOS_UNSIGNED align, |
|
VCOS_UNSIGNED flags, const char *name) |
|
{ |
|
VCOS_STATUS_T status = VCOS_SUCCESS; |
|
|
|
vcos_unused(name); |
|
vcos_unused(flags); |
|
|
|
vcos_log_trace( |
|
"%s: pool %p num_blocks %d block_size %d start %p pool_size %d name %p", |
|
VCOS_FUNCTION, pool, num_blocks, block_size, start, pool_size, name); |
|
|
|
vcos_demand(pool); |
|
vcos_demand(start); |
|
vcos_assert((block_size > 0)); |
|
vcos_assert(num_blocks > 0); |
|
|
|
if (! align) |
|
align = VCOS_BLOCKPOOL_ALIGN_DEFAULT; |
|
|
|
if (align & 0x3) |
|
{ |
|
vcos_log_error("%s: invalid alignment %d", VCOS_FUNCTION, align); |
|
return VCOS_EINVAL; |
|
} |
|
|
|
if (VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) > pool_size) |
|
{ |
|
vcos_log_error("%s: Pool is too small" \ |
|
" num_blocks %d block_size %d align %d" |
|
" pool_size %d required size %d", VCOS_FUNCTION, |
|
num_blocks, block_size, align, |
|
pool_size, (int) VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align)); |
|
return VCOS_ENOMEM; |
|
} |
|
|
|
status = vcos_mutex_create(&pool->mutex, "vcos blockpool mutex"); |
|
if (status != VCOS_SUCCESS) |
|
return status; |
|
|
|
pool->block_data_size = block_size; |
|
|
|
/* TODO - create flag that if set forces the header to be in its own cache |
|
* line */ |
|
pool->block_size = VCOS_BLOCKPOOL_ROUND_UP(pool->block_data_size + |
|
(align >= 4096 ? 32 : 0) + |
|
sizeof(VCOS_BLOCKPOOL_HEADER_T), align); |
|
|
|
pool->magic = VCOS_BLOCKPOOL_MAGIC; |
|
pool->num_subpools = 1; |
|
pool->num_extension_blocks = 0; |
|
pool->align = align; |
|
memset(pool->subpools, 0, sizeof(pool->subpools)); |
|
|
|
vcos_generic_blockpool_subpool_init(pool, &pool->subpools[0], start, |
|
pool_size, num_blocks, align, VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE); |
|
|
|
return status; |
|
} |
|
|
|
VCOS_STATUS_T vcos_generic_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool, |
|
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size, VCOS_UNSIGNED align, |
|
VCOS_UNSIGNED flags, const char *name) |
|
{ |
|
VCOS_STATUS_T status = VCOS_SUCCESS; |
|
size_t size = VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align); |
|
void* mem = vcos_malloc(size, name); |
|
|
|
vcos_log_trace("%s: num_blocks %d block_size %d name %s", |
|
VCOS_FUNCTION, num_blocks, block_size, name); |
|
|
|
if (! mem) |
|
return VCOS_ENOMEM; |
|
|
|
status = vcos_generic_blockpool_init(pool, num_blocks, |
|
block_size, mem, size, align, flags, name); |
|
|
|
if (status != VCOS_SUCCESS) |
|
goto fail; |
|
|
|
pool->subpools[0].flags |= VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM; |
|
return status; |
|
|
|
fail: |
|
vcos_free(mem); |
|
return status; |
|
} |
|
|
|
VCOS_STATUS_T vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool, |
|
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks) |
|
{ |
|
VCOS_UNSIGNED i; |
|
ASSERT_POOL(pool); |
|
|
|
vcos_log_trace("%s: pool %p num_extensions %d num_blocks %d", |
|
VCOS_FUNCTION, pool, num_extensions, num_blocks); |
|
|
|
/* Extend may only be called once */ |
|
if (pool->num_subpools > 1) |
|
return VCOS_EACCESS; |
|
|
|
if (num_extensions < 1 || |
|
num_extensions > VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1) |
|
return VCOS_EINVAL; |
|
|
|
if (num_blocks < 1) |
|
return VCOS_EINVAL; |
|
|
|
pool->num_subpools += num_extensions; |
|
pool->num_extension_blocks = num_blocks; |
|
|
|
/* Mark these subpools as valid but unallocated */ |
|
for (i = 1; i < pool->num_subpools; ++i) |
|
{ |
|
pool->subpools[i].magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC; |
|
pool->subpools[i].start = NULL; |
|
pool->subpools[i].mem = NULL; |
|
} |
|
|
|
return VCOS_SUCCESS; |
|
} |
|
|
|
void *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool) |
|
{ |
|
VCOS_UNSIGNED i; |
|
void* ret = NULL; |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL; |
|
|
|
ASSERT_POOL(pool); |
|
vcos_mutex_lock(&pool->mutex); |
|
|
|
/* Starting with the main pool try and find a free block */ |
|
for (i = 0; i < pool->num_subpools; ++i) |
|
{ |
|
if (pool->subpools[i].start && pool->subpools[i].available_blocks > 0) |
|
{ |
|
subpool = &pool->subpools[i]; |
|
break; /* Found a subpool with free blocks */ |
|
} |
|
} |
|
|
|
if (! subpool) |
|
{ |
|
/* All current subpools are full, try to allocate a new one */ |
|
for (i = 1; i < pool->num_subpools; ++i) |
|
{ |
|
if (! pool->subpools[i].start) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *s = &pool->subpools[i]; |
|
size_t size = VCOS_BLOCKPOOL_SIZE(pool->num_extension_blocks, |
|
pool->block_data_size, pool->align); |
|
void *mem = vcos_malloc(size, pool->name); |
|
if (mem) |
|
{ |
|
vcos_log_trace("%s: Allocated subpool %d", VCOS_FUNCTION, i); |
|
vcos_generic_blockpool_subpool_init(pool, s, mem, size, |
|
pool->num_extension_blocks, |
|
pool->align, |
|
VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM | |
|
VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION); |
|
subpool = s; |
|
break; /* Created a subpool */ |
|
} |
|
else |
|
{ |
|
vcos_log_warn("%s: Failed to allocate subpool", VCOS_FUNCTION); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (subpool) |
|
{ |
|
/* Remove from free list */ |
|
VCOS_BLOCKPOOL_HEADER_T* nb = subpool->free_list; |
|
|
|
vcos_assert(subpool->free_list); |
|
subpool->free_list = nb->owner.next; |
|
|
|
/* Owner is pool so free can be called without passing pool |
|
* as a parameter */ |
|
nb->owner.subpool = subpool; |
|
|
|
ret = nb + 1; /* Return pointer to block data */ |
|
--(subpool->available_blocks); |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
VCOS_BLOCKPOOL_DEBUG_LOG("pool %p subpool %p ret %p", pool, subpool, ret); |
|
|
|
if (ret) |
|
{ |
|
vcos_assert(ret > subpool->start); |
|
vcos_assert(ret < subpool->end); |
|
} |
|
return ret; |
|
} |
|
|
|
void *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool) |
|
{ |
|
void* ret = vcos_generic_blockpool_alloc(pool); |
|
if (ret) |
|
memset(ret, 0, pool->block_data_size); |
|
return ret; |
|
} |
|
|
|
void vcos_generic_blockpool_free(void *block) |
|
{ |
|
VCOS_BLOCKPOOL_DEBUG_LOG("block %p", block); |
|
if (block) |
|
{ |
|
VCOS_BLOCKPOOL_HEADER_T* hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1; |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = hdr->owner.subpool; |
|
VCOS_BLOCKPOOL_T *pool = NULL; |
|
|
|
ASSERT_SUBPOOL(subpool); |
|
pool = subpool->owner; |
|
ASSERT_POOL(pool); |
|
|
|
vcos_mutex_lock(&pool->mutex); |
|
vcos_assert((unsigned) subpool->available_blocks < subpool->num_blocks); |
|
|
|
/* Change ownership of block to be the free list */ |
|
hdr->owner.next = subpool->free_list; |
|
subpool->free_list = hdr; |
|
++(subpool->available_blocks); |
|
|
|
if (VCOS_BLOCKPOOL_OVERWRITE_ON_FREE) |
|
memset(block, 0xBD, pool->block_data_size); /* For debugging */ |
|
|
|
if ( (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION) && |
|
subpool->available_blocks == subpool->num_blocks) |
|
{ |
|
VCOS_BLOCKPOOL_DEBUG_LOG("%s: freeing subpool %p mem %p", VCOS_FUNCTION, |
|
subpool, subpool->mem); |
|
/* Free the sub-pool if it was dynamically allocated */ |
|
vcos_free(subpool->mem); |
|
subpool->mem = NULL; |
|
subpool->start = NULL; |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
} |
|
} |
|
|
|
VCOS_UNSIGNED vcos_generic_blockpool_available_count(VCOS_BLOCKPOOL_T *pool) |
|
{ |
|
VCOS_UNSIGNED ret = 0; |
|
VCOS_UNSIGNED i; |
|
|
|
ASSERT_POOL(pool); |
|
vcos_mutex_lock(&pool->mutex); |
|
for (i = 0; i < pool->num_subpools; ++i) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i]; |
|
ASSERT_SUBPOOL(subpool); |
|
|
|
/* Assume the malloc of sub pool would succeed */ |
|
if (subpool->start) |
|
ret += subpool->available_blocks; |
|
else |
|
ret += pool->num_extension_blocks; |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
return ret; |
|
} |
|
|
|
VCOS_UNSIGNED vcos_generic_blockpool_used_count(VCOS_BLOCKPOOL_T *pool) |
|
{ |
|
VCOS_UNSIGNED ret = 0; |
|
VCOS_UNSIGNED i; |
|
|
|
ASSERT_POOL(pool); |
|
vcos_mutex_lock(&pool->mutex); |
|
|
|
for (i = 0; i < pool->num_subpools; ++i) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i]; |
|
ASSERT_SUBPOOL(subpool); |
|
if (subpool->start) |
|
ret += (subpool->num_blocks - subpool->available_blocks); |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
return ret; |
|
} |
|
|
|
void vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool) |
|
{ |
|
vcos_log_trace("%s: pool %p", VCOS_FUNCTION, pool); |
|
|
|
if (pool) |
|
{ |
|
VCOS_UNSIGNED i; |
|
|
|
ASSERT_POOL(pool); |
|
for (i = 0; i < pool->num_subpools; ++i) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i]; |
|
ASSERT_SUBPOOL(subpool); |
|
if (subpool->mem) |
|
{ |
|
/* For debugging */ |
|
memset(subpool->mem, |
|
0xBE, |
|
VCOS_BLOCKPOOL_SIZE(subpool->num_blocks, |
|
pool->block_data_size, pool->align)); |
|
|
|
if (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM) |
|
vcos_free(subpool->mem); |
|
subpool->mem = NULL; |
|
subpool->start = NULL; |
|
} |
|
} |
|
vcos_mutex_delete(&pool->mutex); |
|
memset(pool, 0xBE, sizeof(VCOS_BLOCKPOOL_T)); /* For debugging */ |
|
} |
|
} |
|
|
|
uint32_t vcos_generic_blockpool_elem_to_handle(void *block) |
|
{ |
|
uint32_t ret = -1; |
|
uint32_t index = -1; |
|
VCOS_BLOCKPOOL_HEADER_T *hdr = NULL; |
|
VCOS_BLOCKPOOL_T *pool = NULL; |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL; |
|
uint32_t subpool_id; |
|
|
|
vcos_assert(block); |
|
hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1; |
|
subpool = hdr->owner.subpool; |
|
ASSERT_SUBPOOL(subpool); |
|
|
|
pool = subpool->owner; |
|
ASSERT_POOL(pool); |
|
vcos_mutex_lock(&pool->mutex); |
|
|
|
/* The handle is the index into the array of blocks combined |
|
* with the subpool id. |
|
*/ |
|
index = ((size_t) hdr - (size_t) subpool->start) / pool->block_size; |
|
vcos_assert(index < subpool->num_blocks); |
|
|
|
subpool_id = ((char*) subpool - (char*) &pool->subpools[0]) / |
|
sizeof(VCOS_BLOCKPOOL_SUBPOOL_T); |
|
|
|
vcos_assert(subpool_id < VCOS_BLOCKPOOL_MAX_SUBPOOLS); |
|
vcos_assert(subpool_id < pool->num_subpools); |
|
ret = VCOS_BLOCKPOOL_HANDLE_CREATE(index, subpool_id); |
|
|
|
vcos_log_trace("%s: index %d subpool_id %d handle 0x%08x", |
|
VCOS_FUNCTION, index, subpool_id, ret); |
|
|
|
vcos_mutex_unlock(&pool->mutex); |
|
return ret; |
|
} |
|
|
|
void *vcos_generic_blockpool_elem_from_handle( |
|
VCOS_BLOCKPOOL_T *pool, uint32_t handle) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool; |
|
uint32_t subpool_id; |
|
uint32_t index; |
|
void *ret = NULL; |
|
|
|
|
|
ASSERT_POOL(pool); |
|
vcos_mutex_lock(&pool->mutex); |
|
subpool_id = VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(handle); |
|
|
|
if (subpool_id < pool->num_subpools) |
|
{ |
|
index = VCOS_BLOCKPOOL_HANDLE_GET_INDEX(handle); |
|
subpool = &pool->subpools[subpool_id]; |
|
if (pool->subpools[subpool_id].magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC && |
|
pool->subpools[subpool_id].mem && index < subpool->num_blocks) |
|
{ |
|
VCOS_BLOCKPOOL_HEADER_T *hdr = (VCOS_BLOCKPOOL_HEADER_T*) |
|
((size_t) subpool->start + (index * pool->block_size)); |
|
|
|
if (hdr->owner.subpool == subpool) /* Check block is allocated */ |
|
ret = hdr + 1; |
|
} |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
|
|
vcos_log_trace("%s: pool %p handle 0x%08x elem %p", VCOS_FUNCTION, pool, |
|
handle, ret); |
|
return ret; |
|
} |
|
|
|
uint32_t vcos_generic_blockpool_is_valid_elem( |
|
VCOS_BLOCKPOOL_T *pool, const void *block) |
|
{ |
|
uint32_t ret = 0; |
|
const char *pool_end; |
|
VCOS_UNSIGNED i = 0; |
|
|
|
ASSERT_POOL(pool); |
|
if (((size_t) block) & 0x3) |
|
return 0; |
|
|
|
vcos_mutex_lock(&pool->mutex); |
|
|
|
for (i = 0; i < pool->num_subpools; ++i) |
|
{ |
|
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i]; |
|
ASSERT_SUBPOOL(subpool); |
|
|
|
if (subpool->mem && subpool->start) |
|
{ |
|
pool_end = (const char*)subpool->start + |
|
(subpool->num_blocks * pool->block_size); |
|
|
|
if ((const char*)block > (const char*)subpool->start && |
|
(const char*)block < pool_end) |
|
{ |
|
const VCOS_BLOCKPOOL_HEADER_T *hdr = ( |
|
const VCOS_BLOCKPOOL_HEADER_T*) block - 1; |
|
|
|
/* If the block has a header where the owner points to the pool then |
|
* it's a valid block. */ |
|
ret = (hdr->owner.subpool == subpool && subpool->owner == pool); |
|
break; |
|
} |
|
} |
|
} |
|
vcos_mutex_unlock(&pool->mutex); |
|
return ret; |
|
}
|
|
|