Static definition of pool's area size and number of chunks in a pool; alignment of mem_block_header_t and mem_pool_state_t to MEM_ALIGNMENT.

This commit is contained in:
Ruben Ayrapetyan 2014-11-26 18:49:00 +03:00
parent 9a0081b856
commit c21e186f2c
7 changed files with 57 additions and 56 deletions

View File

@ -29,7 +29,7 @@
/** /**
* Log2 of maximum number of chunks in a pool * Log2 of maximum number of chunks in a pool
*/ */
#define CONFIG_MEM_POOL_MAX_CHUNKS_NUMBER_LOG 16 #define CONFIG_MEM_POOL_MAX_CHUNKS_NUMBER_LOG 8
/** /**
* Size of pool chunk * Size of pool chunk

View File

@ -90,7 +90,7 @@ JERRY_STATIC_ASSERT (sizeof (mem_heap_offset_t) * JERRY_BITSINBYTE >= MEM_HEAP_O
/** /**
* Description of heap memory block layout * Description of heap memory block layout
*/ */
typedef struct mem_block_header_t typedef struct __attribute__ ((aligned (MEM_ALIGNMENT))) mem_block_header_t
{ {
uint16_t magic_num; /**< magic number (mem_magic_num_of_block_t): uint16_t magic_num; /**< magic number (mem_magic_num_of_block_t):
MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK for allocated block MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK for allocated block
@ -800,7 +800,7 @@ mem_heap_free_block (uint8_t *ptr) /**< pointer to beginning of data space of th
* *
* @return recommended allocation size * @return recommended allocation size
*/ */
size_t size_t __attribute_pure__
mem_heap_recommend_allocation_size (size_t minimum_allocation_size) /**< minimum allocation size */ mem_heap_recommend_allocation_size (size_t minimum_allocation_size) /**< minimum allocation size */
{ {
size_t minimum_allocation_size_with_block_header = minimum_allocation_size + sizeof (mem_block_header_t); size_t minimum_allocation_size_with_block_header = minimum_allocation_size + sizeof (mem_block_header_t);

View File

@ -44,7 +44,7 @@ extern void mem_heap_finalize (void);
extern uint8_t* mem_heap_alloc_block (size_t size_in_bytes, mem_heap_alloc_term_t alloc_term); extern uint8_t* mem_heap_alloc_block (size_t size_in_bytes, mem_heap_alloc_term_t alloc_term);
extern bool mem_heap_try_resize_block (uint8_t *ptr, size_t size_in_bytes); extern bool mem_heap_try_resize_block (uint8_t *ptr, size_t size_in_bytes);
extern void mem_heap_free_block (uint8_t *ptr); extern void mem_heap_free_block (uint8_t *ptr);
extern size_t mem_heap_recommend_allocation_size (size_t minimum_allocation_size); extern size_t __attribute_pure__ mem_heap_recommend_allocation_size (size_t minimum_allocation_size);
extern void mem_heap_print (bool dump_block_headers, bool dump_block_data, bool dump_stats); extern void mem_heap_print (bool dump_block_headers, bool dump_block_data, bool dump_stats);
#ifdef MEM_STATS #ifdef MEM_STATS

View File

@ -56,17 +56,16 @@ mem_pool_init (mem_pool_state_t *pool_p, /**< pool */
JERRY_STATIC_ASSERT(MEM_POOL_MAX_CHUNKS_NUMBER_LOG <= sizeof (mem_pool_chunk_index_t) * JERRY_BITSINBYTE); JERRY_STATIC_ASSERT(MEM_POOL_MAX_CHUNKS_NUMBER_LOG <= sizeof (mem_pool_chunk_index_t) * JERRY_BITSINBYTE);
JERRY_ASSERT(sizeof (mem_pool_chunk_index_t) <= MEM_POOL_CHUNK_SIZE); JERRY_ASSERT(sizeof (mem_pool_chunk_index_t) <= MEM_POOL_CHUNK_SIZE);
const size_t pool_space_size = pool_size - sizeof (mem_pool_state_t); JERRY_ASSERT (MEM_POOL_SIZE == sizeof (mem_pool_state_t) + MEM_POOL_CHUNKS_NUMBER * MEM_POOL_CHUNK_SIZE);
const size_t chunks_number = pool_space_size / MEM_POOL_CHUNK_SIZE; JERRY_ASSERT (MEM_POOL_CHUNKS_NUMBER >= CONFIG_MEM_LEAST_CHUNK_NUMBER_IN_POOL);
JERRY_ASSERT(((mem_pool_chunk_index_t) chunks_number) == chunks_number); JERRY_ASSERT (pool_size == MEM_POOL_SIZE);
pool_p->chunks_number = (mem_pool_chunk_index_t) chunks_number;
/* /*
* All chunks are free right after initialization * All chunks are free right after initialization
*/ */
pool_p->free_chunks_number = pool_p->chunks_number; pool_p->free_chunks_number = (mem_pool_chunk_index_t) MEM_POOL_CHUNKS_NUMBER;
JERRY_ASSERT (pool_p->free_chunks_number == MEM_POOL_CHUNKS_NUMBER);
/* /*
* Chunk with zero index is first free chunk in the pool now * Chunk with zero index is first free chunk in the pool now
@ -74,7 +73,7 @@ mem_pool_init (mem_pool_state_t *pool_p, /**< pool */
pool_p->first_free_chunk = 0; pool_p->first_free_chunk = 0;
for (mem_pool_chunk_index_t chunk_index = 0; for (mem_pool_chunk_index_t chunk_index = 0;
chunk_index < chunks_number; chunk_index < MEM_POOL_CHUNKS_NUMBER;
chunk_index++) chunk_index++)
{ {
mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) MEM_POOL_CHUNK_ADDRESS(pool_p, mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) MEM_POOL_CHUNK_ADDRESS(pool_p,
@ -94,14 +93,8 @@ mem_pool_alloc_chunk (mem_pool_state_t *pool_p) /**< pool */
{ {
mem_check_pool (pool_p); mem_check_pool (pool_p);
if (unlikely (pool_p->free_chunks_number == 0)) JERRY_ASSERT (pool_p->free_chunks_number != 0);
{ JERRY_ASSERT (pool_p->first_free_chunk < MEM_POOL_CHUNKS_NUMBER);
JERRY_ASSERT(pool_p->first_free_chunk == pool_p->chunks_number);
return NULL;
}
JERRY_ASSERT(pool_p->first_free_chunk < pool_p->chunks_number);
mem_pool_chunk_index_t chunk_index = pool_p->first_free_chunk; mem_pool_chunk_index_t chunk_index = pool_p->first_free_chunk;
uint8_t *chunk_p = MEM_POOL_CHUNK_ADDRESS(pool_p, chunk_index); uint8_t *chunk_p = MEM_POOL_CHUNK_ADDRESS(pool_p, chunk_index);
@ -122,9 +115,9 @@ void
mem_pool_free_chunk (mem_pool_state_t *pool_p, /**< pool */ mem_pool_free_chunk (mem_pool_state_t *pool_p, /**< pool */
uint8_t *chunk_p) /**< chunk pointer */ uint8_t *chunk_p) /**< chunk pointer */
{ {
JERRY_ASSERT(pool_p->free_chunks_number < pool_p->chunks_number); JERRY_ASSERT(pool_p->free_chunks_number < MEM_POOL_CHUNKS_NUMBER);
JERRY_ASSERT(chunk_p >= MEM_POOL_SPACE_START(pool_p) JERRY_ASSERT(chunk_p >= MEM_POOL_SPACE_START(pool_p)
&& chunk_p <= MEM_POOL_SPACE_START(pool_p) + pool_p->chunks_number * MEM_POOL_CHUNK_SIZE); && chunk_p <= MEM_POOL_SPACE_START(pool_p) + MEM_POOL_CHUNKS_NUMBER * MEM_POOL_CHUNK_SIZE);
JERRY_ASSERT(((uintptr_t) chunk_p - (uintptr_t) MEM_POOL_SPACE_START(pool_p)) % MEM_POOL_CHUNK_SIZE == 0); JERRY_ASSERT(((uintptr_t) chunk_p - (uintptr_t) MEM_POOL_SPACE_START(pool_p)) % MEM_POOL_CHUNK_SIZE == 0);
mem_check_pool (pool_p); mem_check_pool (pool_p);
@ -149,13 +142,12 @@ static void
mem_check_pool (mem_pool_state_t __unused *pool_p) /**< pool (unused #ifdef JERRY_NDEBUG) */ mem_check_pool (mem_pool_state_t __unused *pool_p) /**< pool (unused #ifdef JERRY_NDEBUG) */
{ {
#ifndef JERRY_NDEBUG #ifndef JERRY_NDEBUG
JERRY_ASSERT(pool_p->chunks_number != 0); JERRY_ASSERT(pool_p->free_chunks_number <= MEM_POOL_CHUNKS_NUMBER);
JERRY_ASSERT(pool_p->free_chunks_number <= pool_p->chunks_number);
size_t met_free_chunks_number = 0; size_t met_free_chunks_number = 0;
mem_pool_chunk_index_t chunk_index = pool_p->first_free_chunk; mem_pool_chunk_index_t chunk_index = pool_p->first_free_chunk;
while (chunk_index != pool_p->chunks_number) while (chunk_index != MEM_POOL_CHUNKS_NUMBER)
{ {
uint8_t *chunk_p = MEM_POOL_CHUNK_ADDRESS(pool_p, chunk_index); uint8_t *chunk_p = MEM_POOL_CHUNK_ADDRESS(pool_p, chunk_index);
mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) chunk_p; mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) chunk_p;

View File

@ -21,11 +21,28 @@
#define JERRY_MEM_POOL_H #define JERRY_MEM_POOL_H
#include "mem-config.h" #include "mem-config.h"
#include "mem-heap.h"
/** \addtogroup pool Memory pool /** \addtogroup pool Memory pool
* @{ * @{
*/ */
/**
* Size of a pool (header + chunks)
*/
#define MEM_POOL_SIZE \
((size_t) JERRY_MIN (sizeof (mem_pool_state_t) + (1ull << MEM_POOL_MAX_CHUNKS_NUMBER_LOG) * MEM_POOL_CHUNK_SIZE, \
JERRY_ALIGNDOWN (mem_heap_recommend_allocation_size (sizeof (mem_pool_state_t) + \
CONFIG_MEM_LEAST_CHUNK_NUMBER_IN_POOL * \
MEM_POOL_CHUNK_SIZE) \
- sizeof (mem_pool_state_t), \
MEM_POOL_CHUNK_SIZE)) + sizeof (mem_pool_state_t))
/**
* Number of chunks in a pool
*/
#define MEM_POOL_CHUNKS_NUMBER ((MEM_POOL_SIZE - sizeof (mem_pool_state_t)) / MEM_POOL_CHUNK_SIZE)
/** /**
* Get pool's space size * Get pool's space size
*/ */
@ -34,21 +51,19 @@
/** /**
* Index of chunk in a pool * Index of chunk in a pool
*/ */
typedef uint16_t mem_pool_chunk_index_t; typedef uint8_t mem_pool_chunk_index_t;
/** /**
* State of a memory pool * State of a memory pool
*/ */
typedef struct mem_pool_state_t typedef struct __attribute__ ((aligned (MEM_ALIGNMENT))) mem_pool_state_t
{ {
/** Number of chunks (mem_pool_chunk_index_t) */
unsigned int chunks_number : MEM_POOL_MAX_CHUNKS_NUMBER_LOG;
/** Number of free chunks (mem_pool_chunk_index_t) */
unsigned int free_chunks_number : MEM_POOL_MAX_CHUNKS_NUMBER_LOG;
/** Offset of first free chunk from the beginning of the pool (mem_pool_chunk_index_t) */ /** Offset of first free chunk from the beginning of the pool (mem_pool_chunk_index_t) */
unsigned int first_free_chunk : MEM_POOL_MAX_CHUNKS_NUMBER_LOG; unsigned int first_free_chunk : MEM_POOL_MAX_CHUNKS_NUMBER_LOG;
/** Number of free chunks (mem_pool_chunk_index_t) */
unsigned int free_chunks_number : MEM_POOL_MAX_CHUNKS_NUMBER_LOG;
/** Pointer to the next pool with same chunk size */ /** Pointer to the next pool with same chunk size */
unsigned int next_pool_cp : MEM_HEAP_OFFSET_LOG; unsigned int next_pool_cp : MEM_HEAP_OFFSET_LOG;
} mem_pool_state_t; } mem_pool_state_t;

View File

@ -104,13 +104,7 @@ mem_pools_alloc (void)
*/ */
if (mem_free_chunks_number == 0) if (mem_free_chunks_number == 0)
{ {
/** mem_pool_state_t *pool_state = (mem_pool_state_t*) mem_heap_alloc_block (MEM_POOL_SIZE, MEM_HEAP_ALLOC_LONG_TERM);
* Space, at least for header and eight chunks.
*/
size_t pool_chunks_area_size = CONFIG_MEM_LEAST_CHUNK_NUMBER_IN_POOL * MEM_POOL_CHUNK_SIZE;
size_t pool_size = mem_heap_recommend_allocation_size (sizeof (mem_pool_state_t) + pool_chunks_area_size);
mem_pool_state_t *pool_state = (mem_pool_state_t*) mem_heap_alloc_block (pool_size, MEM_HEAP_ALLOC_LONG_TERM);
if (pool_state == NULL) if (pool_state == NULL)
{ {
@ -120,7 +114,7 @@ mem_pools_alloc (void)
return NULL; return NULL;
} }
mem_pool_init (pool_state, pool_size); mem_pool_init (pool_state, MEM_POOL_SIZE);
if (mem_pools == NULL) if (mem_pools == NULL)
{ {
@ -133,7 +127,7 @@ mem_pools_alloc (void)
mem_pools = pool_state; mem_pools = pool_state;
mem_free_chunks_number += pool_state->chunks_number; mem_free_chunks_number += MEM_POOL_CHUNKS_NUMBER;
MEM_POOLS_STAT_ALLOC_POOL (); MEM_POOLS_STAT_ALLOC_POOL ();
} }
@ -145,7 +139,7 @@ mem_pools_alloc (void)
*/ */
mem_pool_state_t *pool_state = mem_pools; mem_pool_state_t *pool_state = mem_pools;
while (pool_state->first_free_chunk == pool_state->chunks_number) while (pool_state->first_free_chunk == MEM_POOL_CHUNKS_NUMBER)
{ {
pool_state = mem_decompress_pointer (pool_state->next_pool_cp); pool_state = mem_decompress_pointer (pool_state->next_pool_cp);
@ -174,7 +168,7 @@ mem_pools_free (uint8_t *chunk_p) /**< pointer to the chunk */
* Search for the pool containing specified chunk. * Search for the pool containing specified chunk.
*/ */
while (!(chunk_p >= MEM_POOL_SPACE_START(pool_state) while (!(chunk_p >= MEM_POOL_SPACE_START(pool_state)
&& chunk_p <= MEM_POOL_SPACE_START(pool_state) + pool_state->chunks_number * MEM_POOL_CHUNK_SIZE)) && chunk_p <= MEM_POOL_SPACE_START(pool_state) + MEM_POOL_CHUNKS_NUMBER * MEM_POOL_CHUNK_SIZE))
{ {
prev_pool_state = pool_state; prev_pool_state = pool_state;
pool_state = mem_decompress_pointer (pool_state->next_pool_cp); pool_state = mem_decompress_pointer (pool_state->next_pool_cp);
@ -193,7 +187,7 @@ mem_pools_free (uint8_t *chunk_p) /**< pointer to the chunk */
/** /**
* If all chunks of the pool are free, free the pool itself. * If all chunks of the pool are free, free the pool itself.
*/ */
if (pool_state->free_chunks_number == pool_state->chunks_number) if (pool_state->free_chunks_number == MEM_POOL_CHUNKS_NUMBER)
{ {
if (prev_pool_state != NULL) if (prev_pool_state != NULL)
{ {
@ -211,7 +205,7 @@ mem_pools_free (uint8_t *chunk_p) /**< pointer to the chunk */
} }
} }
mem_free_chunks_number -= pool_state->chunks_number; mem_free_chunks_number -= MEM_POOL_CHUNKS_NUMBER;
mem_heap_free_block ((uint8_t*)pool_state); mem_heap_free_block ((uint8_t*)pool_state);

View File

@ -26,9 +26,6 @@ extern long int time (long int *__timer);
extern int printf (__const char *__restrict __format, ...); extern int printf (__const char *__restrict __format, ...);
extern void *memset (void *__s, int __c, size_t __n); extern void *memset (void *__s, int __c, size_t __n);
// Pool area size is 8K
const size_t test_pool_area_size = 8 * 1024;
// Iterations count // Iterations count
const uint32_t test_iters = 64; const uint32_t test_iters = 64;
@ -46,24 +43,27 @@ main( int __unused argc,
for ( uint32_t i = 0; i < test_iters; i++ ) for ( uint32_t i = 0; i < test_iters; i++ )
{ {
uint8_t test_pool[test_pool_area_size] __attribute__((aligned(MEM_ALIGNMENT))); uint8_t test_pool[MEM_POOL_SIZE] __attribute__((aligned(MEM_ALIGNMENT)));
mem_pool_state_t* pool_p = (mem_pool_state_t*) test_pool; mem_pool_state_t* pool_p = (mem_pool_state_t*) test_pool;
mem_pool_init( pool_p, sizeof (test_pool)); mem_pool_init( pool_p, MEM_POOL_SIZE);
const size_t subiters = ( (size_t) rand() % test_max_sub_iters ) + 1; const size_t subiters = ( (size_t) rand() % test_max_sub_iters ) + 1;
uint8_t* ptrs[subiters]; uint8_t* ptrs[subiters];
for ( size_t j = 0; j < subiters; j++ ) for ( size_t j = 0; j < subiters; j++ )
{ {
ptrs[j] = mem_pool_alloc_chunk( pool_p); if (pool_p->free_chunks_number != 0)
// TODO: Enable check with condition that j <= minimum count of chunks that fit in the pool
// JERRY_ASSERT(ptrs[j] != NULL);
if ( ptrs[j] != NULL )
{ {
memset(ptrs[j], 0, MEM_POOL_CHUNK_SIZE); ptrs[j] = mem_pool_alloc_chunk( pool_p);
memset(ptrs[j], 0, MEM_POOL_CHUNK_SIZE);
}
else
{
JERRY_ASSERT (j >= MEM_POOL_CHUNKS_NUMBER);
ptrs[j] = NULL;
} }
} }