Blame src/mpi/comm/intercomm_create.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpiimpl.h"
Packit Service c5cf8c
#include "mpicomm.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* -- Begin Profiling Symbol Block for routine MPI_Intercomm_create */
Packit Service c5cf8c
#if defined(HAVE_PRAGMA_WEAK)
Packit Service c5cf8c
#pragma weak MPI_Intercomm_create = PMPI_Intercomm_create
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit Service c5cf8c
#pragma _HP_SECONDARY_DEF PMPI_Intercomm_create  MPI_Intercomm_create
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit Service c5cf8c
#pragma _CRI duplicate MPI_Intercomm_create as PMPI_Intercomm_create
Packit Service c5cf8c
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit Service c5cf8c
int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm,
Packit Service c5cf8c
                         int remote_leader, int tag, MPI_Comm * newintercomm)
Packit Service c5cf8c
    __attribute__ ((weak, alias("PMPI_Intercomm_create")));
Packit Service c5cf8c
#endif
Packit Service c5cf8c
/* -- End Profiling Symbol Block */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
Packit Service c5cf8c
   the MPI routines */
Packit Service c5cf8c
#ifndef MPICH_MPI_FROM_PMPI
Packit Service c5cf8c
#undef MPI_Intercomm_create
Packit Service c5cf8c
#define MPI_Intercomm_create PMPI_Intercomm_create
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Intercomm_create_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Intercomm_create_impl(MPIR_Comm * local_comm_ptr, int local_leader,
Packit Service c5cf8c
                               MPIR_Comm * peer_comm_ptr, int remote_leader, int tag,
Packit Service c5cf8c
                               MPIR_Comm ** new_intercomm_ptr)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_Context_id_t final_context_id, recvcontext_id;
Packit Service c5cf8c
    int remote_size = 0, *remote_lpids = NULL;
Packit Service c5cf8c
    int comm_info[3];
Packit Service c5cf8c
    int is_low_group = 0;
Packit Service c5cf8c
    MPIR_Errflag_t errflag = MPIR_ERR_NONE;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_KIND__INTERCOMM_CREATE_IMPL);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_KIND__INTERCOMM_CREATE_IMPL);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Shift tag into the tagged coll space */
Packit Service c5cf8c
    tag |= MPIR_TAG_COLL_BIT;
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPID_Intercomm_exchange_map(local_comm_ptr, local_leader,
Packit Service c5cf8c
                                            peer_comm_ptr, remote_leader,
Packit Service c5cf8c
                                            &remote_size, &remote_lpids, &is_low_group);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Create the contexts.  Each group will have a context for sending
Packit Service c5cf8c
     * to the other group. All processes must be involved.  Because
Packit Service c5cf8c
     * we know that the local and remote groups are disjoint, this
Packit Service c5cf8c
     * step will complete
Packit Service c5cf8c
     */
Packit Service c5cf8c
    MPL_DBG_MSG_FMT(MPIR_DBG_COMM, VERBOSE,
Packit Service c5cf8c
                    (MPL_DBG_FDEST, "About to get contextid (local_size=%d) on rank %d",
Packit Service c5cf8c
                     local_comm_ptr->local_size, local_comm_ptr->rank));
Packit Service c5cf8c
    /* In the multi-threaded case, MPIR_Get_contextid_sparse assumes that the
Packit Service c5cf8c
     * calling routine already holds the single criticial section */
Packit Service c5cf8c
    /* TODO: Make sure this is tag-safe */
Packit Service c5cf8c
    mpi_errno = MPIR_Get_contextid_sparse(local_comm_ptr, &recvcontext_id, FALSE);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
    MPIR_Assert(recvcontext_id != 0);
Packit Service c5cf8c
    MPL_DBG_MSG_FMT(MPIR_DBG_COMM, VERBOSE, (MPL_DBG_FDEST, "Got contextid=%d", recvcontext_id));
Packit Service c5cf8c
Packit Service c5cf8c
    /* Leaders can now swap context ids and then broadcast the value
Packit Service c5cf8c
     * to the local group of processes */
