src/thread/pthread/SDL_systhread.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 20 Sep 2011 17:48:29 -0400
changeset 5963 fe5d2285dffa
parent 5535 96594ac5fd1a
child 5969 3a041d215edc
permissions -rw-r--r--
Don't call pthread_exit(), returning from RunThread() is equivalent.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 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 #include "SDL_config.h"
    22 
    23 #include <pthread.h>
    24 #include <signal.h>
    25 #ifdef __LINUX__
    26 #include <sys/time.h>
    27 #include <sys/resource.h>
    28 #include <sys/syscall.h>
    29 #endif
    30 
    31 #include "SDL_thread.h"
    32 #include "../SDL_thread_c.h"
    33 #include "../SDL_systhread.h"
    34 
    35 /* List of signals to mask in the subthreads */
    36 static const int sig_list[] = {
    37     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
    38     SIGVTALRM, SIGPROF, 0
    39 };
    40 
    41 
    42 static void *
    43 RunThread(void *data)
    44 {
    45     SDL_RunThread(data);
    46     return NULL;
    47 }
    48 
    49 int
    50 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    51 {
    52     pthread_attr_t type;
    53 
    54     /* Set the thread attributes */
    55     if (pthread_attr_init(&type) != 0) {
    56         SDL_SetError("Couldn't initialize pthread attributes");
    57         return (-1);
    58     }
    59     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    60 
    61     /* Create the thread and go! */
    62     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
    63         SDL_SetError("Not enough resources to create thread");
    64         return (-1);
    65     }
    66 
    67     return (0);
    68 }
    69 
    70 void
    71 SDL_SYS_SetupThread(void)
    72 {
    73     int i;
    74     sigset_t mask;
    75 
    76     /* Mask asynchronous signals for this thread */
    77     sigemptyset(&mask);
    78     for (i = 0; sig_list[i]; ++i) {
    79         sigaddset(&mask, sig_list[i]);
    80     }
    81     pthread_sigmask(SIG_BLOCK, &mask, 0);
    82 
    83 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
    84     /* Allow ourselves to be asynchronously cancelled */
    85     {
    86         int oldstate;
    87         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
    88     }
    89 #endif
    90 }
    91 
    92 SDL_threadID
    93 SDL_ThreadID(void)
    94 {
    95     return ((SDL_threadID) pthread_self());
    96 }
    97 
    98 int
    99 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   100 {
   101 #ifdef __LINUX__
   102     int value;
   103 
   104     if (priority == SDL_THREAD_PRIORITY_LOW) {
   105         value = 19;
   106     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   107         value = -20;
   108     } else {
   109         value = 0;
   110     }
   111     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   112         /* Note that this fails if you're trying to set high priority
   113            and you don't have root permission. BUT DON'T RUN AS ROOT!
   114          */
   115         SDL_SetError("setpriority() failed");
   116         return -1;
   117     }
   118     return 0;
   119 #else
   120     struct sched_param sched;
   121     int policy;
   122     pthread_t thread = pthread_self();
   123 
   124     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   125         SDL_SetError("pthread_getschedparam() failed");
   126         return -1;
   127     }
   128     if (priority == SDL_THREAD_PRIORITY_LOW) {
   129         sched.sched_priority = sched_get_priority_min(policy);
   130     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   131         sched.sched_priority = sched_get_priority_max(policy);
   132     } else {
   133         int min_priority = sched_get_priority_min(policy);
   134         int max_priority = sched_get_priority_max(policy);
   135         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   136     }
   137     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   138         SDL_SetError("pthread_setschedparam() failed");
   139         return -1;
   140     }
   141     return 0;
   142 #endif /* linux */
   143 }
   144 
   145 void
   146 SDL_SYS_WaitThread(SDL_Thread * thread)
   147 {
   148     pthread_join(thread->handle, 0);
   149 }
   150 
   151 /* vi: set ts=4 sw=4 expandtab: */