/*---------------------------------------------------------------------------*/ static void remove_key(nbr_table_key_t *least_used_key) { int i; for(i = 0; i < MAX_NUM_TABLES; i++) { if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { /* Call table callback for each table that uses this item */ nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { all_tables[i]->callback(removed_item); } } } /* Empty used map */ used_map[index_from_key(least_used_key)] = 0; /* Remove neighbor from list */ list_remove(nbr_table_keys, least_used_key); }
/*---------------------------------------------------------------------------*/ static nbr_table_key_t * nbr_table_allocate(void) { nbr_table_key_t *key; int least_used_count = 0; nbr_table_key_t *least_used_key = NULL; key = memb_alloc(&neighbor_addr_mem); if(key != NULL) { return key; } else { /* No more space, try to free a neighbor. * The replacement policy is the following: remove neighbor that is: * (1) not locked * (2) used by fewest tables * (3) oldest (the list is ordered by insertion time) * */ /* Get item from first key */ key = list_head(nbr_table_keys); while(key != NULL) { int item_index = index_from_key(key); int locked = locked_map[item_index]; /* Never delete a locked item */ if(!locked) { int used = used_map[item_index]; int used_count = 0; /* Count how many tables are using this item */ while(used != 0) { if((used & 1) == 1) { used_count++; } used >>= 1; } /* Find least used item */ if(least_used_key == NULL || used_count < least_used_count) { least_used_key = key; least_used_count = used_count; if(used_count == 0) { /* We won't find any least used item */ break; } } } key = list_item_next(key); } if(least_used_key == NULL) { /* We haven't found any unlocked item, allocation fails */ return NULL; } else { /* Reuse least used item */ int i; for(i = 0; i<MAX_NUM_TABLES; i++) { if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { /* Call table callback for each table that uses this item */ nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { all_tables[i]->callback(removed_item); } } } /* Empty used map */ used_map[index_from_key(least_used_key)] = 0; /* Remove neighbor from list */ list_remove(nbr_table_keys, least_used_key); /* Return associated key */ return least_used_key; } }