Packit Service c5cf8c
    if (local_comm_ptr->rank == local_leader) {
Packit Service c5cf8c
        MPIR_Context_id_t remote_context_id;
Packit Service c5cf8c
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIC_Sendrecv(&recvcontext_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, remote_leader, tag,
Packit Service c5cf8c
                          &remote_context_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, remote_leader, tag,
Packit Service c5cf8c
                          peer_comm_ptr, MPI_STATUS_IGNORE, &errflag);
Packit Service c5cf8c
        if (mpi_errno)
Packit Service c5cf8c
            MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
        final_context_id = remote_context_id;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Now, send all of our local processes the remote_lpids,
Packit Service c5cf8c
         * along with the final context id */
Packit Service c5cf8c
        comm_info[0] = final_context_id;
Packit Service c5cf8c
        MPL_DBG_MSG(MPIR_DBG_COMM, VERBOSE, "About to bcast on local_comm");
Packit Service c5cf8c
        mpi_errno = MPIR_Bcast(comm_info, 1, MPI_INT, local_leader, local_comm_ptr, &errflag);
Packit Service c5cf8c
        if (mpi_errno)
Packit Service c5cf8c
            MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
        MPIR_ERR_CHKANDJUMP(errflag, mpi_errno, MPI_ERR_OTHER, "**coll_fail");
Packit Service c5cf8c
        MPL_DBG_MSG_D(MPIR_DBG_COMM, VERBOSE, "end of bcast on local_comm of size %d",
Packit Service c5cf8c
                      local_comm_ptr->local_size);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* we're the other processes */
Packit Service c5cf8c
        MPL_DBG_MSG(MPIR_DBG_COMM, VERBOSE, "About to receive bcast on local_comm");
Packit Service c5cf8c
        mpi_errno = MPIR_Bcast(comm_info, 1, MPI_INT, local_leader, local_comm_ptr, &errflag);
Packit Service c5cf8c
        if (mpi_errno)
Packit Service c5cf8c
            MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
        MPIR_ERR_CHKANDJUMP(errflag, mpi_errno, MPI_ERR_OTHER, "**coll_fail");
Packit Service c5cf8c
Packit Service c5cf8c
        /* Extract the context and group sign informatin */
Packit Service c5cf8c
        final_context_id = comm_info[0];
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* At last, we now have the information that we need to build the
Packit Service c5cf8c
     * intercommunicator */
Packit Service c5cf8c
Packit Service c5cf8c
    /* All processes in the local_comm now build the communicator */
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Comm_create(new_intercomm_ptr);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
    (*new_intercomm_ptr)->context_id = final_context_id;
Packit Service c5cf8c
    (*new_intercomm_ptr)->recvcontext_id = recvcontext_id;
Packit Service c5cf8c
    (*new_intercomm_ptr)->remote_size = remote_size;
Packit Service c5cf8c
    (*new_intercomm_ptr)->local_size = local_comm_ptr->local_size;
Packit Service c5cf8c
    (*new_intercomm_ptr)->pof2 = local_comm_ptr->pof2;
Packit Service c5cf8c
    (*new_intercomm_ptr)->rank = local_comm_ptr->rank;
Packit Service c5cf8c
    (*new_intercomm_ptr)->comm_kind = MPIR_COMM_KIND__INTERCOMM;
Packit Service c5cf8c
    (*new_intercomm_ptr)->local_comm = 0;
Packit Service c5cf8c
    (*new_intercomm_ptr)->is_low_group = is_low_group;
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPID_Create_intercomm_from_lpids(*new_intercomm_ptr, remote_size, remote_lpids);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_Comm_map_dup(*new_intercomm_ptr, local_comm_ptr, MPIR_COMM_MAP_DIR__L2L);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Inherit the error handler (if any) */
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(local_comm_ptr));
Packit Service c5cf8c
    (*new_intercomm_ptr)->errhandler = local_comm_ptr->errhandler;
