src/thread/pthread/SDL_systhread.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 25 Mar 2011 12:44:06 -0700
changeset 5509 5b1b4d820d10
parent 5506 82a09d5d0f07
child 5510 55519e27e5d1
permissions -rw-r--r--
The API sets the priority for the current thread, not an arbitrary thread.

Implemented thread priority as the 'nice' value on Linux. High priority threads require root permissions (you shouldn't give your game root permissions though!)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include <pthread.h>
    25 #include <signal.h>
    26 #ifdef linux
    27 #include <sys/time.h>
    28 #include <sys/resource.h>
    29 #include <sys/syscall.h>
    30 #endif
    31 
    32 #include "SDL_thread.h"
    33 #include "../SDL_thread_c.h"
    34 #include "../SDL_systhread.h"
    35 
    36 /* List of signals to mask in the subthreads */
    37 static const int sig_list[] = {
    38     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
    39     SIGVTALRM, SIGPROF, 0
    40 };
    41 
    42 
    43 static void *
    44 RunThread(void *data)
    45 {
    46     SDL_RunThread(data);
    47     pthread_exit((void *) 0);
    48     return ((void *) 0);        /* Prevent compiler warning */
    49 }
    50 
    51 int
    52 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    53 {
    54     pthread_attr_t type;
    55 
    56     /* Set the thread attributes */
    57     if (pthread_attr_init(&type) != 0) {
    58         SDL_SetError("Couldn't initialize pthread attributes");
    59         return (-1);
    60     }
    61     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    62 
    63     /* Create the thread and go! */
    64     if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
    65         SDL_SetError("Not enough resources to create thread");
    66         return (-1);
    67     }
    68 
    69     return (0);
    70 }
    71 
    72 void
    73 SDL_SYS_SetupThread(void)
    74 {
    75     int i;
    76     sigset_t mask;
    77 
    78     /* Mask asynchronous signals for this thread */
    79     sigemptyset(&mask);
    80     for (i = 0; sig_list[i]; ++i) {
    81         sigaddset(&mask, sig_list[i]);
    82     }
    83     pthread_sigmask(SIG_BLOCK, &mask, 0);
    84 
    85 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
    86     /* Allow ourselves to be asynchronously cancelled */
    87     {
    88         int oldstate;
    89         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
    90     }
    91 #endif
    92 }
    93 
    94 SDL_threadID
    95 SDL_ThreadID(void)
    96 {
    97     return ((SDL_threadID) pthread_self());
    98 }
    99 
   100 int
   101 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   102 {
   103 #ifdef linux
   104     int value;
   105 
   106     if (priority == SDL_THREAD_PRIORITY_LOW) {
   107         value = 19;
   108     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   109         value = -20;
   110     } else {
   111         value = 0;
   112     }
   113     if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
   114         SDL_SetError("setpriority() failed");
   115         return -1;
   116     }
   117     return 0;
   118 #else
   119     struct sched_param sched;
   120     int policy;
   121     pthread_t thread = pthread_self();
   122 
   123     if (pthread_getschedparam(thread, &policy, &sched) < 0) {
   124         SDL_SetError("pthread_getschedparam() failed");
   125         return -1;
   126     }
   127     if (priority == SDL_THREAD_PRIORITY_LOW) {
   128         sched.sched_priority = sched_get_priority_min(policy);
   129     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   130         sched.sched_priority = sched_get_priority_max(policy);
   131     } else {
   132         int min_priority = sched_get_priority_min(policy);
   133         int max_priority = sched_get_priority_max(policy);
   134         sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
   135     }
   136     if (pthread_setschedparam(thread, policy, &sched) < 0) {
   137         SDL_SetError("pthread_setschedparam() failed");
   138         return -1;
   139     }
   140     return 0;
   141 #endif /* linux */
   142 }
   143 
   144 void
   145 SDL_SYS_WaitThread(SDL_Thread * thread)
   146 {
   147     pthread_join(thread->handle, 0);
   148 }
   149 
   150 /* vi: set ts=4 sw=4 expandtab: */