1 /*
2 * Copyright (c) 2017 Cray Inc. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33 #include "gnix_util.h"
34 #include "gnix_smrn.h"
35
36 static struct gnix_smrn global_smrn;
37
_gnix_smrn_init(void)38 int _gnix_smrn_init(void)
39 {
40 int ret;
41
42 fastlock_init(&global_smrn.lock);
43 global_smrn.references = 0;
44 dlist_init(&global_smrn.rq_head);
45
46 ret = _gnix_notifier_init();
47
48 return ret;
49 }
50
_gnix_smrn_open(struct gnix_smrn ** smrn)51 int _gnix_smrn_open(struct gnix_smrn **smrn)
52 {
53 struct gnix_smrn *tmp = &global_smrn;
54 int ret = FI_SUCCESS;
55
56 fastlock_acquire(&tmp->lock);
57 if (tmp->references == 0)
58 ret = _gnix_notifier_open(&tmp->notifier);
59
60 if (!ret)
61 tmp->references += 1;
62 fastlock_release(&tmp->lock);
63
64 if (!ret)
65 *smrn = tmp;
66
67 return ret;
68 }
69
_gnix_smrn_close(struct gnix_smrn * smrn)70 int _gnix_smrn_close(struct gnix_smrn *smrn)
71 {
72 int ret = FI_SUCCESS;
73
74 fastlock_acquire(&smrn->lock);
75 if (smrn->references == 0)
76 ret = -FI_EINVAL;
77
78 if (smrn->references == 1)
79 ret = _gnix_notifier_close(smrn->notifier);
80
81 if (!ret)
82 smrn->references -= 1;
83 fastlock_release(&smrn->lock);
84
85 return ret;
86 }
87
_gnix_smrn_monitor(struct gnix_smrn * smrn,struct gnix_smrn_rq * rq,void * addr,uint64_t len,uint64_t cookie,struct gnix_smrn_context * context)88 int _gnix_smrn_monitor(struct gnix_smrn *smrn,
89 struct gnix_smrn_rq *rq,
90 void *addr,
91 uint64_t len,
92 uint64_t cookie,
93 struct gnix_smrn_context *context)
94 {
95 int ret;
96
97 if (!context || !rq || !smrn)
98 return -FI_EINVAL;
99
100 context->rq = rq;
101 context->cookie = cookie;
102
103 ret = _gnix_notifier_monitor(smrn->notifier, addr,
104 len, (uint64_t) context);
105 if (ret == FI_SUCCESS)
106 GNIX_DEBUG(FI_LOG_FABRIC,
107 "monitoring addr=%p len=%d cookie=%p "
108 "context=%p rq=%p notifier=%p\n",
109 addr, len, context->cookie,
110 context, rq, smrn->notifier);
111 return ret;
112 }
113
_gnix_smrn_unmonitor(struct gnix_smrn * smrn,uint64_t cookie,struct gnix_smrn_context * context)114 int _gnix_smrn_unmonitor(struct gnix_smrn *smrn,
115 uint64_t cookie,
116 struct gnix_smrn_context *context)
117 {
118 if (!smrn)
119 return -FI_EINVAL;
120
121 if (cookie != context->cookie)
122 return -FI_EINVAL;
123
124 return _gnix_notifier_unmonitor(smrn->notifier, (uint64_t) context);
125 }
126
__gnix_smrn_read_events(struct gnix_smrn * smrn)127 static void __gnix_smrn_read_events(struct gnix_smrn *smrn)
128 {
129 int ret;
130 struct gnix_smrn_context *context;
131 struct gnix_smrn_rq *rq;
132 int len = sizeof(uint64_t);
133
134 do {
135 ret = _gnix_notifier_get_event(smrn->notifier,
136 (void *) &context, len);
137 if (ret != len) {
138 GNIX_DEBUG(FI_LOG_FABRIC,
139 "no more events to be read\n");
140 break;
141 }
142
143 GNIX_DEBUG(FI_LOG_FABRIC,
144 "found event, context=%p rq=%p cookie=%lx\n",
145 context, context->rq, context->cookie);
146
147 rq = context->rq;
148 fastlock_acquire(&rq->lock);
149 dlist_insert_tail(&context->entry, &rq->list);
150 fastlock_release(&rq->lock);
151 } while (ret == len);
152 }
153
_gnix_smrn_get_event(struct gnix_smrn * smrn,struct gnix_smrn_rq * rq,struct gnix_smrn_context ** context)154 int _gnix_smrn_get_event(struct gnix_smrn *smrn,
155 struct gnix_smrn_rq *rq,
156 struct gnix_smrn_context **context)
157 {
158 int ret;
159
160 if (!smrn || !context)
161 return -FI_EINVAL;
162
163 __gnix_smrn_read_events(smrn);
164
165 fastlock_acquire(&rq->lock);
166 if (!dlist_empty(&rq->list)) {
167 dlist_pop_front(&rq->list, struct gnix_smrn_context,
168 *context, entry);
169 ret = FI_SUCCESS;
170 } else
171 ret = -FI_EAGAIN;
172 fastlock_release(&rq->lock);
173
174 return ret;
175 }
176
177