src/thread/pthread/SDL_systhread.c
author Ryan C. Gordon
Wed, 05 Dec 2018 16:51:22 -0500
changeset 12456 f8041c025fd3
parent 12454 762a775a58cd
child 12462 b57435750c5b
permissions -rw-r--r--
linux: Move SDL_LinuxSetThreadPriority() elsewhere to fix build.

Fixes Bugzilla #4393.
slouken@1361
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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
icculus@8093
    22
#include "../../SDL_internal.h"
icculus@12456
    23
#include "SDL_system.h"
slouken@1361
    24
slouken@1361
    25
#include <pthread.h>
icculus@5969
    26
icculus@5969
    27
#if HAVE_PTHREAD_NP_H
icculus@5969
    28
#include <pthread_np.h>
icculus@5969
    29
#endif
icculus@5969
    30
slouken@1361
    31
#include <signal.h>
icculus@6640
    32
slouken@5513
    33
#ifdef __LINUX__
slouken@5509
    34
#include <sys/time.h>
slouken@5509
    35
#include <sys/resource.h>
slouken@5509
    36
#include <sys/syscall.h>
icculus@5981
    37
#include <unistd.h>
slouken@11946
    38
#include <errno.h>
slouken@11946
    39
slouken@11946
    40
#include "../../core/linux/SDL_dbus.h"
slouken@7191
    41
#endif /* __LINUX__ */
slouken@1361
    42
icculus@6640
    43
#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__)
slouken@6605
    44
#include <dlfcn.h>
icculus@6640
    45
#ifndef RTLD_DEFAULT
icculus@6640
    46
#define RTLD_DEFAULT NULL
icculus@6640
    47
#endif
slouken@6605
    48
#endif
slouken@6605
    49
slouken@11946
    50
#include "SDL_log.h"
icculus@5969
    51
#include "SDL_platform.h"
slouken@1361
    52
#include "SDL_thread.h"
sylvain@12454
    53
#include "SDL_system.h"
slouken@1361
    54
#include "../SDL_thread_c.h"
slouken@1361
    55
#include "../SDL_systhread.h"
gabomdq@6354
    56
#ifdef __ANDROID__
gabomdq@6354
    57
#include "../../core/android/SDL_android.h"
gabomdq@6354
    58
#endif
slouken@1361
    59
icculus@7977
    60
#ifdef __HAIKU__
icculus@10983
    61
#include <kernel/OS.h>
icculus@7977
    62
#endif
icculus@7977
    63
icculus@6640
    64
#include "SDL_assert.h"
icculus@6640
    65
sbc@8879
    66
#ifndef __NACL__
slouken@1361
    67
/* List of signals to mask in the subthreads */
slouken@3162
    68
static const int sig_list[] = {
slouken@1895
    69
    SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
slouken@1895
    70
    SIGVTALRM, SIGPROF, 0
slouken@1361
    71
};
sbc@8879
    72
#endif
slouken@1361
    73
slouken@1895
    74
static void *
slouken@1895
    75
RunThread(void *data)
slouken@1361
    76
{
gabomdq@6354
    77
#ifdef __ANDROID__
gabomdq@6354
    78
    Android_JNI_SetupThread();
gabomdq@6354
    79
#endif
slouken@1895
    80
    SDL_RunThread(data);
icculus@5963
    81
    return NULL;
slouken@1361
    82
}
slouken@1361
    83
icculus@6640
    84
#if defined(__MACOSX__) || defined(__IPHONEOS__)
icculus@6640
    85
static SDL_bool checked_setname = SDL_FALSE;
icculus@6641
    86
static int (*ppthread_setname_np)(const char*) = NULL;
icculus@6640
    87
#elif defined(__LINUX__)
icculus@6640
    88
static SDL_bool checked_setname = SDL_FALSE;
icculus@6641
    89
static int (*ppthread_setname_np)(pthread_t, const char*) = NULL;
icculus@6640
    90
#endif
slouken@1895
    91
