예제 #1
0
/**
 * \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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}