1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2012 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2006-2007 Voltaire. All rights reserved.
14 * Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved.
15 * Copyright (c) 2010-2015 Los Alamos National Security, LLC.
16 * All rights reserved.
17 * Copyright (c) 2010-2012 IBM Corporation. All rights reserved.
18 * $COPYRIGHT$
19 *
20 * Additional copyrights may follow
21 *
22 * $HEADER$
23 */
24 #ifndef MCA_BTL_SMCUDA_FIFO_H
25 #define MCA_BTL_SMCUDA_FIFO_H
26
27 #include "btl_smcuda.h"
28 #include "btl_smcuda_endpoint.h"
29
30 static void
31 add_pending(struct mca_btl_base_endpoint_t *ep, void *data, bool resend)
32 {
33 btl_smcuda_pending_send_item_t *si;
34 opal_free_list_item_t *i;
35 i = opal_free_list_get (&mca_btl_smcuda_component.pending_send_fl);
36
37 /* don't handle error for now */
38 assert(i != NULL);
39
40 si = (btl_smcuda_pending_send_item_t*)i;
41 si->data = data;
42
43 OPAL_THREAD_ADD_FETCH32(&mca_btl_smcuda_component.num_pending_sends, +1);
44
45 /* if data was on pending send list then prepend it to the list to
46 * minimize reordering */
47 OPAL_THREAD_LOCK(&ep->endpoint_lock);
48 if (resend)
49 opal_list_prepend(&ep->pending_sends, (opal_list_item_t*)si);
50 else
51 opal_list_append(&ep->pending_sends, (opal_list_item_t*)si);
52 OPAL_THREAD_UNLOCK(&ep->endpoint_lock);
53 }
54
55 /*
56 * FIFO_MAP(x) defines which FIFO on the receiver should be used
57 * by sender rank x. The map is some many-to-one hash.
58 *
59 * FIFO_MAP_NUM(n) defines how many FIFOs the receiver has for
60 * n senders.
61 *
62 * That is,
63 *
64 * for all 0 <= x < n:
65 *
66 * 0 <= FIFO_MAP(x) < FIFO_MAP_NUM(n)
67 *
68 * For example, using some power-of-two nfifos, we could have
69 *
70 * FIFO_MAP(x) = x & (nfifos-1)
71 * FIFO_MAP_NUM(n) = min(nfifos,n)
72 *
73 * Interesting limits include:
74 *
75 * nfifos very large: In this case, each sender has its
76 * own dedicated FIFO on each receiver and the receiver
77 * has one FIFO per sender.
78 *
79 * nfifos == 1: In this case, all senders use the same
80 * FIFO and each receiver has just one FIFO for all senders.
81 */
82 #define FIFO_MAP(x) ((x) & (mca_btl_smcuda_component.nfifos - 1))
83 #define FIFO_MAP_NUM(n) ( (mca_btl_smcuda_component.nfifos) < (n) ? (mca_btl_smcuda_component.nfifos) : (n) )
84
85
86 #define MCA_BTL_SMCUDA_FIFO_WRITE(endpoint_peer, my_smp_rank, \
87 peer_smp_rank, hdr, resend, retry_pending_sends, rc) \
88 do { \
89 sm_fifo_t* fifo = &(mca_btl_smcuda_component.fifo[peer_smp_rank][FIFO_MAP(my_smp_rank)]); \
90 \
91 if ( retry_pending_sends ) { \
92 if ( 0 < opal_list_get_size(&endpoint_peer->pending_sends) ) { \
93 btl_smcuda_process_pending_sends(endpoint_peer); \
94 } \
95 } \
96 \
97 opal_atomic_lock(&(fifo->head_lock)); \
98 /* post fragment */ \
99 if(sm_fifo_write(hdr, fifo) != OPAL_SUCCESS) { \
100 add_pending(endpoint_peer, hdr, resend); \
101 rc = OPAL_ERR_RESOURCE_BUSY; \
102 } else { \
103 MCA_BTL_SMCUDA_SIGNAL_PEER(endpoint_peer); \
104 rc = OPAL_SUCCESS; \
105 } \
106 opal_atomic_unlock(&(fifo->head_lock)); \
107 } while(0)
108
109 #endif