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