src/thread/pthread/SDL_systhread.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 23 Oct 2012 23:44:56 -0700
changeset 6605 59132ac5df74
parent 6604 70292a6d7dca
child 6640 44a2e00e7c66
permissions -rw-r--r--
Really fixed the Mac build this time.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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 #ifdef __LINUX__
    32 #include <sys/time.h>
    33 #include <sys/resource.h>
    34 #include <sys/syscall.h>
    35 #include <unistd.h>
    36 
    37 #if HAVE_PTHREAD_SETNAME_NP
    38 extern int pthread_setname_np (pthread_t __target_thread, __const char *__name) __THROW __nonnull ((2));
    39 #endif
    40 #endif // __LINUX__
    41 
    42 #if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \
    43       (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) )
    44 #define NEED_DYNAMIC_PTHREAD_SETNAME_NP
    45 #include <dlfcn.h>
    46 #endif
    47 
    48 #include "SDL_platform.h"
    49 #include "SDL_thread.h"
    50 #include "../SDL_thread_c.h"
    51 #include "../SDL_systhread.h"
    52 #ifdef __ANDROID__
    53 #include "../../core/android/SDL_android.h"
    54 #endif
    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 int
    74 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    75 {
    76     pthread_attr_t type;
    77 
    78     /* Set the thread attributes */
    79     if (pthread_attr_init(&type) != 0) {
    80         SDL_SetError("Couldn't initialize pthread attributes");
    81         return (-1);
    82     }
    83     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    84 
    85     /* Create the thread and go! */
    86     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
    87         SDL_SetError("Not enough resources to create thread");
    88         return (-1);
    89     }
    90 
    91     return (0);
    92 }
    93 
    94 void
    95 SDL_SYS_SetupThread(const char *name)
    96 {
    97     int i;
    98     sigset_t mask;
    99 
   100     if (name != NULL) {
   101 #ifdef NEED_DYNAMIC_PTHREAD_SETNAME_NP
   102         int (*dynamic_pthread_setname_np)(const char*);
   103         *(void**)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np");
   104         if ( dynamic_pthread_setname_np )
   105             dynamic_pthread_setname_np( name );
   106 #elif HAVE_PTHREAD_SETNAME_NP
   107         pthread_setname_np(pthread_self(), name);
   108 #elif HAVE_PTHREAD_SET_NAME_NP
   109         pthread_set_name_np(pthread_self(), name);
   110 #endif
   111     }
   112 
   113     /* Mask asynchronous signals for this thread */
   114     sigemptyset(&mask);
   115     for (i = 0; sig_list[i]; ++i) {
   116         sigaddset(&mask, sig_list[i]);
   117     }
   118     pthread_sigmask(SIG_BLOCK, &mask, 0);
   119 
   120 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
   121     /* Allow ourselves to be asynchronously cancelled */
   122     {
   123         int oldstate;
   124         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
   125     }
   126 #endif
   127 }
   128 
   129 SDL_threadID
   130 SDL_ThreadID(void)
   131 {
   132     return ((SDL_threadID) pthread_self());
   133 }
   134 
   135 int
   136 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   137 {
   138 #ifdef __LINUX__
   139     int value;
   140 
   141     if (priority == SDL_THREAD_PRIORITY_LOW) {
   142         value = 19;
   143     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   144         value = -20;
   145     } else {
   146         value = 0;
   147     }
   148     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   149         /* Note that this fails if you're trying to set high priority
   150            and you don't have root permission. BUT DON'T RUN AS ROOT!
   151          */
   152         SDL_SetError("setpriority() failed");
   153         return -1;
   154     }
   155     return 0;
   156 #else
   157     struct sched_param sched;
   158     int policy;
   159     pthread_t thread = pthread_self();
   160 
   161     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   162         SDL_SetError("pthread_getschedparam() failed");
   163         return -1;
   164     }
   165     if (priority == SDL_THREAD_PRIORITY_LOW) {
   166         sched.sched_priority = sched_get_priority_min(policy);
   167     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   168         sched.sched_priority = sched_get_priority_max(policy);
   169     } else {
   170         int min_priority = sched_get_priority_min(policy);
   171         int max_priority = sched_get_priority_max(policy);
   172         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   173     }
   174     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   175         SDL_SetError("pthread_setschedparam() failed");
   176         return -1;
   177     }
   178     return 0;
   179 #endif /* linux */
   180 }
   181 
   182 void
   183 SDL_SYS_WaitThread(SDL_Thread * thread)
   184 {
   185     pthread_join(thread->handle, 0);
   186 }
   187 
   188 /* vi: set ts=4 sw=4 expandtab: */