/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2006 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*
* Portions of this code were written by Intel Corporation.
* Copyright (C) 2011-2016 Intel Corporation. Intel provides this material
* to Argonne National Laboratory subject to Software Grant and Corporate
* Contributor License Agreement dated February 8, 2012.
*/
#ifndef CH4_PROGRESS_H_INCLUDED
#define CH4_PROGRESS_H_INCLUDED
#include "ch4_impl.h"
#undef FUNCNAME
#define FUNCNAME MPIDI_Progress_test
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPIDI_Progress_test(int flags)
{
int mpi_errno, made_progress, i;
mpi_errno = MPI_SUCCESS;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_PROGRESS_TEST);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_PROGRESS_TEST);
#ifdef HAVE_SIGNAL
if (MPIDI_CH4_Global.sigusr1_count > MPIDI_CH4_Global.my_sigusr1_count) {
MPIDI_CH4_Global.my_sigusr1_count = MPIDI_CH4_Global.sigusr1_count;
mpi_errno = MPIDI_check_for_failed_procs();
if (mpi_errno)
MPIR_ERR_POP(mpi_errno);
}
#endif
if (OPA_load_int(&MPIDI_CH4_Global.active_progress_hooks) && (flags & MPIDI_PROGRESS_HOOKS)) {
for (i = 0; i < MAX_PROGRESS_HOOKS; i++) {
progress_func_ptr_t func_ptr = NULL;
MPID_THREAD_CS_ENTER(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
if (MPIDI_CH4_Global.progress_hooks[i].active == TRUE) {
func_ptr = MPIDI_CH4_Global.progress_hooks[i].func_ptr;
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_Assert(func_ptr != NULL);
mpi_errno = func_ptr(&made_progress);
if (mpi_errno)
MPIR_ERR_POP(mpi_errno);
} else {
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
}
}
}
/* todo: progress unexp_list */
mpi_errno = MPIDI_workq_vni_progress();
if (mpi_errno != MPI_SUCCESS)
MPIR_ERR_POP(mpi_errno);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4_Global.vni_lock);
if (flags & MPIDI_PROGRESS_NM) {
mpi_errno = MPIDI_NM_progress(0, 0);
if (mpi_errno != MPI_SUCCESS) {
MPIR_ERR_POP(mpi_errno);
}
}
#ifndef MPIDI_CH4_DIRECT_NETMOD
if (flags & MPIDI_PROGRESS_SHM) {
mpi_errno = MPIDI_SHM_progress(0, 0);
if (mpi_errno != MPI_SUCCESS) {
MPIR_ERR_POP(mpi_errno);
}
}
#endif
fn_exit:
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4_Global.vni_lock);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_PROGRESS_TEST);
return mpi_errno;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_Progress_test
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPID_Progress_test(void)
{
return MPIDI_Progress_test(MPIDI_PROGRESS_ALL);
}
MPL_STATIC_INLINE_PREFIX int MPID_Progress_poke(void)
{
int ret;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_POKE);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_POKE);
ret = MPID_Progress_test();
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_POKE);
return ret;
}
MPL_STATIC_INLINE_PREFIX void MPID_Progress_start(MPID_Progress_state * state)
{
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_START);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_START);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_START);
return;
}
MPL_STATIC_INLINE_PREFIX void MPID_Progress_end(MPID_Progress_state * state)
{
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_END);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_END);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_END);
return;
}
MPL_STATIC_INLINE_PREFIX int MPID_Progress_wait(MPID_Progress_state * state)
{
int ret;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_WAIT);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_WAIT);
if (MPIDI_CH4_MT_MODEL != MPIDI_CH4_MT_DIRECT) {
ret = MPID_Progress_test();
if (unlikely(ret))
MPIR_ERR_POP(ret);
MPID_THREAD_CS_YIELD(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
goto fn_exit;
}
state->progress_count = OPA_load_int(&MPIDI_CH4_Global.progress_count);
do {
ret = MPID_Progress_test();
if (unlikely(ret))
MPIR_ERR_POP(ret);
if (state->progress_count != OPA_load_int(&MPIDI_CH4_Global.progress_count))
break;
MPID_THREAD_CS_YIELD(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
} while (1);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_WAIT);
fn_exit:
return ret;
fn_fail:
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_Progress_register
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPID_Progress_register(int (*progress_fn) (int *), int *id)
{
int mpi_errno = MPI_SUCCESS;
int i;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_REGISTER);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_REGISTER);
MPID_THREAD_CS_ENTER(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
for (i = 0; i < MAX_PROGRESS_HOOKS; i++) {
if (MPIDI_CH4_Global.progress_hooks[i].func_ptr == NULL) {
MPIDI_CH4_Global.progress_hooks[i].func_ptr = progress_fn;
MPIDI_CH4_Global.progress_hooks[i].active = FALSE;
break;
}
}
if (i >= MAX_PROGRESS_HOOKS)
goto fn_fail;
OPA_incr_int(&MPIDI_CH4_Global.active_progress_hooks);
(*id) = i;
fn_exit:
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_REGISTER);
return mpi_errno;
fn_fail:
mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
"MPID_Progress_register", __LINE__,
MPI_ERR_INTERN, "**progresshookstoomany", 0);
goto fn_exit;
}
#undef FUNCNAME
#define FUNCNAME MPID_Progress_deregister
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPID_Progress_deregister(int id)
{
int mpi_errno = MPI_SUCCESS;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_DEREGISTER);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_DEREGISTER);
MPID_THREAD_CS_ENTER(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_Assert(id >= 0);
MPIR_Assert(id < MAX_PROGRESS_HOOKS);
MPIR_Assert(MPIDI_CH4_Global.progress_hooks[id].func_ptr != NULL);
MPIDI_CH4_Global.progress_hooks[id].func_ptr = NULL;
MPIDI_CH4_Global.progress_hooks[id].active = FALSE;
OPA_decr_int(&MPIDI_CH4_Global.active_progress_hooks);
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_DEREGISTER);
return mpi_errno;
}
#undef FUNCNAME
#define FUNCNAME MPID_Progress_activate
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPID_Progress_activate(int id)
{
int mpi_errno = MPI_SUCCESS;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_ACTIVATE);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_ACTIVATE);
MPID_THREAD_CS_ENTER(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_Assert(id >= 0);
MPIR_Assert(id < MAX_PROGRESS_HOOKS);
/* Asserting that active == FALSE shouldn't be done outside the global lock
* model. With fine-grained locks, two threads might try to activate the same
* hook concurrently, in which case one of them will correctly detect that
* active == TRUE because the other thread set it.*/
if (MPIDI_CH4_Global.progress_hooks[id].active == FALSE) {
MPIR_Assert(MPIDI_CH4_Global.progress_hooks[id].func_ptr != NULL);
MPIDI_CH4_Global.progress_hooks[id].active = TRUE;
}
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_ACTIVATE);
return mpi_errno;
}
#undef FUNCNAME
#define FUNCNAME MPID_Progress_deactivate
#undef FCNAME
#define FCNAME MPL_QUOTE(FUNCNAME)
MPL_STATIC_INLINE_PREFIX int MPID_Progress_deactivate(int id)
{
int mpi_errno = MPI_SUCCESS;
MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_PROGRESS_DEACTIVATE);
MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_PROGRESS_DEACTIVATE);
MPID_THREAD_CS_ENTER(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_ENTER(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_Assert(id >= 0);
MPIR_Assert(id < MAX_PROGRESS_HOOKS);
/* We shouldn't assert that active == TRUE here for the same reasons
* as not asserting active == FALSE in Progress_activate */
if (MPIDI_CH4_Global.progress_hooks[id].active == TRUE) {
MPIR_Assert(MPIDI_CH4_Global.progress_hooks[id].func_ptr != NULL);
MPIDI_CH4_Global.progress_hooks[id].active = FALSE;
}
MPID_THREAD_CS_EXIT(VNI, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPID_THREAD_CS_EXIT(POBJ, MPIDI_CH4I_THREAD_PROGRESS_HOOK_MUTEX);
MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_PROGRESS_DEACTIVATE);
return mpi_errno;
}
#endif /* CH4_PROGRESS_H_INCLUDED */