// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include "common/error.h" #include "common/logging/log.h" #include "common/thread.h" #ifdef __APPLE__ #include #elif defined(_WIN32) #include #include "common/string_util.h" #else #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include #else #include #endif #include #endif #ifndef _WIN32 #include #endif #ifdef __FreeBSD__ #define cpu_set_t cpuset_t #endif namespace Common { #ifdef _WIN32 void SetCurrentThreadPriority(ThreadPriority new_priority) { auto handle = GetCurrentThread(); int windows_priority = 0; switch (new_priority) { case ThreadPriority::Low: windows_priority = THREAD_PRIORITY_BELOW_NORMAL; break; case ThreadPriority::Normal: windows_priority = THREAD_PRIORITY_NORMAL; break; case ThreadPriority::High: windows_priority = THREAD_PRIORITY_ABOVE_NORMAL; break; case ThreadPriority::VeryHigh: windows_priority = THREAD_PRIORITY_HIGHEST; break; case ThreadPriority::Critical: windows_priority = THREAD_PRIORITY_TIME_CRITICAL; break; default: windows_priority = THREAD_PRIORITY_NORMAL; break; } SetThreadPriority(handle, windows_priority); } #else void SetCurrentThreadPriority(ThreadPriority new_priority) { pthread_t this_thread = pthread_self(); const auto scheduling_type = SCHED_OTHER; s32 max_prio = sched_get_priority_max(scheduling_type); s32 min_prio = sched_get_priority_min(scheduling_type); u32 level = std::max(static_cast(new_priority) + 1, 4U); struct sched_param params; if (max_prio > min_prio) { params.sched_priority = min_prio + ((max_prio - min_prio) * level) / 4; } else { params.sched_priority = min_prio - ((min_prio - max_prio) * level) / 4; } pthread_setschedparam(this_thread, scheduling_type, ¶ms); } #endif #ifdef _MSC_VER // Sets the debugger-visible name of the current thread. void SetCurrentThreadName(const char* name) { SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); } #else // !MSVC_VER, so must be POSIX threads // MinGW with the POSIX threading model does not support pthread_setname_np #if !defined(_WIN32) || defined(_MSC_VER) void SetCurrentThreadName(const char* name) { #ifdef __APPLE__ pthread_setname_np(name); #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), name); #elif defined(__NetBSD__) pthread_setname_np(pthread_self(), "%s", (void*)name); #elif defined(__linux__) // Linux limits thread names to 15 characters and will outright reject any // attempt to set a longer name with ERANGE. std::string truncated(name, std::min(strlen(name), static_cast(15))); if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { errno = e; LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); } #else pthread_setname_np(pthread_self(), name); #endif } #endif #if defined(_WIN32) void SetCurrentThreadName(const char*) { // Do Nothing on MingW } #endif #endif } // namespace Common