51Degrees Device Detection C/C++  4.2

A device detection library that is used natively or by 51Degrees products

threading.h

1 /* *********************************************************************
2  * This Original Work is copyright of 51 Degrees Mobile Experts Limited.
3  * Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
4  * Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
5  *
6  * This Original Work is licensed under the European Union Public Licence (EUPL)
7  * v.1.2 and is subject to its terms as set out below.
8  *
9  * If a copy of the EUPL was not distributed with this file, You can obtain
10  * one at https://opensource.org/licenses/EUPL-1.2.
11  *
12  * The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
13  * amended by the European Commission) shall be deemed incompatible for
14  * the purposes of the Work and the provisions of the compatibility
15  * clause in Article 5 of the EUPL shall not apply.
16  *
17  * If using the Work as, or as part of, a network application, by
18  * including the attribution notice(s) required under Article 5 of the EUPL
19  * in the end user terms of the application under an appropriate heading,
20  * such notice(s) shall fulfill the requirements of that article.
21  * ********************************************************************* */
22 
33 #ifndef FIFTYONE_DEGREES_THREADING_INCLUDED
34 #define FIFTYONE_DEGREES_THREADING_INCLUDED
35 
36 #include <stdbool.h>
37 #include <stdint.h>
38 
39 #ifdef __cplusplus
40 #define EXTERNAL extern "C"
41 #else
42 #define EXTERNAL
43 #endif
44 
53 
57 #ifdef _MSC_VER
58 #define FIFTYONE_DEGREES_THREAD_ROUTINE LPTHREAD_START_ROUTINE
59 #else
60 typedef void*(*FIFTYONE_DEGREES_THREAD_ROUTINE)(void*);
61 #endif
62 
63 /* Define NDEBUG if needed, to ensure asserts are disabled in release builds */
64 #if !defined(DEBUG) && !defined(_DEBUG) && !defined(NDEBUG)
65 #define NDEBUG
66 #endif
67 
68 #ifdef _MSC_VER
69 #include <windows.h>
70 #include <intrin.h>
71 #pragma intrinsic (_InterlockedIncrement)
72 #pragma intrinsic (_InterlockedDecrement)
73 #else
74 #include <pthread.h>
75 #include <signal.h>
76 #endif
77 #include <assert.h>
78 
87 #ifdef _MSC_VER
88 typedef HANDLE fiftyoneDegreesMutex;
89 #else
90 typedef pthread_mutex_t fiftyoneDegreesMutex;
100 EXTERNAL void fiftyoneDegreesMutexClose(fiftyoneDegreesMutex *mutex);
105 EXTERNAL void fiftyoneDegreesMutexLock(fiftyoneDegreesMutex *mutex);
111 #endif
112 
117 #ifdef _MSC_VER
118 typedef HANDLE fiftyoneDegreesSignal;
119 #else
120 typedef struct fiftyone_degrees_signal_t {
121  volatile bool wait;
122  pthread_cond_t cond;
123  pthread_mutex_t mutex;
125 #endif
126 
137 
148 
157 
165 
169 #ifdef _MSC_VER
170 #define FIFTYONE_DEGREES_THREAD HANDLE
171 #else
172 #define FIFTYONE_DEGREES_THREAD pthread_t
173 #endif
174 
180 #define FIFTYONE_DEGREES_SIGNAL_CREATE(s) s = fiftyoneDegreesSignalCreate()
181 
186 #define FIFTYONE_DEGREES_SIGNAL_CLOSE(s) fiftyoneDegreesSignalClose(s)
187 
192 #define FIFTYONE_DEGREES_SIGNAL_SET(s) fiftyoneDegreesSignalSet(s)
193 
198 #define FIFTYONE_DEGREES_SIGNAL_WAIT(s) fiftyoneDegreesSignalWait(s)
199 
204 #ifdef _MSC_VER
205 #define FIFTYONE_DEGREES_MUTEX_CREATE(m) m = CreateMutex(NULL,FALSE,NULL)
206 #else
207 #define FIFTYONE_DEGREES_MUTEX_CREATE(m) fiftyoneDegreesMutexCreate(&m)
208 #endif
209 
214 #ifdef _MSC_VER
215 #define FIFTYONE_DEGREES_MUTEX_CLOSE(m) if (m != NULL) { CloseHandle(m); }
216 #else
217 #define FIFTYONE_DEGREES_MUTEX_CLOSE(m) fiftyoneDegreesMutexClose(&m)
218 #endif
219 
224 #ifdef _MSC_VER
225 #define FIFTYONE_DEGREES_MUTEX_LOCK(m) WaitForSingleObject(*m, INFINITE)
226 #else
227 #define FIFTYONE_DEGREES_MUTEX_LOCK(m) fiftyoneDegreesMutexLock(m)
228 #endif
229 
234 #ifdef _MSC_VER
235 #define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) ReleaseMutex(*m)
236 #else
237 #define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) fiftyoneDegreesMutexUnlock(m)
238 #endif
239 
245 #ifdef _MSC_VER
246 #define FIFTYONE_DEGREES_MUTEX_VALID(m) (*m != NULL)
247 #else
248 #define FIFTYONE_DEGREES_MUTEX_VALID(m) fiftyoneDegreesMutexValid(m)
249 #endif
250 
258 #ifdef _MSC_VER
259 #define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) t = \
260  (FIFTYONE_DEGREES_THREAD)CreateThread(NULL, 0, m, s, 0, NULL)
261 #else
262 #define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) pthread_create(&t, NULL, m, s)
263 #endif
264 
270 #ifdef _MSC_VER
271 #define FIFTYONE_DEGREES_THREAD_JOIN(t) WaitForSingleObject(t, INFINITE)
272 #else
273 #define FIFTYONE_DEGREES_THREAD_JOIN(t) pthread_join(t, NULL)
274 #endif
275 
280 #ifdef _MSC_VER
281 #define FIFTYONE_DEGREES_THREAD_CLOSE(t) CloseHandle(t)
282 #else
283 #define FIFTYONE_DEGREES_THREAD_CLOSE(t)
284 #endif
285 
289 #ifdef _MSC_VER
290 #define FIFTYONE_DEGREES_THREAD_EXIT ExitThread(0)
291 #else
292 #define FIFTYONE_DEGREES_THREAD_EXIT pthread_exit(NULL)
293 #endif
294 
300 #ifdef _MSC_VER
301 #define FIFTYONE_DEGREES_INTERLOCK_INC(v) _InterlockedIncrement(v)
302 #else
303 #define FIFTYONE_DEGREES_INTERLOCK_INC(v) (__sync_add_and_fetch(v, 1))
304 #endif
305 
311 #ifdef _MSC_VER
312 #define FIFTYONE_DEGREES_INTERLOCK_DEC(v) _InterlockedDecrement(v)
313 #else
314 #define FIFTYONE_DEGREES_INTERLOCK_DEC(v) (__sync_add_and_fetch(v, -1))
315 #endif
316 
325 #ifdef _MSC_VER
326 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
327  InterlockedCompareExchange(&d, e, c)
328 #else
329 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
330  __sync_val_compare_and_swap(&d,c,e)
331 #endif
332 
341 #ifdef _MSC_VER
342 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
343  InterlockedCompareExchange64((volatile __int64*)&d, (__int64)e, (__int64)c)
344 #else
345 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
346  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
347 #endif
348 
357 #ifdef _MSC_VER
358 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
359  InterlockedCompareExchangePointer((volatile PVOID*)&d,e,c)
360 #else
361 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
362  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
363 #endif
364 
365 #ifndef _MSC_VER
366 
385 static __inline int
387  void* destination,
388  const void* exchange,
389  void* compare)
390 {
391  char result;
392  __asm __volatile("lock cmpxchg16b %0; setz %3"
393  : "+m" (*(void**)destination),
394  "=a" (((void**)compare)[0]),
395  "=d" (((void**)compare)[1]),
396  "=q" (result)
397  : "a" (((void**)compare)[0]),
398  "d" (((void**)compare)[1]),
399  "b" (((const void**)exchange)[0]),
400  "c" (((const void**)exchange)[1])
401  : "memory", "cc");
402  return (result);
403 }
404 #endif
405 
415 #ifdef _MSC_VER
416 #ifdef _WIN64
417 typedef struct fiftyone_degrees_interlock_dw_type_t {
418  LONG64 low;
419  LONG64 high;
421 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
422  InterlockedCompareExchange128(&d.low, e.high, e.low, &c.low)
423 #else
424 typedef struct fiftyone_degrees_interlock_dw_type_t {
425  LONG64 value;
427 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
428  InterlockedCompareExchange64(&d.value, e.value, c.value) == c.value
429 #endif
430 #else
431 #if defined(__x86_64__) || defined(__aarch64__)
432 typedef struct fiftyone_degrees_interlock_dw_type_t {
433  int64_t low;
434  int64_t high;
436 #else
437 typedef struct fiftyone_degrees_interlock_dw_type_t {
438  int64_t value;
440 #endif
441 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
442  (sizeof(void*) == 8 ? \
443  __fod_sync_bool_compare_and_swap_16((void*)&d, (void*)&e, (void*)&c) : \
444  __sync_bool_compare_and_swap((int64_t*)&d, *((int64_t*)&c), *((int64_t*)&e)))
445 #endif
446 
451 #endif
void fiftyoneDegreesMutexCreate(fiftyoneDegreesMutex *mutex)
Initialises the mutex passed to the method.
void fiftyoneDegreesMutexUnlock(fiftyoneDegreesMutex *mutex)
Unlocks the mutex passed to the method.
pthread_mutex_t mutex
Mutex for the signal.
Definition: threading.h:123
void fiftyoneDegreesMutexLock(fiftyoneDegreesMutex *mutex)
Locks the mutex passed to the method.
fiftyoneDegreesSignal * fiftyoneDegreesSignalCreate()
Initialises the signal pointer by setting the condition first followed by the mutex if the condition ...
pthread_mutex_t fiftyoneDegreesMutex
MUTEX AND THREADING MACROS.
Definition: threading.h:90
void fiftyoneDegreesMutexClose(fiftyoneDegreesMutex *mutex)
Closes the mutex passed to the method.
pthread_cond_t cond
Condition variable for the signal.
Definition: threading.h:122
A signal used to limit the number of items that can be created by the pool.
Definition: threading.h:120
bool fiftyoneDegreesThreadingGetIsThreadSafe()
Determines if the methods that should be thread safe have been compiled so they are thread safe.
void fiftyoneDegreesSignalWait(fiftyoneDegreesSignal *signal)
Wait for a signal to be set.
static __inline int __fod_sync_bool_compare_and_swap_16(void *destination, const void *exchange, void *compare)
Implements the __sync_bool_compare_and_swap_16 function which is often not implemtned by the compiler...
Definition: threading.h:386
void fiftyoneDegreesSignalClose(fiftyoneDegreesSignal *signal)
Closes the signal ensuring there is a lock on the signal before destroying the signal.
volatile bool wait
Flag indicating if the thread should wait.
Definition: threading.h:121
void fiftyoneDegreesSignalSet(fiftyoneDegreesSignal *signal)
If the signal has not been destroyed then sends a signal to a waiting thread that the signal has been...
Double width (64 or 128 depending on the architecture) compare and exchange.
Definition: threading.h:437