2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
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.
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.
36 #include "orsl-lite/include/orsl-lite.h"
38 #define DISABLE_SYMBOL_VERSIONING
40 #if defined(__linux__) && !defined(DISABLE_SYMBOL_VERSIONING)
41 #define symver(src, tgt, verstr) __asm__(".symver " #src "," #tgt verstr)
42 symver(ORSLReserve0
, ORSLReserve
, "@@ORSL_0.0");
43 symver(ORSLTryReserve0
, ORSLTryReserve
, "@@ORSL_0.0");
44 symver(ORSLReservePartial0
, ORSLReservePartial
, "@@ORSL_0.0");
45 symver(ORSLRelease0
, ORSLRelease
, "@@ORSL_0.0");
47 #define ORSLReserve0 ORSLReserve
48 #define ORSLTryReserve0 ORSLTryReserve
49 #define ORSLReservePartial0 ORSLReservePartial
50 #define ORSLRelease0 ORSLRelease
55 static pthread_mutex_t global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
56 static pthread_cond_t release_cond
= PTHREAD_COND_INITIALIZER
;
61 #pragma intrinsic(_ReadWriteBarrier)
62 static SRWLOCK global_mutex
= SRWLOCK_INIT
;
63 static volatile int release_cond_initialized
= 0;
64 static CONDITION_VARIABLE release_cond
;
66 static void state_lazy_init_sync()
68 if (!release_cond_initialized
) {
69 AcquireSRWLockExclusive(&global_mutex
);
71 if (!release_cond_initialized
) {
72 InitializeConditionVariable(&release_cond
);
73 release_cond_initialized
= 1;
75 ReleaseSRWLockExclusive(&global_mutex
);
80 static int state_lock()
83 return pthread_mutex_lock(&global_mutex
);
87 AcquireSRWLockExclusive(&global_mutex
);
92 static int state_unlock()
95 return pthread_mutex_unlock(&global_mutex
);
99 ReleaseSRWLockExclusive(&global_mutex
);
104 static int state_wait_for_release()
107 return pthread_cond_wait(&release_cond
, &global_mutex
);
111 return SleepConditionVariableSRW(&release_cond
,
112 &global_mutex
, INFINITE
, 0) == 0 ? 1 : 0;
116 static int state_signal_release()
119 return pthread_cond_signal(&release_cond
);
123 WakeConditionVariable(&release_cond
);
129 char owner
[ORSL_MAX_TAG_LEN
+ 1];
130 unsigned long rsrv_cnt
;
131 } rsrv_data
[ORSL_MAX_CARDS
];
133 static int check_args(const int n
, const int *__restrict inds
,
134 const ORSLBusySet
*__restrict bsets
,
135 const ORSLTag __restrict tag
)
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
++) {
147 if (ind
< 0 || ind
>= ORSL_MAX_CARDS
) return -1;
148 if (card_specified
[ind
]) return -1;
149 card_specified
[ind
] = 1;
154 static int check_bsets(const int n
, const ORSLBusySet
*bsets
)
157 for (i
= 0; i
< n
; i
++)
158 if (bsets
[i
].type
== BUSY_SET_PARTIAL
) return -1;
162 static int can_reserve_card(int card
, const ORSLBusySet
*__restrict bset
,
163 const ORSLTag __restrict tag
)
166 assert(bset
!= NULL
);
167 assert(strlen((char *)tag
) < ORSL_MAX_TAG_LEN
);
168 assert(bset
->type
!= BUSY_SET_PARTIAL
);
170 return (bset
->type
== BUSY_SET_EMPTY
||
171 ((rsrv_data
[card
].rsrv_cnt
== 0 ||
173 rsrv_data
[card
].owner
, ORSL_MAX_TAG_LEN
) == 0) &&
174 rsrv_data
[card
].rsrv_cnt
< ULONG_MAX
)) ? 0 : - 1;
177 static void reserve_card(int card
, const ORSLBusySet
*__restrict bset
,
178 const ORSLTag __restrict tag
)
181 assert(bset
!= NULL
);
182 assert(strlen((char *)tag
) < ORSL_MAX_TAG_LEN
);
183 assert(bset
->type
!= BUSY_SET_PARTIAL
);
185 if (bset
->type
== BUSY_SET_EMPTY
)
188 assert(rsrv_data
[card
].rsrv_cnt
== 0 ||
190 rsrv_data
[card
].owner
, ORSL_MAX_TAG_LEN
) == 0);
191 assert(rsrv_data
[card
].rsrv_cnt
< ULONG_MAX
);
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
++;
199 static int can_release_card(int card
, const ORSLBusySet
*__restrict bset
,
200 const ORSLTag __restrict tag
)
203 assert(bset
!= NULL
);
204 assert(strlen((char *)tag
) < ORSL_MAX_TAG_LEN
);
205 assert(bset
->type
!= BUSY_SET_PARTIAL
);
207 return (bset
->type
== BUSY_SET_EMPTY
|| (rsrv_data
[card
].rsrv_cnt
> 0 &&
209 rsrv_data
[card
].owner
, ORSL_MAX_TAG_LEN
) == 0)) ? 0 : 1;
212 static void release_card(int card
, const ORSLBusySet
*__restrict bset
,
213 const ORSLTag __restrict tag
)
216 assert(bset
!= NULL
);
217 assert(strlen((char *)tag
) < ORSL_MAX_TAG_LEN
);
218 assert(bset
->type
!= BUSY_SET_PARTIAL
);
220 if (bset
->type
== BUSY_SET_EMPTY
)
223 assert(strncmp((char *)tag
,
224 rsrv_data
[card
].owner
, ORSL_MAX_TAG_LEN
) == 0);
225 assert(rsrv_data
[card
].rsrv_cnt
> 0);
227 rsrv_data
[card
].rsrv_cnt
--;
230 int ORSLReserve0(const int n
, const int *__restrict inds
,
231 const ORSLBusySet
*__restrict bsets
,
232 const ORSLTag __restrict tag
)
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
;
242 /* Loop until we find that all the resources we want are available */
245 for (i
= 0; i
< n
; i
++)
246 if (can_reserve_card(inds
[i
], &bsets
[i
], tag
) != 0) {
248 /* Wait for someone to release some resources */
249 state_wait_for_release();
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
);
262 int ORSLTryReserve0(const int n
, const int *__restrict inds
,
263 const ORSLBusySet
*__restrict bsets
,
264 const ORSLTag __restrict tag
)
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
;
274 /* Check resource availability once */
275 for (i
= 0; i
< n
; i
++)
276 if (can_reserve_card(inds
[i
], &bsets
[i
], tag
) != 0)
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
);
290 int ORSLReservePartial0(const ORSLPartialGranularity gran
, const int n
,
291 const int *__restrict inds
, ORSLBusySet
*__restrict bsets
,
292 const ORSLTag __restrict tag
)
295 int i
, num_avail
= n
;
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
;
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) {
310 bsets
[i
].type
= BUSY_SET_EMPTY
;
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
);
327 int ORSLRelease0(const int n
, const int *__restrict inds
,
328 const ORSLBusySet
*__restrict bsets
,
329 const ORSLTag __restrict tag
)
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
;
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)
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
);
348 state_signal_release();