src/thread/pthread/SDL_systhread.c
author Gabriel Jacobo <gabomdq@gmail.com>
Mon, 09 Jul 2012 18:08:06 -0300
changeset 6354 17840f487124
parent 6138 4c64952a58fb
child 6600 f16fc9564de4
permissions -rwxr-xr-x
Fixes #1422, removes global JNI Env, uses per thread copies, adds thread auto detaching.
slouken@1361
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1361
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1361
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1361
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1361
    20
*/
icculus@5981
    21
slouken@1402
    22
#include "SDL_config.h"
slouken@1361
    23
slouken@1361
    24
#include <pthread.h>
icculus@5969
    25
icculus@5969
    26
#if HAVE_PTHREAD_NP_H
icculus@5969
    27
#include <pthread_np.h>
icculus@5969
    28
#endif
icculus@5969
    29
slouken@1361
    30
#include <signal.h>
slouken@5513
    31
#ifdef __LINUX__
slouken@5509
    32
#include <sys/time.h>
slouken@5509
    33
#include <sys/resource.h>
slouken@5509
    34
#include <sys/syscall.h>
icculus@5981
    35
#include <unistd.h>
icculus@5981
    36
extern int pthread_setname_np (pthread_t __target_thread, __const char *__name) __THROW __nonnull ((2));
slouken@5509
    37
#endif
slouken@1361
    38
icculus@5969
    39
#include "SDL_platform.h"
slouken@1361
    40
#include "SDL_thread.h"
slouken@1361
    41
#include "../SDL_thread_c.h"
slouken@1361
    42
#include "../SDL_systhread.h"
gabomdq@6354
    43
#ifdef __ANDROID__
gabomdq@6354
    44
#include "../../core/android/SDL_android.h"
gabomdq@6354
    45
#endif
slouken@1361
    46
slouken@1361
    47
/* List of signals to mask in the subthreads */
slouken@3162
    48
static const int sig_list[] = {
slouken@1895
    49
    SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
slouken@1895
    50
    SIGVTALRM, SIGPROF, 0
slouken@1361
    51
};
slouken@1361
    52
slouken@5509
    53
slouken@1895
    54
static void *
slouken@1895
    55
RunThread(void *data)
slouken@1361
    56
{
gabomdq@6354
    57
#ifdef __ANDROID__
gabomdq@6354
    58
    Android_JNI_SetupThread();
gabomdq@6354
    59
#endif
slouken@1895
    60
    SDL_RunThread(data);
icculus@5963
    61
    return NULL;
slouken@1361
    62
}
slouken@1361
    63
slouken@1895
    64
int
slouken@1895
    65
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@1361
    66
{
slouken@1895
    67
    pthread_attr_t type;
slouken@1361
    68
slouken@1895
    69
    /* Set the thread attributes */
slouken@1895
    70
    if (pthread_attr_init(&type) != 0) {
slouken@1895
    71
        SDL_SetError("Couldn't initialize pthread attributes");
slouken@1895
    72
        return (-1);
slouken@1895
    73
    }
slouken@1895
    74
    pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
slouken@1361
    75
slouken@1895
    76
    /* Create the thread and go! */
slouken@1895
    77
    if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
slouken@1895
    78
        SDL_SetError("Not enough resources to create thread");
slouken@1895
    79
        return (-1);
slouken@1895
    80
    }
slouken@1459
    81
slouken@1895
    82
    return (0);
slouken@1361
    83
}
slouken@1361
    84
slouken@1895
    85
void
icculus@5969
    86
SDL_SYS_SetupThread(const char *name)
slouken@1361
    87
{
slouken@1895
    88
    int i;
slouken@1895
    89
    sigset_t mask;
slouken@1361
    90
icculus@6000
    91
    if (name != NULL) {
icculus@5972
    92
#if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \
icculus@5972
    93
      (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) )
icculus@6000
    94
        if (pthread_setname_np != NULL) { pthread_setname_np(name); }
icculus@5969
    95
#elif HAVE_PTHREAD_SETNAME_NP
icculus@6000
    96
        pthread_setname_np(pthread_self(), name);
icculus@5969
    97
#elif HAVE_PTHREAD_SET_NAME_NP
icculus@6000
    98
        pthread_set_name_np(pthread_self(), name);
icculus@5969
    99
#endif
icculus@6000
   100
    }
