From a9e69d519cd5240320e278cdc4efa8b1723a5fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Thu, 16 May 2013 10:55:32 +0200 Subject: [PATCH] eo ptr ind: mostly cosmetic - add and use SHIFT_* macros - rename queue into fifo - try to clarify the structure top table -> mid table -> table[entry] --- src/lib/eo/eo_ptr_indirection.c | 216 ++++++++++++++++---------------- 1 file changed, 111 insertions(+), 105 deletions(-) diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.c index 74a39266f0..47c5295e69 100644 --- a/src/lib/eo/eo_ptr_indirection.c +++ b/src/lib/eo/eo_ptr_indirection.c @@ -17,14 +17,16 @@ * the Eo object to supply a better memory management by preventing bad usage * of the pointers. * - * Eo * is no more a pointer but an index to an entry into a ids table. - * For a better memory usage, we don't allocate all the tables at the beginning, - * but only when needed (i.e no more empty entries in allocated tables. - * In addition, tables are composed of intermediate tables, this for memory - * optimizations. Finding the different table, intermediate table and relative - * entry is done by bits manipulation of the id: + * Eo * is no more a pointer but indexes to an entry into an ids table. + * For a better memory usage: + * - a tree structure is used, composed of a top level table pointing at + * mid tables pointing at tables composed of entries. + * - tables are allocated when needed (i.e no more empty entries in allocated tables. + * For now there is no mechanism to free empty tables. * - * id = Table | Inter_table | Entry | Generation + * An Eo id is contructed by bits manipulation of table indexes and a generation. + * + * id = Mid Table | Table | Entry | Generation * * Generation helps finding abuse of ids. When an entry is assigned to an * object, a generation is inserted into the id. If the developer uses this id @@ -32,69 +34,73 @@ * entry of the table, the generation will be different and an error will * occur when accessing with the old id. * - * Each table is composed of: - * - an index 'start' indicating which entry is the next one to use. - * - 2 indexes 'queue_head' and 'queue_tail' defining a queue (fifo), + * Each Table is composed of: + * - an index 'start' indicating which free entry is the next one to use. + * - 2 indexes 'fifo_head' and 'fifo_tail' defining a fifo, * that will help us to store the entries to be reused. It stores only the * entries that have been used at least one time. The entries that have * never been used are "pointed" by the start parameter. * - entries composed of: * - a pointer to the object + * - an index 'next_in_fifo' used to chain the free entries in the fifo * - a flag indicating if the entry is active * - a generation assigned to the object - * - an index 'next_in_queue' used to chain the entries in the queue * * When an entry is searched into a table, we first use one of the entries that - * has never been used. If there is none, we try to pop from the queue. + * has never been used. If there is none, we try to pop from the fifo. + * If a such entry doesn't exist, we pass to the next table. + * When an entry is found, we reserve it to the object pointer + * then contruct and return the related Eo id. + * * Assigning all the entries of a table before trying to reuse them from * the fifo ensures that we are not going to soon recycle a released entry, * thus minimize the risks of an aggressive del() then use() on a single entry. - * If a such entry doesn't exist, we pass to the next table. - * When an entry is found, we reserve it to the object pointer and create - * the id with the table id, the intermediate table id, the entry and a - * generation. + * * The indexes and a reference to the last table which served an entry is kept * and is reused prior to the others untill it is full. * When an object is freed, the entry into the table is released by appending - * it to the queue. + * it to the fifo. */ #if SIZEOF_UINTPTR_T == 4 /* 32 bits */ -# define BITS_FOR_IDS_TABLE 5 -# define BITS_FOR_IDS_INTER_TABLE 5 -# define BITS_FOR_ID_IN_TABLE 12 -# define BITS_FOR_GENERATION_COUNTER 10 +# define BITS_MID_TABLE_ID 5 +# define BITS_TABLE_ID 5 +# define BITS_ENTRY_ID 12 +# define BITS_GENERATION_COUNTER 10 typedef int16_t Table_Index; typedef uint16_t Generation_Counter; #else /* 64 bits */ -# define BITS_FOR_IDS_TABLE 11 -# define BITS_FOR_IDS_INTER_TABLE 11 -# define BITS_FOR_ID_IN_TABLE 12 -# define BITS_FOR_GENERATION_COUNTER 30 +# define BITS_MID_TABLE_ID 11 +# define BITS_TABLE_ID 11 +# define BITS_ENTRY_ID 12 +# define BITS_GENERATION_COUNTER 30 typedef int16_t Table_Index; typedef uint32_t Generation_Counter; #endif /* Shifts macros to manipulate the Eo id */ -#define SHIFT_FOR_IDS_TABLE \ - (BITS_FOR_IDS_INTER_TABLE + BITS_FOR_ID_IN_TABLE + BITS_FOR_GENERATION_COUNTER) - -#define SHIFT_FOR_IDS_INTER_TABLE \ - (BITS_FOR_ID_IN_TABLE + BITS_FOR_GENERATION_COUNTER) - -#define SHIFT_FOR_ID_IN_TABLE (BITS_FOR_GENERATION_COUNTER) +#define SHIFT_MID_TABLE_ID (BITS_TABLE_ID + \ + BITS_ENTRY_ID + BITS_GENERATION_COUNTER) +#define SHIFT_TABLE_ID (BITS_ENTRY_ID + BITS_GENERATION_COUNTER) +#define SHIFT_ENTRY_ID (BITS_GENERATION_COUNTER) /* Maximum ranges */ -#define MAX_IDS_TABLES (1 << BITS_FOR_IDS_TABLE) -#define MAX_IDS_INTER_TABLES (1 << BITS_FOR_IDS_INTER_TABLE) -#define MAX_IDS_PER_TABLE (1 << BITS_FOR_ID_IN_TABLE) -#define MAX_GENERATIONS (1 << BITS_FOR_GENERATION_COUNTER) +#define MAX_MID_TABLE_ID (1 << BITS_MID_TABLE_ID) +#define MAX_TABLE_ID (1 << BITS_TABLE_ID) +#define MAX_ENTRY_ID (1 << BITS_ENTRY_ID) +#define MAX_GENERATIONS (1 << BITS_GENERATION_COUNTER) -#define MEM_HEADER_SIZE 16 -#define MEM_PAGE_SIZE 4096 -#define MEM_MAGIC 0x3f61ec8a +/* Masks */ +#define MASK_MID_TABLE_ID (MAX_MID_TABLE_ID - 1) +#define MASK_TABLE_ID (MAX_TABLE_ID - 1) +#define MASK_ENTRY_ID (MAX_ENTRY_ID - 1) +#define MASK_GENERATIONS (MAX_GENERATIONS - 1) + +#define MEM_HEADER_SIZE 16 +#define MEM_PAGE_SIZE 4096 +#define MEM_MAGIC 0x3f61ec8a typedef struct _Mem_Header { @@ -159,26 +165,26 @@ typedef struct { /* Pointer to the object */ _Eo *ptr; + /* Indicates where to find the next entry to recycle */ + Table_Index next_in_fifo; /* Active flag */ unsigned int active : 1; /* Generation */ - unsigned int generation : BITS_FOR_GENERATION_COUNTER; - /* Indicates where to find the next entry to recycle */ - Table_Index next_in_queue; + unsigned int generation : BITS_GENERATION_COUNTER; } _Eo_Id_Entry; /* Table */ typedef struct { - /* Entries of the table holding real pointers and generations */ - _Eo_Id_Entry entries[MAX_IDS_PER_TABLE]; /* Indicates where start the "never used" entries */ Table_Index start; /* Indicates where to find the next entry to recycle */ - Table_Index queue_head; + Table_Index fifo_head; /* Indicates where to add an entry to recycle */ - Table_Index queue_tail; + Table_Index fifo_tail; + /* Entries of the table holding real pointers and generations */ + _Eo_Id_Entry entries[MAX_ENTRY_ID]; } _Eo_Ids_Table; /* Table Info */ @@ -186,14 +192,14 @@ typedef struct { /* Table pointer */ _Eo_Ids_Table *table; - /* Top table index */ + /* Index of mid table in top table */ + Table_Index mid_table_id; + /* Index of table in mid table */ Table_Index table_id; - /* Intermediate table index */ - Table_Index int_table_id; } _Eo_Table_Info; /* Tables handling pointers indirection */ -static _Eo_Ids_Table **_eo_ids_tables[MAX_IDS_TABLES] = { NULL }; +static _Eo_Ids_Table **_eo_ids_tables[MAX_MID_TABLE_ID] = { NULL }; /* Current table used for following allocations */ static _Eo_Table_Info current_table = { NULL, 0, 0 }; @@ -202,21 +208,21 @@ static _Eo_Table_Info current_table = { NULL, 0, 0 }; Generation_Counter _eo_generation_counter; /* Macro used to compose an Eo id */ -#define EO_COMPOSE_ID(TABLE, INTER_TABLE, ENTRY, GENERATION) \ - (((Eo_Id)(TABLE & (MAX_IDS_TABLES - 1)) << SHIFT_FOR_IDS_TABLE) | \ - ((Eo_Id)(INTER_TABLE & (MAX_IDS_INTER_TABLES - 1)) << SHIFT_FOR_IDS_INTER_TABLE) | \ - ((ENTRY & (MAX_IDS_PER_TABLE - 1)) << SHIFT_FOR_ID_IN_TABLE) | \ - (GENERATION & (MAX_GENERATIONS - 1) )) +#define EO_COMPOSE_ID(TABLE, INTER_TABLE, ENTRY, GENERATION) \ + (((Eo_Id)(TABLE & MASK_MID_TABLE_ID) << SHIFT_MID_TABLE_ID) | \ + ((Eo_Id)(INTER_TABLE & MASK_TABLE_ID) << SHIFT_TABLE_ID) | \ + ((ENTRY & MASK_ENTRY_ID) << SHIFT_ENTRY_ID) | \ + (GENERATION & MASK_GENERATIONS )) /* Macro to extract from an Eo id the indexes of the tables */ -#define EO_DECOMPOSE_ID(ID, TABLE, INTER_TABLE, ENTRY, GENERATION) \ - TABLE = (ID >> SHIFT_FOR_IDS_TABLE) & (MAX_IDS_TABLES - 1); \ - INTER_TABLE = (ID >> SHIFT_FOR_IDS_INTER_TABLE) & (MAX_IDS_INTER_TABLES - 1); \ - ENTRY = (ID >> SHIFT_FOR_ID_IN_TABLE) & (MAX_IDS_PER_TABLE - 1); \ - GENERATION = ID & (MAX_GENERATIONS - 1); \ +#define EO_DECOMPOSE_ID(ID, TABLE, INTER_TABLE, ENTRY, GENERATION) \ + TABLE = (ID >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID; \ + INTER_TABLE = (ID >> SHIFT_TABLE_ID) & MASK_TABLE_ID; \ + ENTRY = (ID >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID; \ + GENERATION = ID & MASK_GENERATIONS; /* Macro used for readability */ -#define ID_TABLE _eo_ids_tables[table_id][int_table_id] +#define TABLE_FROM_IDS _eo_ids_tables[mid_table_id][table_id] _Eo * _eo_obj_pointer_get(const Eo_Id obj_id) @@ -224,14 +230,14 @@ _eo_obj_pointer_get(const Eo_Id obj_id) #ifdef HAVE_EO_ID _Eo_Id_Entry *entry; Generation_Counter generation; - Table_Index table_id, int_table_id, entry_id; + Table_Index mid_table_id, table_id, entry_id; - EO_DECOMPOSE_ID(obj_id, table_id, int_table_id, entry_id, generation); + EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation); /* Checking the validity of the entry */ - if (_eo_ids_tables[table_id] && ID_TABLE) + if (_eo_ids_tables[mid_table_id] && TABLE_FROM_IDS) { - entry = &(ID_TABLE->entries[entry_id]); + entry = &(TABLE_FROM_IDS->entries[entry_id]); if (entry && entry->active && (entry->generation == generation)) return entry->ptr; } @@ -250,20 +256,20 @@ _get_available_entry(_Eo_Ids_Table *table) { _Eo_Id_Entry *entry = NULL; - if (table->start != MAX_IDS_PER_TABLE) + if (table->start != MAX_ENTRY_ID) { /* Serve never used entries first */ entry = &(table->entries[table->start]); table->start++; } - else if (table->queue_head != -1) + else if (table->fifo_head != -1) { - /* Pop an unused entry from the queue */ - entry = &(table->entries[table->queue_head]); - if (entry->next_in_queue == -1) - table->queue_head = table->queue_tail = -1; + /* Pop a free entry from the fifo */ + entry = &(table->entries[table->fifo_head]); + if (entry->next_in_fifo == -1) + table->fifo_head = table->fifo_tail = -1; else - table->queue_head = entry->next_in_queue; + table->fifo_head = entry->next_in_fifo; } return entry; @@ -275,25 +281,25 @@ _search_tables() _Eo_Ids_Table *table; _Eo_Id_Entry *entry; - for (Table_Index table_id = 1; table_id < MAX_IDS_TABLES; table_id++) + for (Table_Index mid_table_id = 1; mid_table_id < MAX_MID_TABLE_ID; mid_table_id++) { - if (!_eo_ids_tables[table_id]) + if (!_eo_ids_tables[mid_table_id]) { /* Allocate a new intermediate table */ - _eo_ids_tables[table_id] = _eo_id_mem_calloc(MAX_IDS_INTER_TABLES, sizeof(_Eo_Ids_Table*)); + _eo_ids_tables[mid_table_id] = _eo_id_mem_calloc(MAX_TABLE_ID, sizeof(_Eo_Ids_Table*)); } - for (Table_Index int_table_id = 0; int_table_id < MAX_IDS_INTER_TABLES; int_table_id++) + for (Table_Index table_id = 0; table_id < MAX_TABLE_ID; table_id++) { - table = ID_TABLE; + table = TABLE_FROM_IDS; if (!table) { /* Allocate a new table and reserve the first entry */ table = _eo_id_mem_calloc(1, sizeof(_Eo_Ids_Table)); table->start = 1; - table->queue_head = table->queue_tail = -1; - ID_TABLE = table; + table->fifo_head = table->fifo_tail = -1; + TABLE_FROM_IDS = table; entry = &(table->entries[0]); } else @@ -303,8 +309,8 @@ _search_tables() { /* Store table info into current table */ current_table.table = table; + current_table.mid_table_id = mid_table_id; current_table.table_id = table_id; - current_table.int_table_id = int_table_id; return entry; } } @@ -337,8 +343,8 @@ _eo_id_allocate(const _Eo *obj) entry->generation = _eo_generation_counter; _eo_generation_counter++; _eo_generation_counter %= MAX_GENERATIONS; - return EO_COMPOSE_ID(current_table.table_id, - current_table.int_table_id, + return EO_COMPOSE_ID(current_table.mid_table_id, + current_table.table_id, (entry - current_table.table->entries), entry->generation); #else @@ -353,27 +359,27 @@ _eo_id_release(const Eo_Id obj_id) _Eo_Ids_Table *table; _Eo_Id_Entry *entry; Generation_Counter generation; - Table_Index table_id, int_table_id, entry_id; - EO_DECOMPOSE_ID(obj_id, table_id, int_table_id, entry_id, generation); + Table_Index mid_table_id, table_id, entry_id; + EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation); /* Checking the validity of the entry */ - if (_eo_ids_tables[table_id] && (table = ID_TABLE)) + if (_eo_ids_tables[mid_table_id] && (table = TABLE_FROM_IDS)) { entry = &(table->entries[entry_id]); if (entry && entry->active && (entry->generation == generation)) { /* Disable the entry */ entry->active = 0; - entry->next_in_queue = -1; - /* Push the entry into the queue */ - if (table->queue_tail == -1) + entry->next_in_fifo = -1; + /* Push the entry into the fifo */ + if (table->fifo_tail == -1) { - table->queue_head = table->queue_tail = entry_id; + table->fifo_head = table->fifo_tail = entry_id; } else { - table->entries[table->queue_tail].next_in_queue = entry_id; - table->queue_tail = entry_id; + table->entries[table->fifo_tail].next_in_fifo = entry_id; + table->fifo_tail = entry_id; } return; } @@ -388,20 +394,20 @@ _eo_id_release(const Eo_Id obj_id) void _eo_free_ids_tables() { - for (Table_Index table_id = 0; table_id < MAX_IDS_TABLES; table_id++) + for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID; mid_table_id++) { - if (_eo_ids_tables[table_id]) + if (_eo_ids_tables[mid_table_id]) { - for (Table_Index int_table_id = 0; int_table_id < MAX_IDS_INTER_TABLES; int_table_id++) + for (Table_Index table_id = 0; table_id < MAX_TABLE_ID; table_id++) { - if (ID_TABLE) + if (TABLE_FROM_IDS) { - _eo_id_mem_free(ID_TABLE); + _eo_id_mem_free(TABLE_FROM_IDS); } } - _eo_id_mem_free(_eo_ids_tables[table_id]); + _eo_id_mem_free(_eo_ids_tables[mid_table_id]); } - _eo_ids_tables[table_id] = NULL; + _eo_ids_tables[mid_table_id] = NULL; } current_table.table = NULL; } @@ -412,22 +418,22 @@ _eo_print() { _Eo_Id_Entry *entry; unsigned long obj_number = 0; - for (Table_Index table_id = 0; table_id < MAX_IDS_TABLES; table_id++) + for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID; mid_table_id++) { - if (_eo_ids_tables[table_id]) + if (_eo_ids_tables[mid_table_id]) { - for (Table_Index int_table_id = 0; int_table_id < MAX_IDS_INTER_TABLES; int_table_id++) + for (Table_Index table_id = 0; table_id < MAX_TABLE_ID; table_id++) { - if (ID_TABLE) + if (TABLE_FROM_IDS) { - for (Table_Index entry_id = 0; entry_id < MAX_IDS_PER_TABLE; entry_id++) + for (Table_Index entry_id = 0; entry_id < MAX_ENTRY_ID; entry_id++) { - entry = &(ID_TABLE->entries[entry_id]); + entry = &(TABLE_FROM_IDS->entries[entry_id]); if (entry->active) { printf("%ld: %p -> (%p, %p, %p, %p)\n", obj_number++, entry->ptr, - (void *)table_id, (void *)int_table_id, (void *)entry_id, + (void *)mid_table_id, (void *)table_id, (void *)entry_id, (void *)entry->generation); } }