photon  1.1
photon_event.c
Go to the documentation of this file.
1 // =============================================================================
2 // Photon RDMA Library (libphoton)
3 //
4 // Copyright (c) 2016, Trustees of Indiana University,
5 // All rights reserved.
6 //
7 // This software may be modified and distributed under the terms of the BSD
8 // license. See the COPYING file for details.
9 //
10 // This software was created at the Indiana University Center for Research in
11 // Extreme Scale Technologies (CREST).
12 // =============================================================================
13 
14 #include <assert.h>
15 
16 #include "photon_event.h"
17 #include "photon_pwc.h"
18 
20  uint32_t prefix;
21  prefix = (uint32_t)(cookie>>32);
22 
23  if (cookie == NULL_REQUEST)
24  return PHOTON_EVENT_OK;
25 
26  switch (prefix) {
27  case REQUEST_COOK_GPWC:
28  case REQUEST_COOK_EAGER:
29  break;
30  case REQUEST_COOK_EBUF:
31  {
32  int proc = (int)(cookie<<32>>32);
33  assert(IS_VALID_PROC(proc));
34  sync_store(&photon_processes[proc].remote_eager_buf->acct.rloc, 0, SYNC_RELEASE);
35  }
36  break;
37  case REQUEST_COOK_PBUF:
38  {
39  int proc = (int)(cookie<<32>>32);
40  assert(IS_VALID_PROC(proc));
41  sync_store(&photon_processes[proc].remote_pwc_buf->acct.rloc, 0, SYNC_RELEASE);
42  }
43  break;
44  case REQUEST_COOK_FIN:
45  {
46  int proc = (int)(cookie<<32>>32);
47  assert(IS_VALID_PROC(proc));
48  sync_store(&photon_processes[proc].remote_fin_ledger->acct.rloc, 0, SYNC_RELEASE);
49  }
50  break;
51  case REQUEST_COOK_RINFO:
52  {
53  int proc = (int)(cookie<<32>>32);
54  assert(IS_VALID_PROC(proc));
55  sync_store(&photon_processes[proc].remote_rcv_info_ledger->acct.rloc, 0, SYNC_RELEASE);
56  }
57  break;
58  case REQUEST_COOK_SINFO:
59  {
60  int proc = (int)(cookie<<32>>32);
61  assert(IS_VALID_PROC(proc));
62  sync_store(&photon_processes[proc].remote_snd_info_ledger->acct.rloc, 0, SYNC_RELEASE);
63  }
64  break;
65  case REQUEST_COOK_ELEDG:
66  {
67  int proc = (int)(cookie<<32>>32);
68  assert(IS_VALID_PROC(proc));
69  sync_store(&photon_processes[proc].remote_eager_ledger->acct.rloc, 0, SYNC_RELEASE);
70  }
71  break;
72  case REQUEST_COOK_PLEDG:
73  {
74  int proc = (int)(cookie<<32>>32);
75  assert(IS_VALID_PROC(proc));
76  sync_store(&photon_processes[proc].remote_pwc_ledger->acct.rloc, 0, SYNC_RELEASE);
77  }
78  break;
79  default:
80  return PHOTON_EVENT_ERROR;
81  break;
82  }
83 
84  return PHOTON_EVENT_OK;
85 }
86 
87 int __photon_get_event(int proc, photon_rid *id) {
88  int nevents, rc = PHOTON_EVENT_NONE;
89 
90 #ifdef HAVE_SHMEM
91  rc = __photon_shmem->get_event(proc, 1, id, &nevents);
92  if (rc == PHOTON_EVENT_ERROR) {
93  dbg_err("Error getting shmem event, rx=%d", rc);
94  }
95 #endif
96 
97  if (__photon_fabric) {
98  if (rc == PHOTON_EVENT_NONE) {
99  rc = __photon_fabric->get_event(proc, 1, id, &nevents);
100  if (rc == PHOTON_EVENT_ERROR) {
101  dbg_err("Error getting event, rc=%d", rc);
102  }
103  }
104  }
105 
106  if (rc == PHOTON_EVENT_OK) {
107  dbg_trace("got event: 0x%016lx", *id);
108  }
109 
110  return rc;
111 }
112 
113 int __photon_get_nevents(int proc, int max, photon_rid **ids, int *n) {
114  int rc = PHOTON_EVENT_NONE;
115 
116 #ifdef HAVE_SHMEM
117  rc = __photon_shmem->get_event(proc, max, *ids, n);
118  if (rc == PHOTON_EVENT_ERROR) {
119  dbg_err("Error getting shmem event, rx=%d", rc);
120  }
121 #endif
122 
123  if (__photon_fabric) {
124  if (rc == PHOTON_EVENT_NONE) {
125  rc = __photon_fabric->get_event(proc, max, *ids, n);
126  if (rc == PHOTON_EVENT_ERROR) {
127  dbg_err("Error getting events");
128  }
129  }
130  }
131 
132  if (rc == PHOTON_EVENT_OK) {
133  dbg_trace("got %d events", *n);
134  }
135 
136  return rc;
137 }
138 
139 int __photon_get_revent(int proc, photon_rid *id, uint64_t *imm) {
140  int nevents, rc = PHOTON_EVENT_NONE;
141 
142  if (__photon_fabric) {
143  rc = __photon_fabric->get_revent(proc, 1, id, imm, &nevents);
144  if (rc == PHOTON_EVENT_ERROR) {
145  dbg_err("Error getting revent");
146  }
147  }
148 
149  if (rc == PHOTON_EVENT_OK) {
150  dbg_trace("got revent: 0x%016lx (imm=0x%016lx)", *id, *imm);
151  }
152 
153  return rc;
154 }
155 
156 int __photon_get_revents(int proc, int max, photon_rid **ids, uint64_t **imms, int *n) {
157  int rc = PHOTON_EVENT_NONE;
158 
159  if (__photon_fabric) {
160  rc = __photon_fabric->get_revent(proc, max, *ids, *imms, n);
161  if (rc == PHOTON_EVENT_ERROR) {
162  dbg_err("Error getting revents");
163  }
164  }
165 
166  if (rc == PHOTON_EVENT_OK) {
167  dbg_trace("got %d revents", *n);
168  }
169 
170  return rc;
171 }
172 
174  int rc ;
175 
176  rc = __photon_handle_cq_special(cookie);
177  if (rc == PHOTON_EVENT_OK) {
178  return PHOTON_EVENT_OK;
179  }
180 
181  // if we pass in a request to test
182  if (req) {
183  // mark complete if request is type EVQUEUE and request id matches the event
184  if ((cookie == req->id) && (req->type == EVQUEUE)) {
185  req->state = REQUEST_COMPLETED;
186  *rreq = req;
187  dbg_trace("Set request completed with rid: 0x%016lx", cookie);
188  return PHOTON_EVENT_REQCOMP;
189  }
190  }
191 
192  // if no request, or request didn't match, then do a lookup
193  photonRequest treq;
194  treq = photon_lookup_request(cookie);
195  if (treq) {
196  if (treq->type == EVQUEUE) {
197  int nentries = sync_addf(&treq->rattr.events, -1, SYNC_RELAXED);
198  if (nentries == 0) {
199  treq->state = REQUEST_COMPLETED;
200  dbg_trace("Set request completed, rid: 0x%016lx", cookie);
201  *rreq = treq;
202  return PHOTON_EVENT_REQCOMP;
203  }
204  else if (nentries != 1) {
205  dbg_info("Unexpected nentries value: %d, op=%d, 0x%016lx",
206  nentries, treq->op, treq->flags);
207  }
208  }
209  else if (treq->type == LEDGER) {
210  // this was an RDMA event associated with a ledger
211  // mark the request as having the local completion popped
212  treq->flags |= REQUEST_FLAG_LDONE;
213  dbg_trace("Set local completion done flag for ledger rid: 0x%016lx", cookie);
214  }
215  *rreq = treq;
216  return PHOTON_EVENT_REQFOUND;
217  }
218  else {
219  dbg_warn("Got an event that we did not expect: 0x%016lx", cookie);
220  return PHOTON_EVENT_ERROR;
221  }
222 
223  return PHOTON_EVENT_OK;
224 }
225 
226 
228 // __photon_nbpop_event() is non blocking and returns:
229 // PHOTON_EVENT_ERROR if an error occured.
230 // PHOTON_EVENT_REQCOMP if the request (req) specified in the argument has completed.
231 // PHOTON_EVENT_OK if there was an event but not for the specified request (req).
232 // PHOTON_EVENT_NONE if there was no event
234  int rc;
235 
236  dbg_trace("(%d/0x%016lx)", req->proc, req->id);
237 
238  // EAGER exception
239  // this request was EAGER and the associated os_get() is done
240  if (req->flags & REQUEST_FLAG_EDONE) {
241  req->state = REQUEST_COMPLETED;
242  }
243 
244  if (req->state == REQUEST_PENDING) {
245  photon_rid cookie;
246  photonRequest treq;
247  rc = __photon_get_event(PHOTON_ANY_SOURCE, &cookie);
248  if (rc == PHOTON_EVENT_OK) {
249  rc = __photon_handle_cq_event(req, cookie, &treq);
250  if (rc == PHOTON_EVENT_ERROR) {
251  goto error_exit;
252  }
253  else if ((rc == PHOTON_EVENT_REQCOMP) && treq &&
254  (treq->op == REQUEST_OP_PWC)) {
255  photon_pwc_add_req(treq);
256  dbg_trace("Enqueuing PWC local completion");
257  return PHOTON_EVENT_OK;
258  }
259  }
260  else {
261  return rc;
262  }
263  }
264 
265  dbg_trace("returning %d", (req->state == REQUEST_COMPLETED)?PHOTON_EVENT_REQCOMP:PHOTON_EVENT_OK);
267 
268 error_exit:
269  return PHOTON_EVENT_ERROR;
270 }
271 
273 
274  return PHOTON_OK;
275 }
276 
278 // returns
279 // PHOTON_EVENT_ERROR if an error occured.
280 // PHOTON_EVENT_REQCOMP if the FIN associated with "req" was found and popped, or
281 // the "req" is not pending. This is not an error, if a previous
282 // call to __photon_nbpop_ledger() popped the FIN that
283 // corresponds to "req".
284 // PHOTON_EVENT_NONE if the request is pending and the FIN has not arrived yet
286  uint64_t curr;
287  int c_ind, i=-1;
288 
289  dbg_trace("(0x%016lx)", req->id);
290 
291  if (req->state == REQUEST_PENDING) {
292 
293  // clear any completed tasks from the event queue
295  ;
296 
297  // Check if an entry of the FIN LEDGER was written with "id" equal to "req"
298  for(i = 0; i < _photon_nproc; i++) {
299  photonRDMALedgerEntry curr_entry, entries;
301  entries = (photonRDMALedgerEntry)l->entries;
302  curr = sync_load(&l->curr, SYNC_RELAXED);
303  c_ind = curr & (l->num_entries - 1);
304  curr_entry = &(entries[c_ind]);
305  if ((curr_entry->request != (uint64_t) NULL_REQUEST) &&
306  sync_cas(&l->curr, &curr, curr+1, SYNC_RELAXED, SYNC_RELAXED)) {
307  dbg_trace("Found curr: %d, req: 0x%016lx while looking for req: 0x%016lx",
308  c_ind, curr_entry->request, req->id);
309 
310  if (curr_entry->request == req->id) {
311  req->state = REQUEST_COMPLETED;
312  }
313  // handle requests we are not looking for
314  else {
315  photonRequest treq;
316  if ((treq = photon_lookup_request(curr_entry->request)) != NULL) {
317  dbg_trace("Setting request completed, rid: 0x%016lx", curr_entry->request);
318  treq->state = REQUEST_COMPLETED;
319  }
320  }
321  // reset entry
322  curr_entry->request = NULL_REQUEST;
323  sync_fadd(&l->prog, 1, SYNC_RELAXED);
324  }
325  }
326  }
327 
328  if ((req->state != REQUEST_COMPLETED) && (req->state != REQUEST_PENDING)) {
329  dbg_warn("req->state != (PENDING | COMPLETE), returning 0");
330  return PHOTON_EVENT_OK;
331  }
332 
333  dbg_trace("at end, returning %d", (req->state == REQUEST_COMPLETED)?PHOTON_EVENT_REQCOMP:PHOTON_EVENT_NONE);
335 }
336 
338  uint64_t curr;
339  int c_ind, i=-1;
340 
341  dbg_trace("(0x%016lx)",req->id);
342 
343 #ifdef CALLTRACE
344  for(i = 0; i < _photon_nproc; i++) {
345  photonRDMALedgerEntry curr_entry;
346  curr = photon_processes[i].local_fin_ledger->curr;
347  curr_entry = &(photon_processes[i].local_fin_ledger->entries[curr]);
348  dbg_trace("curr_entry(proc==%d)=%p", i ,curr_entry);
349  }
350 #endif
351  while (req->state == REQUEST_PENDING) {
352 
353  // clear any completed tasks from the event queue
355  ;
356 
357  // Check if an entry of the FIN LEDGER was written with "id" equal to "req"
358  for(i = 0; i < _photon_nproc; i++) {
359  photonRDMALedgerEntry curr_entry, entries;
361  entries = (photonRDMALedgerEntry)l->entries;
362  curr = sync_load(&l->curr, SYNC_RELAXED);
363  c_ind = curr & (l->num_entries - 1);
364  curr_entry = &(entries[c_ind]);
365  if ((curr_entry->request != (uint64_t) 0) &&
366  sync_cas(&l->curr, &curr, curr+1, SYNC_RELAXED, SYNC_RELAXED)) {
367  dbg_trace("Found: %d/0x%016lx/0x%016lx", c_ind, curr_entry->request, req->id);
368 
369  if (curr_entry->request == req->id) {
370  req->state = REQUEST_COMPLETED;
371  }
372  else {
373  photonRequest treq;
374  if ((treq = photon_lookup_request(curr_entry->request)) != NULL) {
375  treq->state = REQUEST_COMPLETED;
376  }
377  }
378  curr_entry->request = NULL_REQUEST;
379  sync_fadd(&l->prog, 1, SYNC_RELAXED);
380  }
381  }
382  }
383 
384  return (req->state == REQUEST_COMPLETED)?PHOTON_OK:PHOTON_ERROR;
385 }
386 
388  int rc;
389  photon_rid cookie;
390  photonRequest treq;
391 
392  rc = __photon_get_event(PHOTON_ANY_SOURCE, &cookie);
393  if (rc != PHOTON_OK) {
394  return rc;
395  }
396 
397  rc = __photon_handle_cq_event(NULL, cookie, &treq);
398  if (rc == PHOTON_EVENT_ERROR) {
399  goto error_exit;
400  }
401 
402  if ((rc == PHOTON_EVENT_REQCOMP) && treq) {
403  if (treq->op == REQUEST_OP_PWC) {
404  photon_pwc_add_req(treq);
405  dbg_trace("Enqueuing PWC local completion");
406  }
407  else {
408  *rreq = treq;
409  return PHOTON_EVENT_REQCOMP;
410  }
411  }
412 
413  return PHOTON_EVENT_OK;
414  error_exit:
415  return PHOTON_EVENT_ERROR;
416 }
417 
419  int rc;
420  photonRequest treq = NULL;
421 
422  do {
423  rc = __photon_try_one_event(&treq);
424  } while (rc != PHOTON_EVENT_REQCOMP);
425 
426  assert(treq && treq->id == req->id);
427 
428  return PHOTON_OK;
429 }
#define REQUEST_FLAG_LDONE
int __photon_nbpop_sr(photonRequest req)
Definition: photon_event.c:272
int __photon_get_event(int proc, photon_rid *id)
Definition: photon_event.c:87
int __photon_get_revent(int proc, photon_rid *id, uint64_t *imm)
Definition: photon_event.c:139
photonRequest photon_lookup_request(photon_rid rid)
#define PHOTON_EVENT_REQCOMP
Definition: photon_event.h:26
#define LEDGER
int __photon_handle_cq_event(photonRequest req, photon_rid cookie, photonRequest *rreq)
Definition: photon_event.c:173
#define EVQUEUE
#define REQUEST_COOK_PBUF
int _photon_nproc
Definition: libphoton.c:55
struct photon_rdma_ledger_entry_t * photonRDMALedgerEntry
photonBackend __photon_shmem
Definition: libphoton.c:49
int __photon_get_nevents(int proc, int max, photon_rid **ids, int *n)
Definition: photon_event.c:113
uint64_t photon_rid
The Photon request ID.
Definition: photon.h:75
#define IS_VALID_PROC(p)
photonBackend __photon_fabric
Definition: libphoton.c:50
#define PHOTON_ANY_SOURCE
RNDV and PWC flag: return completions from any source.
Definition: photon.h:54
#define REQUEST_COOK_RINFO
#define REQUEST_COOK_EAGER
#define REQUEST_COOK_SINFO
#define REQUEST_COOK_GPWC
int __photon_nbpop_ledger(photonRequest req)
Definition: photon_event.c:285
#define REQUEST_COOK_ELEDG
int __photon_nbpop_event(photonRequest req)
Definition: photon_event.c:233
#define REQUEST_COOK_EBUF
struct photon_req_t * photonRequest
ProcessInfo * photon_processes
#define NULL_REQUEST
#define PHOTON_EVENT_NONE
Definition: photon_event.h:25
#define PHOTON_ERROR
Error code, general error.
Definition: photon.h:32
#define REQUEST_COOK_FIN
#define PHOTON_OK
Photon success code.
Definition: photon.h:30
#define REQUEST_FLAG_EDONE
int __photon_get_revents(int proc, int max, photon_rid **ids, uint64_t **imms, int *n)
Definition: photon_event.c:156
#define REQUEST_COOK_PLEDG
struct photon_rdma_ledger_t * photonLedger
int __photon_wait_event(photonRequest req)
Definition: photon_event.c:418
#define PHOTON_EVENT_ERROR
Definition: photon_event.h:24
#define REQUEST_OP_PWC
int __photon_handle_cq_special(photon_rid cookie)
Definition: photon_event.c:19
int __photon_wait_ledger(photonRequest req)
Definition: photon_event.c:337
int photon_pwc_add_req(photonRequest req)
Definition: photon_pwc.c:749
int __photon_try_one_event(photonRequest *rreq)
Definition: photon_event.c:387
#define PHOTON_EVENT_REQFOUND
Definition: photon_event.h:27
#define PHOTON_EVENT_OK
Definition: photon_event.h:23
#define REQUEST_COMPLETED
#define REQUEST_PENDING
photonLedger local_fin_ledger