1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2018 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
14 * Copyright (c) 2010 University of Houston. All rights reserved.
15 * Copyright (c) 2013 Los Alamos National Security, LLC. All rights
16 * reserved.
17 * Copyright (c) 2015 Research Organization for Information Science
18 * and Technology (RIST). All rights reserved.
19 * $COPYRIGHT$
20 *
21 * Additional copyrights may follow
22 *
23 * $HEADER$
24 */
25
26 #include "ompi_config.h"
27 #include <stdio.h>
28
29 #include "ompi/mpi/c/bindings.h"
30 #include "ompi/runtime/params.h"
31 #include "ompi/communicator/communicator.h"
32 #include "ompi/errhandler/errhandler.h"
33 #include "ompi/datatype/ompi_datatype.h"
34 #include "ompi/memchecker.h"
35 #include "ompi/runtime/ompi_spc.h"
36
37 #if OMPI_BUILD_MPI_PROFILING
38 #if OPAL_HAVE_WEAK_SYMBOLS
39 #pragma weak MPI_Allgather = PMPI_Allgather
40 #endif
41 #define MPI_Allgather PMPI_Allgather
42 #endif
43
44 static const char FUNC_NAME[] = "MPI_Allgather";
45
46
47 int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
48 void *recvbuf, int recvcount, MPI_Datatype recvtype,
49 MPI_Comm comm)
50 {
51 int err;
52
53 SPC_RECORD(OMPI_SPC_ALLGATHER, 1);
54
55 MEMCHECKER(
56 int rank;
57 ptrdiff_t ext;
58
59 rank = ompi_comm_rank(comm);
60 ompi_datatype_type_extent(recvtype, &ext);
61
62 memchecker_datatype(recvtype);
63 memchecker_comm(comm);
64 /* check whether the actual send buffer is defined. */
65 if (MPI_IN_PLACE == sendbuf) {
66 memchecker_call(&opal_memchecker_base_isdefined,
67 (char *)(recvbuf)+rank*ext,
68 recvcount, recvtype);
69 } else {
70 memchecker_datatype(sendtype);
71 memchecker_call(&opal_memchecker_base_isdefined, sendbuf, sendcount, sendtype);
72 }
73 /* check whether the receive buffer is addressable. */
74 memchecker_call(&opal_memchecker_base_isaddressable, recvbuf, recvcount, recvtype);
75 );
76
77 if (MPI_PARAM_CHECK) {
78
79 /* Unrooted operation -- same checks for all ranks on both
80 intracommunicators and intercommunicators */
81
82 err = MPI_SUCCESS;
83 OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
84 if (ompi_comm_invalid(comm)) {
85 OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM, FUNC_NAME);
86 } else if (MPI_DATATYPE_NULL == recvtype || NULL == recvtype) {
87 err = MPI_ERR_TYPE;
88 } else if (recvcount < 0) {
89 err = MPI_ERR_COUNT;
90 } else if ((MPI_IN_PLACE == sendbuf && OMPI_COMM_IS_INTER(comm)) ||
91 MPI_IN_PLACE == recvbuf) {
92 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
93 } else if (MPI_IN_PLACE != sendbuf) {
94 OMPI_CHECK_DATATYPE_FOR_SEND(err, sendtype, sendcount);
95 }
96 OMPI_ERRHANDLER_CHECK(err, comm, err, FUNC_NAME);
97 }
98
99 /* Do we need to do anything? Everyone had to give the same send
100 signature, which means that everyone must have given a
101 sendcount > 0 if there's anything to send for the intra-communicator
102 case. If we're doing IN_PLACE, however, check recvcount,
103 not sendcount. */
104 if ( OMPI_COMM_IS_INTRA(comm) ) {
105 if ((MPI_IN_PLACE != sendbuf && 0 == sendcount) ||
106 (0 == recvcount)) {
107 return MPI_SUCCESS;
108 }
109 }
110 else if ( OMPI_COMM_IS_INTER(comm) ){
111 /* for inter comunicators, the communication pattern
112 need not be symmetric. Specifically, one group is
113 allows to have sendcount=0, while the other has
114 a valid sendcount. Thus, the only way not to do
115 anything is if both sendcount and recvcount are zero. */
116 if ( 0 == sendcount && 0 == recvcount ) {
117 return MPI_SUCCESS;
118 }
119 }
120
121 OPAL_CR_ENTER_LIBRARY();
122
123 /* Invoke the coll component to perform the back-end operation */
124
125 err = comm->c_coll->coll_allgather(sendbuf, sendcount, sendtype,
126 recvbuf, recvcount, recvtype, comm,
127 comm->c_coll->coll_allgather_module);
128 OMPI_ERRHANDLER_RETURN(err, comm, err, FUNC_NAME);
129 }
130