embb_counter_t* embb_thread_index_counter() { int compare_to = 0; if (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) { if (embb_atomic_compare_and_swap_int( &embb_thread_index_counter_flag, &compare_to, 1)) { embb_counter_init(&embb_thread_index_counter_index); embb_atomic_store_int(&embb_thread_index_counter_flag, 2); } while (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) {} } return &embb_thread_index_counter_index; }
unsigned int* embb_max_number_thread_indices() { int compare_to = 0; if (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) { if (embb_atomic_compare_and_swap_int( &embb_max_number_thread_indices_flag, &compare_to, 1)) { embb_max_number_thread_indices_max = (int)(embb_core_count_available() * 2); embb_atomic_store_int(&embb_max_number_thread_indices_flag, 2); } while (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) {} } return (unsigned int*) &embb_max_number_thread_indices_max; }
mtapi_boolean_t embb_mtapi_thread_context_start( embb_mtapi_thread_context_t* that, embb_mtapi_scheduler_t * scheduler) { int err; embb_mtapi_scheduler_worker_func_t * worker_func; embb_core_set_t core_set; assert(MTAPI_NULL != that); assert(MTAPI_NULL != scheduler); worker_func = embb_mtapi_scheduler_worker_func(scheduler); /* pin thread to core */ embb_core_set_init(&core_set, 0); embb_core_set_add(&core_set, that->core_num); /* create thread */ if (that->is_main_thread) { /* reuse main thread */ that->thread = embb_thread_current(); err = embb_tss_create(&that->tss_id); if (EMBB_SUCCESS != err) { /* report error to scheduler */ embb_atomic_store_int(&that->run, -1); return MTAPI_FALSE; } embb_tss_set(&(that->tss_id), that); embb_atomic_store_int(&that->run, 1); } else { err = embb_thread_create_with_priority( &that->thread, &core_set, that->thread_priority, worker_func, that); if (EMBB_SUCCESS != err) { embb_mtapi_log_error( "embb_mtapi_ThreadContext_initializeWithNodeAndCoreNumber() could not " "create thread %d on core %d\n", that->worker_index, that->core_num); return MTAPI_FALSE; } /* wait for worker to come up */ while (0 == embb_atomic_load_int(&that->run)) { embb_thread_yield(); } } if (0 < embb_atomic_load_int(&that->run)) { return MTAPI_TRUE; } else { return MTAPI_FALSE; } }
void mtapi_group_delete( MTAPI_IN mtapi_group_hndl_t group, MTAPI_OUT mtapi_status_t* status) { mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; if (embb_mtapi_node_is_initialized()) { embb_mtapi_node_t* node = embb_mtapi_node_get_instance(); if (embb_mtapi_group_pool_is_handle_valid(node->group_pool, group)) { embb_mtapi_group_t* local_group = embb_mtapi_group_pool_get_storage_for_handle( node->group_pool, group); if (embb_atomic_load_int(&local_group->deleted)) { local_status = MTAPI_ERR_GROUP_INVALID; } else { embb_mtapi_group_finalize(local_group); embb_mtapi_group_pool_deallocate(node->group_pool, local_group); local_status = MTAPI_SUCCESS; } } else { local_status = MTAPI_ERR_GROUP_INVALID; } } else { local_status = MTAPI_ERR_NODE_NOTINIT; } mtapi_status_set(status, local_status); }
mtapi_task_state_t mtapi_context_taskstate_get( MTAPI_IN mtapi_task_context_t* task_context, MTAPI_OUT mtapi_status_t* status) { mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; mtapi_task_state_t task_state = MTAPI_TASK_ERROR; embb_mtapi_log_trace("mtapi_context_taskstate_get() called\n"); if (MTAPI_NULL != task_context) { embb_mtapi_thread_context_t* local_context = (embb_mtapi_thread_context_t*)embb_tss_get( &(task_context->thread_context->tss_id)); if (local_context == task_context->thread_context) { task_state = (mtapi_task_state_t)embb_atomic_load_int( &task_context->task->state); local_status = MTAPI_SUCCESS; } else { local_status = MTAPI_ERR_CONTEXT_OUTOFCONTEXT; } } else { local_status = MTAPI_ERR_CONTEXT_INVALID; } mtapi_status_set(status, local_status); return task_state; }
void embb_mtapi_thread_context_stop(embb_mtapi_thread_context_t* that) { int result; if (0 < embb_atomic_load_int(&that->run)) { embb_atomic_store_int(&that->run, 0); embb_condition_notify_one(&that->work_available); if (MTAPI_FALSE == that->is_main_thread) { embb_thread_join(&(that->thread), &result); } } }
void mtapi_action_disable( MTAPI_IN mtapi_action_hndl_t action, MTAPI_IN mtapi_timeout_t timeout, MTAPI_OUT mtapi_status_t* status) { mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; embb_mtapi_log_trace("mtapi_action_disable() called\n"); if (embb_mtapi_node_is_initialized()) { embb_mtapi_node_t* node = embb_mtapi_node_get_instance(); if (embb_mtapi_action_pool_is_handle_valid(node->action_pool, action)) { embb_mtapi_action_t* local_action = embb_mtapi_action_pool_get_storage_for_handle( node->action_pool, action); local_action->enabled = MTAPI_FALSE; embb_mtapi_thread_context_t * context = NULL; embb_duration_t wait_duration; embb_time_t end_time; if (MTAPI_INFINITE < timeout) { embb_duration_set_milliseconds( &wait_duration, (unsigned long long)timeout); embb_time_in(&end_time, &wait_duration); } /* cancel all tasks */ embb_mtapi_scheduler_process_tasks( node->scheduler, embb_mtapi_action_disable_visitor, local_action); /* find out on which thread we are */ context = embb_mtapi_scheduler_get_current_thread_context( node->scheduler); local_status = MTAPI_SUCCESS; while (embb_atomic_load_int(&local_action->num_tasks)) { if (MTAPI_INFINITE < timeout) { embb_time_t current_time; embb_time_now(¤t_time); if (embb_time_compare(¤t_time, &end_time) > 0) { /* timeout! */ local_status = MTAPI_TIMEOUT; break; } } /* do other work if applicable */ embb_mtapi_scheduler_execute_task_or_yield( node->scheduler, node, context); } } else { local_status = MTAPI_ERR_ACTION_INVALID; } } else { embb_mtapi_log_error("mtapi not initialized\n"); local_status = MTAPI_ERR_NODE_NOTINIT; } mtapi_status_set(status, local_status); }
void mtapi_group_wait_any( MTAPI_IN mtapi_group_hndl_t group, MTAPI_OUT void** result, MTAPI_IN mtapi_timeout_t timeout, MTAPI_OUT mtapi_status_t* status) { mtapi_status_t local_status = MTAPI_ERR_UNKNOWN; embb_mtapi_log_trace("mtapi_group_wait_any() called\n"); if (embb_mtapi_node_is_initialized()) { embb_mtapi_node_t* node = embb_mtapi_node_get_instance(); if (embb_mtapi_group_pool_is_handle_valid(node->group_pool, group)) { embb_mtapi_group_t* local_group = embb_mtapi_group_pool_get_storage_for_handle( node->group_pool, group); embb_mtapi_task_t* local_task; /* are there any tasks left? */ if (0 == embb_atomic_load_int(&local_group->num_tasks)) { /* group becomes invalid, so delete it */ mtapi_group_delete(group, &local_status); local_status = MTAPI_GROUP_COMPLETED; } else { embb_mtapi_thread_context_t * context = NULL; embb_duration_t wait_duration; embb_time_t end_time; if (MTAPI_INFINITE < timeout) { embb_duration_set_milliseconds( &wait_duration, (unsigned long long)timeout); embb_time_in(&end_time, &wait_duration); } /* find out on which thread we are */ context = embb_mtapi_scheduler_get_current_thread_context( node->scheduler); /* wait for any task to arrive */ local_status = MTAPI_SUCCESS; local_task = embb_mtapi_task_queue_pop(&local_group->queue); while (MTAPI_NULL == local_task) { if (MTAPI_INFINITE < timeout) { embb_time_t current_time; embb_time_now(¤t_time); if (embb_time_compare(¤t_time, &end_time) > 0) { /* timeout! */ local_status = MTAPI_TIMEOUT; break; } } /* do other work if applicable */ embb_mtapi_scheduler_execute_task_or_yield( node->scheduler, node, context); /* try to pop a task from the group queue */ local_task = embb_mtapi_task_queue_pop(&local_group->queue); } /* was there a timeout, or is there a result? */ if (MTAPI_NULL != local_task) { /* store result */ if (MTAPI_NULL != result) { *result = local_task->result_buffer; } /* return error code set by the task */ local_status = local_task->error_code; /* delete task */ embb_mtapi_task_delete(local_task, node->task_pool); embb_atomic_fetch_and_add_int(&local_group->num_tasks, -1); } } } else { local_status = MTAPI_ERR_GROUP_INVALID; } } else { embb_mtapi_log_error("mtapi not initialized\n"); local_status = MTAPI_ERR_NODE_NOTINIT; } mtapi_status_set(status, local_status); embb_mtapi_log_trace("mtapi_group_wait_any() returns\n"); }