/*@ MPI_T_init_thread - Initialize the MPI_T execution environment Input Parameters: . required - desired level of thread support (integer) Output Parameters: . provided - provided level of thread support (integer) Notes: The valid values for the level of thread support are: + MPI_THREAD_SINGLE - Only one thread will execute. . MPI_THREAD_FUNNELED - The process may be multi-threaded, but only the main thread will make MPI_T calls (all MPI_T calls are funneled to the main thread). . MPI_THREAD_SERIALIZED - The process may be multi-threaded, and multiple threads may make MPI_T calls, but only one at a time: MPI_T calls are not made concurrently from two distinct threads (all MPI_T calls are serialized). - MPI_THREAD_MULTIPLE - Multiple threads may call MPI_T, with no restrictions. .N ThreadSafe .N Errors .N MPI_SUCCESS .seealso MPI_T_finalize @*/ int MPI_T_init_thread(int required, int *provided) { int mpi_errno = MPI_SUCCESS; MPID_MPI_STATE_DECL(MPID_STATE_MPI_T_INIT_THREAD); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_T_INIT_THREAD); /* ... body of routine ... */ #if defined MPICH_IS_THREADED MPIR_T_is_threaded = (required == MPI_THREAD_MULTIPLE); #endif /* MPICH_IS_THREADED */ if (provided != NULL) { /* This must be min(required,MPICH_THREAD_LEVEL) if runtime control of thread level is available */ *provided = (MPICH_THREAD_LEVEL < required) ? MPICH_THREAD_LEVEL : required; } ++MPIR_T_init_balance; if (MPIR_T_init_balance == 1) { MPIR_T_THREAD_CS_INIT(); MPIR_T_env_init(); } /* ... end of body of routine ... */ fn_exit: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_T_INIT_THREAD); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_t_init_thread", "**mpi_t_init_thread %d %p", required, provided); } # endif mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Init_thread - Initialize the MPI execution environment Input Parameters: + argc - Pointer to the number of arguments . argv - Pointer to the argument vector - required - Level of desired thread support Output Parameters: . provided - Level of provided thread support Command line arguments: MPI specifies no command-line arguments but does allow an MPI implementation to make use of them. See 'MPI_INIT' for a description of the command line arguments supported by 'MPI_INIT' and 'MPI_INIT_THREAD'. Notes: The valid values for the level of thread support are\: + MPI_THREAD_SINGLE - Only one thread will execute. . MPI_THREAD_FUNNELED - The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are funneled to the main thread). . MPI_THREAD_SERIALIZED - The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are serialized). - MPI_THREAD_MULTIPLE - Multiple threads may call MPI, with no restrictions. Notes for Fortran: Note that the Fortran binding for this routine does not have the 'argc' and 'argv' arguments. ('MPI_INIT_THREAD(required, provided, ierror)') .N Errors .N MPI_SUCCESS .N MPI_ERR_OTHER .seealso: MPI_Init, MPI_Finalize @*/ int MPI_Init_thread(int *argc, char ***argv, int required, int *provided) { int mpi_errno = MPI_SUCCESS; int rc ATTRIBUTE((unused)), reqd = required; MPIR_FUNC_TERSE_INIT_STATE_DECL(MPID_STATE_MPI_INIT_THREAD); rc = MPID_Wtime_init(); #ifdef MPL_USE_DBG_LOGGING MPL_dbg_pre_init(argc, argv, rc); #endif MPIR_FUNC_TERSE_INIT_ENTER(MPID_STATE_MPI_INIT_THREAD); #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { if (OPA_load_int(&MPIR_Process.mpich_state) != MPICH_MPI_STATE__PRE_INIT) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPI_Init_thread", __LINE__, MPI_ERR_OTHER, "**inittwice", 0); } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ /* Temporarily disable thread-safety. This is needed because the * mutexes are not initialized yet, and we don't want to * accidentally use them before they are initialized. We will * reset this value once it is properly initialized. */ #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = 0; #endif /* MPICH_IS_THREADED */ MPIR_T_env_init(); /* If the user requested for asynchronous progress, request for * THREAD_MULTIPLE. */ if (MPIR_CVAR_ASYNC_PROGRESS) reqd = MPI_THREAD_MULTIPLE; mpi_errno = MPIR_Init_thread(argc, argv, reqd, provided); if (mpi_errno != MPI_SUCCESS) goto fn_fail; if (MPIR_CVAR_ASYNC_PROGRESS) { #if MPL_THREAD_PACKAGE_NAME == MPL_THREAD_PACKAGE_ARGOBOTS printf("WARNING: Asynchronous progress is not supported with Argobots\n"); goto fn_fail; #else if (*provided == MPI_THREAD_MULTIPLE) { mpi_errno = MPID_Init_async_thread(); if (mpi_errno) goto fn_fail; MPIR_async_thread_initialized = 1; } else { printf("WARNING: No MPI_THREAD_MULTIPLE support (needed for async progress)\n"); } #endif } /* ... end of body of routine ... */ MPIR_FUNC_TERSE_INIT_EXIT(MPID_STATE_MPI_INIT_THREAD); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_REPORTING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER, "**mpi_init_thread", "**mpi_init_thread %p %p %d %p", argc, argv, required, provided); } #endif mpi_errno = MPIR_Err_return_comm(0, __func__, mpi_errno); MPIR_FUNC_TERSE_INIT_EXIT(MPID_STATE_MPI_INIT_THREAD); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; /* --END ERROR HANDLING-- */ }