summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/thread/generic
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/thread/generic
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/thread/generic')
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_syscond.c216
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_syscond_c.h36
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex.c132
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex_c.h21
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock.c194
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock_c.h38
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_syssem.c183
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_systhread.c57
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_systhread_c.h24
-rw-r--r--contrib/SDL-3.2.8/src/thread/generic/SDL_systls.c44
10 files changed, 945 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond.c
new file mode 100644
index 0000000..5fdfe84
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond.c
@@ -0,0 +1,216 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// An implementation of condition variables using semaphores and mutexes
24/*
25 This implementation borrows heavily from the BeOS condition variable
26 implementation, written by Christopher Tate and Owen Smith. Thanks!
27 */
28
29#include "../generic/SDL_syscond_c.h"
30
31/* If two implementations are to be compiled into SDL (the active one
32 * will be chosen at runtime), the function names need to be
33 * suffixed
34 */
35#ifndef SDL_THREAD_GENERIC_COND_SUFFIX
36#define SDL_CreateCondition_generic SDL_CreateCondition
37#define SDL_DestroyCondition_generic SDL_DestroyCondition
38#define SDL_SignalCondition_generic SDL_SignalCondition
39#define SDL_BroadcastCondition_generic SDL_BroadcastCondition
40#endif
41
42typedef struct SDL_cond_generic
43{
44 SDL_Semaphore *sem;
45 SDL_Semaphore *handshake_sem;
46 SDL_Semaphore *signal_sem;
47 int num_waiting;
48 int num_signals;
49} SDL_cond_generic;
50
51// Create a condition variable
52SDL_Condition *SDL_CreateCondition_generic(void)
53{
54 SDL_cond_generic *cond = (SDL_cond_generic *)SDL_calloc(1, sizeof(*cond));
55
56#ifndef SDL_THREADS_DISABLED
57 if (cond) {
58 cond->sem = SDL_CreateSemaphore(0);
59 cond->handshake_sem = SDL_CreateSemaphore(0);
60 cond->signal_sem = SDL_CreateSemaphore(1);
61 if (!cond->sem || !cond->handshake_sem || !cond->signal_sem) {
62 SDL_DestroyCondition_generic((SDL_Condition *)cond);
63 cond = NULL;
64 }
65 }
66#endif
67
68 return (SDL_Condition *)cond;
69}
70
71// Destroy a condition variable
72void SDL_DestroyCondition_generic(SDL_Condition *_cond)
73{
74 SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
75 if (cond) {
76 if (cond->sem) {
77 SDL_DestroySemaphore(cond->sem);
78 }
79 if (cond->handshake_sem) {
80 SDL_DestroySemaphore(cond->handshake_sem);
81 }
82 if (cond->signal_sem) {
83 SDL_DestroySemaphore(cond->signal_sem);
84 }
85 SDL_free(cond);
86 }
87}
88
89// Restart one of the threads that are waiting on the condition variable
90void SDL_SignalCondition_generic(SDL_Condition *_cond)
91{
92 SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
93 if (!cond) {
94 return;
95 }
96
97#ifndef SDL_THREADS_DISABLED
98 /* If there are waiting threads not already signalled, then
99 signal the condition and wait for the thread to respond.
100 */
101 SDL_WaitSemaphore(cond->signal_sem);
102 if (cond->num_waiting > cond->num_signals) {
103 cond->num_signals++;
104 SDL_SignalSemaphore(cond->sem);
105 SDL_SignalSemaphore(cond->signal_sem);
106 SDL_WaitSemaphore(cond->handshake_sem);
107 } else {
108 SDL_SignalSemaphore(cond->signal_sem);
109 }
110#endif
111}
112
113// Restart all threads that are waiting on the condition variable
114void SDL_BroadcastCondition_generic(SDL_Condition *_cond)
115{
116 SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
117 if (!cond) {
118 return;
119 }
120
121#ifndef SDL_THREADS_DISABLED
122 /* If there are waiting threads not already signalled, then
123 signal the condition and wait for the thread to respond.
124 */
125 SDL_WaitSemaphore(cond->signal_sem);
126 if (cond->num_waiting > cond->num_signals) {
127 const int num_waiting = (cond->num_waiting - cond->num_signals);
128 cond->num_signals = cond->num_waiting;
129 for (int i = 0; i < num_waiting; i++) {
130 SDL_SignalSemaphore(cond->sem);
131 }
132 /* Now all released threads are blocked here, waiting for us.
133 Collect them all (and win fabulous prizes!) :-)
134 */
135 SDL_SignalSemaphore(cond->signal_sem);
136 for (int i = 0; i < num_waiting; i++) {
137 SDL_WaitSemaphore(cond->handshake_sem);
138 }
139 } else {
140 SDL_SignalSemaphore(cond->signal_sem);
141 }
142#endif
143}
144
145/* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
146 The mutex must be locked before entering this function!
147 The mutex is unlocked during the wait, and locked again after the wait.
148
149Typical use:
150
151Thread A:
152 SDL_LockMutex(lock);
153 while ( ! condition ) {
154 SDL_WaitCondition(cond, lock);
155 }
156 SDL_UnlockMutex(lock);
157
158Thread B:
159 SDL_LockMutex(lock);
160 ...
161 condition = true;
162 ...
163 SDL_SignalCondition(cond);
164 SDL_UnlockMutex(lock);
165 */
166bool SDL_WaitConditionTimeoutNS_generic(SDL_Condition *_cond, SDL_Mutex *mutex, Sint64 timeoutNS)
167{
168 SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
169 bool result = true;
170
171 if (!cond || !mutex) {
172 return true;
173 }
174
175#ifndef SDL_THREADS_DISABLED
176 /* Obtain the protection mutex, and increment the number of waiters.
177 This allows the signal mechanism to only perform a signal if there
178 are waiting threads.
179 */
180 SDL_WaitSemaphore(cond->signal_sem);
181 cond->num_waiting++;
182 SDL_SignalSemaphore(cond->signal_sem);
183
184 // Unlock the mutex, as is required by condition variable semantics
185 SDL_UnlockMutex(mutex);
186
187 // Wait for a signal
188 result = SDL_WaitSemaphoreTimeoutNS(cond->sem, timeoutNS);
189
190 /* Let the signaler know we have completed the wait, otherwise
191 the signaler can race ahead and get the condition semaphore
192 if we are stopped between the mutex unlock and semaphore wait,
193 giving a deadlock. See the following URL for details:
194 http://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
195 */
196 SDL_WaitSemaphore(cond->signal_sem);
197 if (cond->num_signals > 0) {
198 SDL_SignalSemaphore(cond->handshake_sem);
199 cond->num_signals--;
200 }
201 cond->num_waiting--;
202 SDL_SignalSemaphore(cond->signal_sem);
203
204 // Lock the mutex, as is required by condition variable semantics
205 SDL_LockMutex(mutex);
206#endif
207
208 return result;
209}
210
211#ifndef SDL_THREAD_GENERIC_COND_SUFFIX
212bool SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS)
213{
214 return SDL_WaitConditionTimeoutNS_generic(cond, mutex, timeoutNS);
215}
216#endif
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond_c.h b/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond_c.h
new file mode 100644
index 0000000..253c394
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_syscond_c.h
@@ -0,0 +1,36 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_syscond_generic_h_
24#define SDL_syscond_generic_h_
25
26#ifdef SDL_THREAD_GENERIC_COND_SUFFIX
27
28SDL_Condition *SDL_CreateCondition_generic(void);
29void SDL_DestroyCondition_generic(SDL_Condition *cond);
30void SDL_SignalCondition_generic(SDL_Condition *cond);
31void SDL_BroadcastCondition_generic(SDL_Condition *cond);
32bool SDL_WaitConditionTimeoutNS_generic(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS);
33
34#endif // SDL_THREAD_GENERIC_COND_SUFFIX
35
36#endif // SDL_syscond_generic_h_
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex.c
new file mode 100644
index 0000000..e58da67
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex.c
@@ -0,0 +1,132 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// An implementation of mutexes using semaphores
24
25#include "SDL_systhread_c.h"
26
27struct SDL_Mutex
28{
29 int recursive;
30 SDL_ThreadID owner;
31 SDL_Semaphore *sem;
32};
33
34SDL_Mutex *SDL_CreateMutex(void)
35{
36 SDL_Mutex *mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
37
38#ifndef SDL_THREADS_DISABLED
39 if (mutex) {
40 // Create the mutex semaphore, with initial value 1
41 mutex->sem = SDL_CreateSemaphore(1);
42 mutex->recursive = 0;
43 mutex->owner = 0;
44 if (!mutex->sem) {
45 SDL_free(mutex);
46 mutex = NULL;
47 }
48 }
49#endif // !SDL_THREADS_DISABLED
50
51 return mutex;
52}
53
54void SDL_DestroyMutex(SDL_Mutex *mutex)
55{
56 if (mutex) {
57 if (mutex->sem) {
58 SDL_DestroySemaphore(mutex->sem);
59 }
60 SDL_free(mutex);
61 }
62}
63
64void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
65{
66#ifndef SDL_THREADS_DISABLED
67 if (mutex != NULL) {
68 SDL_ThreadID this_thread = SDL_GetCurrentThreadID();
69 if (mutex->owner == this_thread) {
70 ++mutex->recursive;
71 } else {
72 /* The order of operations is important.
73 We set the locking thread id after we obtain the lock
74 so unlocks from other threads will fail.
75 */
76 SDL_WaitSemaphore(mutex->sem);
77 mutex->owner = this_thread;
78 mutex->recursive = 0;
79 }
80 }
81#endif // SDL_THREADS_DISABLED
82}
83
84bool SDL_TryLockMutex(SDL_Mutex *mutex)
85{
86 bool result = true;
87#ifndef SDL_THREADS_DISABLED
88 if (mutex) {
89 SDL_ThreadID this_thread = SDL_GetCurrentThreadID();
90 if (mutex->owner == this_thread) {
91 ++mutex->recursive;
92 } else {
93 /* The order of operations is important.
94 We set the locking thread id after we obtain the lock
95 so unlocks from other threads will fail.
96 */
97 result = SDL_TryWaitSemaphore(mutex->sem);
98 if (result) {
99 mutex->owner = this_thread;
100 mutex->recursive = 0;
101 }
102 }
103 }
104#endif // SDL_THREADS_DISABLED
105 return result;
106}
107
108void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
109{
110#ifndef SDL_THREADS_DISABLED
111 if (mutex != NULL) {
112 // If we don't own the mutex, we can't unlock it
113 if (SDL_GetCurrentThreadID() != mutex->owner) {
114 SDL_assert(!"Tried to unlock a mutex we don't own!");
115 return; // (undefined behavior!) SDL_SetError("mutex not owned by this thread");
116 }
117
118 if (mutex->recursive) {
119 --mutex->recursive;
120 } else {
121 /* The order of operations is important.
122 First reset the owner so another thread doesn't lock
123 the mutex and set the ownership before we reset it,
124 then release the lock semaphore.
125 */
126 mutex->owner = 0;
127 SDL_SignalSemaphore(mutex->sem);
128 }
129 }
130#endif // SDL_THREADS_DISABLED
131}
132
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex_c.h b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex_c.h
new file mode 100644
index 0000000..4b0c6f8
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysmutex_c.h
@@ -0,0 +1,21 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock.c
new file mode 100644
index 0000000..24caf51
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock.c
@@ -0,0 +1,194 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// An implementation of rwlocks using mutexes, condition variables, and atomics.
24
25#include "SDL_systhread_c.h"
26
27#include "../generic/SDL_sysrwlock_c.h"
28
29/* If two implementations are to be compiled into SDL (the active one
30 * will be chosen at runtime), the function names need to be
31 * suffixed
32 */
33// !!! FIXME: this is quite a tapdance with macros and the build system, maybe we can simplify how we do this. --ryan.
34#ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
35#define SDL_CreateRWLock_generic SDL_CreateRWLock
36#define SDL_DestroyRWLock_generic SDL_DestroyRWLock
37#define SDL_LockRWLockForReading_generic SDL_LockRWLockForReading
38#define SDL_LockRWLockForWriting_generic SDL_LockRWLockForWriting
39#define SDL_UnlockRWLock_generic SDL_UnlockRWLock
40#endif
41
42struct SDL_RWLock
43{
44#ifdef SDL_THREADS_DISABLED
45 int unused;
46#else
47 SDL_Mutex *lock;
48 SDL_Condition *condition;
49 SDL_ThreadID writer_thread;
50 SDL_AtomicInt reader_count;
51 SDL_AtomicInt writer_count;
52#endif
53};
54
55SDL_RWLock *SDL_CreateRWLock_generic(void)
56{
57 SDL_RWLock *rwlock = (SDL_RWLock *) SDL_calloc(1, sizeof (*rwlock));
58
59 if (!rwlock) {
60 return NULL;
61 }
62
63#ifndef SDL_THREADS_DISABLED
64 rwlock->lock = SDL_CreateMutex();
65 if (!rwlock->lock) {
66 SDL_free(rwlock);
67 return NULL;
68 }
69
70 rwlock->condition = SDL_CreateCondition();
71 if (!rwlock->condition) {
72 SDL_DestroyMutex(rwlock->lock);
73 SDL_free(rwlock);
74 return NULL;
75 }
76
77 SDL_SetAtomicInt(&rwlock->reader_count, 0);
78 SDL_SetAtomicInt(&rwlock->writer_count, 0);
79#endif
80
81 return rwlock;
82}
83
84void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock)
85{
86 if (rwlock) {
87#ifndef SDL_THREADS_DISABLED
88 SDL_DestroyMutex(rwlock->lock);
89 SDL_DestroyCondition(rwlock->condition);
90#endif
91 SDL_free(rwlock);
92 }
93}
94
95void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
96{
97#ifndef SDL_THREADS_DISABLED
98 if (rwlock) {
99 // !!! FIXME: these don't have to be atomic, we always gate them behind a mutex.
100 SDL_LockMutex(rwlock->lock);
101 SDL_assert(SDL_GetAtomicInt(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer!
102 SDL_AddAtomicInt(&rwlock->reader_count, 1);
103 SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock.
104 }
105#endif
106}
107
108void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
109{
110#ifndef SDL_THREADS_DISABLED
111 if (rwlock) {
112 SDL_LockMutex(rwlock->lock);
113 while (SDL_GetAtomicInt(&rwlock->reader_count) > 0) { // while something is holding the shared lock, keep waiting.
114 SDL_WaitCondition(rwlock->condition, rwlock->lock); // release the lock and wait for readers holding the shared lock to release it, regrab the lock.
115 }
116
117 // we hold the lock!
118 SDL_AddAtomicInt(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly!
119 }
120#endif
121}
122
123bool SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock)
124{
125#ifndef SDL_THREADS_DISABLED
126 if (rwlock) {
127 if (!SDL_TryLockMutex(rwlock->lock)) {
128 // !!! FIXME: there is a small window where a reader has to lock the mutex, and if we hit that, we will return SDL_RWLOCK_TIMEDOUT even though we could have shared the lock.
129 return false;
130 }
131
132 SDL_assert(SDL_GetAtomicInt(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer!
133 SDL_AddAtomicInt(&rwlock->reader_count, 1);
134 SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock.
135 }
136#endif
137
138 return true;
139}
140
141#ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
142bool SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
143{
144 return SDL_TryLockRWLockForReading_generic(rwlock);
145}
146#endif
147
148bool SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock)
149{
150#ifndef SDL_THREADS_DISABLED
151 if (rwlock) {
152 if (!SDL_TryLockMutex(rwlock->lock)) {
153 return false;
154 }
155
156 if (SDL_GetAtomicInt(&rwlock->reader_count) > 0) { // a reader is using the shared lock, treat it as unavailable.
157 SDL_UnlockMutex(rwlock->lock);
158 return false;
159 }
160
161 // we hold the lock!
162 SDL_AddAtomicInt(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly!
163 }
164#endif
165
166 return true;
167}
168
169#ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
170bool SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
171{
172 return SDL_TryLockRWLockForWriting_generic(rwlock);
173}
174#endif
175
176void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
177{
178#ifndef SDL_THREADS_DISABLED
179 if (rwlock) {
180 SDL_LockMutex(rwlock->lock); // recursive lock for writers, readers grab lock to make sure things are sane.
181
182 if (SDL_GetAtomicInt(&rwlock->reader_count) > 0) { // we're a reader
183 SDL_AddAtomicInt(&rwlock->reader_count, -1);
184 SDL_BroadcastCondition(rwlock->condition); // alert any pending writers to attempt to try to grab the lock again.
185 } else if (SDL_GetAtomicInt(&rwlock->writer_count) > 0) { // we're a writer
186 SDL_AddAtomicInt(&rwlock->writer_count, -1);
187 SDL_UnlockMutex(rwlock->lock); // recursive unlock.
188 }
189
190 SDL_UnlockMutex(rwlock->lock);
191 }
192#endif
193}
194
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock_c.h b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock_c.h
new file mode 100644
index 0000000..9589d25
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_sysrwlock_c.h
@@ -0,0 +1,38 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_sysrwlock_c_h_
24#define SDL_sysrwlock_c_h_
25
26#ifdef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
27
28SDL_RWLock *SDL_CreateRWLock_generic(void);
29void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock);
30void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock);
31void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock);
32bool SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock);
33bool SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock);
34void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock);
35
36#endif // SDL_THREAD_GENERIC_RWLOCK_SUFFIX
37
38#endif // SDL_sysrwlock_c_h_
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_syssem.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_syssem.c
new file mode 100644
index 0000000..dcd6fcc
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_syssem.c
@@ -0,0 +1,183 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// An implementation of semaphores using mutexes and condition variables
24
25#include "SDL_systhread_c.h"
26
27#ifdef SDL_THREADS_DISABLED
28
29SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value)
30{
31 SDL_SetError("SDL not built with thread support");
32 return NULL;
33}
34
35void SDL_DestroySemaphore(SDL_Semaphore *sem)
36{
37}
38
39bool SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS)
40{
41 return true;
42}
43
44Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
45{
46 return 0;
47}
48
49void SDL_SignalSemaphore(SDL_Semaphore *sem)
50{
51 return;
52}
53
54#else
55
56struct SDL_Semaphore
57{
58 Uint32 count;
59 Uint32 waiters_count;
60 SDL_Mutex *count_lock;
61 SDL_Condition *count_nonzero;
62};
63
64SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value)
65{
66 SDL_Semaphore *sem;
67
68 sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem));
69 if (!sem) {
70 return NULL;
71 }
72 sem->count = initial_value;
73 sem->waiters_count = 0;
74
75 sem->count_lock = SDL_CreateMutex();
76 sem->count_nonzero = SDL_CreateCondition();
77 if (!sem->count_lock || !sem->count_nonzero) {
78 SDL_DestroySemaphore(sem);
79 return NULL;
80 }
81
82 return sem;
83}
84
85/* WARNING:
86 You cannot call this function when another thread is using the semaphore.
87*/
88void SDL_DestroySemaphore(SDL_Semaphore *sem)
89{
90 if (sem) {
91 sem->count = 0xFFFFFFFF;
92 while (sem->waiters_count > 0) {
93 SDL_SignalCondition(sem->count_nonzero);
94 SDL_Delay(10);
95 }
96 SDL_DestroyCondition(sem->count_nonzero);
97 if (sem->count_lock) {
98 SDL_LockMutex(sem->count_lock);
99 SDL_UnlockMutex(sem->count_lock);
100 SDL_DestroyMutex(sem->count_lock);
101 }
102 SDL_free(sem);
103 }
104}
105
106bool SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS)
107{
108 bool result = false;
109
110 if (!sem) {
111 return true;
112 }
113
114 if (timeoutNS == 0) {
115 SDL_LockMutex(sem->count_lock);
116 if (sem->count > 0) {
117 --sem->count;
118 result = true;
119 }
120 SDL_UnlockMutex(sem->count_lock);
121 } else if (timeoutNS < 0) {
122 SDL_LockMutex(sem->count_lock);
123 ++sem->waiters_count;
124 while (sem->count == 0) {
125 SDL_WaitConditionTimeoutNS(sem->count_nonzero, sem->count_lock, -1);
126 }
127 --sem->waiters_count;
128 --sem->count;
129 result = true;
130 SDL_UnlockMutex(sem->count_lock);
131 } else {
132 Uint64 stop_time = SDL_GetTicksNS() + timeoutNS;
133
134 SDL_LockMutex(sem->count_lock);
135 ++sem->waiters_count;
136 while (sem->count == 0) {
137 Sint64 waitNS = (Sint64)(stop_time - SDL_GetTicksNS());
138 if (waitNS > 0) {
139 SDL_WaitConditionTimeoutNS(sem->count_nonzero, sem->count_lock, waitNS);
140 } else {
141 break;
142 }
143 }
144 --sem->waiters_count;
145
146 if (sem->count > 0) {
147 --sem->count;
148 result = true;
149 }
150 SDL_UnlockMutex(sem->count_lock);
151 }
152
153 return result;
154}
155
156Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
157{
158 Uint32 value;
159
160 value = 0;
161 if (sem) {
162 SDL_LockMutex(sem->count_lock);
163 value = sem->count;
164 SDL_UnlockMutex(sem->count_lock);
165 }
166 return value;
167}
168
169void SDL_SignalSemaphore(SDL_Semaphore *sem)
170{
171 if (!sem) {
172 return;
173 }
174
175 SDL_LockMutex(sem->count_lock);
176 if (sem->waiters_count > 0) {
177 SDL_SignalCondition(sem->count_nonzero);
178 }
179 ++sem->count;
180 SDL_UnlockMutex(sem->count_lock);
181}
182
183#endif // SDL_THREADS_DISABLED
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread.c
new file mode 100644
index 0000000..ecfa4e1
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread.c
@@ -0,0 +1,57 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Thread management routines for SDL
24
25#include "../SDL_systhread.h"
26
27bool SDL_SYS_CreateThread(SDL_Thread *thread,
28 SDL_FunctionPointer pfnBeginThread,
29 SDL_FunctionPointer pfnEndThread)
30{
31 return SDL_SetError("Threads are not supported on this platform");
32}
33
34void SDL_SYS_SetupThread(const char *name)
35{
36 return;
37}
38
39SDL_ThreadID SDL_GetCurrentThreadID(void)
40{
41 return 0;
42}
43
44bool SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
45{
46 return true;
47}
48
49void SDL_SYS_WaitThread(SDL_Thread *thread)
50{
51 return;
52}
53
54void SDL_SYS_DetachThread(SDL_Thread *thread)
55{
56 return;
57}
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread_c.h b/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread_c.h
new file mode 100644
index 0000000..9ba55fd
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_systhread_c.h
@@ -0,0 +1,24 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// Stub until we implement threads on this platform
24typedef int SYS_ThreadHandle;
diff --git a/contrib/SDL-3.2.8/src/thread/generic/SDL_systls.c b/contrib/SDL-3.2.8/src/thread/generic/SDL_systls.c
new file mode 100644
index 0000000..b8ebafe
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/generic/SDL_systls.c
@@ -0,0 +1,44 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23#include "../SDL_thread_c.h"
24
25void SDL_SYS_InitTLSData(void)
26{
27 SDL_Generic_InitTLSData();
28}
29
30SDL_TLSData *SDL_SYS_GetTLSData(void)
31{
32 return SDL_Generic_GetTLSData();
33}
34
35bool SDL_SYS_SetTLSData(SDL_TLSData *data)
36{
37 return SDL_Generic_SetTLSData(data);
38}
39
40void SDL_SYS_QuitTLSData(void)
41{
42 SDL_Generic_QuitTLSData();
43}
44