src/thread/pthread/SDL_systhread.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6885 700f1b25f77f
child 7191 75360622e65f
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


Fixes Bugzilla #1778.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.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 #include "SDL_assert.h"
    55 
    56 /* List of signals to mask in the subthreads */
    57 static const int sig_list[] = {
    58     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
    59     SIGVTALRM, SIGPROF, 0
    60 };
    61 
    62 
    63 static void *
    64 RunThread(void *data)
    65 {
    66 #ifdef __ANDROID__
    67     Android_JNI_SetupThread();
    68 #endif
    69     SDL_RunThread(data);
    70     return NULL;
    71 }
    72 
    73 #if defined(__MACOSX__) || defined(__IPHONEOS__)
    74 static SDL_bool checked_setname = SDL_FALSE;
    75 static int (*ppthread_setname_np)(const char*) = NULL;
    76 #elif defined(__LINUX__)
    77 static SDL_bool checked_setname = SDL_FALSE;
    78 static int (*ppthread_setname_np)(pthread_t, const char*) = NULL;
    79 #endif
    80 int
    81 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    82 {
    83     pthread_attr_t type;
    84 
    85     /* do this here before any threads exist, so there's no race condition. */
    86     #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
    87     if (!checked_setname) {
    88         void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
    89         #if defined(__MACOSX__) || defined(__IPHONEOS__)
    90         ppthread_setname_np = (int(*)(const char*)) fn;
    91         #elif defined(__LINUX__)
    92         ppthread_setname_np = (int(*)(pthread_t, const char*)) fn;
    93         #endif
    94         checked_setname = SDL_TRUE;
    95     }
    96     #endif
    97 
    98     /* Set the thread attributes */
    99     if (pthread_attr_init(&type) != 0) {
   100         return SDL_SetError("Couldn't initialize pthread attributes");
   101     }
   102     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
   103 
   104     /* Create the thread and go! */
   105     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
   106         return SDL_SetError("Not enough resources to create thread");
   107     }
   108 
   109     return 0;
   110 }
   111 
   112 void
   113 SDL_SYS_SetupThread(const char *name)
   114 {
   115     int i;
   116     sigset_t mask;
   117 
   118     if (name != NULL) {
   119         #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
   120         SDL_assert(checked_setname);
   121         if (ppthread_setname_np != NULL) {
   122             #if defined(__MACOSX__) || defined(__IPHONEOS__)
   123             ppthread_setname_np(name);
   124             #elif defined(__LINUX__)
   125             ppthread_setname_np(pthread_self(), name);
   126             #endif
   127         }
   128         #elif HAVE_PTHREAD_SETNAME_NP
   129             pthread_setname_np(pthread_self(), name);
   130         #elif HAVE_PTHREAD_SET_NAME_NP
   131             pthread_set_name_np(pthread_self(), name);
   132         #endif
   133     }
   134 
   135     /* Mask asynchronous signals for this thread */
   136     sigemptyset(&mask);
   137     for (i = 0; sig_list[i]; ++i) {
   138         sigaddset(&mask, sig_list[i]);
   139     }
   140     pthread_sigmask(SIG_BLOCK, &mask, 0);
   141 
   142 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
   143     /* Allow ourselves to be asynchronously cancelled */
   144     {
   145         int oldstate;
   146         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
   147     }
   148 #endif
   149 }
   150 
   151 SDL_threadID
   152 SDL_ThreadID(void)
   153 {
   154     return ((SDL_threadID) pthread_self());
   155 }
   156 
   157 int
   158 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   159 {
   160 #ifdef __LINUX__
   161     int value;
   162 
   163     if (priority == SDL_THREAD_PRIORITY_LOW) {
   164         value = 19;
   165     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   166         value = -20;
   167     } else {
   168         value = 0;
   169     }
   170     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   171         /* Note that this fails if you're trying to set high priority
   172            and you don't have root permission. BUT DON'T RUN AS ROOT!
   173          */
   174         return SDL_SetError("setpriority() failed");
   175     }
   176     return 0;
   177 #else
   178     struct sched_param sched;
   179     int policy;
   180     pthread_t thread = pthread_self();
   181 
   182     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   183         return SDL_SetError("pthread_getschedparam() failed");
   184     }
   185     if (priority == SDL_THREAD_PRIORITY_LOW) {
   186         sched.sched_priority = sched_get_priority_min(policy);
   187     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   188         sched.sched_priority = sched_get_priority_max(policy);
   189     } else {
   190         int min_priority = sched_get_priority_min(policy);
   191         int max_priority = sched_get_priority_max(policy);
   192         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   193     }
   194     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   195         return SDL_SetError("pthread_setschedparam() failed");
   196     }
   197     return 0;
   198 #endif /* linux */
   199 }
   200 
   201 void
   202 SDL_SYS_WaitThread(SDL_Thread * thread)
   203 {
   204     pthread_join(thread->handle, 0);
   205 }
   206 
   207 /* vi: set ts=4 sw=4 expandtab: */