1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *
4  *  (C) 2001 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 
8 #include "mpiimpl.h"
9 #include "bsendutil.h"
10 
11 /* -- Begin Profiling Symbol Block for routine MPI_Buffer_detach */
12 #if defined(HAVE_PRAGMA_WEAK)
13 #pragma weak MPI_Buffer_detach = PMPI_Buffer_detach
14 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
15 #pragma _HP_SECONDARY_DEF PMPI_Buffer_detach  MPI_Buffer_detach
16 #elif defined(HAVE_PRAGMA_CRI_DUP)
17 #pragma _CRI duplicate MPI_Buffer_detach as PMPI_Buffer_detach
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_Buffer_detach
25 #define MPI_Buffer_detach PMPI_Buffer_detach
26 
27 #endif
28 
29 #undef FUNCNAME
30 #define FUNCNAME MPI_Buffer_detach
31 
32 /*@
33   MPI_Buffer_detach - Removes an existing buffer (for use in MPI_Bsend etc)
34 
35 Output Parameters:
36 + buffer - initial buffer address (choice)
37 - size - buffer size, in bytes (integer)
38 
39 Notes:
40     The reason that 'MPI_Buffer_detach' returns the address and size of the
41 buffer being detached is to allow nested libraries to replace and restore
42 the buffer.  For example, consider
43 
44 .vb
45     int size, mysize, idummy;
46     void *ptr, *myptr, *dummy;
47     MPI_Buffer_detach( &ptr, &size );
48     MPI_Buffer_attach( myptr, mysize );
49     ...
50     ... library code ...
51     ...
52     MPI_Buffer_detach( &dummy, &idummy );
53     MPI_Buffer_attach( ptr, size );
54 .ve
55 
56 This is much like the action of the Unix signal routine and has the same
57 strengths (it is simple) and weaknesses (it only works for nested usages).
58 
59 Note that for this approach to work, MPI_Buffer_detach must return MPI_SUCCESS
60 even when there is no buffer to detach.  In that case, it returns a size of
61 zero.  The MPI 1.1 standard for 'MPI_BUFFER_DETACH' contains the text
62 
63 .vb
64    The statements made in this section describe the behavior of MPI for
65    buffered-mode sends. When no buffer is currently associated, MPI behaves
66    as if a zero-sized buffer is associated with the process.
67 .ve
68 
69 This could be read as applying only to the various Bsend routines.  This
70 implementation takes the position that this applies to 'MPI_BUFFER_DETACH'
71 as well.
72 
73 .N NotThreadSafe
74 Because the buffer for buffered sends (e.g., 'MPI_Bsend') is shared by all
75 threads in a process, the user is responsible for ensuring that only
76 one thread at a time calls this routine or 'MPI_Buffer_attach'.
77 
78 .N Fortran
79 
80     The Fortran binding for this routine is different.  Because Fortran
81     does not have pointers, it is impossible to provide a way to use the
82     output of this routine to exchange buffers.  In this case, only the
83     size field is set.
84 
85 Notes for C:
86     Even though the 'bufferptr' argument is declared as 'void *', it is
87     really the address of a void pointer.  See the rationale in the
88     standard for more details.
89 
90 .seealso: MPI_Buffer_attach
91 @*/
MPI_Buffer_detach(void * buffer,int * size)92 int MPI_Buffer_detach(void *buffer, int *size)
93 {
94     static const char FCNAME[] = "MPI_Buffer_detach";
95     int mpi_errno = MPI_SUCCESS;
96     MPID_MPI_STATE_DECL(MPID_STATE_MPI_BUFFER_DETACH);
97 
98     MPIR_ERRTEST_INITIALIZED_ORDIE();
99 
100     MPIU_THREAD_CS_ENTER(ALLFUNC,);
101     MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_BUFFER_DETACH);
102 
103 #   ifdef HAVE_ERROR_CHECKING
104     {
105         MPID_BEGIN_ERROR_CHECKS;
106         {
107 	    MPIR_ERRTEST_ARGNULL(size,"size",mpi_errno);
108         }
109         MPID_END_ERROR_CHECKS;
110     }
111 #   endif /* HAVE_ERROR_CHECKING */
112 
113     /* ... body of routine ...  */
114 
115     mpi_errno = MPIR_Bsend_detach( buffer, size );
116     if (mpi_errno != MPI_SUCCESS) goto fn_fail;
117 
118     /* ... end of body of routine ... */
119 
120   fn_exit:
121     MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_BUFFER_DETACH);
122     MPIU_THREAD_CS_EXIT(ALLFUNC,);
123     return mpi_errno;
124 
125   fn_fail:
126     /* --BEGIN ERROR HANDLING-- */
127 #   ifdef HAVE_ERROR_CHECKING
128     {
129 	mpi_errno = MPIR_Err_create_code(
130 	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_buffer_detach",
131 	    "**mpi_buffer_detach %p %p", buffer, size);
132     }
133 #   endif
134     mpi_errno = MPIR_Err_return_comm( 0, FCNAME, mpi_errno );
135     goto fn_exit;
136     /* --END ERROR HANDLING-- */
137 }
138 
139