// Allocates a new block and updates core id => block mapping. 'old_block' // points to the block that the caller thinks is attached to // 'core_id'. 'old_block' may be NULL. Returns true if: // - allocated a new block OR // - 'core_id' => 'old_block' mapping changed (another thread allocated a // block before lock was acquired). static bool cl_allocate_core_local_block(uint32_t core_id, cl_block* old_block) { // Now that we have the lock, check if core-local mapping has changed. cl_core_local_block* core_local_block = &g_log.core_local_blocks[core_id]; cl_block* block = cl_core_local_block_get_block(core_local_block); if ((block != NULL) && (block != old_block)) { return true; } if (block != NULL) { cl_core_local_block_set_block(core_local_block, NULL); cl_block_list_insert_at_tail(&g_log.dirty_block_list, block); } block = cl_allocate_block(); if (block == NULL) { return false; } cl_core_local_block_set_block(core_local_block, block); cl_block_enable_access(block); return true; }
/* Allocates a new block and updates core id => block mapping. 'old_block' points to the block that the caller thinks is attached to 'core_id'. 'old_block' may be NULL. Returns non-zero if: - allocated a new block OR - 'core_id' => 'old_block' mapping changed (another thread allocated a block before lock was acquired). */ static int cl_allocate_core_local_block(gpr_int32 core_id, cl_block *old_block) { /* Now that we have the lock, check if core-local mapping has changed. */ cl_core_local_block *core_local_block = &g_log.core_local_blocks[core_id]; cl_block *block = cl_core_local_block_get_block(core_local_block); if ((block != NULL) && (block != old_block)) { return 1; } if (block != NULL) { cl_core_local_block_set_block(core_local_block, NULL); cl_block_list_insert_at_tail(&g_log.dirty_block_list, block); } block = cl_allocate_block(); if (block == NULL) { gpr_atm_rel_store(&g_log.is_full, 1); return 0; } cl_core_local_block_set_block(core_local_block, block); cl_block_enable_access(block); return 1; }
void *census_log_start_write(size_t size) { /* Used to bound number of times block allocation is attempted. */ gpr_int32 attempts_remaining = g_log.num_blocks; /* TODO(aveitch): move this inside the do loop when current_cpu is fixed */ gpr_int32 core_id = gpr_cpu_current_cpu(); GPR_ASSERT(g_log.initialized); if (size > CENSUS_LOG_MAX_RECORD_SIZE) { return NULL; } do { int allocated; void *record = NULL; cl_block *block = cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]); if (block && (record = cl_block_start_write(block, size))) { return record; } /* Need to allocate a new block. We are here if: - No block associated with the core OR - Write in-progress on the block OR - block is out of space */ if (gpr_atm_acq_load(&g_log.is_full)) { gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } gpr_mu_lock(&g_log.lock); allocated = cl_allocate_core_local_block(core_id, block); gpr_mu_unlock(&g_log.lock); if (!allocated) { gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } } while (attempts_remaining--); /* Give up. */ gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; }