/* FIXME: this is not a scalable algorithm because everyone is polling on the same cacheline */ int MPID_nem_barrier(void) { int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_BARRIER); MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_BARRIER); if (MPID_nem_mem_region.num_local == 1) goto fn_exit; MPIR_ERR_CHKINTERNAL(!barrier_init, mpi_errno, "barrier not initialized"); if (OPA_fetch_and_incr_int(&MPID_nem_mem_region.barrier->val) == MPID_nem_mem_region.num_local - 1) { OPA_store_int(&MPID_nem_mem_region.barrier->val, 0); OPA_store_int(&MPID_nem_mem_region.barrier->wait, 1 - sense); OPA_write_barrier(); } else { /* wait */ while (OPA_load_int(&MPID_nem_mem_region.barrier->wait) == sense) MPL_sched_yield(); /* skip */ } sense = 1 - sense; fn_fail: fn_exit: MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_BARRIER); return mpi_errno; }
static void nbglReleaseSceneLocks(scene_t* scene) { OPA_store_int(&scene->paused, 0); OPA_store_int(&scene->blockSimulationOnGraphics, 0); OPA_store_int(&scene->attachedLock, 0); /* Set this last */ OPA_store_int(&scene->attachedPID, 0); }
static int nbglGetExclusiveSceneAccess(scene_t* scene) { int pid = (int) getpid(); int oldPID = OPA_cas_int(&scene->attachedLock, 0, pid); if (oldPID != 0) { if (mwProcessIsAlive(oldPID)) { mw_printf("Could not get exclusive access to simulation shared segment " "(Owned by process %d)\n", oldPID); return 1; } else { mw_printf("Simulation shared segment owned by dead process %d, stealing it\n", oldPID); /* Process is dead, steal the lock */ nbglReleaseSceneLocks(scene); return 0; } } else { OPA_store_int(&scene->attachedPID, 0); return 0; } }
int MPID_nem_barrier_init(MPID_nem_barrier_t *barrier_region, int init_values) { MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_BARRIER_INIT); MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_BARRIER_INIT); MPID_nem_mem_region.barrier = barrier_region; if (init_values) { OPA_store_int(&MPID_nem_mem_region.barrier->val, 0); OPA_store_int(&MPID_nem_mem_region.barrier->wait, 0); OPA_write_barrier(); } sense = 0; barrier_init = 1; MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_BARRIER_INIT); return MPI_SUCCESS; }
int MPIDI_POSIX_barrier_vars_init(MPIDI_POSIX_barrier_vars_t * barrier_region) { int mpi_errno = MPI_SUCCESS; int i; MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_POSIX_BARRIER_VARS_INIT); MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_POSIX_BARRIER_VARS_INIT); if (MPIDI_POSIX_mem_region.local_rank == 0) for (i = 0; i < MPIDI_POSIX_NUM_BARRIER_VARS; ++i) { OPA_store_int(&barrier_region[i].context_id, -1); OPA_store_int(&barrier_region[i].usage_cnt, 0); OPA_store_int(&barrier_region[i].cnt, 0); OPA_store_int(&barrier_region[i].sig0, 0); OPA_store_int(&barrier_region[i].sig, 0); } MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_POSIX_BARRIER_VARS_INIT); return mpi_errno; }
int MPIDU_shm_barrier_init(MPIDU_shm_barrier_t * barrier_region, MPIDU_shm_barrier_t ** barrier, int init_values) { MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDU_SHM_BARRIER_INIT); MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDU_SHM_BARRIER_INIT); *barrier = barrier_region; if (init_values) { OPA_store_int(&(*barrier)->val, 0); OPA_store_int(&(*barrier)->wait, 0); OPA_write_barrier(); } sense = 0; barrier_init = 1; MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDU_SHM_BARRIER_INIT); return MPI_SUCCESS; }
int MPIDIG_init(MPIR_Comm * comm_world, MPIR_Comm * comm_self, int n_vcis) { int mpi_errno = MPI_SUCCESS; MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDIG_INIT); MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDIG_INIT); MPIDI_global.is_ch4u_initialized = 0; MPIDI_global.comm_req_lists = (MPIDIG_comm_req_list_t *) MPL_calloc(MPIR_MAX_CONTEXT_MASK * MPIR_CONTEXT_INT_BITS, sizeof(MPIDIG_comm_req_list_t), MPL_MEM_OTHER); #ifndef MPIDI_CH4U_USE_PER_COMM_QUEUE MPIDI_global.posted_list = NULL; MPIDI_global.unexp_list = NULL; #endif MPIDI_global.cmpl_list = NULL; OPA_store_int(&MPIDI_global.exp_seq_no, 0); OPA_store_int(&MPIDI_global.nxt_seq_no, 0); MPIDI_global.buf_pool = MPIDIU_create_buf_pool(MPIDIU_BUF_POOL_NUM, MPIDIU_BUF_POOL_SZ); MPIR_Assert(MPIDI_global.buf_pool); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SEND, &MPIDIG_send_origin_cb, &MPIDIG_send_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SEND_LONG_REQ, NULL /* Injection only */ , &MPIDIG_send_long_req_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SEND_LONG_ACK, NULL /* Injection only */ , &MPIDIG_send_long_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SEND_LONG_LMT, &MPIDIG_send_long_lmt_origin_cb, &MPIDIG_send_long_lmt_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SSEND_REQ, &MPIDIG_send_origin_cb, &MPIDIG_ssend_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_SSEND_ACK, &MPIDIG_ssend_ack_origin_cb, &MPIDIG_ssend_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_PUT_REQ, &MPIDIG_put_origin_cb, &MPIDIG_put_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_PUT_ACK, NULL, &MPIDIG_put_ack_taget_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_REQ, &MPIDIG_get_origin_cb, &MPIDIG_get_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACK, &MPIDIG_get_ack_origin_cb, &MPIDIG_get_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_CSWAP_REQ, &MPIDIG_cswap_origin_cb, &MPIDIG_cswap_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_CSWAP_ACK, &MPIDIG_cswap_ack_origin_cb, &MPIDIG_cswap_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_ACC_REQ, &MPIDIG_acc_origin_cb, &MPIDIG_acc_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACC_REQ, &MPIDIG_get_acc_origin_cb, &MPIDIG_get_acc_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_ACC_ACK, NULL, &MPIDIG_acc_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACC_ACK, &MPIDIG_get_acc_ack_origin_cb, &MPIDIG_get_acc_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_COMPLETE, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_POST, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_LOCK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_LOCK_ACK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_UNLOCK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_UNLOCK_ACK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_LOCKALL, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_LOCKALL_ACK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_UNLOCKALL, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_WIN_UNLOCKALL_ACK, NULL, &MPIDIG_win_ctrl_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_PUT_IOV_REQ, &MPIDIG_put_iov_origin_cb, &MPIDIG_put_iov_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_PUT_IOV_ACK, NULL, &MPIDIG_put_iov_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_PUT_DAT_REQ, &MPIDIG_put_data_origin_cb, &MPIDIG_put_data_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_ACC_IOV_REQ, &MPIDIG_acc_iov_origin_cb, &MPIDIG_acc_iov_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACC_IOV_REQ, &MPIDIG_get_acc_iov_origin_cb, &MPIDIG_get_acc_iov_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_ACC_IOV_ACK, NULL, &MPIDIG_acc_iov_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACC_IOV_ACK, NULL, &MPIDIG_get_acc_iov_ack_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_ACC_DAT_REQ, &MPIDIG_acc_data_origin_cb, &MPIDIG_acc_data_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_GET_ACC_DAT_REQ, &MPIDIG_get_acc_data_origin_cb, &MPIDIG_get_acc_data_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_am_reg_cb(MPIDIG_COMM_ABORT, &MPIDIG_comm_abort_origin_cb, &MPIDIG_comm_abort_target_msg_cb); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_init_comm(comm_world); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_init_comm(comm_self); if (mpi_errno) MPIR_ERR_POP(mpi_errno); MPIDIU_map_create((void **) &(MPIDI_global.win_map), MPL_MEM_RMA); mpi_errno = MPIDIG_RMA_Init_sync_pvars(); if (mpi_errno) MPIR_ERR_POP(mpi_errno); mpi_errno = MPIDIG_RMA_Init_targetcb_pvars(); if (mpi_errno) MPIR_ERR_POP(mpi_errno); MPIDI_global.is_ch4u_initialized = 1; MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDIG_INIT); fn_exit: return mpi_errno; fn_fail: goto fn_exit; }
static scene_t* nbglLoadStaticSceneFromFile(const char* filename) { FILE* f; size_t lnCount; /* ~= nbody */ size_t line = 0; int nbody = 0; char lnBuf[4096]; int rc = 0; int ignore; double x, y, z; double vx, vy, vz; double lambda; FloatPos* r; int hasError = FALSE; scene_t* scene = NULL; f = fopen(filename, "r"); if (!f) { mwPerror("Failed to open file '%s'", filename); return NULL; } lnCount = mwCountLinesInFile(f); if (lnCount == 0) { mw_printf("Error counting lines from file '%s'\n", filename); fclose(f); return NULL; } scene = mwCalloc(sizeof(scene_t) + 1 * (lnCount * sizeof(FloatPos)), sizeof(char)); /* We don't need the buffering features so just use first buffer slot */ r = &scene->queue.bodyData[0]; scene->hasInfo = FALSE; scene->staticScene = TRUE; /* Make read data fake that we have 1 element in the queue */ OPA_store_int(&scene->queue.head, 0); OPA_store_int(&scene->queue.tail, 1); readCoordinateSystem = FALSE; readHasGalaxy = FALSE; readCenterOfMass = FALSE; while (fgets(lnBuf, (int) sizeof(lnBuf), f) && line < lnCount) { ++line; if (strlen(lnBuf) + 1 >= sizeof(lnBuf)) { mw_printf("Error reading histogram line "ZU" (Line buffer too small): %s", line, lnBuf); hasError = TRUE; break; } /* Skip comments and blank lines */ if (lnBuf[0] == '#' || lnBuf[0] == '\n') continue; if (nbglTryReadSceneItems(lnBuf, scene)) continue; rc = sscanf(lnBuf, "%d , %lf , %lf , %lf , %lf , %lf , %lf ", &ignore, &x, &y, &z, &vx, &vy, &vz); if (rc == 7) { /* May or may not be there */ rc = sscanf(lnBuf, " , %lf \n", &lambda); if (rc != 1) { sscanf(lnBuf, " \n"); } r[nbody].x = (float) x; r[nbody].y = (float) y; r[nbody].z = (float) z; ++nbody; } else { hasError = TRUE; } } if (fclose(f)) { mwPerror("Failed to close file '%s'", filename); } if (!readCoordinateSystem || !readHasGalaxy || !readCenterOfMass) { mw_printf("Warning: Failed to read some scene info items\n"); } scene->nbody = nbody; if (hasError) { free(scene); return NULL; } return scene; }
void init() { OPA_store_int(&flag, 1); }
void unlock() { OPA_store_int(&flag, 1); }
int MPIR_Init_thread(int *argc, char ***argv, int required, int *provided) { int mpi_errno = MPI_SUCCESS; int has_args; int has_env; int thread_provided = 0; int exit_init_cs_on_failure = 0; MPIR_Info *info_ptr; #if defined(MPICH_IS_THREADED) bool cs_initialized = false; #endif /* The threading library must be initialized at the very beginning because * it manages all synchronization objects (e.g., mutexes) that will be * initialized later */ { int thread_err; MPL_thread_init(&thread_err); if (thread_err) goto fn_fail; } #ifdef HAVE_HWLOC MPIR_Process.bindset = hwloc_bitmap_alloc(); hwloc_topology_init(&MPIR_Process.hwloc_topology); MPIR_Process.bindset_is_valid = 0; hwloc_topology_set_io_types_filter(MPIR_Process.hwloc_topology, HWLOC_TYPE_FILTER_KEEP_ALL); if (!hwloc_topology_load(MPIR_Process.hwloc_topology)) { MPIR_Process.bindset_is_valid = !hwloc_get_proc_cpubind(MPIR_Process.hwloc_topology, getpid(), MPIR_Process.bindset, HWLOC_CPUBIND_PROCESS); } #endif #ifdef HAVE_NETLOC MPIR_Process.network_attr.u.tree.node_levels = NULL; MPIR_Process.network_attr.network_endpoint = NULL; MPIR_Process.netloc_topology = NULL; MPIR_Process.network_attr.type = MPIR_NETLOC_NETWORK_TYPE__INVALID; if (strlen(MPIR_CVAR_NETLOC_NODE_FILE)) { mpi_errno = netloc_parse_topology(&MPIR_Process.netloc_topology, MPIR_CVAR_NETLOC_NODE_FILE); if (mpi_errno == NETLOC_SUCCESS) { MPIR_Netloc_parse_topology(MPIR_Process.netloc_topology, &MPIR_Process.network_attr); } } #endif /* For any code in the device that wants to check for runtime * decisions on the value of isThreaded, set a provisional * value here. We could let the MPID_Init routine override this */ #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = required == MPI_THREAD_MULTIPLE; #endif /* MPICH_IS_THREADED */ #if defined(MPICH_IS_THREADED) mpi_errno = thread_cs_init(); cs_initialized = true; if (mpi_errno) MPIR_ERR_POP(mpi_errno); #endif /* FIXME: Move to os-dependent interface? */ #ifdef HAVE_WINDOWS_H /* prevent the process from bringing up an error message window if mpich * asserts */ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, assert_hook); #ifdef _WIN64 { /* FIXME: (Windows) This severly degrades performance but fixes alignment * issues with the datatype code. */ /* Prevent misaligned faults on Win64 machines */ UINT mode, old_mode; old_mode = SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT); mode = old_mode | SEM_NOALIGNMENTFAULTEXCEPT; SetErrorMode(mode); } #endif #endif /* We need this inorder to implement IS_THREAD_MAIN */ #if (MPICH_THREAD_LEVEL >= MPI_THREAD_SERIALIZED) && defined(MPICH_IS_THREADED) { MPID_Thread_self(&MPIR_ThreadInfo.master_thread); } #endif #ifdef HAVE_ERROR_CHECKING /* Because the PARAM system has not been initialized, temporarily * uncondtionally enable error checks. Once the PARAM system is * initialized, this may be reset */ MPIR_Process.do_error_checks = 1; #else MPIR_Process.do_error_checks = 0; #endif /* Initialize necessary subsystems and setup the predefined attribute * values. Subsystems may change these values. */ MPIR_Process.attrs.appnum = -1; MPIR_Process.attrs.host = MPI_PROC_NULL; MPIR_Process.attrs.io = MPI_PROC_NULL; MPIR_Process.attrs.lastusedcode = MPI_ERR_LASTCODE; MPIR_Process.attrs.universe = MPIR_UNIVERSE_SIZE_NOT_SET; MPIR_Process.attrs.wtime_is_global = 0; /* Set the functions used to duplicate attributes. These are * when the first corresponding keyval is created */ MPIR_Process.attr_dup = 0; MPIR_Process.attr_free = 0; #ifdef HAVE_CXX_BINDING /* Set the functions used to call functions in the C++ binding * for reductions and attribute operations. These are null * until a C++ operation is defined. This allows the C code * that implements these operations to not invoke a C++ code * directly, which may force the inclusion of symbols known only * to the C++ compiler (e.g., under more non-GNU compilers, including * Solaris and IRIX). */ MPIR_Process.cxx_call_op_fn = 0; #endif #ifdef HAVE_F08_BINDING MPIR_C_MPI_UNWEIGHTED = MPI_UNWEIGHTED; MPIR_C_MPI_WEIGHTS_EMPTY = MPI_WEIGHTS_EMPTY; #endif /* This allows the device to select an alternative function for * dimsCreate */ MPIR_Process.dimsCreate = 0; /* "Allocate" from the reserved space for builtin communicators and * (partially) initialize predefined communicators. comm_parent is * intially NULL and will be allocated by the device if the process group * was started using one of the MPI_Comm_spawn functions. */ MPIR_Process.comm_world = MPIR_Comm_builtin + 0; MPII_Comm_init(MPIR_Process.comm_world); MPIR_Process.comm_world->handle = MPI_COMM_WORLD; MPIR_Process.comm_world->context_id = 0 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->recvcontext_id = 0 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->comm_kind = MPIR_COMM_KIND__INTRACOMM; /* This initialization of the comm name could be done only when * comm_get_name is called */ MPL_strncpy(MPIR_Process.comm_world->name, "MPI_COMM_WORLD", MPI_MAX_OBJECT_NAME); MPIR_Process.comm_self = MPIR_Comm_builtin + 1; MPII_Comm_init(MPIR_Process.comm_self); MPIR_Process.comm_self->handle = MPI_COMM_SELF; MPIR_Process.comm_self->context_id = 1 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->recvcontext_id = 1 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->comm_kind = MPIR_COMM_KIND__INTRACOMM; MPL_strncpy(MPIR_Process.comm_self->name, "MPI_COMM_SELF", MPI_MAX_OBJECT_NAME); #ifdef MPID_NEEDS_ICOMM_WORLD MPIR_Process.icomm_world = MPIR_Comm_builtin + 2; MPII_Comm_init(MPIR_Process.icomm_world); MPIR_Process.icomm_world->handle = MPIR_ICOMM_WORLD; MPIR_Process.icomm_world->context_id = 2 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->recvcontext_id = 2 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->comm_kind = MPIR_COMM_KIND__INTRACOMM; MPL_strncpy(MPIR_Process.icomm_world->name, "MPI_ICOMM_WORLD", MPI_MAX_OBJECT_NAME); /* Note that these communicators are not ready for use - MPID_Init * will setup self and world, and icomm_world if it desires it. */ #endif MPIR_Process.comm_parent = NULL; /* Setup the initial communicator list in case we have * enabled the debugger message-queue interface */ MPII_COMML_REMEMBER(MPIR_Process.comm_world); MPII_COMML_REMEMBER(MPIR_Process.comm_self); /* MPIU_Timer_pre_init(); */ /* Wait for debugger to attach if requested. */ if (MPIR_CVAR_DEBUG_HOLD) { volatile int hold = 1; while (hold) #ifdef HAVE_USLEEP usleep(100); #endif ; } #if defined(HAVE_ERROR_CHECKING) && (HAVE_ERROR_CHECKING == MPID_ERROR_LEVEL_RUNTIME) MPIR_Process.do_error_checks = MPIR_CVAR_ERROR_CHECKING; #endif /* define MPI as initialized so that we can use MPI functions within * MPID_Init if necessary */ OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__IN_INIT); /* We can't acquire any critical sections until this point. Any * earlier the basic data structures haven't been initialized */ MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); exit_init_cs_on_failure = 1; /* create MPI_INFO_NULL object */ /* FIXME: Currently this info object is empty, we need to add data to this * as defined by the standard. */ info_ptr = MPIR_Info_builtin + 1; info_ptr->handle = MPI_INFO_ENV; MPIR_Object_set_ref(info_ptr, 1); info_ptr->next = NULL; info_ptr->key = NULL; info_ptr->value = NULL; #ifdef USE_MEMORY_TRACING MPL_trinit(); #endif /* Set the number of tag bits. The device may override this value. */ MPIR_Process.tag_bits = MPIR_TAG_BITS_DEFAULT; /* Create complete request to return in the event of immediately complete * operations. Use a SEND request to cover all possible use-cases. */ MPIR_Process.lw_req = MPIR_Request_create(MPIR_REQUEST_KIND__SEND); MPIR_ERR_CHKANDSTMT(MPIR_Process.lw_req == NULL, mpi_errno, MPIX_ERR_NOREQ, goto fn_fail, "**nomemreq"); MPIR_cc_set(&MPIR_Process.lw_req->cc, 0); mpi_errno = MPID_Init(argc, argv, required, &thread_provided, &has_args, &has_env); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* Initialize collectives infrastructure */ mpi_errno = MPII_Coll_init(); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* Set tag_ub as function of tag_bits set by the device */ MPIR_Process.attrs.tag_ub = MPIR_TAG_USABLE_BITS; /* Assert: tag_ub should be a power of 2 minus 1 */ MPIR_Assert(((unsigned) MPIR_Process. attrs.tag_ub & ((unsigned) MPIR_Process.attrs.tag_ub + 1)) == 0); /* Assert: tag_ub is at least the minimum asked for in the MPI spec */ MPIR_Assert(MPIR_Process.attrs.tag_ub >= 32767); /* Capture the level of thread support provided */ MPIR_ThreadInfo.thread_provided = thread_provided; if (provided) *provided = thread_provided; #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = (thread_provided == MPI_THREAD_MULTIPLE); #endif /* MPICH_IS_THREADED */ /* FIXME: Define these in the interface. Does Timer init belong here? */ MPII_Timer_init(MPIR_Process.comm_world->rank, MPIR_Process.comm_world->local_size); #ifdef USE_MEMORY_TRACING #ifdef MPICH_IS_THREADED MPL_trconfig(MPIR_Process.comm_world->rank, MPIR_ThreadInfo.isThreaded); #else MPL_trconfig(MPIR_Process.comm_world->rank, 0); #endif /* Indicate that we are near the end of the init step; memory * allocated already will have an id of zero; this helps * separate memory leaks in the initialization code from * leaks in the "active" code */ #endif #ifdef MPL_USE_DBG_LOGGING /* FIXME: This is a hack to handle the common case of two worlds. * If the parent comm is not NULL, we always give the world number * as "1" (false). */ #ifdef MPICH_IS_THREADED MPL_dbg_init(argc, argv, has_args, has_env, MPIR_Process.comm_parent != NULL, MPIR_Process.comm_world->rank, MPIR_ThreadInfo.isThreaded); #else MPL_dbg_init(argc, argv, has_args, has_env, MPIR_Process.comm_parent != NULL, MPIR_Process.comm_world->rank, 0); #endif MPIR_DBG_INIT = MPL_dbg_class_alloc("INIT", "init"); MPIR_DBG_PT2PT = MPL_dbg_class_alloc("PT2PT", "pt2pt"); MPIR_DBG_THREAD = MPL_dbg_class_alloc("THREAD", "thread"); MPIR_DBG_DATATYPE = MPL_dbg_class_alloc("DATATYPE", "datatype"); MPIR_DBG_HANDLE = MPL_dbg_class_alloc("HANDLE", "handle"); MPIR_DBG_COMM = MPL_dbg_class_alloc("COMM", "comm"); MPIR_DBG_BSEND = MPL_dbg_class_alloc("BSEND", "bsend"); MPIR_DBG_ERRHAND = MPL_dbg_class_alloc("ERRHAND", "errhand"); MPIR_DBG_OTHER = MPL_dbg_class_alloc("OTHER", "other"); MPIR_DBG_REQUEST = MPL_dbg_class_alloc("REQUEST", "request"); MPIR_DBG_COLL = MPL_dbg_class_alloc("COLL", "coll"); MPIR_DBG_ASSERT = MPL_dbg_class_alloc("ASSERT", "assert"); MPIR_DBG_STRING = MPL_dbg_class_alloc("STRING", "string"); #endif /* Initialize the C versions of the Fortran link-time constants. * * We now initialize the Fortran symbols from within the Fortran * interface in the routine that first needs the symbols. * This fixes a problem with symbols added by a Fortran compiler that * are not part of the C runtime environment (the Portland group * compilers would do this) */ #if defined(HAVE_FORTRAN_BINDING) && defined(HAVE_MPI_F_INIT_WORKS_WITH_C) mpirinitf_(); #endif /* FIXME: Does this need to come before the call to MPID_InitComplete? * For some debugger support, MPII_Wait_for_debugger may want to use * MPI communication routines to collect information for the debugger */ #ifdef HAVE_DEBUGGER_SUPPORT MPII_Wait_for_debugger(); #endif /* Let the device know that the rest of the init process is completed */ if (mpi_errno == MPI_SUCCESS) mpi_errno = MPID_InitCompleted(); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); /* Make fields of MPIR_Process global visible and set mpich_state * atomically so that MPI_Initialized() etc. are thread safe */ OPA_write_barrier(); OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__POST_INIT); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ /* signal to error handling routines that core services are unavailable */ OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__PRE_INIT); if (exit_init_cs_on_failure) { MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); } #if defined(MPICH_IS_THREADED) if (cs_initialized) { MPIR_Thread_CS_Finalize(); } #endif return mpi_errno; /* --END ERROR HANDLING-- */ }
/*@ MPI_Finalize - Terminates MPI execution environment Notes: All processes must call this routine before exiting. The number of processes running `after` this routine is called is undefined; it is best not to perform much more than a 'return rc' after calling 'MPI_Finalize'. Thread and Signal Safety: The MPI standard requires that 'MPI_Finalize' be called `only` by the same thread that initialized MPI with either 'MPI_Init' or 'MPI_Init_thread'. .N Fortran .N Errors .N MPI_SUCCESS @*/ int MPI_Finalize( void ) { static const char FCNAME[] = "MPI_Finalize"; int mpi_errno = MPI_SUCCESS; #if defined(HAVE_USLEEP) && defined(USE_COVERAGE) int rank=0; #endif MPID_MPI_FINALIZE_STATE_DECL(MPID_STATE_MPI_FINALIZE); MPIR_ERRTEST_INITIALIZED_ORDIE(); /* Note: Only one thread may ever call MPI_Finalize (MPI_Finalize may be called at most once in any program) */ MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPID_MPI_FINALIZE_FUNC_ENTER(MPID_STATE_MPI_FINALIZE); /* ... body of routine ... */ /* If the user requested for asynchronous progress, we need to * shutdown the progress thread */ if (MPIR_async_thread_initialized) { mpi_errno = MPIR_Finalize_async_thread(); if (mpi_errno) goto fn_fail; } #if defined(HAVE_USLEEP) && defined(USE_COVERAGE) /* We need to get the rank before freeing MPI_COMM_WORLD */ rank = MPIR_Process.comm_world->rank; #endif /* Remove the attributes, executing the attribute delete routine. Do this only if the attribute functions are defined. */ /* The standard (MPI-2, section 4.8) says that the attributes on MPI_COMM_SELF are deleted before almost anything else happens */ /* Note that the attributes need to be removed from the communicators so that they aren't freed twice. (The communicators are released in MPID_Finalize) */ if (MPIR_Process.attr_free && MPIR_Process.comm_self->attributes) { mpi_errno = MPIR_Process.attr_free( MPI_COMM_SELF, &MPIR_Process.comm_self->attributes); if (mpi_errno) MPIR_ERR_POP(mpi_errno); MPIR_Process.comm_self->attributes = 0; } if (MPIR_Process.attr_free && MPIR_Process.comm_world->attributes) { mpi_errno = MPIR_Process.attr_free( MPI_COMM_WORLD, &MPIR_Process.comm_world->attributes); if (mpi_errno) MPIR_ERR_POP(mpi_errno); MPIR_Process.comm_world->attributes = 0; } /* * Now that we're finalizing, we need to take control of the error handlers * At this point, we will release any user-defined error handlers on * comm self and comm world */ if (MPIR_Process.comm_world->errhandler && ! (HANDLE_GET_KIND(MPIR_Process.comm_world->errhandler->handle) == HANDLE_KIND_BUILTIN) ) { int in_use; MPIR_Errhandler_release_ref( MPIR_Process.comm_world->errhandler, &in_use); if (!in_use) { MPIU_Handle_obj_free( &MPID_Errhandler_mem, MPIR_Process.comm_world->errhandler ); } /* always set to NULL to avoid a double-release later in finalize */ MPIR_Process.comm_world->errhandler = NULL; } if (MPIR_Process.comm_self->errhandler && ! (HANDLE_GET_KIND(MPIR_Process.comm_self->errhandler->handle) == HANDLE_KIND_BUILTIN) ) { int in_use; MPIR_Errhandler_release_ref( MPIR_Process.comm_self->errhandler, &in_use); if (!in_use) { MPIU_Handle_obj_free( &MPID_Errhandler_mem, MPIR_Process.comm_self->errhandler ); } /* always set to NULL to avoid a double-release later in finalize */ MPIR_Process.comm_self->errhandler = NULL; } /* FIXME: Why is this not one of the finalize callbacks?. Do we need pre and post MPID_Finalize callbacks? */ MPIU_Timer_finalize(); /* Call the high-priority callbacks */ MPIR_Call_finalize_callbacks( MPIR_FINALIZE_CALLBACK_PRIO+1, MPIR_FINALIZE_CALLBACK_MAX_PRIO ); /* Signal the debugger that we are about to exit. */ /* FIXME: Should this also be a finalize callback? */ #ifdef HAVE_DEBUGGER_SUPPORT MPIR_DebuggerSetAborting( (char *)0 ); #endif mpi_errno = MPID_Finalize(); if (mpi_errno) { MPIR_ERR_POP(mpi_errno); } /* Call the low-priority (post Finalize) callbacks */ MPIR_Call_finalize_callbacks( 0, MPIR_FINALIZE_CALLBACK_PRIO-1 ); /* At this point, if there has been a failure, exit before completing the finalize */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* Users did not call MPI_T_init_thread(), so we free memories allocated to * MPIR_T during MPI_Init here. Otherwise, free them in MPI_T_finalize() */ if (!MPIR_T_is_initialized()) MPIR_T_env_finalize(); /* FIXME: Many of these debugging items could/should be callbacks, added to the finalize callback list */ /* FIXME: the memory tracing code block should be a finalize callback */ /* If memory debugging is enabled, check the memory here, after all finalize callbacks */ MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); OPA_store_int(&MPIR_Process.mpich_state, MPICH_POST_FINALIZED); #if defined(MPICH_IS_THREADED) MPIR_Thread_CS_Finalize(); #endif /* We place the memory tracing at the very end because any of the other steps may have allocated memory that they still need to release*/ #ifdef USE_MEMORY_TRACING /* FIXME: We'd like to arrange for the mem dump output to go to separate files or to be sorted by rank (note that the rank is at the head of the line) */ { if (MPIR_CVAR_MEMDUMP) { /* The second argument is the min id to print; memory allocated after MPI_Init is given an id of one. This allows us to ignore, if desired, memory leaks in the MPID_Init call */ MPL_trdump( (void *)0, -1 ); } } #endif #if defined(HAVE_USLEEP) && defined(USE_COVERAGE) /* If performing coverage analysis, make each process sleep for rank * 100 ms, to give time for the coverage tool to write out any files. It would be better if the coverage tool and runtime was more careful about file updates, though the lack of OS support for atomic file updates makes this harder. */ /* On some systems, a 0.1 second delay appears to be too short for the file system. This code allows the use of the environment variable MPICH_FINALDELAY, which is the delay in milliseconds. It must be an integer value. */ { int microseconds = 100000; char *delayStr = getenv( "MPICH_FINALDELAY" ); if (delayStr) { /* Because this is a maintainer item, we won't check for errors in the delayStr */ microseconds = 1000 * atoi( delayStr ); } usleep( rank * microseconds ); } #endif /* ... end of body of routine ... */ fn_exit: MPID_MPI_FINALIZE_FUNC_EXIT(MPID_STATE_MPI_FINALIZE); 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_finalize", 0); } # endif mpi_errno = MPIR_Err_return_comm( 0, FCNAME, mpi_errno ); if (OPA_load_int(&MPIR_Process.mpich_state) < MPICH_POST_FINALIZED) { MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); } goto fn_exit; /* --END ERROR HANDLING-- */ }