diff --git a/common/utils/itti/memory_pools.c b/common/utils/itti/memory_pools.c index a5289a24b0fda18ed3764997a9e28abea3aaab2e..6004c70e66d733488b1b15c61e2ec688b92af78b 100644 --- a/common/utils/itti/memory_pools.c +++ b/common/utils/itti/memory_pools.c @@ -31,18 +31,46 @@ #include "assertions.h" #include "memory_pools.h" +/*------------------------------------------------------------------------------*/ +const static int mp_debug = 0; + +#ifdef RTAI +# define MP_DEBUG(x, args...) do { if (mp_debug) rt_printk("[MP][D]"x, ##args); } \ + while(0) +#else +# define MP_DEBUG(x, args...) do { if (mp_debug) fprintf(stdout, "[MP][D]"x, ##args); fflush (stdout); } \ + while(0) +#endif + /*------------------------------------------------------------------------------*/ #define CHARS_TO_UINT32(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4)) /*------------------------------------------------------------------------------*/ -typedef uint32_t pool_item_start_mark_t; -typedef uint32_t pool_item_end_mark_t; +typedef int32_t items_group_position_t; +typedef int32_t items_group_index_t; -typedef uint32_t pool_start_mark_t; +typedef struct items_group_s { + items_group_position_t number; + volatile items_group_position_t current; + volatile items_group_position_t minimum; + volatile items_group_index_t *indexes; +} items_group_t; -typedef uint32_t pools_start_mark_t; +/*------------------------------------------------------------------------------*/ +static const items_group_position_t ITEMS_GROUP_POSITION_INVALID = -1; +static const items_group_index_t ITEMS_GROUP_INDEX_INVALID = -1; -typedef uint8_t pool_id_t; +/*------------------------------------------------------------------------------*/ +typedef uint32_t pool_item_start_mark_t; +typedef uint32_t pool_item_end_mark_t; + +typedef uint32_t memory_pool_data_t; + +typedef uint32_t pool_start_mark_t; + +typedef uint32_t pools_start_mark_t; + +typedef uint8_t pool_id_t; typedef struct memory_pool_item_start_s { pool_item_start_mark_t start_mark; @@ -57,22 +85,16 @@ typedef struct memory_pool_item_end_s { typedef struct memory_pool_item_s { memory_pool_item_start_t start; - uint32_t data[0]; + memory_pool_data_t data[0]; memory_pool_item_end_t end; } memory_pool_item_t; -typedef struct items_group_s { - volatile int32_t current; - volatile int32_t minimum; - int32_t *indexes; -} items_group_t; - typedef struct memory_pool_s { pool_start_mark_t start_mark; pool_id_t pool_id; - uint32_t items_number; - uint32_t item_size; + uint32_t item_data_number; + uint32_t pool_item_size; items_group_t items_group_free; memory_pool_item_t *items; } memory_pool_t; @@ -87,7 +109,7 @@ typedef struct memory_pools_s { /*------------------------------------------------------------------------------*/ static const uint32_t MAX_POOLS_NUMBER = 20; -static const uint32_t MAX_POOL_ITEMS_NUMBER = 1000 * 1000; +static const uint32_t MAX_POOL_ITEMS_NUMBER = 200 * 1000; static const uint32_t MAX_POOL_ITEM_SIZE = 100 * 1000; static const pool_item_start_mark_t POOL_ITEM_START_MARK = CHARS_TO_UINT32 ('P', 'I', 's', 't'); @@ -98,9 +120,92 @@ static const pool_start_mark_t POOL_START_MARK = CHARS_TO_UINT32 ('P' static const pools_start_mark_t POOLS_START_MARK = CHARS_TO_UINT32 ('P', 'S', 's', 't'); /*------------------------------------------------------------------------------*/ +static inline items_group_index_t items_group_get_free_item (items_group_t *items_group) +{ + items_group_position_t current; + items_group_index_t index = -1; + + /* Get current position and decrease it */ + current = __sync_fetch_and_add (&items_group->current, -1); + if (current <= ITEMS_GROUP_POSITION_INVALID) + { + /* Current index is not valid, restore previous value */ + __sync_fetch_and_add (&items_group->current, 1); + } + else + { + /* Updates minimum position if needed */ + while (items_group->minimum > current) + { + items_group->minimum = current; + } + + /* Get index at current position */ + index = items_group->indexes[current]; + DevCheck (index > ITEMS_GROUP_INDEX_INVALID, current, index, 0); + + /* Clear index at current position */ + items_group->indexes[current] = ITEMS_GROUP_INDEX_INVALID; + } + + return (index); +} + +static inline void items_group_put_free_item (items_group_t *items_group, items_group_index_t index) +{ + items_group_position_t next; + items_group_position_t current = ITEMS_GROUP_POSITION_INVALID; + items_group_index_t index_to_add; + items_group_index_t index_previous; + + index_to_add = index - ITEMS_GROUP_INDEX_INVALID; + + do + { + /* Calculate next position */ + next = items_group->current + 1; + /* Checks if next position is free */ + if (items_group->indexes[next] == ITEMS_GROUP_INDEX_INVALID) + { + /* Try to write index in next position */ + index_previous = __sync_fetch_and_add (&items_group->indexes[next], index_to_add); + /* Checks if next position was still free */ + if (index_previous != ITEMS_GROUP_INDEX_INVALID) + { + /* Next position was not free anymore, restore its value */ + __sync_fetch_and_add (&items_group->indexes[next], -index_to_add); + current = ITEMS_GROUP_POSITION_INVALID; + } + else + { + /* Checks if next position content is correctly set */ + if (items_group->indexes[next] != index) + { + /* Next position content has been changed, restore its value */ + __sync_fetch_and_add (&items_group->indexes[next], -index_to_add); + current = ITEMS_GROUP_POSITION_INVALID; + } + else + { + /* Increase current position and get it */ + current = __sync_add_and_fetch (&items_group->current, 1); + + if (next != current) + { + /* Current position does not match calculated next position, restore previous values */ + __sync_fetch_and_add (&items_group->current, -1); + __sync_fetch_and_add (&items_group->indexes[next], -index_to_add); + } + } + } + } + } while (next != current); + + DevCheck (current < items_group->number, current, items_group->number, 0); +} /*------------------------------------------------------------------------------*/ -static inline memory_pools_t *memory_pools_from_handler(memory_pools_handle_t *memory_pools_handle) +static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle) { memory_pools_t *memory_pools; @@ -112,59 +217,38 @@ static inline memory_pools_t *memory_pools_from_handler(memory_pools_handle_t *m return (memory_pools); } -static inline memory_pool_item_t *memory_pool_item_from_handler(memory_pool_item_handle_t *memory_pool_item_handle) +static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle) { void *address; memory_pool_item_t *memory_pool_item; /* Recover memory_pools */ - address = ((void *) memory_pool_item_handle) - sizeof (memory_pool_item_start_t); + address = memory_pool_item_handle - sizeof(memory_pool_item_start_t); memory_pool_item = (memory_pool_item_t *) address; + /* Sanity check on passed handle */ DevAssert (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK); return (memory_pool_item); } -static inline int32_t items_group_get_free_item(items_group_t *items_group) +static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index) { - int32_t current; - int32_t index = -1; - - /* Get current position and decrease it */ - current = __sync_fetch_and_add (&items_group->current, -1); - if (current < 0) - { - /* Current index is not valid, restore previous value */ - __sync_fetch_and_add (&items_group->current, 1); - } - else - { - /* Updates minimum position if needed */ - while (items_group->minimum > current) - { - items_group->minimum = current; - } - - /* Get index at current position */ - index = items_group->indexes[current]; - DevCheck (index >= 0, current, index, 0); + void *address; - /* Clear index at current position */ - items_group->indexes[current] = -1; - } + address = (void *) memory_pool->items; + address += index * memory_pool->pool_item_size; - return (index); + return (address); } /*------------------------------------------------------------------------------*/ - -memory_pools_handle_t *memory_pools_create (uint32_t pools_number) +memory_pools_handle_t memory_pools_create (uint32_t pools_number) { memory_pools_t *memory_pools; pool_id_t pool; - DevCheck (pools_number < MAX_POOLS_NUMBER, pools_number, MAX_POOLS_NUMBER, 0); /* Limit to a reasonable number of pools */ + DevCheck (pools_number <= MAX_POOLS_NUMBER, pools_number, MAX_POOLS_NUMBER, 0); /* Limit to a reasonable number of pools */ /* Allocate memory_pools */ memory_pools = malloc (sizeof(memory_pools_t)); @@ -190,15 +274,48 @@ memory_pools_handle_t *memory_pools_create (uint32_t pools_number) return ((memory_pools_handle_t) memory_pools); } -int memory_pools_add_pool (memory_pools_handle_t *memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size) +char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle) { - memory_pools_t *memory_pools; - memory_pool_t *memory_pool; - pool_id_t pool; - uint32_t item; + memory_pools_t *memory_pools; + pool_id_t pool; + char *statistics; + int printed_chars; + uint32_t allocated_pool_memory; + uint32_t allocated_pools_memory = 0; - DevCheck (pool_items_number < MAX_POOL_ITEMS_NUMBER, pool_items_number, MAX_POOL_ITEMS_NUMBER, 0); /* Limit to a reasonable number of items */ - DevCheck (pool_item_size < MAX_POOL_ITEM_SIZE, pool_item_size, MAX_POOL_ITEM_SIZE, 0); /* Limit to a reasonable item size */ + /* Recover memory_pools */ + memory_pools = memory_pools_from_handler (memory_pools_handle); + + statistics = malloc(memory_pools->pools_defined * 200); + + printed_chars = sprintf (&statistics[0], "Pool: number, size, minimum, free\n"); + for (pool = 0; pool < memory_pools->pools_defined; pool++) + { + allocated_pool_memory = memory_pools->pools[pool].items_group_free.number * memory_pools->pools[pool].pool_item_size; + allocated_pools_memory += allocated_pool_memory; + printed_chars += sprintf (&statistics[printed_chars], " %2u: %6u, %6u, %6u, %6u, %6u Kbytes\n", + pool, + memory_pools->pools[pool].items_group_free.number, + memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t), + memory_pools->pools[pool].items_group_free.minimum + 1, + memory_pools->pools[pool].items_group_free.current + 1, + allocated_pool_memory / (1020)); + } + printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024)); + + return (statistics); +} + +int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size) +{ + memory_pools_t *memory_pools; + memory_pool_t *memory_pool; + pool_id_t pool; + items_group_index_t item_index; + memory_pool_item_t *memory_pool_item; + + DevCheck (pool_items_number <= MAX_POOL_ITEMS_NUMBER, pool_items_number, MAX_POOL_ITEMS_NUMBER, 0); /* Limit to a reasonable number of items */ + DevCheck (pool_item_size <= MAX_POOL_ITEM_SIZE, pool_item_size, MAX_POOL_ITEM_SIZE, 0); /* Limit to a reasonable item size */ /* Recover memory_pools */ memory_pools = memory_pools_from_handler (memory_pools_handle); @@ -213,31 +330,34 @@ int memory_pools_add_pool (memory_pools_handle_t *memory_pools_handle, uint32_t /* Initialize pool */ { memory_pool->pool_id = pool; - memory_pool->items_number = pool_items_number; - memory_pool->item_size = pool_item_size; + /* Item size in memory_pool_data_t items by excess */ + memory_pool->item_data_number = (pool_item_size + sizeof(memory_pool_data_t) - 1) / sizeof(memory_pool_data_t); + memory_pool->pool_item_size = (memory_pool->item_data_number * sizeof(memory_pool_data_t)) + sizeof(memory_pool_item_t); + memory_pool->items_group_free.number = pool_items_number; memory_pool->items_group_free.current = pool_items_number - 1; memory_pool->items_group_free.minimum = pool_items_number - 1; /* Allocate free indexes */ - memory_pool->items_group_free.indexes = malloc(pool_items_number * sizeof(uint32_t)); + memory_pool->items_group_free.indexes = malloc(pool_items_number * sizeof(items_group_index_t)); DevAssert (memory_pool->items_group_free.indexes != NULL); /* Initialize free indexes */ - for (item = 0; item < pool_items_number; item++) + for (item_index = 0; item_index < pool_items_number; item_index++) { - memory_pool->items_group_free.indexes[item] = item; + memory_pool->items_group_free.indexes[item_index] = item_index; } /* Allocate items */ - memory_pool->items = calloc (pool_items_number, (sizeof(memory_pool_item_t) + pool_item_size)); + memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size); DevAssert (memory_pool->items != NULL); /* Initialize items */ - for (item = 0; item < pool_items_number; item++) + for (item_index = 0; item_index < pool_items_number; item_index++) { - memory_pool->items[item].start.start_mark = POOL_ITEM_START_MARK; - memory_pool->items[item].start.pool_id = pool; - memory_pool->items[item].data[pool_item_size / sizeof(uint32_t)] = POOL_ITEM_END_MARK; + memory_pool_item = memory_pool_item_from_index (memory_pool, item_index); + memory_pool_item->start.start_mark = POOL_ITEM_START_MARK; + memory_pool_item->start.pool_id = pool; + memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK; } } @@ -246,29 +366,31 @@ int memory_pools_add_pool (memory_pools_handle_t *memory_pools_handle, uint32_t return (0); } -memory_pool_item_handle_t *memory_pools_allocate (memory_pools_handle_t *memory_pools_handle, uint32_t item_size) +memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint32_t info) { - memory_pools_t *memory_pools; - memory_pool_item_t *memory_pool_item = NULL; - pool_id_t pool; - int32_t item; + memory_pools_t *memory_pools; + memory_pool_item_t *memory_pool_item; + memory_pool_item_handle_t memory_pool_item_handle = NULL; + pool_id_t pool; + items_group_index_t item_index = ITEMS_GROUP_INDEX_INVALID; /* Recover memory_pools */ memory_pools = memory_pools_from_handler (memory_pools_handle); - for (pool = 0; pool <= memory_pools->pools_defined; pool++) + for (pool = 0; pool < memory_pools->pools_defined; pool++) { - if (memory_pools->pools[pool].item_size < item_size) + if ((memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t)) < item_size) { /* This memory pool has too small items, skip it */ continue; } - item = items_group_get_free_item(&memory_pools->pools[pool].items_group_free); - if (item < 0) + item_index = items_group_get_free_item(&memory_pools->pools[pool].items_group_free); + if (item_index <= ITEMS_GROUP_INDEX_INVALID) { /* Allocation failed, skip this pool */ - continue; + break; + //continue; } else { @@ -277,22 +399,33 @@ memory_pool_item_handle_t *memory_pools_allocate (memory_pools_handle_t *memory_ } } - if (item >= 0) + if (item_index > ITEMS_GROUP_INDEX_INVALID) { /* Convert item index into memory_pool_item address */ - memory_pool_item = &memory_pools->pools[pool].items[item]; + memory_pool_item = memory_pool_item_from_index (&memory_pools->pools[pool], item_index); + memory_pool_item->start.info = info; + memory_pool_item_handle = memory_pool_item->data; + + MP_DEBUG(" Alloc [%2u][%6d]{%6u}, %4u, %6u, %p, %p, %p\n", + pool, item_index, memory_pools->pools[pool].items_group_free.minimum, + info, item_size, memory_pools->pools[pool].items, memory_pool_item, memory_pool_item_handle); + } + else + { + MP_DEBUG(" Alloc [--][------]{------}, %4u, %6u, failed!\n", info, item_size); } - return (memory_pool_item_handle_t *) memory_pool_item->data; + return memory_pool_item_handle; } -void memory_pools_free (memory_pools_handle_t *memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle) +void memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint32_t info) { memory_pools_t *memory_pools; - memory_pool_item_t *memory_pool_item = NULL; + memory_pool_item_t *memory_pool_item; pool_id_t pool; - int32_t item; + items_group_index_t item_index; uint32_t item_size; + uint32_t pool_item_size; /* Recover memory_pools */ memory_pools = memory_pools_from_handler (memory_pools_handle); @@ -302,12 +435,19 @@ void memory_pools_free (memory_pools_handle_t *memory_pools_handle, memory_pool_ pool = memory_pool_item->start.pool_id; DevCheck (pool < memory_pools->pools_defined, pool, memory_pools->pools_defined, 0); - item_size = memory_pools->pools[pool].item_size; - item = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / (sizeof(memory_pool_item_t) + item_size); + item_size = memory_pools->pools[pool].item_data_number; + pool_item_size = memory_pools->pools[pool].pool_item_size; + item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size; + + MP_DEBUG(" Free [%2u][%6d]{%6u}, %4u, %p, %p, %p, %u\n", + pool, item_index, memory_pools->pools[pool].items_group_free.current, + info, memory_pool_item_handle, memory_pool_item, memory_pools->pools[pool].items, item_size * sizeof(memory_pool_data_t)); + /* Sanity check on calculated item index */ - DevCheck (memory_pool_item == &memory_pools->pools[pool].items[item], memory_pool_item, &memory_pools->pools[pool].items[item], pool); + DevCheck (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index), memory_pool_item, + memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool); /* Check if end marker is still present (no write overflow) */ - DevCheck (memory_pool_item->data[item_size / sizeof(uint32_t)] == POOL_ITEM_END_MARK, pool, 0, 0); - + DevCheck (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK, pool, 0, 0); + items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index); } diff --git a/common/utils/itti/memory_pools.h b/common/utils/itti/memory_pools.h index c1e2ec8b146aa68f59b926153e588ab22a940825..7ed44c661a2a1b727cb469a425a25f1cf6add6e0 100644 --- a/common/utils/itti/memory_pools.h +++ b/common/utils/itti/memory_pools.h @@ -36,12 +36,14 @@ typedef void * memory_pools_handle_t; typedef void * memory_pool_item_handle_t; -memory_pools_handle_t *memory_pools_create (uint32_t pools_number); +memory_pools_handle_t memory_pools_create (uint32_t pools_number); -int memory_pools_add_pool (memory_pools_handle_t *memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size); +char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle); -memory_pool_item_handle_t *memory_pools_allocate (memory_pools_handle_t *memory_pools_handle, uint32_t item_size); +int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size); -void memory_pools_free (memory_pools_handle_t *memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle); +memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint32_t info); + +void memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint32_t info); #endif /* MEMORY_POOLS_H_ */