1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#pragma once
#include "fastfetch.h"
#ifdef FF_HAVE_THREADS
#if defined(_WIN32)
#include <winternl.h>
#include <synchapi.h>
#include <process.h>
#include <processthreadsapi.h>
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
typedef SRWLOCK FFThreadMutex;
typedef HANDLE FFThreadType;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) {
AcquireSRWLockExclusive(mutex);
}
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) {
ReleaseSRWLockExclusive(mutex);
}
static inline FFThreadType ffThreadCreate(unsigned(__stdcall* func)(void*), void* data) {
return (FFThreadType) _beginthreadex(NULL, 0, func, data, 0, NULL);
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) \
static __stdcall unsigned fn##ThreadMain(void* data) { \
fn((paramType) data); \
return 0; \
}
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) \
static __stdcall unsigned fn##ThreadMain() { \
fn(); \
return 0; \
}
static inline void ffThreadDetach(FFThreadType thread) {
NtClose(thread);
}
static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout) {
if (NtWaitForSingleObject(thread, FALSE, timeout == 0 ? NULL : &(LARGE_INTEGER) { .QuadPart = (int64_t) timeout * -10000 }) != STATUS_WAIT_0) {
TerminateThread(thread, (DWORD) -1);
NtClose(thread);
return false;
}
NtClose(thread);
return true;
}
#else
#include <pthread.h>
#include <signal.h>
#if FF_HAVE_PTHREAD_NP
#include <pthread_np.h>
#endif
typedef pthread_t FFThreadType;
#if __APPLE__
#include <os/lock.h>
#define FF_THREAD_MUTEX_INITIALIZER OS_UNFAIR_LOCK_INIT
typedef os_unfair_lock FFThreadMutex;
static inline void ffThreadMutexLock(os_unfair_lock* mutex) {
os_unfair_lock_lock(mutex);
}
static inline void ffThreadMutexUnlock(os_unfair_lock* mutex) {
os_unfair_lock_unlock(mutex);
}
#else
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t FFThreadMutex;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) {
pthread_mutex_lock(mutex);
}
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) {
pthread_mutex_unlock(mutex);
}
#endif
static inline FFThreadType ffThreadCreate(void* (*func)(void*), void* data) {
FFThreadType newThread = 0;
pthread_create(&newThread, NULL, func, data);
return newThread;
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) \
static void* fn##ThreadMain(void* data) { \
fn((paramType) data); \
return NULL; \
}
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) \
static void* fn##ThreadMain() { \
fn(); \
return NULL; \
}
static inline void ffThreadDetach(FFThreadType thread) {
pthread_detach(thread);
}
static inline bool ffThreadJoin(FFThreadType thread, FF_A_UNUSED uint32_t timeout) {
#if HAVE_TIMEDJOIN_NP
if (timeout > 0) {
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
ts.tv_sec += timeout / 1000;
ts.tv_nsec += (timeout % 1000) * 1000000;
if (pthread_timedjoin_np(thread, NULL, &ts) != 0) {
pthread_kill(thread, SIGTERM);
return false;
}
return true;
}
}
#endif
pthread_join(thread, NULL);
return true;
}
#endif
#else // FF_HAVE_THREADS
#define FF_THREAD_MUTEX_INITIALIZER 0
typedef char FFThreadMutex;
static inline void ffThreadMutexLock(FF_A_UNUSED FFThreadMutex* mutex) {}
static inline void ffThreadMutexUnlock(FF_A_UNUSED FFThreadMutex* mutex) {}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType)
#endif // FF_HAVE_THREADS
|