icculus@5969
   101
slouken@1895
   102
    /* Mask asynchronous signals for this thread */
slouken@1895
   103
    sigemptyset(&mask);
slouken@1895
   104
    for (i = 0; sig_list[i]; ++i) {
slouken@1895
   105
        sigaddset(&mask, sig_list[i]);
slouken@1895
   106
    }
slouken@1895
   107
    pthread_sigmask(SIG_BLOCK, &mask, 0);
slouken@1361
   108
slouken@1361
   109
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
slouken@1895
   110
    /* Allow ourselves to be asynchronously cancelled */
slouken@1895
   111
    {
slouken@1895
   112
        int oldstate;
slouken@1895
   113
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
slouken@1895
   114
    }
slouken@1361
   115
#endif
slouken@1361
   116
}
slouken@1361
   117
slouken@3578
   118
SDL_threadID
slouken@1895
   119
SDL_ThreadID(void)
slouken@1361
   120
{
slouken@3578
   121
    return ((SDL_threadID) pthread_self());
slouken@1361
   122
}
slouken@1361
   123
slouken@5506
   124
int
slouken@5509
   125
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
slouken@5506
   126
{
slouken@5513
   127
#ifdef __LINUX__
slouken@5509
   128
    int value;
slouken@5509
   129
slouken@5509
   130
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5509
   131
        value = 19;
slouken@5509
   132
    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@5509
   133
        value = -20;
slouken@5509
   134
    } else {
slouken@5509
   135
        value = 0;
slouken@5509
   136
    }
slouken@5509
   137
    if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
slouken@5510
   138
        /* Note that this fails if you're trying to set high priority
slouken@5510
   139
           and you don't have root permission. BUT DON'T RUN AS ROOT!
slouken@5510
   140
         */
slouken@5509
   141
        SDL_SetError("setpriority() failed");
slouken@5509
   142
        return -1;
slouken@5509
   143
    }
slouken@5509
   144
    return 0;
slouken@5509
   145
#else
slouken@5506
   146
    struct sched_param sched;
slouken@5506
   147
    int policy;
slouken@5509
   148
    pthread_t thread = pthread_self();
slouken@5506
   149
slouken@5509
   150
    if (pthread_getschedparam(thread, &policy, &sched) < 0) {
slouken@5506
   151
        SDL_SetError("pthread_getschedparam() failed");
slouken@5506
   152
        return -1;
slouken@5506
   153
    }
slouken@5506
   154
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5506
   155
        sched.sched_priority = sched_get_priority_min(policy);
slouken@5506
   156
    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@5506
   157
        sched.sched_priority = sched_get_priority_max(policy);
slouken@5506
   158
    } else {
slouken@5506
   159
        int min_priority = sched_get_priority_min(policy);
slouken@5506
   160
        int max_priority = sched_get_priority_max(policy);
slouken@5509
   161
        sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
slouken@5506
   162
    }
slouken@5509
   163
    if (pthread_setschedparam(thread, policy, &sched) < 0) {
slouken@5506
   164
        SDL_SetError("pthread_setschedparam() failed");
slouken@5506
   165
        return -1;
slouken@5506
   166
    }
slouken@5506
   167
    return 0;
slouken@5509
   168
#endif /* linux */
slouken@5506
   169
}
slouken@5506
   170
slouken@1895
   171
void
slouken@1895
   172
SDL_SYS_WaitThread(SDL_Thread * thread)
slouken@1361
   173
{
slouken@1895
   174
    pthread_join(thread->handle, 0);
slouken@1361
   175
}
slouken@1361
   176
slouken@1895
   177
/* vi: set ts=4 sw=4 expandtab: */