mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-13 10:45:54 +00:00
569 lines
18 KiB
C
569 lines
18 KiB
C
/*
|
|
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;
|
|
}
|