src/thread/pthread/SDL_systhread.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 23 Oct 2012 17:46:57 -0700
changeset 6604 70292a6d7dca
parent 6600 f16fc9564de4
child 6605 59132ac5df74
permissions -rw-r--r--
Fixed Mac OS X build
     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 #include "SDL_platform.h"
    43 #include "SDL_thread.h"
    44 #include "../SDL_thread_c.h"
    45 #include "../SDL_systhread.h"
    46 #ifdef __ANDROID__
    47 #include "../../core/android/SDL_android.h"
    48 #endif
    49 
    50 /* List of signals to mask in the subthreads */
    51 static const int sig_list[] = {
    52     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
    53     SIGVTALRM, SIGPROF, 0
    54 };
    55 
    56 
    57 static void *
    58 RunThread(void *data)
    59 {
    60 #ifdef __ANDROID__
    61     Android_JNI_SetupThread();
    62 #endif
    63     SDL_RunThread(data);
    64     return NULL;
    65 }
    66 
    67 int
    68 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    69 {
    70     pthread_attr_t type;
    71 
    72     /* Set the thread attributes */
    73     if (pthread_attr_init(&type) != 0) {
    74         SDL_SetError("Couldn't initialize pthread attributes");
    75         return (-1);
    76     }
    77     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    78 
    79     /* Create the thread and go! */
    80     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
    81         SDL_SetError("Not enough resources to create thread");
    82         return (-1);
    83     }
    84 
    85     return (0);
    86 }
    87 
    88 void
    89 SDL_SYS_SetupThread(const char *name)
    90 {
    91     int i;
    92     sigset_t mask;
    93 
    94     if (name != NULL) {
    95 #if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \
    96       (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) )
    97         int (*dynamic_pthread_setname_np)(const char*);
    98         *(void**)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np");
    99         if ( dynamic_pthread_setname_np )
   100             dynamic_pthread_setname_np( name );
   101 #elif HAVE_PTHREAD_SETNAME_NP
   102         pthread_setname_np(pthread_self(), name);
   103 #elif HAVE_PTHREAD_SET_NAME_NP
   104         pthread_set_name_np(pthread_self(), name);
   105 #endif
   106     }
   107 
   108     /* Mask asynchronous signals for this thread */
   109     sigemptyset(&mask);
   110     for (i = 0; sig_list[i]; ++i) {
   111         sigaddset(&mask, sig_list[i]);
   112     }
   113     pthread_sigmask(SIG_BLOCK, &mask, 0);
   114 
   115 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
   116     /* Allow ourselves to be asynchronously cancelled */
   117     {
   118         int oldstate;
   119         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
   120     }
   121 #endif
   122 }
   123 
   124 SDL_threadID
   125 SDL_ThreadID(void)
   126 {
   127     return ((SDL_threadID) pthread_self());
   128 }
   129 
   130 int
   131 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   132 {
   133 #ifdef __LINUX__
   134     int value;
   135 
   136     if (priority == SDL_THREAD_PRIORITY_LOW) {
   137         value = 19;
   138     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   139         value = -20;
   140     } else {
   141         value = 0;
   142     }
   143     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   144         /* Note that this fails if you're trying to set high priority
   145            and you don't have root permission. BUT DON'T RUN AS ROOT!
   146          */
   147         SDL_SetError("setpriority() failed");
   148         return -1;
   149     }
   150     return 0;
   151 #else
   152     struct sched_param sched;
   153     int policy;
   154     pthread_t thread = pthread_self();
   155 
   156     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   157         SDL_SetError("pthread_getschedparam() failed");
   158         return -1;
   159     }
   160     if (priority == SDL_THREAD_PRIORITY_LOW) {
   161         sched.sched_priority = sched_get_priority_min(policy);
   162     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   163         sched.sched_priority = sched_get_priority_max(policy);
   164     } else {
   165         int min_priority = sched_get_priority_min(policy);
   166         int max_priority = sched_get_priority_max(policy);
   167         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   168     }
   169     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   170         SDL_SetError("pthread_setschedparam() failed");
   171         return -1;
   172     }
   173     return 0;
   174 #endif /* linux */
   175 }
   176 
   177 void
   178 SDL_SYS_WaitThread(SDL_Thread * thread)
   179 {
   180     pthread_join(thread->handle, 0);
   181 }
   182 
   183 /* vi: set ts=4 sw=4 expandtab: */