SDL_systhread.c (6617B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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 24#include <pthread.h> 25 26#if HAVE_PTHREAD_NP_H 27#include <pthread_np.h> 28#endif 29 30#include <signal.h> 31 32#ifdef __LINUX__ 33#include <sys/time.h> 34#include <sys/resource.h> 35#include <sys/syscall.h> 36#include <unistd.h> 37#endif /* __LINUX__ */ 38 39#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__) 40#include <dlfcn.h> 41#ifndef RTLD_DEFAULT 42#define RTLD_DEFAULT NULL 43#endif 44#endif 45 46#include "SDL_platform.h" 47#include "SDL_thread.h" 48#include "../SDL_thread_c.h" 49#include "../SDL_systhread.h" 50#ifdef __ANDROID__ 51#include "../../core/android/SDL_android.h" 52#endif 53 54#ifdef __HAIKU__ 55#include <be/kernel/OS.h> 56#endif 57 58#include "SDL_assert.h" 59 60#ifndef __NACL__ 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 * 69RunThread(void *data) 70{ 71#ifdef __ANDROID__ 72 Android_JNI_SetupThread(); 73#endif 74 SDL_RunThread(data); 75 return NULL; 76} 77 78#if defined(__MACOSX__) || defined(__IPHONEOS__) 79static SDL_bool checked_setname = SDL_FALSE; 80static int (*ppthread_setname_np)(const char*) = NULL; 81#elif defined(__LINUX__) 82static SDL_bool checked_setname = SDL_FALSE; 83static int (*ppthread_setname_np)(pthread_t, const char*) = NULL; 84#endif 85int 86SDL_SYS_CreateThread(SDL_Thread * thread, void *args) 87{ 88 pthread_attr_t type; 89 90 /* do this here before any threads exist, so there's no race condition. */ 91 #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__) 92 if (!checked_setname) { 93 void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np"); 94 #if defined(__MACOSX__) || defined(__IPHONEOS__) 95 ppthread_setname_np = (int(*)(const char*)) fn; 96 #elif defined(__LINUX__) 97 ppthread_setname_np = (int(*)(pthread_t, const char*)) fn; 98 #endif 99 checked_setname = SDL_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 /* Create the thread and go! */ 110 if (pthread_create(&thread->handle, &type, RunThread, args) != 0) { 111 return SDL_SetError("Not enough resources to create thread"); 112 } 113 114 return 0; 115} 116 117void 118SDL_SYS_SetupThread(const char *name) 119{ 120#ifndef __NACL__ 121 int i; 122 sigset_t mask; 123#endif 124 125 if (name != NULL) { 126 #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__) 127 SDL_assert(checked_setname); 128 if (ppthread_setname_np != NULL) { 129 #if defined(__MACOSX__) || defined(__IPHONEOS__) 130 ppthread_setname_np(name); 131 #elif defined(__LINUX__) 132 ppthread_setname_np(pthread_self(), name); 133 #endif 134 } 135 #elif HAVE_PTHREAD_SETNAME_NP 136 pthread_setname_np(pthread_self(), name); 137 #elif HAVE_PTHREAD_SET_NAME_NP 138 pthread_set_name_np(pthread_self(), name); 139 #elif defined(__HAIKU__) 140 /* The docs say the thread name can't be longer than B_OS_NAME_LENGTH. */ 141 char namebuf[B_OS_NAME_LENGTH]; 142 SDL_snprintf(namebuf, sizeof (namebuf), "%s", name); 143 namebuf[sizeof (namebuf) - 1] = '\0'; 144 rename_thread(find_thread(NULL), namebuf); 145 #endif 146 } 147 148 /* NativeClient does not yet support signals.*/ 149#ifndef __NACL__ 150 /* Mask asynchronous signals for this thread */ 151 sigemptyset(&mask); 152 for (i = 0; sig_list[i]; ++i) { 153 sigaddset(&mask, sig_list[i]); 154 } 155 pthread_sigmask(SIG_BLOCK, &mask, 0); 156#endif 157 158#ifdef PTHREAD_CANCEL_ASYNCHRONOUS 159 /* Allow ourselves to be asynchronously cancelled */ 160 { 161 int oldstate; 162 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); 163 } 164#endif 165} 166 167SDL_threadID 168SDL_ThreadID(void) 169{ 170 return ((SDL_threadID) pthread_self()); 171} 172 173int 174SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) 175{ 176#if __NACL__ 177 /* FIXME: Setting thread priority does not seem to be supported in NACL */ 178 return 0; 179#elif __LINUX__ 180 int value; 181 182 if (priority == SDL_THREAD_PRIORITY_LOW) { 183 value = 19; 184 } else if (priority == SDL_THREAD_PRIORITY_HIGH) { 185 value = -20; 186 } else { 187 value = 0; 188 } 189 if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) { 190 /* Note that this fails if you're trying to set high priority 191 and you don't have root permission. BUT DON'T RUN AS ROOT! 192 */ 193 return SDL_SetError("setpriority() failed"); 194 } 195 return 0; 196#else 197 struct sched_param sched; 198 int policy; 199 pthread_t thread = pthread_self(); 200 201 if (pthread_getschedparam(thread, &policy, &sched) < 0) { 202 return SDL_SetError("pthread_getschedparam() failed"); 203 } 204 if (priority == SDL_THREAD_PRIORITY_LOW) { 205 sched.sched_priority = sched_get_priority_min(policy); 206 } else if (priority == SDL_THREAD_PRIORITY_HIGH) { 207 sched.sched_priority = sched_get_priority_max(policy); 208 } else { 209 int min_priority = sched_get_priority_min(policy); 210 int max_priority = sched_get_priority_max(policy); 211 sched.sched_priority = (min_priority + (max_priority - min_priority) / 2); 212 } 213 if (pthread_setschedparam(thread, policy, &sched) < 0) { 214 return SDL_SetError("pthread_setschedparam() failed"); 215 } 216 return 0; 217#endif /* linux */ 218} 219 220void 221SDL_SYS_WaitThread(SDL_Thread * thread) 222{ 223 pthread_join(thread->handle, 0); 224} 225 226void 227SDL_SYS_DetachThread(SDL_Thread * thread) 228{ 229 pthread_detach(thread->handle); 230} 231 232/* vi: set ts=4 sw=4 expandtab: */