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