/** * @ingroup SELF * @brief Check if the caller is the primary ULT. * * \c ABT_self_is_primary() confirms whether the caller is the primary ULT and * returns the result through \c flag. * If the caller is the primary ULT, \c flag is set to \c ABT_TRUE. * Otherwise, \c flag is set to \c ABT_FALSE. * * @param[out] flag result (<tt>ABT_TRUE</tt>: primary ULT, * <tt>ABT_FALSE</tt>: not) * @return Error code * @retval ABT_SUCCESS on success * @retval ABT_ERR_UNINITIALIZED Argobots has not been initialized * @retval ABT_ERR_INV_XSTREAM called by an external thread, e.g., pthread * @retval ABT_ERR_INV_THREAD called by a tasklet */ int ABT_self_is_primary(ABT_bool *flag) { int abt_errno = ABT_SUCCESS; ABTI_thread *p_thread; /* If Argobots has not been initialized, set flag to ABT_FALSE. */ if (gp_ABTI_global == NULL) { abt_errno = ABT_ERR_UNINITIALIZED; *flag = ABT_FALSE; goto fn_exit; } /* This is when an external thread called this routine. */ if (lp_ABTI_local == NULL) { abt_errno = ABT_ERR_INV_XSTREAM; *flag = ABT_FALSE; goto fn_exit; } p_thread = ABTI_local_get_thread(); if (p_thread) { *flag = (p_thread->type == ABTI_THREAD_TYPE_MAIN) ? ABT_TRUE : ABT_FALSE; } else { abt_errno = ABT_ERR_INV_THREAD; *flag = ABT_FALSE; } fn_exit: return abt_errno; }
void ABTD_thread_func_wrapper(int func_upper, int func_lower, int arg_upper, int arg_lower) { void (*thread_func)(void *); void *p_arg; size_t ptr_size, int_size; ptr_size = sizeof(void *); int_size = sizeof(int); if (ptr_size == int_size) { thread_func = (void (*)(void *))(uintptr_t)func_lower; p_arg = (void *)(uintptr_t)arg_lower; } else if (ptr_size == int_size * 2) { uintptr_t shift_bits = CHAR_BIT * int_size; uintptr_t mask = ((uintptr_t)1 << shift_bits) - 1; thread_func = (void (*)(void *))( ((uintptr_t)func_upper << shift_bits) | ((uintptr_t)func_lower & mask)); p_arg = (void *)( ((uintptr_t)arg_upper << shift_bits) | ((uintptr_t)arg_lower & mask)); } else { ABTI_ASSERT(0); } thread_func(p_arg); /* Now, the ULT has finished its job. Terminate the ULT. * We don't need to use the atomic operation here because the ULT will be * terminated regardless of other requests. */ ABTI_thread *p_thread = ABTI_local_get_thread(); p_thread->request |= ABTI_THREAD_REQ_TERMINATE; }
void ABTI_log_event(FILE *fh, const char *format, ...) { if (gp_ABTI_global->use_logging == ABT_FALSE) return; ABT_unit_type type; ABTI_xstream *p_xstream = NULL; ABTI_thread *p_thread = NULL; ABTI_task *p_task = NULL; char *prefix_fmt = NULL, *prefix = NULL; char *newfmt; size_t tid, rank; int tid_len = 0, rank_len = 0; size_t newfmt_len; ABT_self_get_type(&type); switch (type) { case ABT_UNIT_TYPE_THREAD: p_xstream = ABTI_local_get_xstream(); p_thread = ABTI_local_get_thread(); if (p_thread == NULL) { if (p_xstream && p_xstream->type != ABTI_XSTREAM_TYPE_PRIMARY) { prefix_fmt = "<U%" PRIu64 ":E%" PRIu64 "> %s"; rank = p_xstream->rank; tid = 0; } else { prefix = "<U0:E0> "; prefix_fmt = "%s%s"; } } else { rank = p_xstream->rank; if (lp_ABTI_log->p_sched) { prefix_fmt = "<S%" PRIu64 ":E%" PRIu64 "> %s"; tid = lp_ABTI_log->p_sched->id; } else { prefix_fmt = "<U%" PRIu64 ":E%" PRIu64 "> %s"; tid = ABTI_thread_get_id(p_thread); } } break; case ABT_UNIT_TYPE_TASK: p_xstream = ABTI_local_get_xstream(); rank = p_xstream->rank; p_task = ABTI_local_get_task(); if (lp_ABTI_log->p_sched) { prefix_fmt = "<S%" PRIu64 ":E%" PRIu64 "> %s"; tid = lp_ABTI_log->p_sched->id; } else { prefix_fmt = "<T%" PRIu64 ":E%" PRIu64 "> %s"; tid = ABTI_task_get_id(p_task); } break; case ABT_UNIT_TYPE_EXT: prefix = "<EXT> "; prefix_fmt = "%s%s"; break; default: prefix = "<UNKNOWN> "; prefix_fmt = "%s%s"; break; } if (prefix == NULL) { tid_len = ABTU_get_int_len(tid); rank_len = ABTU_get_int_len(rank); newfmt_len = 6 + tid_len + rank_len + strlen(format); newfmt = (char *)ABTU_malloc(newfmt_len + 1); sprintf(newfmt, prefix_fmt, tid, rank, format); } else { newfmt_len = strlen(prefix) + strlen(format); newfmt = (char *)ABTU_malloc(newfmt_len + 1); sprintf(newfmt, prefix_fmt, prefix, format); } va_list list; va_start(list, format); vfprintf(fh, newfmt, list); va_end(list); fflush(fh); ABTU_free(newfmt); }
/** * @ingroup COND * @brief Wait on the condition. * * The ULT calling \c ABT_cond_wait() waits on the condition variable until * it is signaled. * The user should call this routine while the mutex specified as \c mutex is * locked. The mutex will be automatically released while waiting. After signal * is received and the waiting ULT is awakened, the mutex will be * automatically locked for use by the ULT. The user is then responsible for * unlocking mutex when the ULT is finished with it. * * @param[in] cond handle to the condition variable * @param[in] mutex handle to the mutex * @return Error code * @retval ABT_SUCCESS on success */ int ABT_cond_wait(ABT_cond cond, ABT_mutex mutex) { int abt_errno = ABT_SUCCESS; ABTI_cond *p_cond = ABTI_cond_get_ptr(cond); ABTI_CHECK_NULL_COND_PTR(p_cond); ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex); ABTI_CHECK_NULL_MUTEX_PTR(p_mutex); ABTI_thread *p_thread; ABTI_unit *p_unit; ABT_unit_type type; volatile int ext_signal = 0; if (lp_ABTI_local != NULL) { p_thread = ABTI_local_get_thread(); ABTI_CHECK_TRUE(p_thread != NULL, ABT_ERR_COND); type = ABT_UNIT_TYPE_THREAD; p_unit = &p_thread->unit_def; p_unit->thread = ABTI_thread_get_handle(p_thread); p_unit->type = type; } else { /* external thread */ type = ABT_UNIT_TYPE_EXT; p_unit = (ABTI_unit *)ABTU_calloc(1, sizeof(ABTI_unit)); p_unit->pool = (ABT_pool)&ext_signal; p_unit->type = type; } ABTI_mutex_spinlock(&p_cond->mutex); if (p_cond->p_waiter_mutex == NULL) { p_cond->p_waiter_mutex = p_mutex; } else { ABT_bool result = ABTI_mutex_equal(p_cond->p_waiter_mutex, p_mutex); if (result == ABT_FALSE) { ABTI_mutex_unlock(&p_cond->mutex); abt_errno = ABT_ERR_INV_MUTEX; goto fn_fail; } } if (p_cond->num_waiters == 0) { p_unit->p_prev = p_unit; p_unit->p_next = p_unit; p_cond->p_head = p_unit; p_cond->p_tail = p_unit; } else { p_cond->p_tail->p_next = p_unit; p_cond->p_head->p_prev = p_unit; p_unit->p_prev = p_cond->p_tail; p_unit->p_next = p_cond->p_head; p_cond->p_tail = p_unit; } p_cond->num_waiters++; if (type == ABT_UNIT_TYPE_THREAD) { /* Change the ULT's state to BLOCKED */ ABTI_thread_set_blocked(p_thread); ABTI_mutex_unlock(&p_cond->mutex); /* Unlock the mutex that the calling ULT is holding */ /* FIXME: should check if mutex was locked by the calling ULT */ ABTI_mutex_unlock(p_mutex); /* Suspend the current ULT */ ABTI_thread_suspend(p_thread); } else { /* TYPE == ABT_UNIT_TYPE_EXT */ ABTI_mutex_unlock(&p_cond->mutex); ABTI_mutex_unlock(p_mutex); /* External thread is waiting here polling ext_signal. */ /* FIXME: need a better implementation */ while (!ext_signal) { } ABTU_free(p_unit); } /* Lock the mutex again */ ABTI_mutex_spinlock(p_mutex); fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }