]> git.ipfire.org Git - thirdparty/gcc.git/blame - liboffloadmic/runtime/orsl-lite/lib/orsl-lite.c
backport: Makefile.am (liboffloadmic_host_la_DEPENDENCIES): Remove libcoi_host and...
[thirdparty/gcc.git] / liboffloadmic / runtime / orsl-lite / lib / orsl-lite.c
CommitLineData
5f520819 1/*
2eab9666 2 Copyright (c) 2014-2015 Intel Corporation. All Rights Reserved.
5f520819
KY
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30
31#include <errno.h>
32#include <string.h>
33#include <limits.h>
34#include <assert.h>
35
36#include "orsl-lite/include/orsl-lite.h"
37
38#define DISABLE_SYMBOL_VERSIONING
39
40#if defined(__linux__) && !defined(DISABLE_SYMBOL_VERSIONING)
41#define symver(src, tgt, verstr) __asm__(".symver " #src "," #tgt verstr)
42symver(ORSLReserve0, ORSLReserve, "@@ORSL_0.0");
43symver(ORSLTryReserve0, ORSLTryReserve, "@@ORSL_0.0");
44symver(ORSLReservePartial0, ORSLReservePartial, "@@ORSL_0.0");
45symver(ORSLRelease0, ORSLRelease, "@@ORSL_0.0");
46#else
47#define ORSLReserve0 ORSLReserve
48#define ORSLTryReserve0 ORSLTryReserve
49#define ORSLReservePartial0 ORSLReservePartial
50#define ORSLRelease0 ORSLRelease
51#endif
52
53#ifdef __linux__
54#include <pthread.h>
55static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
56static pthread_cond_t release_cond = PTHREAD_COND_INITIALIZER;
57#endif
58
59#ifdef _WIN32
60#include <windows.h>
61#pragma intrinsic(_ReadWriteBarrier)
62static SRWLOCK global_mutex = SRWLOCK_INIT;
63static volatile int release_cond_initialized = 0;
64static CONDITION_VARIABLE release_cond;
65
66static void state_lazy_init_sync()
67{
68 if (!release_cond_initialized) {
69 AcquireSRWLockExclusive(&global_mutex);
70 _ReadWriteBarrier();
71 if (!release_cond_initialized) {
72 InitializeConditionVariable(&release_cond);
73 release_cond_initialized = 1;
74 }
75 ReleaseSRWLockExclusive(&global_mutex);
76 }
77}
78#endif
79
80static int state_lock()
81{
82#ifdef __linux__
83 return pthread_mutex_lock(&global_mutex);
84#endif
85
86#ifdef _WIN32
87 AcquireSRWLockExclusive(&global_mutex);
88 return 0;
89#endif
90}
91
92static int state_unlock()
93{
94#ifdef __linux__
95 return pthread_mutex_unlock(&global_mutex);
96#endif
97
98#ifdef _WIN32
99 ReleaseSRWLockExclusive(&global_mutex);
100 return 0;
101#endif
102}
103
104static int state_wait_for_release()
105{
106#ifdef __linux__
107 return pthread_cond_wait(&release_cond, &global_mutex);
108#endif
109
110#ifdef _WIN32
111 return SleepConditionVariableSRW(&release_cond,
112 &global_mutex, INFINITE, 0) == 0 ? 1 : 0;
113#endif
114}
115
116static int state_signal_release()
117{
118#ifdef __linux__
119 return pthread_cond_signal(&release_cond);
120#endif
121
122#ifdef _WIN32
123 WakeConditionVariable(&release_cond);
124 return 0;
125#endif
126}
127
128static struct {
129 char owner[ORSL_MAX_TAG_LEN + 1];
130 unsigned long rsrv_cnt;
131} rsrv_data[ORSL_MAX_CARDS];
132
133static int check_args(const int n, const int *__restrict inds,
134 const ORSLBusySet *__restrict bsets,
135 const ORSLTag __restrict tag)
136{
137 int i;
138 int card_specified[ORSL_MAX_CARDS];
139 if (tag == NULL) return -1;
140 if (strlen((char *)tag) > ORSL_MAX_TAG_LEN) return -1;
141 if (n < 0 || n >= ORSL_MAX_CARDS) return -1;
142 if (n != 0 && (inds == NULL || bsets == NULL)) return -1;
143 for (i = 0; i < ORSL_MAX_CARDS; i++)
144 card_specified[i] = 0;
145 for (i = 0; i < n; i++) {
146 int ind = inds[i];
147 if (ind < 0 || ind >= ORSL_MAX_CARDS) return -1;
148 if (card_specified[ind]) return -1;
149 card_specified[ind] = 1;
150 }
151 return 0;
152}
153
154static int check_bsets(const int n, const ORSLBusySet *bsets)
155{
156 int i;
157 for (i = 0; i < n; i++)
158 if (bsets[i].type == BUSY_SET_PARTIAL) return -1;
159 return 0;
160}
161
162static int can_reserve_card(int card, const ORSLBusySet *__restrict bset,
163 const ORSLTag __restrict tag)
164{
165 assert(tag != NULL);
166 assert(bset != NULL);
167 assert(strlen((char *)tag) < ORSL_MAX_TAG_LEN);
168 assert(bset->type != BUSY_SET_PARTIAL);
169
170 return (bset->type == BUSY_SET_EMPTY ||
171 ((rsrv_data[card].rsrv_cnt == 0 ||
172 strncmp((char *)tag,
173 rsrv_data[card].owner, ORSL_MAX_TAG_LEN) == 0) &&
174 rsrv_data[card].rsrv_cnt < ULONG_MAX)) ? 0 : - 1;
175}
176
177static void reserve_card(int card, const ORSLBusySet *__restrict bset,
178 const ORSLTag __restrict tag)
179{
180 assert(tag != NULL);
181 assert(bset != NULL);
182 assert(strlen((char *)tag) < ORSL_MAX_TAG_LEN);
183 assert(bset->type != BUSY_SET_PARTIAL);
184
185 if (bset->type == BUSY_SET_EMPTY)
186 return;
187
188 assert(rsrv_data[card].rsrv_cnt == 0 ||
189 strncmp((char *)tag,
190 rsrv_data[card].owner, ORSL_MAX_TAG_LEN) == 0);
191 assert(rsrv_data[card].rsrv_cnt < ULONG_MAX);
192
193 if (rsrv_data[card].rsrv_cnt == 0)
194 strncpy(rsrv_data[card].owner, (char *)tag, ORSL_MAX_TAG_LEN);
195 rsrv_data[card].owner[ORSL_MAX_TAG_LEN] = '\0';
196 rsrv_data[card].rsrv_cnt++;
197}
198
199static int can_release_card(int card, const ORSLBusySet *__restrict bset,
200 const ORSLTag __restrict tag)
201{
202 assert(tag != NULL);
203 assert(bset != NULL);
204 assert(strlen((char *)tag) < ORSL_MAX_TAG_LEN);
205 assert(bset->type != BUSY_SET_PARTIAL);
206
207 return (bset->type == BUSY_SET_EMPTY || (rsrv_data[card].rsrv_cnt > 0 &&
208 strncmp((char *)tag,
209 rsrv_data[card].owner, ORSL_MAX_TAG_LEN) == 0)) ? 0 : 1;
210}
211
212static void release_card(int card, const ORSLBusySet *__restrict bset,
213 const ORSLTag __restrict tag)
214{
215 assert(tag != NULL);
216 assert(bset != NULL);
217 assert(strlen((char *)tag) < ORSL_MAX_TAG_LEN);
218 assert(bset->type != BUSY_SET_PARTIAL);
219
220 if (bset->type == BUSY_SET_EMPTY)
221 return;
222
223 assert(strncmp((char *)tag,
224 rsrv_data[card].owner, ORSL_MAX_TAG_LEN) == 0);
225 assert(rsrv_data[card].rsrv_cnt > 0);
226
227 rsrv_data[card].rsrv_cnt--;
228}
229
230int ORSLReserve0(const int n, const int *__restrict inds,
231 const ORSLBusySet *__restrict bsets,
232 const ORSLTag __restrict tag)
233{
234 int i, ok;
235
236 if (n == 0) return 0;
237 if (check_args(n, inds, bsets, tag) != 0) return EINVAL;
238 if (check_bsets(n, bsets) != 0) return ENOSYS;
239
240 state_lock();
241
242 /* Loop until we find that all the resources we want are available */
243 do {
244 ok = 1;
245 for (i = 0; i < n; i++)
246 if (can_reserve_card(inds[i], &bsets[i], tag) != 0) {
247 ok = 0;
248 /* Wait for someone to release some resources */
249 state_wait_for_release();
250 break;
251 }
252 } while (!ok);
253
254 /* At this point we are good to reserve_card the resources we want */
255 for (i = 0; i < n; i++)
256 reserve_card(inds[i], &bsets[i], tag);
257
258 state_unlock();
259 return 0;
260}
261
262int ORSLTryReserve0(const int n, const int *__restrict inds,
263 const ORSLBusySet *__restrict bsets,
264 const ORSLTag __restrict tag)
265{
266 int i, rc = EBUSY;
267
268 if (n == 0) return 0;
269 if (check_args(n, inds, bsets, tag) != 0) return EINVAL;
270 if (check_bsets(n, bsets) != 0) return ENOSYS;
271
272 state_lock();
273
274 /* Check resource availability once */
275 for (i = 0; i < n; i++)
276 if (can_reserve_card(inds[i], &bsets[i], tag) != 0)
277 goto bail_out;
278
279 /* At this point we are good to reserve the resources we want */
280 for (i = 0; i < n; i++)
281 reserve_card(inds[i], &bsets[i], tag);
282
283 rc = 0;
284
285bail_out:
286 state_unlock();
287 return rc;
288}
289
290int ORSLReservePartial0(const ORSLPartialGranularity gran, const int n,
291 const int *__restrict inds, ORSLBusySet *__restrict bsets,
292 const ORSLTag __restrict tag)
293{
294 int rc = EBUSY;
295 int i, num_avail = n;
296
297 if (n == 0) return 0;
298 if (gran != GRAN_CARD && gran != GRAN_THREAD) return EINVAL;
299 if (gran != GRAN_CARD) return EINVAL;
300 if (check_args(n, inds, bsets, tag) != 0) return EINVAL;
301 if (check_bsets(n, bsets) != 0) return ENOSYS;
302
303 state_lock();
304
305 /* Check resource availability once; remove unavailable resources from the
306 * user-provided list */
307 for (i = 0; i < n; i++)
308 if (can_reserve_card(inds[i], &bsets[i], tag) != 0) {
309 num_avail--;
310 bsets[i].type = BUSY_SET_EMPTY;
311 }
312
313 if (num_avail == 0)
314 goto bail_out;
315
316 /* At this point we are good to reserve the resources we want */
317 for (i = 0; i < n; i++)
318 reserve_card(inds[i], &bsets[i], tag);
319
320 rc = 0;
321
322bail_out:
323 state_unlock();
324 return rc;
325}
326
327int ORSLRelease0(const int n, const int *__restrict inds,
328 const ORSLBusySet *__restrict bsets,
329 const ORSLTag __restrict tag)
330{
331 int i, rc = EPERM;
332
333 if (n == 0) return 0;
334 if (check_args(n, inds, bsets, tag) != 0) return EINVAL;
335 if (check_bsets(n, bsets) != 0) return ENOSYS;
336
337 state_lock();
338
339 /* Check that we can release all the resources */
340 for (i = 0; i < n; i++)
341 if (can_release_card(inds[i], &bsets[i], tag) != 0)
342 goto bail_out;
343
344 /* At this point we are good to release the resources we want */
345 for (i = 0; i < n; i++)
346 release_card(inds[i], &bsets[i], tag);
347
348 state_signal_release();
349
350 rc = 0;
351
352bail_out:
353 state_unlock();
354 return rc;
355}
356
357/* vim:set et: */