/ src / common / thread.cpp
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, &params);
 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