📄 mpid_vc.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include "mpidimpl.h"/*S * MPIDI_VCRT - virtual connection reference table * * handle - this element is not used, but exists so that we may use the * MPIU_Object routines for reference counting * * ref_count - number of references to this table * * vcr_table - array of virtual connection references S*/typedef struct MPIDI_VCRT{ int handle; volatile int ref_count; int size; MPIDI_VC_t * vcr_table[1];}MPIDI_VCRT_t;/* What is the arrangement of VCRT and VCR and VC? Each VC (the virtual connection itself) is refered to by a reference (pointer) or VCR. Each communicator has a VCRT, which is nothing more than a structure containing a count (size) and an array of pointers to virtual connections (as an abstraction, this could be a sparse array, allowing a more scalable representation on massively parallel systems). */static int MPIDI_CH3U_VC_FinishPending( MPIDI_VCRT_t *vcrt );/*@ MPID_VCRT_Create - Create a table of VC references Notes: This routine only provides space for the VC references. Those should be added by assigning to elements of the vc array within the 'MPID_VCRT' object. @*/#undef FUNCNAME#define FUNCNAME MPID_VCRT_Create#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr){ MPIDI_VCRT_t * vcrt; int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_CREATE); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_CREATE); vcrt = MPIU_Malloc(sizeof(MPIDI_VCRT_t) + (size - 1) * sizeof(MPIDI_VC_t *)); if (vcrt != NULL) { MPIU_Object_set_ref(vcrt, 1); vcrt->size = size; *vcrt_ptr = vcrt; } else { MPIU_ERR_SET(mpi_errno,MPI_ERR_OTHER,"**nomem"); } MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_CREATE); return mpi_errno;}/*@ MPID_VCRT_Add_ref - Add a reference to a VC reference table Notes: This is called when a communicator duplicates its group of processes. It is used in 'commutil.c' and in routines to create communicators from dynamic process operations. It does not change the state of any of the virtural connections (VCs). @*/#undef FUNCNAME#define FUNCNAME MPID_VCRT_Add_ref#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCRT_Add_ref(MPID_VCRT vcrt){ MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_ADD_REF); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_ADD_REF); MPIU_Object_add_ref(vcrt); MPIU_DBG_MSG_FMT(REFCOUNT,TYPICAL,(MPIU_DBG_FDEST, "Incr VCRT %p ref count to %d",vcrt,vcrt->ref_count)); MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_ADD_REF); return MPI_SUCCESS;}/* FIXME: What should this do? See proc group and vc discussion *//*@ MPID_VCRT_Release - Release a reference to a VC reference table Notes: @*/#undef FUNCNAME#define FUNCNAME MPID_VCRT_Release#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCRT_Release(MPID_VCRT vcrt, int isDisconnect ){ int in_use; int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_RELEASE); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_RELEASE); MPIU_Object_release_ref(vcrt, &in_use); MPIU_DBG_MSG_FMT(REFCOUNT,TYPICAL,(MPIU_DBG_FDEST, "Decr VCRT %p ref count to %d",vcrt,vcrt->ref_count)); /* If this VC reference table is no longer in use, we can decrement the reference count of each of the VCs. If the count on the VCs goes to zero, then we can decrement the ref count on the process group and so on. */ if (!in_use) { int i, inuse; /* FIXME: Need a better way to define how vc's are closed that takes into account pending operations on vcs, including close events received from other processes. */ /* mpi_errno = MPIDI_CH3U_VC_FinishPending( vcrt ); if (mpi_errno) { MPIU_ERR_POP(mpi_errno); } */ for (i = 0; i < vcrt->size; i++) { MPIDI_VC_t * const vc = vcrt->vcr_table[i]; MPIDI_VC_release_ref(vc, &in_use); /* The rule for disconnect that we use is that if MPI_Comm_disconnect removes the last reference to this VC, we fully remove the VC. This is not quite what the MPI standard says, but this is sufficient to give the expected behavior for most user programs that use MPI_Comm_disconnect */ if (isDisconnect && vc->ref_count == 1) { MPIDI_VC_release_ref(vc, &in_use); } if (!in_use) { /* If the VC is myself then skip the close message */ if (vc->pg == MPIDI_Process.my_pg && vc->pg_rank == MPIDI_Process.my_pg_rank) { MPIDI_PG_release_ref(vc->pg, &inuse); if (inuse == 0) { MPIDI_PG_Destroy(vc->pg); } continue; } /* FIXME: the correct test is ACTIVE or REMOTE_CLOSE */ if (vc->state != MPIDI_VC_STATE_INACTIVE) { /* printf( "Sending close to vc[%d]\n", i ); */ MPIDI_CH3U_VC_SendClose( vc, i ); } else { MPIDI_PG_release_ref(vc->pg, &inuse); if (inuse == 0) { MPIDI_PG_Destroy(vc->pg); } MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST, "vc=%p: not sending a close to %d, vc in state %s", vc, i, MPIDI_VC_GetStateString(vc->state))); } mpi_errno = MPIU_CALL(MPIDI_CH3,VC_Destroy(vc)); if (mpi_errno) { MPIU_ERR_POP(mpi_errno); } } } MPIU_Free(vcrt); } /* Commented out blocks that are not needed unless MPIU_ERR_POP is used above */ fn_exit: MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_RELEASE); return mpi_errno; fn_fail: goto fn_exit;}/*@ MPID_VCRT_Get_ptr - Return a pointer to the array of VCs for this reference table Notes: This routine is always used with MPID_VCRT_Create and should be combined with it. @*/#undef FUNCNAME#define FUNCNAME MPID_VCRT_Get_ptr#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCRT_Get_ptr(MPID_VCRT vcrt, MPID_VCR **vc_pptr){ MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_GET_PTR); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_GET_PTR); *vc_pptr = vcrt->vcr_table; MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_GET_PTR); return MPI_SUCCESS;}/*@ MPID_VCR_Dup - Duplicate a virtual connection reference Notes: If the VC is being used for the first time in a VC reference table, the reference count is set to two, not one, in order to distinquish between freeing a communicator with 'MPI_Comm_free' and 'MPI_Comm_disconnect', and the reference count on the process group is incremented (to indicate that the process group is in use). While this has no effect on the process group of 'MPI_COMM_WORLD', it is important for process groups accessed through 'MPI_Comm_spawn' or 'MPI_Comm_connect/MPI_Comm_accept'. @*/#undef FUNCNAME#define FUNCNAME MPID_VCR_Dup#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCR_Dup(MPID_VCR orig_vcr, MPID_VCR * new_vcr){ MPIDI_STATE_DECL(MPID_STATE_MPID_VCR_DUP); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCR_DUP); /* We are allowed to create a vc that belongs to no process group as part of the initial connect/accept action, so in that case, ignore the pg ref count update */ if (orig_vcr->ref_count == 0 && orig_vcr->pg) { MPIU_Object_set_ref( orig_vcr, 2 ); MPIDI_PG_add_ref( orig_vcr->pg ); } else { MPIU_Object_add_ref(orig_vcr); } MPIU_DBG_MSG_FMT(REFCOUNT,TYPICAL,(MPIU_DBG_FDEST,\ "Incr VCR %p ref count to %d",orig_vcr,orig_vcr->ref_count)); *new_vcr = orig_vcr; MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCR_DUP); return MPI_SUCCESS;}/*@ MPID_VCR_Get_lpid - Get the local process ID for a given VC reference @*/#undef FUNCNAME#define FUNCNAME MPID_VCR_Get_lpid#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_VCR_Get_lpid(MPID_VCR vcr, int * lpid_ptr){ MPIDI_STATE_DECL(MPID_STATE_MPID_VCR_GET_LPID); MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCR_GET_LPID); *lpid_ptr = vcr->lpid; MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCR_GET_LPID); return MPI_SUCCESS;}/* * The following routines convert to/from the global pids, which are * represented as pairs of ints (process group id, rank in that process group) *//* FIXME: These routines belong in a different place */#undef FUNCNAME#define FUNCNAME MPID_GPID_GetAllInComm#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_GPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size, int local_gpids[], int *singlePG ){ int i; int *gpid = local_gpids; int lastPGID = -1, pgid; MPID_VCR vc; *singlePG = 1; for (i=0; i<comm_ptr->local_size; i++) { vc = comm_ptr->vcr[i]; /* Get the process group id as an int */ MPIDI_PG_IdToNum( vc->pg, &pgid ); *gpid++ = pgid; if (lastPGID != pgid) { if (lastPGID != -1) *singlePG = 0; lastPGID = pgid; } *gpid++ = vc->pg_rank; if (vc->pg_rank != vc->lpid) { return 1;/* printf( "Unexpected results %d != %d\n", vc->pg_rank, vc->lpid ); */ } } return 0;}#undef FUNCNAME#define FUNCNAME MPID_GPID_Get#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPID_GPID_Get( MPID_Comm *comm_ptr, int rank, int gpid[] ){ int pgid; MPID_VCR vc; vc = comm_ptr->vcr[rank]; /* Get the process group id as an int */ MPIDI_PG_IdToNum( vc->pg, &pgid );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -