1 /* begin_generated_IBM_copyright_prolog                             */
2 /*                                                                  */
3 /* This is an automatically generated copyright prolog.             */
4 /* After initializing,  DO NOT MODIFY OR MOVE                       */
5 /*  --------------------------------------------------------------- */
6 /* Licensed Materials - Property of IBM                             */
7 /* Blue Gene/Q 5765-PER 5765-PRP                                    */
8 /*                                                                  */
9 /* (C) Copyright IBM Corp. 2011, 2012 All Rights Reserved           */
10 /* US Government Users Restricted Rights -                          */
11 /* Use, duplication, or disclosure restricted                       */
12 /* by GSA ADP Schedule Contract with IBM Corp.                      */
13 /*                                                                  */
14 /*  --------------------------------------------------------------- */
15 /*                                                                  */
16 /* end_generated_IBM_copyright_prolog                               */
17 /*  (C)Copyright IBM Corp.  2007, 2011  */
18 /**
19  * \file src/mpid_request.h
20  * \brief ???
21  */
22 
23 #ifndef __src_mpid_request_h__
24 #define __src_mpid_request_h__
25 
26 #include "mpid_datatype.h"
27 
28 /**
29  * \addtogroup MPID_REQUEST
30  * \{
31  */
32 
33 #define MPID_Request_create    MPID_Request_create_inline
34 #define MPID_Request_release   MPID_Request_release_inline
35 #define MPIDI_Request_complete MPIDI_Request_complete_inline
36 #define MPIDI_Request_complete_norelease MPIDI_Request_complete_norelease_inline
37 #define MPID_Request_discard   MPID_Request_discard_inline
38 
39 
40 extern MPIU_Object_alloc_t MPID_Request_mem;
41 
42 
43 void    MPIDI_Request_uncomplete(MPID_Request *req);
44 #if (MPIU_HANDLE_ALLOCATION_METHOD == MPIU_HANDLE_ALLOCATION_THREAD_LOCAL) && defined(__BGQ__)
45 void    MPIDI_Request_allocate_pool();
46 #endif
47 
48 #define MPIDI_Request_getCA(_req)                ({ (_req)->mpid.ca;                                })
49 #define MPIDI_Request_getPeerRank_pami(_req)     ({ (_req)->mpid.peer_pami;                         })
50 #define MPIDI_Request_getPeerRank_comm(_req)     ({ (_req)->mpid.peer_comm;                         })
51 #define MPIDI_Request_getPType(_req)             ({ (_req)->mpid.ptype;                             })
52 #define MPIDI_Request_getControl(_req)           ({ (_req)->mpid.envelope.msginfo.control;          })
53 #define MPIDI_Request_isSync(_req)               ({ (_req)->mpid.envelope.msginfo.isSync;           })
54 #define MPIDI_Request_isRzv(_req)                ({ (_req)->mpid.envelope.msginfo.isRzv;            })
55 #define MPIDI_Request_getMatchTag(_req)          ({ (_req)->mpid.envelope.msginfo.MPItag;           })
56 #define MPIDI_Request_getMatchRank(_req)         ({ (_req)->mpid.envelope.msginfo.MPIrank;          })
57 #define MPIDI_Request_getMatchCtxt(_req)         ({ (_req)->mpid.envelope.msginfo.MPIctxt;          })
58 
59 #define MPIDI_Request_setCA(_req, _ca)           ({ (_req)->mpid.ca                        = (_ca); })
60 #define MPIDI_Request_setPeerRank_pami(_req,_r)  ({ (_req)->mpid.peer_pami                 = (_r);  })
61 #define MPIDI_Request_setPeerRank_comm(_req,_r)  ({ (_req)->mpid.peer_comm                 = (_r);  })
62 #define MPIDI_Request_setPType(_req,_t)          ({ (_req)->mpid.ptype                     = (_t);  })
63 #define MPIDI_Request_setControl(_req,_t)        ({ (_req)->mpid.envelope.msginfo.control  = (_t);  })
64 #define MPIDI_Request_setSync(_req,_t)           ({ (_req)->mpid.envelope.msginfo.isSync   = (_t);  })
65 #define MPIDI_Request_setRzv(_req,_t)            ({ (_req)->mpid.envelope.msginfo.isRzv    = (_t);  })
66 #ifdef OUT_OF_ORDER_HANDLING
67 #define MPIDI_Request_getMatchSeq(_req)          ({ (_req)->mpid.envelope.msginfo.MPIseqno;           })
68 #define MPIDI_Request_setMatchSeq(_req,_sq)      ({ (_req)->mpid.envelope.msginfo.MPIseqno = (_sq);  })
69 #endif
70 #define MPIDI_Request_setMatch(_req,_tag,_rank,_ctxtid) \
71 ({                                                      \
72   (_req)->mpid.envelope.msginfo.MPItag=(_tag);          \
73   (_req)->mpid.envelope.msginfo.MPIrank=(_rank);        \
74   (_req)->mpid.envelope.msginfo.MPIctxt=(_ctxtid);      \
75 })
76 
77 #define MPIDI_Msginfo_getPeerRequest(_msg)       ({ MPID_Request *req=NULL; MPID_Request_get_ptr((_msg)->req, req); MPID_assert(req != NULL); req; })
78 #define MPIDI_Msginfo_getPeerRequestH(_msg)      ({                       (_msg)->req;                               })
79 #define MPIDI_Msginfo_cpyPeerRequestH(_dst,_src) ({                       (_dst)->req = (_src)->req;    MPI_SUCCESS; })
80 #define MPIDI_Request_getPeerRequest(_req)       MPIDI_Msginfo_getPeerRequest(&(_req)->mpid.envelope.msginfo)
81 #define MPIDI_Request_getPeerRequestH(_req)      ({ (_req)->mpid.envelope.msginfo.req;                               })
82 #define MPIDI_Request_setPeerRequestH(_req)      ({ (_req)->mpid.envelope.msginfo.req = (_req)->handle; MPI_SUCCESS; })
83 #define MPIDI_Request_cpyPeerRequestH(_dst,_src) MPIDI_Msginfo_cpyPeerRequestH(&(_dst)->mpid.envelope.msginfo,_src)
84 
85 
86 #define MPIU_HANDLE_ALLOCATION_MUTEX         0
87 #define MPIU_HANDLE_ALLOCATION_THREAD_LOCAL  1
88 
89 /* XXX DJG for TLS hack */
90 #define MPID_REQUEST_TLS_MAX 128
91 
92 #if (MPIU_HANDLE_ALLOCATION_METHOD == MPIU_HANDLE_ALLOCATION_THREAD_LOCAL) && defined(__BGQ__)
93 
94 #  define MPIDI_Request_tls_alloc(req)                                  \
95 ({                                                                      \
96   size_t tid = MPIDI_THREAD_ID();                                       \
97   MPIDI_RequestHandle_t *rh = &MPIDI_Process.request_handles[tid];      \
98   if (unlikely(rh->head == NULL))                                       \
99     MPIDI_Request_allocate_pool();                                      \
100   (req) = rh->head;                                                     \
101   rh->head = req->mpid.next;                                            \
102   rh->count --;                                                         \
103 })
104 
105 #  define MPIDI_Request_tls_free(req)                                   \
106 ({                                                                      \
107   size_t tid = MPIDI_THREAD_ID();                                       \
108   MPIDI_RequestHandle_t *rh = &MPIDI_Process.request_handles[tid];      \
109   if (likely(rh->count < MPID_REQUEST_TLS_MAX))				\
110     {                                                                   \
111       /* push request onto the top of the stack */                      \
112       req->mpid.next = rh->head;                                        \
113       rh->head = req;                                                   \
114       rh->count ++;                                                     \
115     }                                                                   \
116   else                                                                  \
117     {                                                                   \
118       MPIU_Handle_obj_free(&MPID_Request_mem, req);                     \
119     }                                                                   \
120 })
121 
122 #else
123 
124 #  define MPIDI_Request_tls_alloc(req)                                  \
125 ({                                                                      \
126   (req) = MPIU_Handle_obj_alloc(&MPID_Request_mem);                     \
127   if (req == NULL)                                                      \
128     MPID_Abort(NULL, MPI_ERR_NO_SPACE, -1, "Cannot allocate Request");  \
129 })
130 
131 #  define MPIDI_Request_tls_free(req) MPIU_Handle_obj_free(&MPID_Request_mem, (req))
132 
133 #endif
134 
135 
136 /**
137  * \brief Create a very generic request
138  * \note  This should only ever be called by more specific allocators
139  */
140 static inline MPID_Request *
MPIDI_Request_create_basic()141 MPIDI_Request_create_basic()
142 {
143   MPID_Request * req = NULL;
144 
145   MPIDI_Request_tls_alloc(req);
146   MPID_assert(req != NULL);
147   MPID_assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);
148   MPID_cc_set(&req->cc, 1);
149   req->cc_ptr = &req->cc;
150 
151 #if 0
152   /* This will destroy the MPID part of the request.  Use this to
153      check for fields that are not being correctly initialized. */
154   memset(&req->mpid, 0xFFFFFFFF, sizeof(struct MPIDI_Request));
155 #endif
156   req->mpid.next = NULL;
157 
158   return req;
159 }
160 
161 
162 /**
163  * \brief Create new request without initalizing
164  */
165 static inline MPID_Request *
MPIDI_Request_create2_fast()166 MPIDI_Request_create2_fast()
167 {
168   MPID_Request * req;
169   req = MPIDI_Request_create_basic();
170   MPIU_Object_set_ref(req, 2);
171 
172   return req;
173 }
174 
175 
176 /**
177  * \brief Create and initialize a new request
178  */
179 static inline void
MPIDI_Request_initialize(MPID_Request * req)180 MPIDI_Request_initialize(MPID_Request * req)
181 {
182   req->greq_fns          = NULL;
183 
184   req->status.count      = 0;
185   req->status.cancelled  = FALSE;
186   req->status.MPI_SOURCE = MPI_UNDEFINED;
187   req->status.MPI_TAG    = MPI_UNDEFINED;
188   req->status.MPI_ERROR  = MPI_SUCCESS;
189 
190   struct MPIDI_Request* mpid = &req->mpid;
191   mpid->envelope.msginfo.flags = 0;
192   mpid->cancel_pending   = FALSE;
193   mpid->datatype_ptr     = NULL;
194   mpid->uebuf            = NULL;
195   mpid->uebuflen         = 0;
196   mpid->uebuf_malloc     = 0;
197 #ifdef OUT_OF_ORDER_HANDLING
198   mpid->prev             = NULL;
199   mpid->prevR            = NULL;
200   mpid->nextR            = NULL;
201   mpid->oo_peer          = NULL;
202 #endif
203   MPIDI_Request_setCA(req, MPIDI_CA_COMPLETE);
204 }
205 
206 
207 /**
208  * \brief Create and initialize a new request
209  */
210 static inline MPID_Request *
MPID_Request_create_inline()211 MPID_Request_create_inline()
212 {
213   MPID_Request * req;
214   req = MPIDI_Request_create_basic();
215   MPIU_Object_set_ref(req, 1);
216 
217   MPIDI_Request_initialize(req);
218   req->comm=NULL;
219 
220   return req;
221 }
222 
223 
224 /**
225  * \brief Create and initialize a new request
226  */
227 static inline MPID_Request *
MPIDI_Request_create2()228 MPIDI_Request_create2()
229 {
230   MPID_Request * req;
231   req = MPID_Request_create();
232   MPIU_Object_set_ref(req, 2);
233 
234   return req;
235 }
236 
237 
238 /**
239  * \brief Mark a request as cancel-pending
240  * \param[in]  _req  The request to cancel
241  * \return           The previous state
242  */
243 #define MPIDI_Request_cancel_pending(_req)      \
244 ({                                              \
245   int _flag = (_req)->mpid.cancel_pending;      \
246   (_req)->mpid.cancel_pending = TRUE;           \
247   _flag;                                        \
248 })
249 
250 
251 static inline void
MPID_Request_release_inline(MPID_Request * req)252 MPID_Request_release_inline(MPID_Request *req)
253 {
254   int count;
255   MPID_assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);
256   MPIU_Object_release_ref(req, &count);
257   MPID_assert(count >= 0);
258 
259   if (count == 0)
260   {
261     MPID_assert(MPID_cc_is_complete(&req->cc));
262 
263     if (req->comm)              MPIR_Comm_release(req->comm, 0);
264     if (req->greq_fns)          MPIU_Free(req->greq_fns);
265     if (req->mpid.datatype_ptr) MPID_Datatype_release(req->mpid.datatype_ptr);
266     if (req->mpid.uebuf_malloc) MPIU_Free(req->mpid.uebuf);
267     MPIDI_Request_tls_free(req);
268   }
269 }
270 
271 
272 /* This request was never used, at most had uebuf allocated. */
273 static inline void
MPID_Request_discard_inline(MPID_Request * req)274 MPID_Request_discard_inline(MPID_Request *req)
275 {
276     if (req->mpid.uebuf_malloc) MPIU_Free(req->mpid.uebuf);
277     MPIDI_Request_tls_free(req);
278 }
279 
280 #define MPID_REQUEST_SET_COMPLETED(req_) \
281   MPIDI_Request_complete_inline(req_)
282 
283 static inline void
MPIDI_Request_complete_inline(MPID_Request * req)284 MPIDI_Request_complete_inline(MPID_Request *req)
285 {
286     int count;
287     MPID_cc_decr(req->cc_ptr, &count);
288     MPID_assert(count >= 0);
289 
290     MPID_Request_release(req);
291     if (count == 0) /* decrement completion count; if 0, signal progress engine */
292     {
293       MPIDI_Progress_signal();
294     }
295 }
296 
297 
298 static inline void
MPIDI_Request_complete_norelease_inline(MPID_Request * req)299 MPIDI_Request_complete_norelease_inline(MPID_Request *req)
300 {
301     int count;
302     MPID_cc_decr(req->cc_ptr, &count);
303     MPID_assert(count >= 0);
304 
305     if (count == 0) /* decrement completion count; if 0, signal progress engine */
306     {
307       MPIDI_Progress_signal();
308     }
309 }
310 
311 
312 /** \} */
313 
314 
315 #endif
316