Packit Service c5cf8c
    if (local_comm_ptr->errhandler) {
Packit Service c5cf8c
        MPIR_Errhandler_add_ref(local_comm_ptr->errhandler);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(local_comm_ptr));
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Comm_commit(*new_intercomm_ptr);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    if (remote_lpids) {
Packit Service c5cf8c
        MPL_free(remote_lpids);
Packit Service c5cf8c
        remote_lpids = NULL;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_KIND__INTERCOMM_CREATE_IMPL);
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#endif /* MPICH_MPI_FROM_PMPI */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPI_Intercomm_create
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
/*@
Packit Service c5cf8c
Packit Service c5cf8c
MPI_Intercomm_create - Creates an intercommuncator from two intracommunicators
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ local_comm - Local (intra)communicator
Packit Service c5cf8c
. local_leader - Rank in local_comm of leader (often 0)
Packit Service c5cf8c
. peer_comm - Communicator used to communicate between a
Packit Service c5cf8c
              designated process in the other communicator.
Packit Service c5cf8c
              Significant only at the process in 'local_comm' with
Packit Service c5cf8c
              rank 'local_leader'.
Packit Service c5cf8c
. remote_leader - Rank in peer_comm of remote leader (often 0)
Packit Service c5cf8c
- tag - Message tag to use in constructing intercommunicator; if multiple
Packit Service c5cf8c
  'MPI_Intercomm_creates' are being made, they should use different tags (more
Packit Service c5cf8c
  precisely, ensure that the local and remote leaders are using different
Packit Service c5cf8c
  tags for each 'MPI_intercomm_create').
Packit Service c5cf8c
Packit Service c5cf8c
Output Parameters:
Packit Service c5cf8c
. newintercomm - Created intercommunicator
Packit Service c5cf8c
Packit Service c5cf8c
Notes:
Packit Service c5cf8c
   'peer_comm' is significant only for the process designated the
Packit Service c5cf8c
   'local_leader' in the 'local_comm'.
Packit Service c5cf8c
Packit Service c5cf8c
  The MPI 1.1 Standard contains two mutually exclusive comments on the
Packit Service c5cf8c
  input intercommunicators.  One says that their repective groups must be
Packit Service c5cf8c
  disjoint; the other that the leaders can be the same process.  After
Packit Service c5cf8c
  some discussion by the MPI Forum, it has been decided that the groups must
Packit Service c5cf8c
  be disjoint.  Note that the `reason` given for this in the standard is
Packit Service c5cf8c
  `not` the reason for this choice; rather, the `other` operations on
Packit Service c5cf8c
  intercommunicators (like 'MPI_Intercomm_merge') do not make sense if the
Packit Service c5cf8c
  groups are not disjoint.
Packit Service c5cf8c
Packit Service c5cf8c
.N ThreadSafe
Packit Service c5cf8c
Packit Service c5cf8c
.N Fortran
Packit Service c5cf8c
Packit Service c5cf8c
.N Errors
Packit Service c5cf8c
.N MPI_SUCCESS
Packit Service c5cf8c
.N MPI_ERR_COMM
Packit Service c5cf8c
.N MPI_ERR_TAG
Packit Service c5cf8c
.N MPI_ERR_EXHAUSTED
Packit Service c5cf8c
.N MPI_ERR_RANK
Packit Service c5cf8c
Packit Service c5cf8c
.seealso: MPI_Intercomm_merge, MPI_Comm_free, MPI_Comm_remote_group,
Packit Service c5cf8c
          MPI_Comm_remote_size
Packit Service c5cf8c
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader,
Packit Service c5cf8c
                         MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm * newintercomm)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_Comm *local_comm_ptr = NULL;
Packit Service c5cf8c
    MPIR_Comm *peer_comm_ptr = NULL;
Packit Service c5cf8c
    MPIR_Comm *new_intercomm_ptr;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_INTERCOMM_CREATE);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_INTERCOMM_CREATE);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters, especially handles needing to be converted */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            MPIR_ERRTEST_COMM_TAG(tag, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_COMM(local_comm, mpi_errno);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Convert MPI object handles to object pointers */
Packit Service c5cf8c
    MPIR_Comm_get_ptr(local_comm, local_comm_ptr);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters and objects (post conversion) */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            /* Validate local_comm_ptr */
Packit Service c5cf8c
            MPIR_Comm_valid_ptr(local_comm_ptr, mpi_errno, FALSE);
Packit Service c5cf8c
            if (local_comm_ptr) {
Packit Service c5cf8c
                /*  Only check if local_comm_ptr valid */
Packit Service c5cf8c
                MPIR_ERRTEST_COMM_INTRA(local_comm_ptr, mpi_errno);
Packit Service c5cf8c
                if ((local_leader < 0 || local_leader >= local_comm_ptr->local_size)) {
Packit Service c5cf8c
                    MPIR_ERR_SET2(mpi_errno, MPI_ERR_RANK,
Packit Service c5cf8c
                                  "**ranklocal", "**ranklocal %d %d",
Packit Service c5cf8c
                                  local_leader, local_comm_ptr->local_size - 1);
Packit Service c5cf8c
                    /* If local_comm_ptr is not valid, it will be reset to null */
Packit Service c5cf8c
                    if (mpi_errno)
Packit Service c5cf8c
                        goto fn_fail;
Packit Service c5cf8c
                }
Packit Service c5cf8c
                if (local_comm_ptr->rank == local_leader) {
Packit Service c5cf8c
                    MPIR_ERRTEST_COMM(peer_comm, mpi_errno);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
            MPIR_ERRTEST_ARGNULL(newintercomm, "newintercomm", mpi_errno);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
Packit Service c5cf8c
    if (local_comm_ptr->rank == local_leader) {
Packit Service c5cf8c
Packit Service c5cf8c
        MPIR_Comm_get_ptr(peer_comm, peer_comm_ptr);
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
        {
Packit Service c5cf8c
            MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
            {
Packit Service c5cf8c
                MPIR_Comm_valid_ptr(peer_comm_ptr, mpi_errno, FALSE);
Packit Service c5cf8c
                /* Note: In MPI 1.0, peer_comm was restricted to
Packit Service c5cf8c
                 * intracommunicators.  In 1.1, it may be any communicator */
Packit Service c5cf8c
Packit Service c5cf8c
                /* In checking the rank of the remote leader,
Packit Service c5cf8c
                 * allow the peer_comm to be in intercommunicator
Packit Service c5cf8c
                 * by checking against the remote size */
Packit Service c5cf8c
                if (!mpi_errno && peer_comm_ptr &&
Packit Service c5cf8c
                    (remote_leader < 0 || remote_leader >= peer_comm_ptr->remote_size)) {
Packit Service c5cf8c
                    MPIR_ERR_SET2(mpi_errno, MPI_ERR_RANK,
Packit Service c5cf8c
                                  "**rankremote", "**rankremote %d %d",
Packit Service c5cf8c
                                  remote_leader, peer_comm_ptr->remote_size - 1);
Packit Service c5cf8c
                }
Packit Service c5cf8c
                /* Check that the local leader and the remote leader are
Packit Service c5cf8c
                 * different processes.  This test requires looking at
Packit Service c5cf8c
                 * the lpid for the two ranks in their respective
Packit Service c5cf8c
                 * communicators.  However, an easy test is for
Packit Service c5cf8c
                 * the same ranks in an intracommunicator; we only
Packit Service c5cf8c
                 * need the lpid comparison for intercommunicators */
Packit Service c5cf8c
                /* Here is the test.  We restrict this test to the
Packit Service c5cf8c
                 * process that is the local leader (local_comm_ptr->rank ==
Packit Service c5cf8c
                 * local_leader because we can then use peer_comm_ptr->rank
Packit Service c5cf8c
                 * to get the rank in peer_comm of the local leader. */
Packit Service c5cf8c
                if (peer_comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM &&
Packit Service c5cf8c
                    local_comm_ptr->rank == local_leader && peer_comm_ptr->rank == remote_leader) {
Packit Service c5cf8c
                    MPIR_ERR_SET(mpi_errno, MPI_ERR_RANK, "**ranksdistinct");
Packit Service c5cf8c
                }
Packit Service c5cf8c
                if (mpi_errno)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
                MPIR_ERRTEST_ARGNULL(newintercomm, "newintercomm", mpi_errno);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
        }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... body of routine ... */
Packit Service c5cf8c
    mpi_errno = MPIR_Intercomm_create_impl(local_comm_ptr, local_leader, peer_comm_ptr,
Packit Service c5cf8c
                                           remote_leader, tag, &new_intercomm_ptr);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_OBJ_PUBLISH_HANDLE(*newintercomm, new_intercomm_ptr->handle);
Packit Service c5cf8c
    /* ... end of body of routine ... */
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_INTERCOMM_CREATE);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
Packit Service c5cf8c
                                 "**mpi_intercomm_create",
Packit Service c5cf8c
                                 "**mpi_intercomm_create %C %d %C %d %d %p", local_comm,
Packit Service c5cf8c
                                 local_leader, peer_comm, remote_leader, tag, newintercomm);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
    mpi_errno = MPIR_Err_return_comm(local_comm_ptr, FCNAME, mpi_errno);
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
}