static struct mm_lock_stat_set * mm_lock_get_stat_set(struct mm_lock_stat_info *info) { ASSERT(info->location != NULL); // Find the pertinent hash table bucket. uint32_t hash = mm_hash_fnv(info->location, strlen(info->location)); if (info->moreinfo != NULL) hash = mm_hash_fnv_with_seed(info->moreinfo, strlen(info->moreinfo), hash); uint32_t bucket = hash % MM_LOCK_STAT_TABLE_SIZE; // Try to find statistics optimistically (w/o acquiring a lock). struct mm_lock_stat_set *stat_set = mm_lock_find_stat_set(bucket, info->location, info->moreinfo); if (likely(stat_set != NULL)) return stat_set; // Copy identification information. char *location = mm_global_strdup(info->location); char *moreinfo = info->moreinfo == NULL ? NULL : mm_global_strdup(info->moreinfo); // Allocate a new statistics collection entry. stat_set = mm_global_alloc(sizeof(struct mm_lock_stat_set)); stat_set->location = location; stat_set->moreinfo = moreinfo; // Initialize thread statistics. mm_stack_prepare(&stat_set->domain_list); mm_stack_prepare(&stat_set->thread_list); stat_set->domain_lock = (mm_lock_t) MM_LOCK_INIT; // Start critical section. mm_global_lock(&mm_lock_stat_lock); // Try to find it again in case it was added concurrently. struct mm_lock_stat_set *recheck_stat = mm_lock_find_stat_set(bucket, location, moreinfo); if (unlikely(recheck_stat != NULL)) { // Bail out if so. mm_global_unlock(&mm_lock_stat_lock); mm_global_free(location); mm_global_free(moreinfo); mm_global_free(stat_set); return recheck_stat; } // Make the entry globally visible. stat_set->common_link.next = mm_lock_stat_list.head.next; stat_set->bucket_link.next = mm_lock_stat_table[bucket].head.next; mm_memory_store_fence(); mm_lock_stat_list.head.next = &stat_set->common_link; mm_lock_stat_table[bucket].head.next = &stat_set->bucket_link; // End critical section. mm_global_unlock(&mm_lock_stat_lock); return stat_set; }
static void mm_pool_prepare_low(struct mm_pool *pool, const char *pool_name, const struct mm_arena *arena, uint32_t item_size) { ASSERT(item_size < 0x200); if (item_size < sizeof(struct mm_slink)) item_size = sizeof(struct mm_slink); mm_verbose("make the '%s' memory pool with element size %u", pool_name, item_size); pool->item_last = 0; pool->item_size = item_size; pool->block_capacity = MM_POOL_BLOCK_SIZE / item_size; pool->block_array_used = 0; pool->block_array_size = 0; pool->arena = arena; pool->block_array = NULL; pool->block_cur_ptr = NULL; pool->block_end_ptr = NULL; mm_stack_prepare(&pool->free_list); pool->pool_name = mm_global_strdup(pool_name); }