thread.cpp
1 // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #include <string> 6 7 #include "common/error.h" 8 #include "common/logging/log.h" 9 #include "common/thread.h" 10 #ifdef __APPLE__ 11 #include <mach/mach.h> 12 #elif defined(_WIN32) 13 #include <windows.h> 14 #include "common/string_util.h" 15 #else 16 #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) 17 #include <pthread_np.h> 18 #else 19 #include <pthread.h> 20 #endif 21 #include <sched.h> 22 #endif 23 #ifndef _WIN32 24 #include <unistd.h> 25 #endif 26 27 #ifdef __FreeBSD__ 28 #define cpu_set_t cpuset_t 29 #endif 30 31 namespace Common { 32 33 #ifdef _WIN32 34 35 void SetCurrentThreadPriority(ThreadPriority new_priority) { 36 auto handle = GetCurrentThread(); 37 int windows_priority = 0; 38 switch (new_priority) { 39 case ThreadPriority::Low: 40 windows_priority = THREAD_PRIORITY_BELOW_NORMAL; 41 break; 42 case ThreadPriority::Normal: 43 windows_priority = THREAD_PRIORITY_NORMAL; 44 break; 45 case ThreadPriority::High: 46 windows_priority = THREAD_PRIORITY_ABOVE_NORMAL; 47 break; 48 case ThreadPriority::VeryHigh: 49 windows_priority = THREAD_PRIORITY_HIGHEST; 50 break; 51 case ThreadPriority::Critical: 52 windows_priority = THREAD_PRIORITY_TIME_CRITICAL; 53 break; 54 default: 55 windows_priority = THREAD_PRIORITY_NORMAL; 56 break; 57 } 58 SetThreadPriority(handle, windows_priority); 59 } 60 61 #else 62 63 void SetCurrentThreadPriority(ThreadPriority new_priority) { 64 pthread_t this_thread = pthread_self(); 65 66 const auto scheduling_type = SCHED_OTHER; 67 s32 max_prio = sched_get_priority_max(scheduling_type); 68 s32 min_prio = sched_get_priority_min(scheduling_type); 69 u32 level = std::max(static_cast<u32>(new_priority) + 1, 4U); 70 71 struct sched_param params; 72 if (max_prio > min_prio) { 73 params.sched_priority = min_prio + ((max_prio - min_prio) * level) / 4; 74 } else { 75 params.sched_priority = min_prio - ((min_prio - max_prio) * level) / 4; 76 } 77 78 pthread_setschedparam(this_thread, scheduling_type, ¶ms); 79 } 80 81 #endif 82 83 #ifdef _MSC_VER 84 85 // Sets the debugger-visible name of the current thread. 86 void SetCurrentThreadName(const char* name) { 87 SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); 88 } 89 90 #else // !MSVC_VER, so must be POSIX threads 91 92 // MinGW with the POSIX threading model does not support pthread_setname_np 93 #if !defined(_WIN32) || defined(_MSC_VER) 94 void SetCurrentThreadName(const char* name) { 95 #ifdef __APPLE__ 96 pthread_setname_np(name); 97 #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) 98 pthread_set_name_np(pthread_self(), name); 99 #elif defined(__NetBSD__) 100 pthread_setname_np(pthread_self(), "%s", (void*)name); 101 #elif defined(__linux__) 102 // Linux limits thread names to 15 characters and will outright reject any 103 // attempt to set a longer name with ERANGE. 104 std::string truncated(name, std::min(strlen(name), static_cast<std::size_t>(15))); 105 if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { 106 errno = e; 107 LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); 108 } 109 #else 110 pthread_setname_np(pthread_self(), name); 111 #endif 112 } 113 #endif 114 115 #if defined(_WIN32) 116 void SetCurrentThreadName(const char*) { 117 // Do Nothing on MingW 118 } 119 #endif 120 121 #endif 122 123 } // namespace Common