1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpiimpl.h"
7 
8 /* -- Begin Profiling Symbol Block for routine MPI_Unpack */
9 #if defined(HAVE_PRAGMA_WEAK)
10 #pragma weak MPI_Unpack = PMPI_Unpack
11 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
12 #pragma _HP_SECONDARY_DEF PMPI_Unpack  MPI_Unpack
13 #elif defined(HAVE_PRAGMA_CRI_DUP)
14 #pragma _CRI duplicate MPI_Unpack as PMPI_Unpack
15 #elif defined(HAVE_WEAK_ATTRIBUTE)
16 int MPI_Unpack(const void *inbuf, int insize, int *position, void *outbuf, int outcount,
17                MPI_Datatype datatype, MPI_Comm comm) __attribute__ ((weak, alias("PMPI_Unpack")));
18 #endif
19 /* -- End Profiling Symbol Block */
20 
21 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
22    the MPI routines */
23 #ifndef MPICH_MPI_FROM_PMPI
24 #undef MPI_Unpack
25 #define MPI_Unpack PMPI_Unpack
26 #endif
27 
28 /*@
29     MPI_Unpack - Unpack a buffer according to a datatype into contiguous memory
30 
31 Input Parameters:
32 + inbuf - input buffer start (choice)
33 . insize - size of input buffer, in bytes (integer)
34 . outcount - number of items to be unpacked (integer)
35 . datatype - datatype of each output data item (handle)
36 - comm - communicator for packed message (handle)
37 
38 Output Parameters:
39 . outbuf - output buffer start (choice)
40 
41 Inout/Output Parameters:
42 . position - current position in bytes (integer)
43 
44 
45 .N ThreadSafe
46 
47 .N Fortran
48 
49 .N Errors
50 .N MPI_SUCCESS
51 .N MPI_ERR_COMM
52 .N MPI_ERR_COUNT
53 .N MPI_ERR_TYPE
54 .N MPI_ERR_ARG
55 
56 .seealso: MPI_Pack, MPI_Pack_size
57 @*/
MPI_Unpack(const void * inbuf,int insize,int * position,void * outbuf,int outcount,MPI_Datatype datatype,MPI_Comm comm)58 int MPI_Unpack(const void *inbuf, int insize, int *position,
59                void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm)
60 {
61     int mpi_errno = MPI_SUCCESS;
62     MPI_Aint position_x;
63     MPIR_Comm *comm_ptr = NULL;
64     MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_UNPACK);
65 
66     MPIR_ERRTEST_INITIALIZED_ORDIE();
67 
68     MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_UNPACK);
69 
70     /* Validate parameters, especially handles needing to be converted */
71 #ifdef HAVE_ERROR_CHECKING
72     {
73         MPID_BEGIN_ERROR_CHECKS;
74         {
75             MPIR_ERRTEST_COMM(comm, mpi_errno);
76         }
77         MPID_END_ERROR_CHECKS;
78     }
79 #endif
80 
81     /* Convert MPI object handles to object pointers */
82     MPIR_Comm_get_ptr(comm, comm_ptr);
83 
84     /* Validate parameters and objects (post conversion) */
85 #ifdef HAVE_ERROR_CHECKING
86     {
87         MPID_BEGIN_ERROR_CHECKS;
88         {
89             if (insize > 0) {
90                 MPIR_ERRTEST_ARGNULL(inbuf, "input buffer", mpi_errno);
91             }
92             /* Note: outbuf could be MPI_BOTTOM; don't test for NULL */
93             MPIR_ERRTEST_COUNT(insize, mpi_errno);
94             MPIR_ERRTEST_COUNT(outcount, mpi_errno);
95 
96             /* Validate comm_ptr */
97             MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, FALSE);
98             if (mpi_errno != MPI_SUCCESS)
99                 goto fn_fail;
100             /* If comm_ptr is not valid, it will be reset to null */
101 
102             MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
103 
104             if (datatype != MPI_DATATYPE_NULL && !HANDLE_IS_BUILTIN(datatype)) {
105                 MPIR_Datatype *datatype_ptr = NULL;
106 
107                 MPIR_Datatype_get_ptr(datatype, datatype_ptr);
108                 MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
109                 MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
110             }
111             if (mpi_errno != MPI_SUCCESS)
112                 goto fn_fail;
113         }
114         MPID_END_ERROR_CHECKS;
115     }
116 #endif /* HAVE_ERROR_CHECKING */
117 
118     /* ... body of routine ...  */
119 
120     position_x = *position;
121 
122     MPI_Aint actual_unpack_bytes;
123     void *buf = (void *) ((char *) inbuf + position_x);
124     mpi_errno =
125         MPIR_Typerep_unpack(buf, insize, outbuf, outcount, datatype, 0, &actual_unpack_bytes);
126     if (mpi_errno)
127         goto fn_fail;
128 
129     position_x += actual_unpack_bytes;
130     MPIR_Assign_trunc(*position, position_x, int);
131 
132     /* ... end of body of routine ... */
133 
134   fn_exit:
135     MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_UNPACK);
136     return mpi_errno;
137 
138 
139   fn_fail:
140     /* --BEGIN ERROR HANDLING-- */
141 #ifdef HAVE_ERROR_CHECKING
142     {
143         mpi_errno =
144             MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
145                                  "**mpi_unpack", "**mpi_unpack %p %d %p %p %d %D %C", inbuf, insize,
146                                  position, outbuf, outcount, datatype, comm);
147     }
148 #endif
149     mpi_errno = MPIR_Err_return_comm(comm_ptr, __func__, mpi_errno);
150     goto fn_exit;
151     /* --END ERROR HANDLING-- */
152 }
153