/** * \brief Persistent work function for nbc schedule progress */ pami_result_t mpidi_nbc_work_function (pami_context_t context, void *cookie) { int made_progress = 0; MPIDU_Sched_progress (&made_progress); return PAMI_EAGAIN; }
static int MPIDI_CH3i_Progress_test(void) { MPIDU_Sock_event_t event; int mpi_errno = MPI_SUCCESS; int made_progress; MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3I_PROGRESS_TEST); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3I_PROGRESS_TEST); # ifdef MPICH_IS_THREADED { /* We don't bother testing whether threads are enabled in the runtime-checking case because this simple test will always be false if threads are not enabled. */ if (MPIDI_CH3I_progress_blocked == TRUE) { /* * Another thread is already blocking in the progress engine. * We are not going to block waiting for progress, so we * simply return. It might make sense to yield before * returning, * giving the PE thread a change to make progress. * * MT: Another thread is already blocking in poll. Right now, * calls to the progress routines are effectively * serialized by the device. The only way another thread may * enter this function is if MPIDU_Sock_wait() blocks. If * this changes, a flag other than MPIDI_CH3I_Progress_blocked * may be required to determine if another thread is in * the progress engine. */ goto fn_exit; } } # endif /* make progress on NBC schedules */ mpi_errno = MPIDU_Sched_progress(&made_progress); if (mpi_errno) MPIU_ERR_POP(mpi_errno); mpi_errno = MPIDU_Sock_wait(MPIDI_CH3I_sock_set, 0, &event); if (mpi_errno == MPI_SUCCESS) { mpi_errno = MPIDI_CH3I_Progress_handle_sock_event(&event); if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**ch3|sock|handle_sock_event"); } } else if (MPIR_ERR_GET_CLASS(mpi_errno) == MPIDU_SOCK_ERR_TIMEOUT) { mpi_errno = MPI_SUCCESS; goto fn_exit; } else { MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**progress_sock_wait"); } fn_exit: MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3I_PROGRESS_TEST); return mpi_errno; fn_fail: goto fn_exit; }
static int MPIDI_CH3i_Progress_wait(MPID_Progress_state * progress_state) { MPIDU_Sock_event_t event; int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3I_PROGRESS_WAIT); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3I_PROGRESS_WAIT); /* * MT: the following code will be needed if progress can occur between * MPIDI_CH3_Progress_start() and * MPIDI_CH3_Progress_wait(), or iterations of MPIDI_CH3_Progress_wait(). * * This is presently not possible, and thus the code is commented out. */ # if 0 /* FIXME: Was (USE_THREAD_IMPL == MPICH_THREAD_IMPL_NOT_IMPLEMENTED), which really meant not-using-global-mutex-thread model . This was true for the single threaded case, but was probably not intended for that case*/ { if (progress_state->ch.completion_count != MPIDI_CH3I_progress_completion_count) { goto fn_exit; } } # endif # ifdef MPICH_IS_THREADED MPIU_THREAD_CHECK_BEGIN { if (MPIDI_CH3I_progress_blocked == TRUE) { /* * Another thread is already blocking in the progress engine. * * MT: Another thread is already blocking in poll. Right now, * calls to MPIDI_CH3_Progress_wait() are effectively * serialized by the device. The only way another thread may * enter this function is if MPIDU_Sock_wait() blocks. If * this changes, a flag other than MPIDI_CH3I_Progress_blocked * may be required to determine if another thread is in * the progress engine. */ MPIDI_CH3I_Progress_delay(MPIDI_CH3I_progress_completion_count); goto fn_exit; } } MPIU_THREAD_CHECK_END # endif do { int made_progress = FALSE; /* make progress on NBC schedules, must come before we block on sock_wait */ mpi_errno = MPIDU_Sched_progress(&made_progress); if (mpi_errno) MPIU_ERR_POP(mpi_errno); if (made_progress) { MPIDI_CH3_Progress_signal_completion(); break; } # ifdef MPICH_IS_THREADED /* The logic for this case is just complicated enough that we write separate code for each possibility */ # ifdef HAVE_RUNTIME_THREADCHECK if (MPIR_ThreadInfo.isThreaded) { MPIDI_CH3I_progress_blocked = TRUE; mpi_errno = MPIDU_Sock_wait(MPIDI_CH3I_sock_set, MPIDU_SOCK_INFINITE_TIME, &event); MPIDI_CH3I_progress_blocked = FALSE; MPIDI_CH3I_progress_wakeup_signalled = FALSE; } else { mpi_errno = MPIDU_Sock_wait(MPIDI_CH3I_sock_set, MPIDU_SOCK_INFINITE_TIME, &event); } # else MPIDI_CH3I_progress_blocked = TRUE; mpi_errno = MPIDU_Sock_wait(MPIDI_CH3I_sock_set, MPIDU_SOCK_INFINITE_TIME, &event); MPIDI_CH3I_progress_blocked = FALSE; MPIDI_CH3I_progress_wakeup_signalled = FALSE; # endif /* HAVE_RUNTIME_THREADCHECK */ # else mpi_errno = MPIDU_Sock_wait(MPIDI_CH3I_sock_set, MPIDU_SOCK_INFINITE_TIME, &event); # endif /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) { MPIU_Assert(MPIR_ERR_GET_CLASS(mpi_errno) != MPIDU_SOCK_ERR_TIMEOUT); MPIU_ERR_SET(mpi_errno,MPI_ERR_OTHER,"**progress_sock_wait"); goto fn_fail; } /* --END ERROR HANDLING-- */ mpi_errno = MPIDI_CH3I_Progress_handle_sock_event(&event); if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**ch3|sock|handle_sock_event"); } } while (progress_state->ch.completion_count == MPIDI_CH3I_progress_completion_count); /* * We could continue to call MPIU_Sock_wait in a non-blocking fashion * and process any other events; however, this would not * give the application a chance to post new receives, and thus could * result in an increased number of unexpected messages * that would need to be buffered. */ # if MPICH_IS_THREADED { /* * Awaken any threads which are waiting for the progress that just * occurred */ MPIDI_CH3I_Progress_continue(MPIDI_CH3I_progress_completion_count); } # endif fn_exit: /* * Reset the progress state so it is fresh for the next iteration */ progress_state->ch.completion_count = MPIDI_CH3I_progress_completion_count; MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3I_PROGRESS_WAIT); return mpi_errno; fn_fail: goto fn_exit; }