summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/thread/pthread
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/thread/pthread')
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_syscond.c128
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex.c154
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex_c.h40
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_sysrwlock.c113
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_syssem.c160
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread.c293
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread_c.h25
-rw-r--r--contrib/SDL-3.2.8/src/thread/pthread/SDL_systls.c78
8 files changed, 991 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_syscond.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_syscond.c
new file mode 100644
index 0000000..c3e4098
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_syscond.c
@@ -0,0 +1,128 @@
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#include <sys/time.h>
24#include <time.h>
25#include <unistd.h>
26#include <errno.h>
27#include <pthread.h>
28
29#include "SDL_sysmutex_c.h"
30
31struct SDL_Condition
32{
33 pthread_cond_t cond;
34};
35
36// Create a condition variable
37SDL_Condition *SDL_CreateCondition(void)
38{
39 SDL_Condition *cond;
40
41 cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition));
42 if (cond) {
43 if (pthread_cond_init(&cond->cond, NULL) != 0) {
44 SDL_SetError("pthread_cond_init() failed");
45 SDL_free(cond);
46 cond = NULL;
47 }
48 }
49 return cond;
50}
51
52// Destroy a condition variable
53void SDL_DestroyCondition(SDL_Condition *cond)
54{
55 if (cond) {
56 pthread_cond_destroy(&cond->cond);
57 SDL_free(cond);
58 }
59}
60
61// Restart one of the threads that are waiting on the condition variable
62void SDL_SignalCondition(SDL_Condition *cond)
63{
64 if (!cond) {
65 return;
66 }
67
68 pthread_cond_signal(&cond->cond);
69}
70
71// Restart all threads that are waiting on the condition variable
72void SDL_BroadcastCondition(SDL_Condition *cond)
73{
74 if (!cond) {
75 return;
76 }
77
78 pthread_cond_broadcast(&cond->cond);
79}
80
81bool SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS)
82{
83#ifndef HAVE_CLOCK_GETTIME
84 struct timeval delta;
85#endif
86 struct timespec abstime;
87
88 if (!cond || !mutex) {
89 return true;
90 }
91
92 if (timeoutNS < 0) {
93 return (pthread_cond_wait(&cond->cond, &mutex->id) == 0);
94 }
95
96#ifdef HAVE_CLOCK_GETTIME
97 clock_gettime(CLOCK_REALTIME, &abstime);
98
99 abstime.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
100 abstime.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
101#else
102 gettimeofday(&delta, NULL);
103
104 abstime.tv_sec = delta.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
105 abstime.tv_nsec = SDL_US_TO_NS(delta.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
106#endif
107 while (abstime.tv_nsec >= 1000000000) {
108 abstime.tv_sec += 1;
109 abstime.tv_nsec -= 1000000000;
110 }
111
112 bool result;
113 int rc;
114tryagain:
115 rc = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime);
116 switch (rc) {
117 case EINTR:
118 goto tryagain;
119 // break; -Wunreachable-code-break
120 case ETIMEDOUT:
121 result = false;
122 break;
123 default:
124 result = true;
125 break;
126 }
127 return result;
128}
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex.c
new file mode 100644
index 0000000..7bba286
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex.c
@@ -0,0 +1,154 @@
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#include <errno.h>
24#include <pthread.h>
25
26#include "SDL_sysmutex_c.h"
27
28SDL_Mutex *SDL_CreateMutex(void)
29{
30 SDL_Mutex *mutex;
31 pthread_mutexattr_t attr;
32
33 // Allocate the structure
34 mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
35 if (mutex) {
36 pthread_mutexattr_init(&attr);
37#ifdef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
38 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
39#elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP)
40 pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
41#else
42 // No extra attributes necessary
43#endif
44 if (pthread_mutex_init(&mutex->id, &attr) != 0) {
45 SDL_SetError("pthread_mutex_init() failed");
46 SDL_free(mutex);
47 mutex = NULL;
48 }
49 }
50 return mutex;
51}
52
53void SDL_DestroyMutex(SDL_Mutex *mutex)
54{
55 if (mutex) {
56 pthread_mutex_destroy(&mutex->id);
57 SDL_free(mutex);
58 }
59}
60
61void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
62{
63 if (mutex) {
64#ifdef FAKE_RECURSIVE_MUTEX
65 pthread_t this_thread = pthread_self();
66 if (mutex->owner == this_thread) {
67 ++mutex->recursive;
68 } else {
69 /* The order of operations is important.
70 We set the locking thread id after we obtain the lock
71 so unlocks from other threads will fail.
72 */
73 const int rc = pthread_mutex_lock(&mutex->id);
74 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
75 mutex->owner = this_thread;
76 mutex->recursive = 0;
77 }
78#else
79 const int rc = pthread_mutex_lock(&mutex->id);
80 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
81#endif
82 }
83}
84
85bool SDL_TryLockMutex(SDL_Mutex *mutex)
86{
87 bool result = true;
88
89 if (mutex) {
90#ifdef FAKE_RECURSIVE_MUTEX
91 pthread_t this_thread = pthread_self();
92 if (mutex->owner == this_thread) {
93 ++mutex->recursive;
94 } else {
95 /* The order of operations is important.
96 We set the locking thread id after we obtain the lock
97 so unlocks from other threads will fail.
98 */
99 const int rc = pthread_mutex_trylock(&mutex->id);
100 if (rc == 0) {
101 mutex->owner = this_thread;
102 mutex->recursive = 0;
103 } else if (rc == EBUSY) {
104 result = false;
105 } else {
106 SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
107 result = false;
108 }
109 }
110#else
111 const int rc = pthread_mutex_trylock(&mutex->id);
112 if (rc != 0) {
113 if (rc == EBUSY) {
114 result = false;
115 } else {
116 SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
117 result = false;
118 }
119 }
120#endif
121 }
122
123 return result;
124}
125
126void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
127{
128 if (mutex) {
129#ifdef FAKE_RECURSIVE_MUTEX
130 // We can only unlock the mutex if we own it
131 if (pthread_self() == mutex->owner) {
132 if (mutex->recursive) {
133 --mutex->recursive;
134 } else {
135 /* The order of operations is important.
136 First reset the owner so another thread doesn't lock
137 the mutex and set the ownership before we reset it,
138 then release the lock semaphore.
139 */
140 mutex->owner = 0;
141 pthread_mutex_unlock(&mutex->id);
142 }
143 } else {
144 SDL_SetError("mutex not owned by this thread");
145 return;
146 }
147
148#else
149 const int rc = pthread_mutex_unlock(&mutex->id);
150 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
151#endif // FAKE_RECURSIVE_MUTEX
152 }
153}
154
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex_c.h b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex_c.h
new file mode 100644
index 0000000..f69e7b3
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysmutex_c.h
@@ -0,0 +1,40 @@
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_mutex_c_h_
24#define SDL_mutex_c_h_
25
26#if !(defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX) || \
27 defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP))
28#define FAKE_RECURSIVE_MUTEX
29#endif
30
31struct SDL_Mutex
32{
33 pthread_mutex_t id;
34#ifdef FAKE_RECURSIVE_MUTEX
35 int recursive;
36 pthread_t owner;
37#endif
38};
39
40#endif // SDL_mutex_c_h_
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysrwlock.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysrwlock.c
new file mode 100644
index 0000000..3cf02e5
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_sysrwlock.c
@@ -0,0 +1,113 @@
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#include <errno.h>
24#include <pthread.h>
25
26struct SDL_RWLock
27{
28 pthread_rwlock_t id;
29};
30
31
32SDL_RWLock *SDL_CreateRWLock(void)
33{
34 SDL_RWLock *rwlock;
35
36 // Allocate the structure
37 rwlock = (SDL_RWLock *)SDL_calloc(1, sizeof(*rwlock));
38 if (rwlock) {
39 if (pthread_rwlock_init(&rwlock->id, NULL) != 0) {
40 SDL_SetError("pthread_rwlock_init() failed");
41 SDL_free(rwlock);
42 rwlock = NULL;
43 }
44 }
45 return rwlock;
46}
47
48void SDL_DestroyRWLock(SDL_RWLock *rwlock)
49{
50 if (rwlock) {
51 pthread_rwlock_destroy(&rwlock->id);
52 SDL_free(rwlock);
53 }
54}
55
56void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
57{
58 if (rwlock) {
59 const int rc = pthread_rwlock_rdlock(&rwlock->id);
60 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
61 }
62}
63
64void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
65{
66 if (rwlock) {
67 const int rc = pthread_rwlock_wrlock(&rwlock->id);
68 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
69 }
70}
71
72bool SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
73{
74 bool result = true;
75
76 if (rwlock) {
77 const int rc = pthread_rwlock_tryrdlock(&rwlock->id);
78 if (rc != 0) {
79 result = false;
80 if (rc != EBUSY) {
81 SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails.
82 }
83 }
84 }
85
86 return result;
87}
88
89bool SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
90{
91 bool result = true;
92
93 if (rwlock) {
94 const int rc = pthread_rwlock_trywrlock(&rwlock->id);
95 if (rc != 0) {
96 result = false;
97 if (rc != EBUSY) {
98 SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails.
99 }
100 }
101 }
102
103 return result;
104}
105
106void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
107{
108 if (rwlock) {
109 const int rc = pthread_rwlock_unlock(&rwlock->id);
110 SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
111 }
112}
113
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_syssem.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_syssem.c
new file mode 100644
index 0000000..d5d3298
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_syssem.c
@@ -0,0 +1,160 @@
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#include <errno.h>
24#include <pthread.h>
25#include <semaphore.h>
26#include <sys/time.h>
27#include <time.h>
28
29// Wrapper around POSIX 1003.1b semaphores
30
31#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)
32// macOS doesn't support sem_getvalue() as of version 10.4
33#include "../generic/SDL_syssem.c"
34#else
35
36struct SDL_Semaphore
37{
38 sem_t sem;
39};
40
41// Create a semaphore, initialized with value
42SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value)
43{
44 SDL_Semaphore *sem = (SDL_Semaphore *)SDL_malloc(sizeof(SDL_Semaphore));
45 if (sem) {
46 if (sem_init(&sem->sem, 0, initial_value) < 0) {
47 SDL_SetError("sem_init() failed");
48 SDL_free(sem);
49 sem = NULL;
50 }
51 }
52 return sem;
53}
54
55void SDL_DestroySemaphore(SDL_Semaphore *sem)
56{
57 if (sem) {
58 sem_destroy(&sem->sem);
59 SDL_free(sem);
60 }
61}
62
63bool SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS)
64{
65#ifdef HAVE_SEM_TIMEDWAIT
66#ifndef HAVE_CLOCK_GETTIME
67 struct timeval now;
68#endif
69 struct timespec ts_timeout;
70#else
71 Uint64 stop_time;
72#endif
73
74 if (!sem) {
75 return true;
76 }
77
78 // Try the easy cases first
79 if (timeoutNS == 0) {
80 return (sem_trywait(&sem->sem) == 0);
81 }
82
83 if (timeoutNS < 0) {
84 int rc;
85 do {
86 rc = sem_wait(&sem->sem);
87 } while (rc < 0 && errno == EINTR);
88
89 return (rc == 0);
90 }
91
92#ifdef HAVE_SEM_TIMEDWAIT
93 /* Setup the timeout. sem_timedwait doesn't wait for
94 * a lapse of time, but until we reach a certain time.
95 * This time is now plus the timeout.
96 */
97#ifdef HAVE_CLOCK_GETTIME
98 clock_gettime(CLOCK_REALTIME, &ts_timeout);
99
100 // Add our timeout to current time
101 ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
102 ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
103#else
104 gettimeofday(&now, NULL);
105
106 // Add our timeout to current time
107 ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
108 ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
109#endif
110
111 // Wrap the second if needed
112 while (ts_timeout.tv_nsec >= 1000000000) {
113 ts_timeout.tv_sec += 1;
114 ts_timeout.tv_nsec -= 1000000000;
115 }
116
117 // Wait.
118 int rc;
119 do {
120 rc = sem_timedwait(&sem->sem, &ts_timeout);
121 } while (rc < 0 && errno == EINTR);
122
123 return (rc == 0);
124#else
125 stop_time = SDL_GetTicksNS() + timeoutNS;
126 while (sem_trywait(&sem->sem) != 0) {
127 if (SDL_GetTicksNS() >= stop_time) {
128 return false;
129 }
130 SDL_DelayNS(100);
131 }
132 return true;
133#endif // HAVE_SEM_TIMEDWAIT
134}
135
136Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
137{
138 int ret = 0;
139
140 if (!sem) {
141 return 0;
142 }
143
144 sem_getvalue(&sem->sem, &ret);
145 if (ret < 0) {
146 ret = 0;
147 }
148 return (Uint32)ret;
149}
150
151void SDL_SignalSemaphore(SDL_Semaphore *sem)
152{
153 if (!sem) {
154 return;
155 }
156
157 sem_post(&sem->sem);
158}
159
160#endif // SDL_PLATFORM_MACOS
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread.c
new file mode 100644
index 0000000..ae4a94c
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread.c
@@ -0,0 +1,293 @@
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#include <pthread.h>
24
25#ifdef HAVE_PTHREAD_NP_H
26#include <pthread_np.h>
27#endif
28
29#ifdef HAVE_SIGNAL_H
30#include <signal.h>
31#endif
32#include <errno.h>
33
34#ifdef SDL_PLATFORM_LINUX
35#include <sys/time.h>
36#include <sys/resource.h>
37#include <sys/syscall.h>
38#include <unistd.h>
39
40#include "../../core/linux/SDL_dbus.h"
41#endif // SDL_PLATFORM_LINUX
42
43#if (defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)) && defined(HAVE_DLOPEN)
44#include <dlfcn.h>
45#ifndef RTLD_DEFAULT
46#define RTLD_DEFAULT NULL
47#endif
48#endif
49
50#include "../SDL_thread_c.h"
51#include "../SDL_systhread.h"
52#ifdef SDL_PLATFORM_ANDROID
53#include "../../core/android/SDL_android.h"
54#endif
55
56#ifdef SDL_PLATFORM_HAIKU
57#include <kernel/OS.h>
58#endif
59
60#ifdef HAVE_SIGNAL_H
61// List of signals to mask in the subthreads
62static const int sig_list[] = {
63 SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
64 SIGVTALRM, SIGPROF, 0
65};
66#endif
67
68static void *RunThread(void *data)
69{
70#ifdef SDL_PLATFORM_ANDROID
71 Android_JNI_SetupThread();
72#endif
73 SDL_RunThread((SDL_Thread *)data);
74 return NULL;
75}
76
77#if (defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)) && defined(HAVE_DLOPEN)
78static bool checked_setname = false;
79static int (*ppthread_setname_np)(const char *) = NULL;
80#elif (defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(HAVE_DLOPEN)
81static bool checked_setname = false;
82static int (*ppthread_setname_np)(pthread_t, const char *) = NULL;
83#endif
84bool SDL_SYS_CreateThread(SDL_Thread *thread,
85 SDL_FunctionPointer pfnBeginThread,
86 SDL_FunctionPointer pfnEndThread)
87{
88 pthread_attr_t type;
89
90// do this here before any threads exist, so there's no race condition.
91#if (defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(HAVE_DLOPEN)
92 if (!checked_setname) {
93 void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
94#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)
95 ppthread_setname_np = (int (*)(const char *))fn;
96#elif defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)
97 ppthread_setname_np = (int (*)(pthread_t, const char *))fn;
98#endif
99 checked_setname = true;
100 }
101 #endif
102
103 // Set the thread attributes
104 if (pthread_attr_init(&type) != 0) {
105 return SDL_SetError("Couldn't initialize pthread attributes");
106 }
107 pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
108
109 // Set caller-requested stack size. Otherwise: use the system default.
110 if (thread->stacksize) {
111 pthread_attr_setstacksize(&type, thread->stacksize);
112 }
113
114 // Create the thread and go!
115 if (pthread_create(&thread->handle, &type, RunThread, thread) != 0) {
116 return SDL_SetError("Not enough resources to create thread");
117 }
118
119 return true;
120}
121
122void SDL_SYS_SetupThread(const char *name)
123{
124#ifdef HAVE_SIGNAL_H
125 int i;
126 sigset_t mask;
127#endif
128
129 if (name) {
130#if (defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(HAVE_DLOPEN)
131 SDL_assert(checked_setname);
132 if (ppthread_setname_np) {
133#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)
134 ppthread_setname_np(name);
135#elif defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)
136 if (ppthread_setname_np(pthread_self(), name) == ERANGE) {
137 char namebuf[16]; // Limited to 16 char
138 SDL_strlcpy(namebuf, name, sizeof(namebuf));
139 ppthread_setname_np(pthread_self(), namebuf);
140 }
141#endif
142 }
143#elif defined(HAVE_PTHREAD_SETNAME_NP)
144#ifdef SDL_PLATFORM_NETBSD
145 pthread_setname_np(pthread_self(), "%s", name);
146#else
147 if (pthread_setname_np(pthread_self(), name) == ERANGE) {
148 char namebuf[16]; // Limited to 16 char
149 SDL_strlcpy(namebuf, name, sizeof(namebuf));
150 pthread_setname_np(pthread_self(), namebuf);
151 }
152#endif
153#elif defined(HAVE_PTHREAD_SET_NAME_NP)
154 pthread_set_name_np(pthread_self(), name);
155#elif defined(SDL_PLATFORM_HAIKU)
156 // The docs say the thread name can't be longer than B_OS_NAME_LENGTH.
157 char namebuf[B_OS_NAME_LENGTH];
158 SDL_strlcpy(namebuf, name, sizeof(namebuf));
159 rename_thread(find_thread(NULL), namebuf);
160#endif
161 }
162
163#ifdef HAVE_SIGNAL_H
164 // Mask asynchronous signals for this thread
165 sigemptyset(&mask);
166 for (i = 0; sig_list[i]; ++i) {
167 sigaddset(&mask, sig_list[i]);
168 }
169 pthread_sigmask(SIG_BLOCK, &mask, 0);
170#endif
171
172#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
173 // Allow ourselves to be asynchronously cancelled
174 {
175 int oldstate;
176 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
177 }
178#endif
179}
180
181SDL_ThreadID SDL_GetCurrentThreadID(void)
182{
183 return (SDL_ThreadID)pthread_self();
184}
185
186bool SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
187{
188#ifdef SDL_PLATFORM_RISCOS
189 // FIXME: Setting thread priority does not seem to be supported
190 return true;
191#else
192 struct sched_param sched;
193 int policy;
194 int pri_policy;
195 pthread_t thread = pthread_self();
196 const char *policyhint = SDL_GetHint(SDL_HINT_THREAD_PRIORITY_POLICY);
197 const bool timecritical_realtime_hint = SDL_GetHintBoolean(SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL, false);
198
199 if (pthread_getschedparam(thread, &policy, &sched) != 0) {
200 return SDL_SetError("pthread_getschedparam() failed");
201 }
202
203 /* Higher priority levels may require changing the pthread scheduler policy
204 * for the thread. SDL will make such changes by default but there is
205 * also a hint allowing that behavior to be overridden. */
206 switch (priority) {
207 case SDL_THREAD_PRIORITY_LOW:
208 case SDL_THREAD_PRIORITY_NORMAL:
209 pri_policy = SCHED_OTHER;
210 break;
211 case SDL_THREAD_PRIORITY_HIGH:
212 case SDL_THREAD_PRIORITY_TIME_CRITICAL:
213#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)
214 // Apple requires SCHED_RR for high priority threads
215 pri_policy = SCHED_RR;
216 break;
217#else
218 pri_policy = SCHED_OTHER;
219 break;
220#endif
221 default:
222 pri_policy = policy;
223 break;
224 }
225
226 if (timecritical_realtime_hint && priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
227 pri_policy = SCHED_RR;
228 }
229
230 if (policyhint) {
231 if (SDL_strcmp(policyhint, "current") == 0) {
232 // Leave current thread scheduler policy unchanged
233 } else if (SDL_strcmp(policyhint, "other") == 0) {
234 policy = SCHED_OTHER;
235 } else if (SDL_strcmp(policyhint, "rr") == 0) {
236 policy = SCHED_RR;
237 } else if (SDL_strcmp(policyhint, "fifo") == 0) {
238 policy = SCHED_FIFO;
239 } else {
240 policy = pri_policy;
241 }
242 } else {
243 policy = pri_policy;
244 }
245
246#ifdef SDL_PLATFORM_LINUX
247 {
248 pid_t linuxTid = syscall(SYS_gettid);
249 return SDL_SetLinuxThreadPriorityAndPolicy(linuxTid, priority, policy);
250 }
251#else
252 if (priority == SDL_THREAD_PRIORITY_LOW) {
253 sched.sched_priority = sched_get_priority_min(policy);
254 } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
255 sched.sched_priority = sched_get_priority_max(policy);
256 } else {
257 int min_priority = sched_get_priority_min(policy);
258 int max_priority = sched_get_priority_max(policy);
259
260#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)
261 if (min_priority == 15 && max_priority == 47) {
262 // Apple has a specific set of thread priorities
263 if (priority == SDL_THREAD_PRIORITY_HIGH) {
264 sched.sched_priority = 45;
265 } else {
266 sched.sched_priority = 37;
267 }
268 } else
269#endif // SDL_PLATFORM_MACOS || SDL_PLATFORM_IOS || SDL_PLATFORM_TVOS
270 {
271 sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
272 if (priority == SDL_THREAD_PRIORITY_HIGH) {
273 sched.sched_priority += ((max_priority - min_priority) / 4);
274 }
275 }
276 }
277 if (pthread_setschedparam(thread, policy, &sched) != 0) {
278 return SDL_SetError("pthread_setschedparam() failed");
279 }
280 return true;
281#endif // linux
282#endif // #if SDL_PLATFORM_RISCOS
283}
284
285void SDL_SYS_WaitThread(SDL_Thread *thread)
286{
287 pthread_join(thread->handle, 0);
288}
289
290void SDL_SYS_DetachThread(SDL_Thread *thread)
291{
292 pthread_detach(thread->handle);
293}
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread_c.h b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread_c.h
new file mode 100644
index 0000000..bdfcd68
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systhread_c.h
@@ -0,0 +1,25 @@
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#include <pthread.h>
24
25typedef pthread_t SYS_ThreadHandle;
diff --git a/contrib/SDL-3.2.8/src/thread/pthread/SDL_systls.c b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systls.c
new file mode 100644
index 0000000..18e9a01
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/thread/pthread/SDL_systls.c
@@ -0,0 +1,78 @@
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#include "../SDL_systhread.h"
23#include "../SDL_thread_c.h"
24
25#include <pthread.h>
26
27#define INVALID_PTHREAD_KEY ((pthread_key_t)-1)
28
29static pthread_key_t thread_local_storage = INVALID_PTHREAD_KEY;
30static bool generic_local_storage = false;
31
32void SDL_SYS_InitTLSData(void)
33{
34 if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
35 if (pthread_key_create(&thread_local_storage, NULL) != 0) {
36 thread_local_storage = INVALID_PTHREAD_KEY;
37 SDL_Generic_InitTLSData();
38 generic_local_storage = true;
39 }
40 }
41}
42
43SDL_TLSData *SDL_SYS_GetTLSData(void)
44{
45 if (generic_local_storage) {
46 return SDL_Generic_GetTLSData();
47 }
48
49 if (thread_local_storage != INVALID_PTHREAD_KEY) {
50 return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
51 }
52 return NULL;
53}
54
55bool SDL_SYS_SetTLSData(SDL_TLSData *data)
56{
57 if (generic_local_storage) {
58 return SDL_Generic_SetTLSData(data);
59 }
60
61 if (pthread_setspecific(thread_local_storage, data) != 0) {
62 return SDL_SetError("pthread_setspecific() failed");
63 }
64 return true;
65}
66
67void SDL_SYS_QuitTLSData(void)
68{
69 if (generic_local_storage) {
70 SDL_Generic_QuitTLSData();
71 generic_local_storage = false;
72 } else {
73 if (thread_local_storage != INVALID_PTHREAD_KEY) {
74 pthread_key_delete(thread_local_storage);
75 thread_local_storage = INVALID_PTHREAD_KEY;
76 }
77 }
78}