int
slouken@1895
    92
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@1361
    93
{
slouken@1895
    94
    pthread_attr_t type;
slouken@1361
    95
icculus@6640
    96
    /* do this here before any threads exist, so there's no race condition. */
icculus@6640
    97
    #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
icculus@6640
    98
    if (!checked_setname) {
icculus@6640
    99
        void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
sezero@11872
   100
        #if defined(__MACOSX__) || defined(__IPHONEOS__)
sezero@11872
   101
        ppthread_setname_np = (int(*)(const char*)) fn;
sezero@11872
   102
        #elif defined(__LINUX__)
sezero@11872
   103
        ppthread_setname_np = (int(*)(pthread_t, const char*)) fn;
sezero@11872
   104
        #endif
icculus@6640
   105
        checked_setname = SDL_TRUE;
icculus@6640
   106
    }
icculus@6640
   107
    #endif
icculus@6640
   108
slouken@1895
   109
    /* Set the thread attributes */
slouken@1895
   110
    if (pthread_attr_init(&type) != 0) {
icculus@7037
   111
        return SDL_SetError("Couldn't initialize pthread attributes");
slouken@1895
   112
    }
slouken@1895
   113
    pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
icculus@9648
   114
    
icculus@10145
   115
    /* Set caller-requested stack size. Otherwise: use the system default. */
icculus@10145
   116
    if (thread->stacksize) {
icculus@10145
   117
        pthread_attr_setstacksize(&type, (size_t) thread->stacksize);
icculus@9648
   118
    }
slouken@1459
   119
slouken@1895
   120
    /* Create the thread and go! */
slouken@1895
   121
    if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
icculus@7037
   122
        return SDL_SetError("Not enough resources to create thread");
slouken@1895
   123
    }
slouken@1459
   124
icculus@7037
   125
    return 0;
slouken@1361
   126
}
slouken@1361
   127
slouken@1895
   128
void
icculus@5969
   129
SDL_SYS_SetupThread(const char *name)
slouken@1361
   130
{
slouken@10534
   131
#if !defined(__NACL__)
slouken@1895
   132
    int i;
slouken@1895
   133
    sigset_t mask;
slouken@10534
   134
#endif /* !__NACL__ */
slouken@1361
   135
icculus@6000
   136
    if (name != NULL) {
icculus@6640
   137
        #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
icculus@6640
   138
        SDL_assert(checked_setname);
icculus@6641
   139
        if (ppthread_setname_np != NULL) {
icculus@6640
   140
            #if defined(__MACOSX__) || defined(__IPHONEOS__)
icculus@6641
   141
            ppthread_setname_np(name);
icculus@6640
   142
            #elif defined(__LINUX__)
icculus@6641
   143
            ppthread_setname_np(pthread_self(), name);
icculus@6640
   144
            #endif
icculus@6640
   145
        }
icculus@6640
   146
        #elif HAVE_PTHREAD_SETNAME_NP
icculus@9987
   147
            #if defined(__NETBSD__)
icculus@9987
   148
            pthread_setname_np(pthread_self(), "%s", name);
icculus@9987
   149
            #else
icculus@6640
   150
            pthread_setname_np(pthread_self(), name);
icculus@9987
   151
            #endif
icculus@6640
   152
        #elif HAVE_PTHREAD_SET_NAME_NP
icculus@6640
   153
            pthread_set_name_np(pthread_self(), name);
icculus@7977
   154
        #elif defined(__HAIKU__)
icculus@7977
   155
            /* The docs say the thread name can't be longer than B_OS_NAME_LENGTH. */
icculus@7977
   156
            char namebuf[B_OS_NAME_LENGTH];
icculus@7977
   157
            SDL_snprintf(namebuf, sizeof (namebuf), "%s", name);
icculus@7977
   158
            namebuf[sizeof (namebuf) - 1] = '\0';
icculus@7977
   159
            rename_thread(find_thread(NULL), namebuf);
icculus@6640
   160
        #endif
icculus@6000
   161
    }
icculus@5969
   162
gabomdq@8833
   163
   /* NativeClient does not yet support signals.*/
slouken@10534
   164
#if !defined(__NACL__)
slouken@1895
   165
    /* Mask asynchronous signals for this thread */
slouken@1895
   166
    sigemptyset(&mask);
slouken@1895
   167
    for (i = 0; sig_list[i]; ++i) {
slouken@1895
   168
        sigaddset(&mask, sig_list[i]);
slouken@1895
   169
    }
slouken@1895
   170
    pthread_sigmask(SIG_BLOCK, &mask, 0);
slouken@10534
   171
#endif /* !__NACL__ */
slouken@9752
   172
slouken@1361
   173
slouken@1361
   174
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
slouken@1895
   175
    /* Allow ourselves to be asynchronously cancelled */
slouken@1895
   176
    {
slouken@1895
   177
        int oldstate;
slouken@1895
   178
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
slouken@1895
   179
    }
slouken@1361
   180
#endif
slouken@1361
   181
}
slouken@1361
   182
