The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_linux_NativeCode.cpp, rather than being
  19. // compiled on its own).
  20. #if JUCE_INCLUDED_FILE
  21. /*
  22. Note that a lot of methods that you'd expect to find in this file actually
  23. live in juce_posix_SharedCode.h!
  24. */
  25. //==============================================================================
  26. void JUCE_API juce_threadEntryPoint (void*);
  27. void* threadEntryProc (void* value)
  28. {
  29. // New threads start off as root when running suid
  30. Process::lowerPrivilege();
  31. juce_threadEntryPoint (value);
  32. return 0;
  33. }
  34. void* juce_createThread (void* userData)
  35. {
  36. pthread_t handle = 0;
  37. if (pthread_create (&handle, 0, threadEntryProc, userData) == 0)
  38. {
  39. pthread_detach (handle);
  40. return (void*) handle;
  41. }
  42. return 0;
  43. }
  44. void juce_killThread (void* handle)
  45. {
  46. if (handle != 0)
  47. pthread_cancel ((pthread_t)handle);
  48. }
  49. void juce_setCurrentThreadName (const String& /*name*/)
  50. {
  51. }
  52. Thread::ThreadID Thread::getCurrentThreadId()
  53. {
  54. return (ThreadID) pthread_self();
  55. }
  56. /*
  57. * This is all a bit non-ideal... the trouble is that on Linux you
  58. * need to call setpriority to affect the dynamic priority for
  59. * non-realtime processes, but this requires the pid, which is not
  60. * accessible from the pthread_t. We could get it by calling getpid
  61. * once each thread has started, but then we would need a list of
  62. * running threads etc etc.
  63. * Also there is no such thing as IDLE priority on Linux.
  64. * For the moment, map idle, low and normal process priorities to
  65. * SCHED_OTHER, with the thread priority ignored for these classes.
  66. * Map high priority processes to the lower half of the SCHED_RR
  67. * range, and realtime to the upper half
  68. */
  69. // priority 1 to 10 where 5=normal, 1=low. If the handle is 0, sets the
  70. // priority of the current thread
  71. bool juce_setThreadPriority (void* handle, int priority)
  72. {
  73. struct sched_param param;
  74. int policy, maxp, minp, pri;
  75. if (handle == 0)
  76. handle = (void*) pthread_self();
  77. if (pthread_getschedparam ((pthread_t) handle, &policy, &param) == 0
  78. && policy != SCHED_OTHER)
  79. {
  80. minp = sched_get_priority_min(policy);
  81. maxp = sched_get_priority_max(policy);
  82. pri = ((maxp - minp) / 2) * (priority - 1) / 9;
  83. if (param.__sched_priority >= (minp + (maxp - minp) / 2))
  84. // Realtime process priority
  85. param.__sched_priority = minp + ((maxp - minp) / 2) + pri;
  86. else
  87. // High process priority
  88. param.__sched_priority = minp + pri;
  89. param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11);
  90. return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;
  91. }
  92. return false;
  93. }
  94. /* Remove this macro if you're having problems compiling the cpu affinity
  95. calls (the API for these has changed about quite a bit in various Linux
  96. versions, and a lot of distros seem to ship with obsolete versions)
  97. */
  98. #if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES)
  99. #define SUPPORT_AFFINITIES 1
  100. #endif
  101. void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
  102. {
  103. #if SUPPORT_AFFINITIES
  104. cpu_set_t affinity;
  105. CPU_ZERO (&affinity);
  106. for (int i = 0; i < 32; ++i)
  107. if ((affinityMask & (1 << i)) != 0)
  108. CPU_SET (i, &affinity);
  109. /*
  110. N.B. If this line causes a compile error, then you've probably not got the latest
  111. version of glibc installed.
  112. If you don't want to update your copy of glibc and don't care about cpu affinities,
  113. then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0.
  114. */
  115. sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity);
  116. sched_yield();
  117. #else
  118. /* affinities aren't supported because either the appropriate header files weren't found,
  119. or the SUPPORT_AFFINITIES macro was turned off
  120. */
  121. jassertfalse
  122. #endif
  123. }
  124. void Thread::yield()
  125. {
  126. sched_yield();
  127. }
  128. //==============================================================================
  129. // sets the process to 0=low priority, 1=normal, 2=high, 3=realtime
  130. void Process::setPriority (ProcessPriority prior)
  131. {
  132. struct sched_param param;
  133. int policy, maxp, minp;
  134. const int p = (int) prior;
  135. if (p <= 1)
  136. policy = SCHED_OTHER;
  137. else
  138. policy = SCHED_RR;
  139. minp = sched_get_priority_min (policy);
  140. maxp = sched_get_priority_max (policy);
  141. if (p < 2)
  142. param.__sched_priority = 0;
  143. else if (p == 2 )
  144. // Set to middle of lower realtime priority range
  145. param.__sched_priority = minp + (maxp - minp) / 4;
  146. else
  147. // Set to middle of higher realtime priority range
  148. param.__sched_priority = minp + (3 * (maxp - minp) / 4);
  149. pthread_setschedparam (pthread_self(), policy, &param);
  150. }
  151. void Process::terminate()
  152. {
  153. exit (0);
  154. }
  155. bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger()
  156. {
  157. static char testResult = 0;
  158. if (testResult == 0)
  159. {
  160. testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0);
  161. if (testResult >= 0)
  162. {
  163. ptrace (PT_DETACH, 0, (caddr_t) 1, 0);
  164. testResult = 1;
  165. }
  166. }
  167. return testResult < 0;
  168. }
  169. bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
  170. {
  171. return juce_isRunningUnderDebugger();
  172. }
  173. void Process::raisePrivilege()
  174. {
  175. // If running suid root, change effective user
  176. // to root
  177. if (geteuid() != 0 && getuid() == 0)
  178. {
  179. setreuid (geteuid(), getuid());
  180. setregid (getegid(), getgid());
  181. }
  182. }
  183. void Process::lowerPrivilege()
  184. {
  185. // If runing suid root, change effective user
  186. // back to real user
  187. if (geteuid() == 0 && getuid() != 0)
  188. {
  189. setreuid (geteuid(), getuid());
  190. setregid (getegid(), getgid());
  191. }
  192. }
  193. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  194. void* PlatformUtilities::loadDynamicLibrary (const String& name)
  195. {
  196. return dlopen (name.toUTF8(), RTLD_LOCAL | RTLD_NOW);
  197. }
  198. void PlatformUtilities::freeDynamicLibrary (void* handle)
  199. {
  200. dlclose(handle);
  201. }
  202. void* PlatformUtilities::getProcedureEntryPoint (void* libraryHandle, const String& procedureName)
  203. {
  204. return dlsym (libraryHandle, procedureName.toCString());
  205. }
  206. #endif
  207. #endif