OpenMPI  0.1.1
common_ugni.h
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3  * Copyright (c) 2011-2012 Los Alamos National Security, LLC. All rights
4  * reserved.
5  * Copyright (c) 2011 UT-Battelle, LLC. All rights reserved.
6  * $COPYRIGHT$
7  *
8  * Additional copyrights may follow
9  *
10  * $HEADER$
11  */
12 
13 #include "ompi_config.h"
14 
15 #include "opal/util/output.h"
16 #include "opal/class/opal_list.h"
18 #include "opal_stdint.h"
19 
20 #include "ompi/include/ompi/constants.h"
22 #include "ompi/proc/proc.h"
23 
24 #include <errno.h>
25 #include <stdint.h>
26 #include <sys/types.h>
27 #include <assert.h>
28 #include <sys/time.h>
29 #include <gni_pub.h>
30 
31 #include "common_ugni_ep.h"
32 
33 #if !defined(MPI_COMMON_UGNI_H)
34 #define MPI_COMMON_UGNI_H
35 
37  uint32_t addr;
38  int id;
39 };
41 
43  opal_object_t super;
44 
45  gni_nic_handle_t dev_handle;
46 
47  /* Minor number of the Gemini NIC */
48  int32_t dev_id;
49  uint32_t dev_pe_addr;
50  uint32_t dev_addr;
51  uint32_t dev_cpu_id;
52 
53  gni_cq_handle_t dev_local_cq;
54 
55  size_t dev_ep_count;
57  void *btl_ctx;
58 };
60 
62  /* protection tag */
63  uint8_t ptag;
64 
65  /* unique id for this process assigned by the system */
66  uint32_t cookie;
67 
68  /* communication domain handle */
69  gni_cdm_handle_t cd_handle;
70 
71  /* device count. to be used if we have more than 1 common per ugni device */
72  int device_count;
74 
75  int local_cq_size;
76 
77  int rdma_max_retries;
78 };
80 
82  gni_post_descriptor_t base;
83 
85  int tries;
86 
87  /* NTH: callback function for this post. this may change in the future */
88  void (*cbfunc) (struct ompi_common_ugni_post_desc_t *, int);
89 };
91 
92 extern ompi_common_ugni_module_t ompi_common_ugni_module;
93 extern mca_base_component_t ompi_common_ugni_component;
94 
95 static inline int
96 ompi_common_rc_ugni_to_ompi (gni_return_t rc)
97 {
98  int codes[] = {OMPI_SUCCESS,
99  OMPI_ERR_RESOURCE_BUSY,
100  OMPI_ERR_BAD_PARAM,
101  OMPI_ERR_OUT_OF_RESOURCE,
102  OMPI_ERR_TIMEOUT,
103  OMPI_ERR_PERM,
104  OMPI_ERROR,
105  OMPI_ERR_BAD_PARAM,
106  OMPI_ERR_BAD_PARAM,
107  OMPI_ERR_NOT_FOUND,
108  OMPI_ERR_VALUE_OUT_OF_BOUNDS,
109  OMPI_ERROR,
110  OMPI_ERR_NOT_SUPPORTED,
111  OMPI_ERR_OUT_OF_RESOURCE};
112  return codes[rc];
113 }
114 
115 /*
116  * Initialize uGNI communication domain and device(s).
117  */
118 int ompi_common_ugni_init (void);
119 
120 /*
121  * Finalize uGNI communication domain and device(s).
122  */
123 int ompi_common_ugni_fini (void);
124 
125 extern void mca_btl_ugni_local_smsg_complete (void *, uint32_t, int);
126 
127 static inline int
128 ompi_common_ugni_process_completed_post (ompi_common_ugni_device_t *dev,
129  gni_cq_handle_t cq_handle) {
131  gni_return_t rc = GNI_RC_NOT_DONE;
132  gni_cq_entry_t event_data = 0;
133  uint32_t recoverable = 1;
134 
135  rc = GNI_CqGetEvent (cq_handle, &event_data);
136  if (GNI_RC_NOT_DONE == rc) {
137  return 0;
138  }
139 
140  if (OPAL_UNLIKELY((GNI_RC_SUCCESS != rc && !event_data) || GNI_CQ_OVERRUN(event_data))) {
141  /* TODO -- need to handle overrun -- how do we do this without an event?
142  will the event eventually come back? Ask Cray */
143  OPAL_OUTPUT((-1, "post error! cq overrun = %d", (int)GNI_CQ_OVERRUN(event_data)));
144  assert (0);
145  return ompi_common_rc_ugni_to_ompi (rc);
146  }
147 
148  /* local SMS completion */
149  if (GNI_CQ_GET_TYPE(event_data) == GNI_CQ_EVENT_TYPE_SMSG) {
150  uint32_t msg_id = GNI_CQ_GET_MSG_ID(event_data);
151 
152  assert (GNI_CQ_STATUS_OK(event_data));
153 
154  if ((uint32_t)-1 == msg_id) {
155  /* nothing to do */
156  return 1;
157  }
158 
159  /* inform the btl of local smsg completion */
160  mca_btl_ugni_local_smsg_complete (dev->btl_ctx, msg_id,
161  GNI_CQ_STATUS_OK(event_data) ? OMPI_SUCCESS : OMPI_ERROR);
162 
163  return 1;
164  }
165 
166  rc = GNI_GetCompleted (cq_handle, event_data, (gni_post_descriptor_t **) &desc);
167  if (OPAL_UNLIKELY(GNI_RC_SUCCESS != rc)) {
168  OPAL_OUTPUT((-1, "Error in GNI_GetComplete %s", gni_err_str[rc]));
169  return ompi_common_rc_ugni_to_ompi (rc);
170  }
171 
172  if (OPAL_UNLIKELY(!GNI_CQ_STATUS_OK(event_data))) {
173  (void) GNI_CqErrorRecoverable (event_data, &recoverable);
174 
175  if (OPAL_UNLIKELY(!recoverable ||
176  ++desc->tries >= ompi_common_ugni_module.rdma_max_retries)) {
177  OPAL_OUTPUT((-1, "giving up on descriptor %p", (void *) desc));
178  /* give up */
179  desc->cbfunc (desc, OMPI_ERROR);
180 
181  return OMPI_ERROR;
182  }
183 
184  /* repost transaction */
185  if (GNI_POST_RDMA_PUT == desc->base.type ||
186  GNI_POST_RDMA_GET == desc->base.type) {
187  rc = GNI_PostRdma (desc->endpoint->ep_handle, &desc->base);
188  } else {
189  rc = GNI_PostFma (desc->endpoint->ep_handle, &desc->base);
190  }
191 
192  return ompi_common_rc_ugni_to_ompi (rc);
193  }
194 
195  desc->cbfunc (desc, OMPI_SUCCESS);
196 
197  return 1;
198 }
199 
200 static inline int ompi_common_ugni_progress (void) {
202  int count, i;
203 
204  for (i = 0, count = 0 ; i < ompi_common_ugni_module.device_count ; ++i) {
205  dev = ompi_common_ugni_module.devices + i;
206  /* progress fma/local smsg completions */
207  count += ompi_common_ugni_process_completed_post (dev, dev->dev_local_cq);
208  }
209 
210  return count;
211 }
212 
213 #endif /* MPI_COMMON_UGNI_H */
#define OPAL_OUTPUT(a)
Main macro for use in sending debugging output to output streams; will be "compiled out" when OPAL is...
Definition: output.h:534
Common type for all MCA components.
Definition: mca.h:250
OPAL output stream facility.
The opal_list_t interface is used to provide a generic doubly-linked list container for Open MPI...
Process identification structure interface.
Definition: common_ugni.h:61
Definition: common_ugni.h:36
Definition: common_ugni.h:42
gni_ep_handle_t ep_handle
uGNI handle for this endpoint
Definition: common_ugni_ep.h:28
Base object.
Definition: opal_object.h:182
Open MPI module-related data transfer mechanism.
Compiler-specific prefetch functions.
Definition: common_ugni_ep.h:26
Definition: common_ugni.h:81