1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #ifndef OFI_TYPES_H_INCLUDED
7 #define OFI_TYPES_H_INCLUDED
8 
9 #include <netdb.h>
10 #include <stddef.h>
11 #include <inttypes.h>
12 #ifdef HAVE_STDINT_H
13 #include <stdint.h>
14 #endif
15 #include "ofi_pre.h"
16 #include "ch4_types.h"
17 #include "mpidch4r.h"
18 #include "mpidu_genq.h"
19 
20 #define __SHORT_FILE__                          \
21     (strrchr(__FILE__,'/')                      \
22      ? strrchr(__FILE__,'/')+1                  \
23      : __FILE__                                 \
24 )
25 
26 /* TODO: This should come from provider capability */
27 #define MPIDI_OFI_MAX_VNIS                  16
28 
29 #define MPIDI_OFI_MAP_NOT_FOUND            ((void*)(-1UL))
30 #define MPIDI_OFI_DEFAULT_SHORT_SEND_SIZE  (16 * 1024)
31 #define MPIDI_OFI_MAX_NUM_AM_BUFFERS       (8)
32 #define MPIDI_OFI_AM_BUFF_SZ               (1 * 1024 * 1024)
33 #define MPIDI_OFI_CACHELINE_SIZE           (MPL_CACHELINE_SIZE)
34 #define MPIDI_OFI_IOV_MAX                  (32)
35 #define MPIDI_OFI_AM_HDR_POOL_CELL_SIZE            (1024)
36 #define MPIDI_OFI_AM_HDR_POOL_NUM_CELLS_PER_CHUNK   (1024)
37 #define MPIDI_OFI_AM_HDR_POOL_MAX_NUM_CELLS         (257 * 1024)
38 #define MPIDI_OFI_NUM_CQ_BUFFERED          (1024)
39 
40 /* The number of bits in the immediate data field allocated to the source rank. */
41 #define MPIDI_OFI_IDATA_SRC_BITS (30)
42 /* The number of bits in the immediate data field allocated to the error propagation. */
43 #define MPIDI_OFI_IDATA_ERROR_BITS (2)
44 /* Bit mask for MPIR_ERR_OTHER */
45 #define MPIDI_OFI_ERR_OTHER (0x1ULL)
46 /* Bit mask for MPIR_PROC_FAILED */
47 #define MPIDI_OFI_ERR_PROC_FAILED (0x2ULL)
48 
49 /* Set the error bits */
MPIDI_OFI_idata_set_error_bits(uint64_t * data_field,MPIR_Errflag_t errflag)50 MPL_STATIC_INLINE_PREFIX void MPIDI_OFI_idata_set_error_bits(uint64_t * data_field,
51                                                              MPIR_Errflag_t errflag)
52 {
53     switch (errflag) {
54         case MPIR_ERR_OTHER:
55             *data_field = (*data_field) | (MPIDI_OFI_ERR_OTHER << MPIDI_OFI_IDATA_SRC_BITS);
56             break;
57         case MPIR_ERR_PROC_FAILED:
58             *data_field = (*data_field) | (MPIDI_OFI_ERR_PROC_FAILED << MPIDI_OFI_IDATA_SRC_BITS);
59             break;
60         case MPIR_ERR_NONE:
61             /*do nothing */
62             break;
63     }
64 }
65 
66 /* Get the error flag from the OFI data field. */
MPIDI_OFI_idata_get_error_bits(uint64_t idata)67 MPL_STATIC_INLINE_PREFIX int MPIDI_OFI_idata_get_error_bits(uint64_t idata)
68 {
69     if ((idata >> MPIDI_OFI_IDATA_SRC_BITS) & MPIDI_OFI_ERR_OTHER) {
70         return MPIR_ERR_OTHER;
71     } else if ((idata >> MPIDI_OFI_IDATA_SRC_BITS) & MPIDI_OFI_ERR_PROC_FAILED) {
72         return MPIR_ERR_PROC_FAILED;
73     } else {
74         return MPI_SUCCESS;
75     }
76 }
77 
78 
79 #define MPIDI_OFI_PROTOCOL_BITS (3)     /* This is set to 3 even though we actually use 4. The ssend
80                                          * ack bit needs to live outside the protocol bit space to avoid
81                                          * accidentally matching unintended messages. Because of this,
82                                          * we shift the PROTOCOL_MASK one extra bit to the left to take
83                                          * the place of the empty SSEND_ACK bit. */
84 
85 #if MPIDI_OFI_ENABLE_RUNTIME_CHECKS == MPIDI_OFI_ON
86 #define MPIDI_OFI_SYNC_SEND_ACK      (1ULL << (MPIDI_OFI_CONTEXT_BITS + MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
87 #define MPIDI_OFI_SYNC_SEND          (2ULL << (MPIDI_OFI_CONTEXT_BITS + MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
88 #define MPIDI_OFI_DYNPROC_SEND       (4ULL << (MPIDI_OFI_CONTEXT_BITS + MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
89 #define MPIDI_OFI_HUGE_SEND          (8ULL << (MPIDI_OFI_CONTEXT_BITS + MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
90 #define MPIDI_OFI_PROTOCOL_MASK      (((1ULL << MPIDI_OFI_PROTOCOL_BITS) - 1) << 1 << (MPIDI_OFI_CONTEXT_BITS + MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
91 #define MPIDI_OFI_CONTEXT_MASK       (((1ULL << MPIDI_OFI_CONTEXT_BITS) - 1) << (MPIDI_OFI_SOURCE_BITS + MPIDI_OFI_TAG_BITS))
92 #define MPIDI_OFI_SOURCE_MASK        (((1ULL << MPIDI_OFI_SOURCE_BITS) - 1) << MPIDI_OFI_TAG_BITS)
93 #define MPIDI_OFI_TAG_MASK           ((1ULL << MPIDI_OFI_TAG_BITS) - 1)
94 /* This value comes from the fact that we use a uint32_t in
95  * MPIDI_OFI_send_handler to define the dest and that is the size we expect
96  * from the OFI provider for its immediate data field. */
97 #define MPIDI_OFI_MAX_RANK_BITS      (MPIDI_OFI_SOURCE_BITS > 0 ? MPIDI_OFI_SOURCE_BITS : 32)
98 #else
99 #if MPIDI_OFI_SOURCE_BITS == 0
100 /* This value comes from the fact that we use a uint32_t in
101  * MPIDI_OFI_send_handler to define the dest and that is the size we expect
102  * from the OFI provider for its immediate data field. */
103 #define MPIDI_OFI_MAX_RANK_BITS      32
104 #else
105 #define MPIDI_OFI_MAX_RANK_BITS      MPIDI_OFI_SOURCE_BITS
106 #endif
107 #endif
108 
109 #define MPIDI_OFI_THREAD_UTIL_MUTEX     MPIDI_OFI_global.mutexes[0].m
110 #define MPIDI_OFI_THREAD_PROGRESS_MUTEX MPIDI_OFI_global.mutexes[1].m
111 #define MPIDI_OFI_THREAD_FI_MUTEX       MPIDI_OFI_global.mutexes[2].m
112 #define MPIDI_OFI_THREAD_SPAWN_MUTEX    MPIDI_OFI_global.mutexes[3].m
113 #define MAX_OFI_MUTEXES 4
114 
115 /* Field accessor macros */
116 #define MPIDI_OFI_AMREQUEST(req,field)     ((req)->dev.ch4.am.netmod_am.ofi.field)
117 #define MPIDI_OFI_AMREQUEST_HDR(req,field) ((req)->dev.ch4.am.netmod_am.ofi.req_hdr->field)
118 #define MPIDI_OFI_AMREQUEST_HDR_PTR(req)   ((req)->dev.ch4.am.netmod_am.ofi.req_hdr)
119 #define MPIDI_OFI_REQUEST(req,field)       ((req)->dev.ch4.netmod.ofi.field)
120 #define MPIDI_OFI_AV(av)                   ((av)->netmod.ofi)
121 
122 #define MPIDI_OFI_COMM(comm)     ((comm)->dev.ch4.netmod.ofi)
123 
124 #define MPIDI_OFI_NUM_CQ_ENTRIES 8
125 
126 /* Typedefs */
127 enum {
128     MPIDI_OFI_CTRL_HUGE,      /**< Huge message          */
129     MPIDI_OFI_CTRL_HUGEACK    /**< Huge message ack      */
130     /**< Huge message cleanup  */
131 };
132 
133 enum {
134     MPIDI_OFI_EVENT_ABORT,
135     MPIDI_OFI_EVENT_SEND,
136     MPIDI_OFI_EVENT_RECV,
137     MPIDI_OFI_EVENT_AM_SEND,
138     MPIDI_OFI_EVENT_AM_SEND_PIPELINE,
139     MPIDI_OFI_EVENT_AM_RECV,
140     MPIDI_OFI_EVENT_AM_READ,
141     MPIDI_OFI_EVENT_PEEK,
142     MPIDI_OFI_EVENT_RECV_HUGE,
143     MPIDI_OFI_EVENT_RECV_PACK,
144     MPIDI_OFI_EVENT_RECV_NOPACK,
145     MPIDI_OFI_EVENT_SEND_HUGE,
146     MPIDI_OFI_EVENT_SEND_PACK,
147     MPIDI_OFI_EVENT_SEND_NOPACK,
148     MPIDI_OFI_EVENT_SSEND_ACK,
149     MPIDI_OFI_EVENT_GET_HUGE,
150     MPIDI_OFI_EVENT_CHUNK_DONE,
151     MPIDI_OFI_EVENT_INJECT_EMU,
152     MPIDI_OFI_EVENT_DYNPROC_DONE,
153     MPIDI_OFI_EVENT_ACCEPT_PROBE
154 };
155 
156 enum {
157     MPIDI_OFI_PEEK_START,
158     MPIDI_OFI_PEEK_NOT_FOUND,
159     MPIDI_OFI_PEEK_FOUND
160 };
161 
162 enum {
163     MPIDI_OFI_DYNPROC_DISCONNECTED = 0,
164     MPIDI_OFI_DYNPROC_LOCAL_DISCONNECTED_CHILD,
165     MPIDI_OFI_DYNPROC_LOCAL_DISCONNECTED_PARENT,
166     MPIDI_OFI_DYNPROC_CONNECTED_CHILD,
167     MPIDI_OFI_DYNPROC_CONNECTED_PARENT
168 };
169 
170 typedef struct {
171     char pad[MPIDI_REQUEST_HDR_SIZE];
172     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
173     int event_id;               /* fixed field, do not move */
174     int index;
175 } MPIDI_OFI_am_repost_request_t;
176 
177 /* chunked request for AM eager/pipeline send operation */
178 typedef struct MPIDI_OFI_am_send_pipeline_request {
179     char pad[MPIDI_REQUEST_HDR_SIZE];
180     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
181     int event_id;               /* fixed field, do not move */
182     MPIR_Request *sreq;
183     void *pack_buffer;
184     void *am_hdr;
185     uint16_t am_hdr_sz;
186     MPIDI_OFI_am_header_t msg_hdr MPL_ATTR_ALIGNED(MAX_ALIGNMENT);
187     uint8_t am_hdr_buf[MPIDI_OFI_MAX_AM_HDR_SIZE] MPL_ATTR_ALIGNED(MAX_ALIGNMENT);
188     /* FI_ASYNC_IOV requires an iov storage to be alive until a request completes */
189     struct iovec iov[3];
190 } MPIDI_OFI_am_send_pipeline_request_t;
191 
192 typedef struct {
193     char pad[MPIDI_REQUEST_HDR_SIZE];
194     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
195     int event_id;               /* fixed field, do not move */
196     MPIR_Request *signal_req;
197 } MPIDI_OFI_ssendack_request_t;
198 
199 typedef struct {
200     char pad[MPIDI_REQUEST_HDR_SIZE];
201     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
202     int event_id;               /* fixed field, do not move */
203     int done;
204     uint32_t tag;
205     uint32_t source;
206     uint64_t msglen;
207 } MPIDI_OFI_dynamic_process_request_t;
208 
209 typedef struct {
210     uint8_t op;
211     uint8_t dt;
212     unsigned atomic_valid:2;
213     unsigned fetch_atomic_valid:2;
214     unsigned compare_atomic_valid:2;
215     unsigned dtsize:10;
216     uint64_t max_atomic_count;
217     uint64_t max_compare_atomic_count;
218     uint64_t max_fetch_atomic_count;
219     bool mpi_acc_valid;
220 } MPIDI_OFI_atomic_valid_t;
221 
222 typedef struct {
223     struct fid_domain *domain;
224     struct fid_av *av;
225     struct fid_ep *ep;
226     struct fid_cntr *rma_cmpl_cntr;
227 
228     struct fid_ep *tx;
229     struct fid_ep *rx;
230     struct fid_cq *cq;
231 } MPIDI_OFI_context_t;
232 
233 typedef union {
234     MPID_Thread_mutex_t m;
235     char cacheline[MPIDI_OFI_CACHELINE_SIZE];
236 } MPIDI_OFI_cacheline_mutex_t MPL_ATTR_ALIGNED(MPIDI_OFI_CACHELINE_SIZE);
237 
238 typedef struct MPIDI_OFI_cq_list_t {
239     struct fi_cq_tagged_entry cq_entry;
240     fi_addr_t source;
241     struct MPIDI_OFI_cq_list_t *next;
242 } MPIDI_OFI_cq_list_t;
243 
244 typedef struct {
245     struct fi_cq_tagged_entry cq_entry;
246 } MPIDI_OFI_cq_buff_entry_t;
247 
248 typedef struct {
249     unsigned enable_av_table:1;
250     unsigned enable_scalable_endpoints:1;
251     unsigned enable_shared_contexts:1;
252     unsigned enable_mr_scalable:1;
253     unsigned enable_mr_virt_address:1;
254     unsigned enable_mr_allocated:1;
255     unsigned enable_mr_prov_key:1;
256     unsigned enable_tagged:1;
257     unsigned enable_am:1;
258     unsigned enable_rma:1;
259     unsigned enable_atomics:1;
260     unsigned enable_pt2pt_nopack:1;
261     unsigned enable_hmem:1;
262     unsigned enable_data_auto_progress:1;
263     unsigned enable_control_auto_progress:1;
264 
265     int max_endpoints;
266     int max_endpoints_bits;
267 
268     int fetch_atomic_iovecs;
269 
270     int context_bits;
271     int source_bits;
272     int tag_bits;
273     int major_version;
274     int minor_version;
275     int num_am_buffers;
276 } MPIDI_OFI_capabilities_t;
277 
278 typedef struct {
279     fi_addr_t dest;
280     int rank;
281     int state;
282 } MPIDI_OFI_conn_t;
283 
284 typedef struct MPIDI_OFI_conn_manager_t {
285     int max_n_conn;             /* Maximum number of connections up to this point */
286     int n_conn;                 /* Current number of open connections */
287     int next_conn_id;           /* The next connection id to be used. */
288     int *free_conn_id;          /* The list of the next connection id to be used so we
289                                  * can garbage collect as we go. */
290     MPIDI_OFI_conn_t *conn_list;        /* The list of connection structs to track the
291                                          * outstanding dynamic process connections. */
292 } MPIDI_OFI_conn_manager_t;
293 
294 /* Global state data */
295 #define MPIDI_KVSAPPSTRLEN 1024
296 typedef struct {
297     /* OFI objects */
298     int avtid;
299     struct fi_info *prov_use;
300     struct fid_fabric *fabric;
301 
302     struct fid_stx *rma_stx_ctx;        /* shared TX context for RMA */
303     struct fid_ep *rma_sep;     /* dedicated scalable EP for RMA */
304 
305     int got_named_av;
306 
307     /* Queryable limits */
308     uint64_t max_buffered_send;
309     uint64_t max_buffered_write;
310     uint64_t max_msg_size;
311     uint64_t max_short_send;
312     uint64_t max_mr_key_size;
313     uint64_t max_rma_key_bits;
314     uint64_t max_huge_rmas;
315     int rma_key_type_bits;
316     int context_shift;
317     size_t tx_iov_limit;
318     size_t rx_iov_limit;
319     size_t rma_iov_limit;
320     int max_rma_sep_tx_cnt;     /* Max number of transmit context on one RMA scalable EP */
321     size_t max_order_raw;
322     size_t max_order_war;
323     size_t max_order_waw;
324 
325     /* Mutexes and endpoints */
326     MPIDI_OFI_cacheline_mutex_t mutexes[MAX_OFI_MUTEXES];
327     MPIDI_OFI_context_t ctx[MPIDI_OFI_MAX_VNIS];
328     int num_vnis;
329 
330     /* Window/RMA Globals */
331     void *win_map;
332     uint64_t rma_issued_cntr;
333     /* OFI atomics limitation of each pair of <dtype, op> returned by the
334      * OFI provider at MPI initialization.*/
335     MPIDI_OFI_atomic_valid_t win_op_table[MPIR_DATATYPE_N_PREDEFINED][MPIDIG_ACCU_NUM_OP];
336     UT_array *rma_sep_idx_array;        /* Array of available indexes of transmit contexts on sep */
337 
338     /* Active Message Globals */
339     struct iovec am_iov[MPIDI_OFI_MAX_NUM_AM_BUFFERS];
340     struct fi_msg am_msg[MPIDI_OFI_MAX_NUM_AM_BUFFERS];
341     void *am_bufs[MPIDI_OFI_MAX_NUM_AM_BUFFERS];
342     MPIDI_OFI_am_repost_request_t am_reqs[MPIDI_OFI_MAX_NUM_AM_BUFFERS];
343     MPIDU_genq_private_pool_t am_hdr_buf_pool;
344     MPL_atomic_int_t am_inflight_inject_emus;
345     MPL_atomic_int_t am_inflight_rma_send_mrs;
346     /* Sequence number trackers for active messages */
347     void *am_send_seq_tracker;
348     void *am_recv_seq_tracker;
349     /* Queue (utlist) to store early-arrival active messages */
350     MPIDI_OFI_am_unordered_msg_t *am_unordered_msgs;
351 
352     /* Pack buffers for various communication */
353     MPIDU_genq_private_pool_t pack_buf_pool;
354 
355     /* Completion queue buffering */
356     MPIDI_OFI_cq_buff_entry_t cq_buffered_static_list[MPIDI_OFI_NUM_CQ_BUFFERED];
357     int cq_buffered_static_head;
358     int cq_buffered_static_tail;
359     MPIDI_OFI_cq_list_t *cq_buffered_dynamic_head, *cq_buffered_dynamic_tail;
360 
361     /* Process management and PMI globals */
362     int pname_set;
363     int pname_len;
364     char addrname[FI_NAME_MAX];
365     size_t addrnamelen;
366     char pname[MPI_MAX_PROCESSOR_NAME];
367     int port_name_tag_mask[MPIR_MAX_CONTEXT_MASK];
368 
369     /* Communication info for dynamic processes */
370     MPIDI_OFI_conn_manager_t conn_mgr;
371 
372     void *req_map;
373     MPIDI_OFI_deferred_am_isend_req_t *deferred_am_isend_q;
374 
375     /* Capability settings */
376 #ifdef MPIDI_OFI_ENABLE_RUNTIME_CHECKS
377     MPIDI_OFI_capabilities_t settings;
378 #endif
379 } MPIDI_OFI_global_t;
380 
381 typedef struct {
382     int16_t type;
383     int16_t seqno;
384     int origin_rank;
385     MPIR_Request *ackreq;
386     uintptr_t send_buf;
387     size_t msgsize;
388     int comm_id;
389     uint64_t rma_key;
390     int tag;
391     int vni_src;
392     int vni_dst;
393 } MPIDI_OFI_send_control_t;
394 
395 typedef struct MPIDI_OFI_win_acc_hint {
396     uint64_t dtypes_max_count[MPIR_DATATYPE_N_PREDEFINED];      /* translate CH4 which_accumulate_ops hints to
397                                                                  * atomicity support of all OFI datatypes. A datatype
398                                                                  * is supported only when all enabled ops are valid atomic
399                                                                  * provided by the OFI provider (recored in MPIDI_OFI_global.win_op_table).
400                                                                  * Invalid <dtype, op> defined in MPI standard are excluded.
401                                                                  * This structure is prepared at window creation time. */
402 } MPIDI_OFI_win_acc_hint_t;
403 
404 enum {
405     MPIDI_OFI_PUT,
406     MPIDI_OFI_GET,
407     MPIDI_OFI_ACC,
408     MPIDI_OFI_GET_ACC,
409 };
410 
411 typedef struct MPIDI_OFI_pack_chunk {
412     struct MPIDI_OFI_pack_chunk *next;
413     void *pack_buffer;
414     MPI_Aint unpack_size;
415     MPI_Aint unpack_offset;
416 } MPIDI_OFI_pack_chunk;
417 
418 typedef struct MPIDI_OFI_win_request {
419     struct MPIDI_OFI_win_request *next;
420     struct MPIDI_OFI_win_request *prev;
421     int rma_type;
422     MPIR_Request **sigreq;
423     MPIDI_OFI_pack_chunk *chunks;
424     union {
425         struct {
426             struct {
427                 const void *addr;
428                 int count;
429                 MPI_Datatype datatype;
430                 MPI_Aint total_bytes;
431                 MPI_Aint pack_offset;
432             } origin;
433             struct {
434                 void *base;
435                 int count;
436                 MPI_Datatype datatype;
437                 struct iovec *iov;
438                 MPI_Aint iov_len;
439                 MPI_Aint total_iov_len;
440                 MPI_Aint iov_offset;
441                 MPI_Aint iov_cur;
442                 MPIDI_av_entry_t *addr;
443                 uint64_t key;
444             } target;
445         } put;
446         struct {
447             struct {
448                 void *addr;
449                 int count;
450                 MPI_Datatype datatype;
451                 MPI_Aint total_bytes;
452                 MPI_Aint pack_offset;
453             } origin;
454             struct {
455                 void *base;
456                 int count;
457                 MPI_Datatype datatype;
458                 struct iovec *iov;
459                 MPI_Aint iov_len;
460                 MPI_Aint total_iov_len;
461                 MPI_Aint iov_offset;
462                 MPI_Aint iov_cur;
463                 MPIDI_av_entry_t *addr;
464                 uint64_t key;
465             } target;
466         } get;
467     } noncontig;
468 } MPIDI_OFI_win_request_t;
469 
470 typedef struct {
471     char pad[MPIDI_REQUEST_HDR_SIZE];
472     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
473     int event_id;               /* fixed field, do not move */
474     MPIR_Request *parent;       /* Parent request           */
475 } MPIDI_OFI_chunk_request;
476 
477 typedef struct MPIDI_OFI_target_mr {
478     uint64_t addr;              /* Unlikely used. Needed for calculating relative offset
479                                  * only when FI_MR_VIRT_ADDRESS is off but registration with MPI_BOTTOM fails
480                                  * at win creation. However, we always store it for code simplicity. */
481     uint64_t mr_key;
482 } MPIDI_OFI_target_mr_t;
483 
484 typedef struct MPIDI_OFI_huge_recv {
485     char pad[MPIDI_REQUEST_HDR_SIZE];
486     struct fi_context context[MPIDI_OFI_CONTEXT_STRUCTS];       /* fixed field, do not move */
487     int event_id;               /* fixed field, do not move */
488     int (*done_fn) (struct fi_cq_tagged_entry * wc, MPIR_Request * req, int event_id);
489     MPIDI_OFI_send_control_t remote_info;
490     bool peek;                  /* Flag to indicate whether this struct has been created to track an uncompleted peek
491                                  * operation. */
492     size_t cur_offset;
493     MPIR_Comm *comm_ptr;
494     MPIR_Request *localreq;
495     struct fi_cq_tagged_entry wc;
496     struct MPIDI_OFI_huge_recv *next;   /* Points to the next entry in the unexpected list
497                                          * (when in the unexpected list) */
498 } MPIDI_OFI_huge_recv_t;
499 
500 /* The list of posted huge receives that haven't been matched yet. These need
501  * to get matched up when handling the control message that starts transfering
502  * data from the remote memory region and we need a way of matching up the
503  * control messages with the "real" requests. */
504 typedef struct MPIDI_OFI_huge_recv_list {
505     int comm_id;
506     int rank;
507     int tag;
508     MPIR_Request *rreq;
509     struct MPIDI_OFI_huge_recv_list *next;
510 } MPIDI_OFI_huge_recv_list_t;
511 
512 /* Externs */
513 extern MPIDI_OFI_global_t MPIDI_OFI_global;
514 extern MPIDI_OFI_huge_recv_t *MPIDI_unexp_huge_recv_head;
515 extern MPIDI_OFI_huge_recv_t *MPIDI_unexp_huge_recv_tail;
516 extern MPIDI_OFI_huge_recv_list_t *MPIDI_posted_huge_recv_head;
517 extern MPIDI_OFI_huge_recv_list_t *MPIDI_posted_huge_recv_tail;
518 
519 extern MPIDI_OFI_capabilities_t MPIDI_OFI_caps_list[MPIDI_OFI_NUM_SETS];
520 
521 #endif /* OFI_TYPES_H_INCLUDED */
522