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