int MPIDI_CH3_Connect_to_root (const char *port_name, MPIDI_VC_t **new_vc) { int mpi_errno = MPI_SUCCESS; MPIDI_VC_t * vc; MPIU_CHKPMEM_DECL(1); MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_CONNECT_TO_ROOT); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_CONNECT_TO_ROOT); *new_vc = NULL; /* so that the err handling knows to cleanup */ MPIU_CHKPMEM_MALLOC (vc, MPIDI_VC_t *, sizeof(MPIDI_VC_t), mpi_errno, "vc"); /* FIXME - where does this vc get freed? ANSWER (goodell@) - ch3u_port.c FreeNewVC (but the VC_Destroy is in this file) */ /* init ch3 portion of vc */ MPIDI_VC_Init (vc, NULL, 0); /* init channel portion of vc */ MPIR_ERR_CHKINTERNAL(!nemesis_initialized, mpi_errno, "Nemesis not initialized"); vc->ch.recv_active = NULL; MPIDI_CHANGE_VC_STATE(vc, ACTIVE); *new_vc = vc; /* we now have a valid, disconnected, temp VC */ mpi_errno = MPID_nem_connect_to_root (port_name, vc); if (mpi_errno) MPIR_ERR_POP (mpi_errno); MPIU_CHKPMEM_COMMIT(); fn_exit: MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_CONNECT_TO_ROOT); return mpi_errno; fn_fail: /* freeing without giving the lower layer a chance to cleanup can lead to leaks on error */ if (*new_vc) MPIDI_CH3_VC_Destroy(*new_vc); MPIU_CHKPMEM_REAP(); goto fn_exit; }
int MPIDI_PG_Destroy(MPIDI_PG_t * pg) { MPIDI_PG_t * pg_prev; MPIDI_PG_t * pg_cur; int i; int mpi_errno = MPI_SUCCESS; MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_PG_DESTROY); MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_PG_DESTROY); MPIR_Assert(MPIR_Object_get_ref(pg) == 0); pg_prev = NULL; pg_cur = MPIDI_PG_list; while(pg_cur != NULL) { if (pg_cur == pg) { if (MPIDI_PG_iterator_next == pg) { MPIDI_PG_iterator_next = MPIDI_PG_iterator_next->next; } if (pg_prev == NULL) MPIDI_PG_list = pg->next; else pg_prev->next = pg->next; MPL_DBG_MSG_FMT(MPIDI_CH3_DBG_DISCONNECT, VERBOSE, (MPL_DBG_FDEST, "destroying pg=%p pg->id=%s", pg, (char *)pg->id)); for (i = 0; i < pg->size; ++i) { /* FIXME it would be good if we could make this assertion. Unfortunately, either: 1) We're not being disciplined and some caller of this function doesn't bother to manage all the refcounts because he thinks he knows better. Annoying, but not strictly a bug. (wdg - actually, that is a bug - managing the ref counts IS required and missing one is a bug.) 2) There is a real bug lurking out there somewhere and we just haven't hit it in the tests yet. */ /*MPIR_Assert(MPIR_Object_get_ref(pg->vct[i]) == 0);*/ MPL_DBG_MSG_FMT(MPIDI_CH3_DBG_DISCONNECT, VERBOSE, (MPL_DBG_FDEST, "about to free pg->vct=%p which contains vc=%p", pg->vct, &pg->vct[i])); /* This used to be handled in MPIDI_VCRT_Release, but that was not the right place to do this. The VC should only be freed when the PG that it belongs to is freed, not just when the VC's refcount drops to zero. [goodell@ 2008-06-13] */ /* In that case, the fact that the VC is in the PG should increment the ref count - reflecting the fact that the use in the PG constitutes a reference-count-incrementing use. Alternately, if the PG is able to recreate a VC, and can thus free unused (or idle) VCs, it should be allowed to do so. [wdg 2008-08-31] */ mpi_errno = MPIDI_CH3_VC_Destroy(&(pg->vct[i])); if (mpi_errno) { MPIR_ERR_POP(mpi_errno); } } MPIDI_PG_Destroy_fn(pg); MPL_free(pg->vct); if (pg->connData) { if (pg->freeConnInfo) { (*pg->freeConnInfo)( pg ); } else { MPL_free(pg->connData); } } mpi_errno = MPIDI_CH3_PG_Destroy(pg); MPL_free(pg); goto fn_exit; } pg_prev = pg_cur; pg_cur = pg_cur->next; } /* PG not found if we got here */ MPIR_ERR_SET1(mpi_errno,MPI_ERR_OTHER, "**dev|pg_not_found", "**dev|pg_not_found %p", pg); fn_exit: MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_PG_DESTROY); return mpi_errno; fn_fail: goto fn_exit; }