src/thread/pthread/SDL_systhread.c
author Jinke Fan <fanjinke@hygon.cn>
Wed, 15 May 2019 19:54:36 +0800
changeset 13082 f77988be3607
parent 12503 806492103856
permissions -rw-r--r--
Add Hygon Dhyana processor support

Background:
Chengdu Haiguang IC Design Co., Ltd (Hygon) is a Joint Venture
between AMD and Haiguang Information Technology Co.,Ltd., aims at
providing high performance x86 processor for China server market.
Its first generation processor codename is Dhyana, which
originates from AMD technology and shares most of the
architecture with AMD's family 17h, but with different CPU Vendor
ID("HygonGenuine")/Family series number(Family 18h).

Related Hygon kernel patch can be found on:
http://lkml.kernel.org/r/5ce86123a7b9dad925ac583d88d2f921040e859b.1538583282.git.puwen@hygon.cn

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