int MPIR_Group_init(void) { int mpi_errno = MPI_SUCCESS; MPIU_Assert(MPID_GROUP_N_BUILTIN == 1); /* update this func if this ever triggers */ MPID_Group_builtin[0].handle = MPI_GROUP_EMPTY; MPIU_Object_set_ref(&MPID_Group_builtin[0], 1); MPID_Group_builtin[0].size = 0; MPID_Group_builtin[0].rank = MPI_UNDEFINED; MPID_Group_builtin[0].idx_of_first_lpid = -1; MPID_Group_builtin[0].lrank_to_lpid = NULL; /* the mutex is probably never used, but initializing it doesn't hurt */ MPIU_THREAD_MPI_OBJ_INIT(&MPID_Group_builtin[0]); /* TODO hook for device here? */ return mpi_errno; }
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; int exit_init_cs_on_failure = 0; MPID_Info *info_ptr; /* 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 */ #ifdef HAVE_RUNTIME_THREADCHECK MPIR_ThreadInfo.isThreaded = required == MPI_THREAD_MULTIPLE; #endif MPIU_THREAD_CS_INIT; /* 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 = 0; MPIR_Process.attrs.io = 0; MPIR_Process.attrs.lastusedcode = MPI_ERR_LASTCODE; MPIR_Process.attrs.tag_ub = 0; 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 /* 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 = MPID_Comm_builtin + 0; MPIR_Comm_init(MPIR_Process.comm_world); MPIR_Process.comm_world->handle = MPI_COMM_WORLD; MPIR_Process.comm_world->context_id = 0 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->recvcontext_id = 0 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->comm_kind = MPID_INTRACOMM; /* This initialization of the comm name could be done only when comm_get_name is called */ MPIU_Strncpy(MPIR_Process.comm_world->name, "MPI_COMM_WORLD", MPI_MAX_OBJECT_NAME); MPIR_Process.comm_self = MPID_Comm_builtin + 1; MPIR_Comm_init(MPIR_Process.comm_self); MPIR_Process.comm_self->handle = MPI_COMM_SELF; MPIR_Process.comm_self->context_id = 1 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->recvcontext_id = 1 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->comm_kind = MPID_INTRACOMM; MPIU_Strncpy(MPIR_Process.comm_self->name, "MPI_COMM_SELF", MPI_MAX_OBJECT_NAME); #ifdef MPID_NEEDS_ICOMM_WORLD MPIR_Process.icomm_world = MPID_Comm_builtin + 2; MPIR_Comm_init(MPIR_Process.icomm_world); MPIR_Process.icomm_world->handle = MPIR_ICOMM_WORLD; MPIR_Process.icomm_world->context_id = 2 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->recvcontext_id= 2 << MPID_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->comm_kind = MPID_INTRACOMM; MPIU_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 */ MPIR_COMML_REMEMBER( MPIR_Process.comm_world ); MPIR_COMML_REMEMBER( MPIR_Process.comm_self ); /* Call any and all MPID_Init type functions */ MPIR_Err_init(); MPIR_Datatype_init(); MPIR_Group_init(); /* MPIU_Timer_pre_init(); */ mpi_errno = MPIR_Param_init_params(); if (mpi_errno) MPIU_ERR_POP(mpi_errno); /* Wait for debugger to attach if requested. */ if (MPIR_PARAM_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_PARAM_ERROR_CHECKING; #endif /* define MPI as initialized so that we can use MPI functions within MPID_Init if necessary */ MPIR_Process.initialized = MPICH_WITHIN_MPI; /* We can't acquire any critical sections until this point. Any * earlier the basic data structures haven't been initialized */ MPIU_THREAD_CS_ENTER(INIT,required); 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 = MPID_Info_builtin + 1; info_ptr->handle = MPI_INFO_ENV; MPIU_Object_set_ref(info_ptr, 1); MPIU_THREAD_MPI_OBJ_INIT(info_ptr); info_ptr->next = NULL; info_ptr->key = NULL; info_ptr->value = NULL; mpi_errno = MPID_Init(argc, argv, required, &thread_provided, &has_args, &has_env); if (mpi_errno) MPIU_ERR_POP(mpi_errno); /* Assert: tag_ub should be a power of 2 minus 1 */ MPIU_Assert(((unsigned)MPIR_Process.attrs.tag_ub & ((unsigned)MPIR_Process.attrs.tag_ub + 1)) == 0); /* Set aside tag space for tagged collectives */ MPIR_Process.attrs.tag_ub >>= 1; MPIR_Process.tagged_coll_mask = MPIR_Process.attrs.tag_ub + 1; /* Assert: tag_ub is at least the minimum asked for in the MPI spec */ MPIU_Assert( MPIR_Process.attrs.tag_ub >= 32767 ); /* very nasty bugs will occur if this does not hold */ #if defined(HAVE_FORTRAN_BINDING) MPIU_Assert(sizeof(MPI_Status) == MPIF_STATUS_SIZE*sizeof(MPI_Fint)); #endif /* Capture the level of thread support provided */ MPIR_ThreadInfo.thread_provided = thread_provided; if (provided) *provided = thread_provided; #ifdef HAVE_RUNTIME_THREADCHECK MPIR_ThreadInfo.isThreaded = (thread_provided == MPI_THREAD_MULTIPLE); #endif /* FIXME: Define these in the interface. Does Timer init belong here? */ MPIU_dbg_init(MPIR_Process.comm_world->rank); MPIU_Timer_init(MPIR_Process.comm_world->rank, MPIR_Process.comm_world->local_size); #ifdef USE_MEMORY_TRACING MPIU_trinit( MPIR_Process.comm_world->rank ); /* 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 */ /* Uncomment this code to leave out any of the MPID_Init/etc memory allocations from the memory leak testing */ /* MPIU_trid( 1 ); */ #endif #ifdef USE_DBG_LOGGING MPIU_DBG_Init( argc, argv, has_args, has_env, MPIR_Process.comm_world->rank ); #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, MPIR_WaitForDebugger may want to use MPI communication routines to collect information for the debugger */ #ifdef HAVE_DEBUGGER_SUPPORT MPIR_WaitForDebugger(); #endif /* Let the device know that the rest of the init process is completed */ if (mpi_errno == MPI_SUCCESS) mpi_errno = MPID_InitCompleted(); fn_exit: MPIU_THREAD_CS_EXIT(INIT,required); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ /* signal to error handling routines that core services are unavailable */ MPIR_Process.initialized = MPICH_PRE_INIT; if (exit_init_cs_on_failure) { MPIU_THREAD_CS_EXIT(INIT,required); } MPIU_THREAD_CS_FINALIZE; return mpi_errno; /* --END ERROR HANDLING-- */ }
void *MPIU_Handle_obj_alloc_unsafe(MPIU_Object_alloc_t *objmem) { MPIU_Handle_common *ptr; if (objmem->avail) { ptr = objmem->avail; objmem->avail = objmem->avail->next; /* We do not clear ptr->next as we set it to an invalid pattern when doing memory debugging and we don't need to set it for the production/default case */ /* ptr points to object to allocate */ } else { int objsize, objkind; int performed_initialize = 0; objsize = objmem->size; objkind = objmem->kind; if (!objmem->initialized) { performed_initialize = 1; MPL_VG_CREATE_MEMPOOL(objmem, 0/*rzB*/, 0/*is_zeroed*/); /* Setup the first block. This is done here so that short MPI jobs do not need to include any of the Info code if no Info-using routines are used */ objmem->initialized = 1; ptr = MPIU_Handle_direct_init(objmem->direct, objmem->direct_size, objsize, objkind); if (ptr) { objmem->avail = ptr->next; } #ifdef MPICH_DEBUG_HANDLEALLOC /* The priority of these callbacks must be greater than the priority of the callback that frees the objmem direct and indirect storage. */ MPIR_Add_finalize(MPIU_CheckHandlesOnFinalize, objmem, MPIR_FINALIZE_CALLBACK_HANDLE_CHECK_PRIO); #endif /* ptr points to object to allocate */ } else { /* no space left in direct block; setup the indirect block. */ ptr = MPIU_Handle_indirect_init(&objmem->indirect, &objmem->indirect_size, HANDLE_BLOCK_INDEX_SIZE, HANDLE_BLOCK_SIZE, objsize, objkind); if (ptr) { objmem->avail = ptr->next; } /* ptr points to object to allocate */ } MPIU_Handle_obj_alloc_complete(objmem, performed_initialize); } if (ptr) { #ifdef USE_MEMORY_TRACING /* We set the object to an invalid pattern. This is similar to what is done by MPIU_trmalloc by default (except that trmalloc uses 0xda as the byte in the memset) */ /* if the object was previously freed then MEMPOOL_FREE marked it as * NOACCESS, so we need to make it addressable again before memsetting * it */ /* save and restore the handle -- it's a more robust method than * encoding the layout of the structure */ int tmp_handle; MPL_VG_MAKE_MEM_DEFINED(ptr, objmem->size); tmp_handle = ptr->handle ; memset(ptr, 0xef, objmem->size); ptr->handle = tmp_handle; #endif /* USE_MEMORY_TRACING */ /* mark the mem as addressable yet undefined if valgrind is available */ MPL_VG_MEMPOOL_ALLOC(objmem, ptr, objmem->size); /* the handle value is always valid at return from this function */ MPL_VG_MAKE_MEM_DEFINED(&ptr->handle, sizeof(ptr->handle)); /* necessary to prevent annotations from being misinterpreted. HB/HA * arcs will be drawn between a req object in across a free/alloc * boundary otherwise */ /* NOTE: basically causes DRD's --trace-addr option to be useless for * handlemem-allocated objects. Consider one of the trace-inducing * annotations instead. */ MPL_VG_ANNOTATE_NEW_MEMORY(ptr, objmem->size); /* must come after NEW_MEMORY annotation above to avoid problems */ MPIU_THREAD_MPI_OBJ_INIT(ptr); MPIU_DBG_MSG_FMT(HANDLE,TYPICAL,(MPIU_DBG_FDEST, "Allocating object ptr %p (handle val 0x%08x)", ptr, ptr->handle)); } return ptr; }