slouken@3578
   183
SDL_threadID
slouken@1895
   184
SDL_ThreadID(void)
slouken@1361
   185
{
slouken@3578
   186
    return ((SDL_threadID) pthread_self());
slouken@1361
   187
}
slouken@1361
   188
slouken@5506
   189
int
slouken@5509
   190
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
slouken@5506
   191
{
gabomdq@8833
   192
#if __NACL__ 
gabomdq@8833
   193
    /* FIXME: Setting thread priority does not seem to be supported in NACL */
gabomdq@8833
   194
    return 0;
gabomdq@8833
   195
#elif __LINUX__
slouken@5509
   196
    int value;
slouken@11946
   197
    pid_t thread = syscall(SYS_gettid);
slouken@5509
   198
slouken@5509
   199
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5509
   200
        value = 19;
slouken@5509
   201
    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@11952
   202
        value = -10;
slouken@11952
   203
    } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
slouken@5509
   204
        value = -20;
slouken@5509
   205
    } else {
slouken@5509
   206
        value = 0;
slouken@5509
   207
    }
slouken@11947
   208
    return SDL_LinuxSetThreadPriority(thread, value);
slouken@5509
   209
#else
slouken@5506
   210
    struct sched_param sched;
slouken@5506
   211
    int policy;
slouken@5509
   212
    pthread_t thread = pthread_self();
slouken@5506
   213
icculus@11881
   214
    if (pthread_getschedparam(thread, &policy, &sched) != 0) {
icculus@7037
   215
        return SDL_SetError("pthread_getschedparam() failed");
slouken@5506
   216
    }
slouken@5506
   217
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5506
   218
        sched.sched_priority = sched_get_priority_min(policy);
slouken@11952
   219
    } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
slouken@5506
   220
        sched.sched_priority = sched_get_priority_max(policy);
slouken@5506
   221
    } else {
slouken@5506
   222
        int min_priority = sched_get_priority_min(policy);
slouken@5506
   223
        int max_priority = sched_get_priority_max(policy);
slouken@5509
   224
        sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
slouken@11952
   225
        if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@11953
   226
            sched.sched_priority += ((max_priority - min_priority) / 4);
slouken@11952
   227
        }
slouken@5506
   228
    }
icculus@11881
   229
    if (pthread_setschedparam(thread, policy, &sched) != 0) {
icculus@7037
   230
        return SDL_SetError("pthread_setschedparam() failed");
slouken@5506
   231
    }
slouken@5506
   232
    return 0;
slouken@5509
   233
#endif /* linux */
slouken@5506
   234
}
slouken@5506
   235
slouken@1895
   236
void
slouken@1895
   237
SDL_SYS_WaitThread(SDL_Thread * thread)
slouken@1361
   238
{
slouken@1895
   239
    pthread_join(thread->handle, 0);
slouken@1361
   240
}
slouken@1361
   241
icculus@7978
   242
void
icculus@7978
   243
SDL_SYS_DetachThread(SDL_Thread * thread)
icculus@7978
   244
{
icculus@7978
   245
    pthread_detach(thread->handle);
icculus@7978
   246
}
icculus@7978
   247
slouken@1895
   248
/* vi: set ts=4 sw=4 expandtab: */