1 /*
2 * Copyright (c) 2015-2016 Intel Corporation, 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 #ifdef _WIN32
34
35 #include "netdir.h"
36 #include "netdir_ov.h"
37 #include "netdir_iface.h"
38
39 #include "rdma/fabric.h"
40 #include "ofi_util.h"
41
42 static int ofi_nd_cntr_close(struct fid *fid);
43 static uint64_t ofi_nd_cntr_read(struct fid_cntr *cntr);
44 static uint64_t ofi_nd_cntr_readerr(struct fid_cntr *cntr);
45 static int ofi_nd_cntr_add(struct fid_cntr *cntr, uint64_t value);
46 static int ofi_nd_cntr_set(struct fid_cntr *cntr, uint64_t value);
47 static int ofi_nd_cntr_wait(struct fid_cntr *cntr,
48 uint64_t threshold, int timeout);
49
50 static struct fi_ops ofi_nd_fi_ops = {
51 .size = sizeof(ofi_nd_fi_ops),
52 .close = ofi_nd_cntr_close,
53 .bind = fi_no_bind,
54 .control = fi_no_control,
55 .ops_open = fi_no_ops_open,
56 };
57
58 static struct fid ofi_nd_fid = {
59 .fclass = FI_CLASS_CNTR,
60 .context = NULL,
61 .ops = &ofi_nd_fi_ops
62 };
63
64 static struct fi_ops_cntr ofi_nd_cntr_ops = {
65 .size = sizeof(ofi_nd_cntr_ops),
66 .read = ofi_nd_cntr_read,
67 .readerr = ofi_nd_cntr_readerr,
68 .add = ofi_nd_cntr_add,
69 .set = ofi_nd_cntr_set,
70 .wait = ofi_nd_cntr_wait
71 };
72
ofi_nd_cntr_close(struct fid * fid)73 static int ofi_nd_cntr_close(struct fid *fid)
74 {
75 assert(fid->fclass == FI_CLASS_CNTR);
76 if (fid->fclass != FI_CLASS_CQ)
77 return -FI_EINVAL;
78
79 struct nd_cntr *cntr = container_of(fid, struct nd_cntr, fid.fid);
80
81 free(cntr);
82
83 return FI_SUCCESS;
84 }
85
ofi_nd_cntr_open(struct fid_domain * pdomain,struct fi_cntr_attr * attr,struct fid_cntr ** pcntr,void * context)86 int ofi_nd_cntr_open(struct fid_domain *pdomain, struct fi_cntr_attr *attr,
87 struct fid_cntr **pcntr, void *context)
88 {
89 OFI_UNUSED(context);
90
91 assert(pdomain);
92 assert(pdomain->fid.fclass == FI_CLASS_DOMAIN);
93
94 if (attr) {
95 if (attr->wait_obj != FI_WAIT_NONE &&
96 attr->wait_obj != FI_WAIT_UNSPEC)
97 return -FI_EBADFLAGS;
98 }
99
100 struct nd_cntr *cntr = (struct nd_cntr*)calloc(1, sizeof(*cntr));
101 if (!cntr)
102 return -FI_ENOMEM;
103
104 struct nd_cntr def = {
105 .fid = {
106 .fid = ofi_nd_fid,
107 .ops = &ofi_nd_cntr_ops
108 },
109 };
110
111 *cntr = def;
112
113 *pcntr = &cntr->fid;
114
115 return FI_SUCCESS;
116 }
117
ofi_nd_cntr_read(struct fid_cntr * pcntr)118 static uint64_t ofi_nd_cntr_read(struct fid_cntr *pcntr)
119 {
120 assert(pcntr);
121 assert(pcntr->fid.fclass == FI_CLASS_CNTR);
122
123 struct nd_cntr *cntr = container_of(pcntr, struct nd_cntr, fid);
124 return cntr->counter;
125 }
126
ofi_nd_cntr_readerr(struct fid_cntr * pcntr)127 static uint64_t ofi_nd_cntr_readerr(struct fid_cntr *pcntr)
128 {
129 assert(pcntr);
130 assert(pcntr->fid.fclass == FI_CLASS_CNTR);
131
132 struct nd_cntr *cntr = container_of(pcntr, struct nd_cntr, fid);
133 return cntr->err;
134 }
135
ofi_nd_cntr_add(struct fid_cntr * pcntr,uint64_t value)136 static int ofi_nd_cntr_add(struct fid_cntr *pcntr, uint64_t value)
137 {
138 assert(pcntr);
139 assert(pcntr->fid.fclass == FI_CLASS_CNTR);
140
141 if (pcntr->fid.fclass != FI_CLASS_CNTR)
142 return -FI_EINVAL;
143
144 struct nd_cntr *cntr = container_of(pcntr, struct nd_cntr, fid);
145
146 cntr->counter += value;
147 WakeByAddressAll((void*)&cntr->counter);
148
149 return FI_SUCCESS;
150 }
151
ofi_nd_cntr_set(struct fid_cntr * pcntr,uint64_t value)152 static int ofi_nd_cntr_set(struct fid_cntr *pcntr, uint64_t value)
153 {
154 assert(pcntr);
155 assert(pcntr->fid.fclass == FI_CLASS_CNTR);
156
157 if (pcntr->fid.fclass != FI_CLASS_CNTR)
158 return -FI_EINVAL;
159
160 struct nd_cntr *cntr = container_of(pcntr, struct nd_cntr, fid);
161
162 cntr->counter = value;
163 WakeByAddressAll((void*)&cntr->counter);
164
165 return FI_SUCCESS;
166 }
167
ofi_nd_cntr_wait(struct fid_cntr * pcntr,uint64_t threshold,int timeout)168 static int ofi_nd_cntr_wait(struct fid_cntr *pcntr,
169 uint64_t threshold, int timeout)
170 {
171 assert(pcntr);
172 assert(pcntr->fid.fclass == FI_CLASS_CNTR);
173
174 if (pcntr->fid.fclass != FI_CLASS_CNTR)
175 return -FI_EINVAL;
176
177 struct nd_cntr *cntr = container_of(pcntr, struct nd_cntr, fid);
178
179 /* process corner timeouts separately to optimize */
180 if (!timeout) { /* no wait */
181 return (cntr->counter >= (LONGLONG)threshold) ?
182 FI_SUCCESS : -FI_ETIMEDOUT;
183 }
184 else if (timeout < 0) { /* infinite wait */
185 while (cntr->counter < (LONG64)threshold) {
186 LONG64 val = cntr->counter;
187 WaitOnAddress(&cntr->counter, &val,
188 sizeof(val), INFINITE);
189 }
190 return FI_SUCCESS;
191 }
192 else { /* timeout wait */
193 OFI_ND_TIMEOUT_INIT(timeout);
194
195 do {
196 if (cntr->counter >= (LONG64)threshold)
197 return FI_SUCCESS;
198 LONG64 val = cntr->counter;
199 WaitOnAddress(&cntr->counter, &val,
200 sizeof(val), timeout);
201 } while (!OFI_ND_TIMEDOUT());
202 }
203
204 return FI_SUCCESS;
205 }
206
207 #endif /* _WIN32 */
208
209