From c21e186f2caaba41cd977ab0717cbc25801a37be Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 26 Nov 2014 18:49:00 +0300 Subject: [PATCH] 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. --- src/config.h | 2 +- src/liballocator/mem-heap.c | 4 ++-- src/liballocator/mem-heap.h | 2 +- src/liballocator/mem-pool.c | 32 ++++++++++++-------------------- src/liballocator/mem-pool.h | 29 ++++++++++++++++++++++------- src/liballocator/mem-poolman.c | 20 +++++++------------- tests/unit/test_pool.c | 24 ++++++++++++------------ 7 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/config.h b/src/config.h index d4929cd48..d4a4852f7 100644 --- a/src/config.h +++ b/src/config.h @@ -29,7 +29,7 @@ /** * 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 diff --git a/src/liballocator/mem-heap.c b/src/liballocator/mem-heap.c index 6dcc38514..9969c202b 100644 --- a/src/liballocator/mem-heap.c +++ b/src/liballocator/mem-heap.c @@ -90,7 +90,7 @@ JERRY_STATIC_ASSERT (sizeof (mem_heap_offset_t) * JERRY_BITSINBYTE >= MEM_HEAP_O /** * 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): 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 */ -size_t +size_t __attribute_pure__ 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); diff --git a/src/liballocator/mem-heap.h b/src/liballocator/mem-heap.h index c6361a7ab..55c1aaa36 100644 --- a/src/liballocator/mem-heap.h +++ b/src/liballocator/mem-heap.h @@ -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 bool mem_heap_try_resize_block (uint8_t *ptr, size_t size_in_bytes); 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); #ifdef MEM_STATS diff --git a/src/liballocator/mem-pool.c b/src/liballocator/mem-pool.c index 7c791ac8c..1087c7fca 100644 --- a/src/liballocator/mem-pool.c +++ b/src/liballocator/mem-pool.c @@ -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_ASSERT(sizeof (mem_pool_chunk_index_t) <= MEM_POOL_CHUNK_SIZE); - const size_t pool_space_size = pool_size - sizeof (mem_pool_state_t); - const size_t chunks_number = pool_space_size / MEM_POOL_CHUNK_SIZE; + JERRY_ASSERT (MEM_POOL_SIZE == sizeof (mem_pool_state_t) + MEM_POOL_CHUNKS_NUMBER * 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); - - pool_p->chunks_number = (mem_pool_chunk_index_t) chunks_number; + JERRY_ASSERT (pool_size == MEM_POOL_SIZE); /* * 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 @@ -74,7 +73,7 @@ mem_pool_init (mem_pool_state_t *pool_p, /**< pool */ pool_p->first_free_chunk = 0; for (mem_pool_chunk_index_t chunk_index = 0; - chunk_index < chunks_number; + chunk_index < MEM_POOL_CHUNKS_NUMBER; chunk_index++) { 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); - if (unlikely (pool_p->free_chunks_number == 0)) - { - JERRY_ASSERT(pool_p->first_free_chunk == pool_p->chunks_number); - - return NULL; - } - - JERRY_ASSERT(pool_p->first_free_chunk < pool_p->chunks_number); + JERRY_ASSERT (pool_p->free_chunks_number != 0); + JERRY_ASSERT (pool_p->first_free_chunk < MEM_POOL_CHUNKS_NUMBER); mem_pool_chunk_index_t chunk_index = pool_p->first_free_chunk; 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 */ 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) - && 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); 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) */ { #ifndef JERRY_NDEBUG - JERRY_ASSERT(pool_p->chunks_number != 0); - JERRY_ASSERT(pool_p->free_chunks_number <= pool_p->chunks_number); + JERRY_ASSERT(pool_p->free_chunks_number <= MEM_POOL_CHUNKS_NUMBER); size_t met_free_chunks_number = 0; 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); mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) chunk_p; diff --git a/src/liballocator/mem-pool.h b/src/liballocator/mem-pool.h index 43b2d471c..d65d52e57 100644 --- a/src/liballocator/mem-pool.h +++ b/src/liballocator/mem-pool.h @@ -21,11 +21,28 @@ #define JERRY_MEM_POOL_H #include "mem-config.h" +#include "mem-heap.h" /** \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 */ @@ -34,21 +51,19 @@ /** * 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 */ -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) */ 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 */ unsigned int next_pool_cp : MEM_HEAP_OFFSET_LOG; } mem_pool_state_t; diff --git a/src/liballocator/mem-poolman.c b/src/liballocator/mem-poolman.c index 9b5e0f481..eb34e1bf0 100644 --- a/src/liballocator/mem-poolman.c +++ b/src/liballocator/mem-poolman.c @@ -104,13 +104,7 @@ mem_pools_alloc (void) */ if (mem_free_chunks_number == 0) { - /** - * 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); + mem_pool_state_t *pool_state = (mem_pool_state_t*) mem_heap_alloc_block (MEM_POOL_SIZE, MEM_HEAP_ALLOC_LONG_TERM); if (pool_state == NULL) { @@ -120,7 +114,7 @@ mem_pools_alloc (void) return NULL; } - mem_pool_init (pool_state, pool_size); + mem_pool_init (pool_state, MEM_POOL_SIZE); if (mem_pools == NULL) { @@ -133,7 +127,7 @@ mem_pools_alloc (void) 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 (); } @@ -145,7 +139,7 @@ mem_pools_alloc (void) */ 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); @@ -174,7 +168,7 @@ mem_pools_free (uint8_t *chunk_p) /**< pointer to the chunk */ * Search for the pool containing specified chunk. */ 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; 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 (pool_state->free_chunks_number == pool_state->chunks_number) + if (pool_state->free_chunks_number == MEM_POOL_CHUNKS_NUMBER) { 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); diff --git a/tests/unit/test_pool.c b/tests/unit/test_pool.c index 01e84b542..c6073279e 100644 --- a/tests/unit/test_pool.c +++ b/tests/unit/test_pool.c @@ -26,9 +26,6 @@ extern long int time (long int *__timer); extern int printf (__const char *__restrict __format, ...); 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 const uint32_t test_iters = 64; @@ -46,24 +43,27 @@ main( int __unused argc, 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_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; uint8_t* ptrs[subiters]; for ( size_t j = 0; j < subiters; j++ ) { - ptrs[j] = mem_pool_alloc_chunk( pool_p); - - // 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 ) + if (pool_p->free_chunks_number != 0) { - 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; } }