src/thread/pthread/SDL_systhread.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 08 Apr 2011 13:03:26 -0700
changeset 5535 96594ac5fd1a
parent 5513 0a72c9c29099
child 5963 fe5d2285dffa
permissions -rw-r--r--
SDL 1.3 is now under the zlib license.
     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     pthread_exit((void *) 0);
    47     return ((void *) 0);        /* Prevent compiler warning */
    48 }
    49 
    50 int
    51 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    52 {
    53     pthread_attr_t type;
    54 
    55     /* Set the thread attributes */
    56     if (pthread_attr_init(&type) != 0) {
    57         SDL_SetError("Couldn't initialize pthread attributes");
    58         return (-1);
    59     }
    60     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    61 
    62     /* Create the thread and go! */
    63     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
    64         SDL_SetError("Not enough resources to create thread");
    65         return (-1);
    66     }
    67 
    68     return (0);
    69 }
    70 
    71 void
    72 SDL_SYS_SetupThread(void)
    73 {
    74     int i;
    75     sigset_t mask;
    76 
    77     /* Mask asynchronous signals for this thread */
    78     sigemptyset(&mask);
    79     for (i = 0; sig_list[i]; ++i) {
    80         sigaddset(&mask, sig_list[i]);
    81     }
    82     pthread_sigmask(SIG_BLOCK, &mask, 0);
    83 
    84 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
    85     /* Allow ourselves to be asynchronously cancelled */
    86     {
    87         int oldstate;
    88         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
    89     }
    90 #endif
    91 }
    92 
    93 SDL_threadID
    94 SDL_ThreadID(void)
    95 {
    96     return ((SDL_threadID) pthread_self());
    97 }
    98 
    99 int
   100 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   101 {
   102 #ifdef __LINUX__
   103     int value;
   104 
   105     if (priority == SDL_THREAD_PRIORITY_LOW) {
   106         value = 19;
   107     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   108         value = -20;
   109     } else {
   110         value = 0;
   111     }
   112     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   113         /* Note that this fails if you're trying to set high priority
   114            and you don't have root permission. BUT DON'T RUN AS ROOT!
   115          */
   116         SDL_SetError("setpriority() failed");
   117         return -1;
   118     }
   119     return 0;
   120 #else
   121     struct sched_param sched;
   122     int policy;
   123     pthread_t thread = pthread_self();
   124 
   125     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   126         SDL_SetError("pthread_getschedparam() failed");
   127         return -1;
   128     }
   129     if (priority == SDL_THREAD_PRIORITY_LOW) {
   130         sched.sched_priority = sched_get_priority_min(policy);
   131     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   132         sched.sched_priority = sched_get_priority_max(policy);
   133     } else {
   134         int min_priority = sched_get_priority_min(policy);
   135         int max_priority = sched_get_priority_max(policy);
   136         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   137     }
   138     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   139         SDL_SetError("pthread_setschedparam() failed");
   140         return -1;
   141     }
   142     return 0;
   143 #endif /* linux */
   144 }
   145 
   146 void
   147 SDL_SYS_WaitThread(SDL_Thread * thread)
   148 {
   149     pthread_join(thread->handle, 0);
   150 }
   151 
   152 /* vi: set ts=4 sw=4 expandtab: */