1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
4 * reserved.
5 * $COPYRIGHT$
6 *
7 * Additional copyrights may follow
8 *
9 * $HEADER$
10 */
11
12 #ifndef OMPI_OSC_RDMA_PEER_H
13 #define OMPI_OSC_RDMA_PEER_H
14
15 #include "osc_rdma_types.h"
16
17 struct ompi_osc_rdma_module_t;
18
19 /**
20 * @brief osc rdma peer object
21 *
22 * This object is used as a cache for information associated with a peer.
23 */
24 struct ompi_osc_rdma_peer_t {
25 opal_list_item_t super;
26
27 /** rdma data endpoint for this peer */
28 struct mca_btl_base_endpoint_t *data_endpoint;
29
30 /** endpoint for reading/modifying peer state */
31 struct mca_btl_base_endpoint_t *state_endpoint;
32
33 /** remote peer's state pointer */
34 osc_rdma_base_t state;
35
36 /** registration handle associated with the state */
37 mca_btl_base_registration_handle_t *state_handle;
38
39 /** lock to protrct peer structure */
40 opal_mutex_t lock;
41
42 /** rank of this peer in the window */
43 int rank;
44
45 /** peer flags */
46 opal_atomic_int32_t flags;
47 };
48 typedef struct ompi_osc_rdma_peer_t ompi_osc_rdma_peer_t;
49
50 /**
51 * @brief peer object used when using dynamic windows
52 */
53 struct ompi_osc_rdma_peer_dynamic_t {
54 ompi_osc_rdma_peer_t super;
55
56 /** last region id seen for this peer */
57 uint32_t region_id;
58
59 /** number of regions in the regions array */
60 uint32_t region_count;
61
62 /** cached array of attached regions for this peer */
63 struct ompi_osc_rdma_region_t *regions;
64 };
65
66 typedef struct ompi_osc_rdma_peer_dynamic_t ompi_osc_rdma_peer_dynamic_t;
67
68 /**
69 * @brief basic peer object for non-dynamic windows used when all peers
70 * have the same displacement unit and size
71 */
72 struct ompi_osc_rdma_peer_basic_t {
73 ompi_osc_rdma_peer_t super;
74
75 /** remote peer's base pointer */
76 osc_rdma_base_t base;
77
78 /** local pointer to peer's base */
79 osc_rdma_base_t local_base;
80
81 /** registration handle associated with the base */
82 mca_btl_base_registration_handle_t *base_handle;
83 };
84
85 typedef struct ompi_osc_rdma_peer_basic_t ompi_osc_rdma_peer_basic_t;
86
87 /**
88 * @brief peer object used when no assumption can be made about the
89 * peer's displacement unit or size
90 */
91 struct ompi_osc_rdma_peer_extended_t {
92 ompi_osc_rdma_peer_basic_t super;
93
94 /** remote peer's region size */
95 osc_rdma_size_t size;
96
97 /** displacement unit */
98 int disp_unit;
99 };
100
101 typedef struct ompi_osc_rdma_peer_extended_t ompi_osc_rdma_peer_extended_t;
102
103 /**
104 * @brief object class declarations
105 */
106 OBJ_CLASS_DECLARATION(ompi_osc_rdma_peer_t);
107 OBJ_CLASS_DECLARATION(ompi_osc_rdma_peer_dynamic_t);
108 OBJ_CLASS_DECLARATION(ompi_osc_rdma_peer_basic_t);
109 OBJ_CLASS_DECLARATION(ompi_osc_rdma_peer_extended_t);
110
111 /**
112 * @brief used to identify the node and local rank of a peer
113 */
114 struct ompi_osc_rdma_rank_data_t {
115 /** index of none in none_comm_info array */
116 unsigned int node_id;
117 /** local rank of process */
118 unsigned int rank;
119 };
120 typedef struct ompi_osc_rdma_rank_data_t ompi_osc_rdma_rank_data_t;
121
122 enum {
123 /** peer is locked for exclusive access */
124 OMPI_OSC_RDMA_PEER_EXCLUSIVE = 0x01,
125 /** peer's base is accessible with direct loads/stores */
126 OMPI_OSC_RDMA_PEER_LOCAL_BASE = 0x02,
127 /** peer state is local */
128 OMPI_OSC_RDMA_PEER_LOCAL_STATE = 0x04,
129 /** currently accumulating on peer */
130 OMPI_OSC_RDMA_PEER_ACCUMULATING = 0x08,
131 /** peer is in an active access epoch (pscw) */
132 OMPI_OSC_RDMA_PEER_ACCESS_ACTIVE_EPOCH = 0x10,
133 /** peer state handle should be freed */
134 OMPI_OSC_RDMA_PEER_STATE_FREE = 0x20,
135 /** peer base handle should be freed */
136 OMPI_OSC_RDMA_PEER_BASE_FREE = 0x40,
137 /** peer was demand locked as part of lock-all (when in demand locking mode) */
138 OMPI_OSC_RDMA_PEER_DEMAND_LOCKED = 0x80,
139 };
140
141 /**
142 * @brief allocate a peer object and initialize some of it structures
143 *
144 * @param[in] module osc rdma module
145 * @param[in] peer_id peer's rank in the communicator
146 * @param[out] peer_out new peer object
147 *
148 * The type of the object returned depends on the window settings. For example for a dynamic window
149 * this will return a peer of type \ref ompi_osc_rdma_peer_dynamic_t.
150 */
151 int ompi_osc_rdma_new_peer (struct ompi_osc_rdma_module_t *module, int peer_id, ompi_osc_rdma_peer_t **peer_out);
152
153 /**
154 * @brief lookup (or allocate) a peer
155 *
156 * @param[in] module osc rdma module
157 * @param[in] peer_id peer's rank in the communicator
158 *
159 * This function is used by the ompi_osc_rdma_module_peer() inline function to allocate a peer object. It is not
160 * intended to be called from anywhere else.
161 */
162 struct ompi_osc_rdma_peer_t *ompi_osc_rdma_peer_lookup (struct ompi_osc_rdma_module_t *module, int peer_id);
163
164 /**
165 * @brief lookup the btl endpoint for a peer
166 *
167 * @param[in] module osc rdma module
168 * @param[in] peer_id peer's rank in the communicator
169 *
170 * @returns btl endpoint for the peer on success
171 * @returns NULL on failure
172 */
173 struct mca_btl_base_endpoint_t *ompi_osc_rdma_peer_btl_endpoint (struct ompi_osc_rdma_module_t *module, int peer_id);
174
175 /**
176 * @brief check if this process holds an exclusive lock on a peer
177 *
178 * @param[in] peer peer object to check
179 */
180 static inline bool ompi_osc_rdma_peer_is_exclusive (ompi_osc_rdma_peer_t *peer)
181 {
182 return !!(peer->flags & OMPI_OSC_RDMA_PEER_EXCLUSIVE);
183 }
184
185 /**
186 * @brief try to set a flag on a peer object
187 *
188 * @param[in] peer peer object to modify
189 * @param[in] flag flag to set
190 *
191 * @returns true if the flag was not already set
192 * @returns flase otherwise
193 */
194 static inline bool ompi_osc_rdma_peer_test_set_flag (ompi_osc_rdma_peer_t *peer, int flag)
195 {
196 int32_t flags;
197
198 opal_atomic_mb ();
199 flags = peer->flags;
200
201 do {
202 if (flags & flag) {
203 return false;
204 }
205 } while (!OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_32 (&peer->flags, &flags, flags | flag));
206
207 return true;
208 }
209
210 /**
211 * @brief clear a flag from a peer object
212 *
213 * @param[in] peer peer object to modify
214 * @param[in] flag flag to set
215 */
216 static inline void ompi_osc_rdma_peer_clear_flag (ompi_osc_rdma_peer_t *peer, int flag)
217 {
218 OPAL_ATOMIC_AND_FETCH32(&peer->flags, ~flag);
219 opal_atomic_mb ();
220 }
221
222 /**
223 * @brief check if the peer's base pointer is local to this process
224 *
225 * @param[in] peer peer object to check
226 */
227 static inline bool ompi_osc_rdma_peer_local_base (ompi_osc_rdma_peer_t *peer)
228 {
229 return !!(peer->flags & OMPI_OSC_RDMA_PEER_LOCAL_BASE);
230 }
231
232 /**
233 * @brief check if the peer's state pointer is local to this process
234 *
235 * @param[in] peer peer object to check
236 *
237 * The OMPI_OSC_RDMA_PEER_LOCAL_STATE flag will only be set if either 1) we
238 * will not be mixing btl atomics and cpu atomics, or 2) it is safe to mix
239 * btl and cpu atomics.
240 */
241 static inline bool ompi_osc_rdma_peer_local_state (ompi_osc_rdma_peer_t *peer)
242 {
243 return !!(peer->flags & OMPI_OSC_RDMA_PEER_LOCAL_STATE);
244 }
245
246 /**
247 * @brief check if the peer has been demand locked as part of the current epoch
248 *
249 * @param[in] peer peer object to check
250 *
251 */
252 static inline bool ompi_osc_rdma_peer_is_demand_locked (ompi_osc_rdma_peer_t *peer)
253 {
254 return !!(peer->flags & OMPI_OSC_RDMA_PEER_DEMAND_LOCKED);
255 }
256
257 #endif /* OMPI_OSC_RDMA_PEER_H */