Atlas - SDL_systhread.c

Home / ext / SDL / src / thread / pthread Lines: 1 | Size: 9613 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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, NULL); 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, NULL); 288} 289 290void SDL_SYS_DetachThread(SDL_Thread *thread) 291{ 292 pthread_detach(thread->handle); 293} 294
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.