jack2 codebase
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.

232 lines
8.8KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include "JackMachThread.h"
  17. #include "JackError.h"
  18. #ifdef MY_TARGET_OS_IPHONE
  19. #include "/Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.h"
  20. #endif
  21. namespace Jack
  22. {
  23. int JackMachThread::SetThreadToPriority(jack_native_thread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint)
  24. {
  25. if (inPriority == 96) {
  26. // REAL-TIME / TIME-CONSTRAINT THREAD
  27. thread_time_constraint_policy_data_t theTCPolicy;
  28. #ifdef MY_TARGET_OS_IPHONE
  29. theTCPolicy.period = CAHostTimeBase::ConvertFromNanos(period);
  30. theTCPolicy.computation = CAHostTimeBase::ConvertFromNanos(computation);
  31. theTCPolicy.constraint = CAHostTimeBase::ConvertFromNanos(constraint);
  32. #else
  33. theTCPolicy.period = AudioConvertNanosToHostTime(period);
  34. theTCPolicy.computation = AudioConvertNanosToHostTime(computation);
  35. theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint);
  36. #endif
  37. theTCPolicy.preemptible = true;
  38. kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
  39. jack_log("JackMachThread::thread_policy_set res = %ld", res);
  40. return (res == KERN_SUCCESS) ? 0 : -1;
  41. } else {
  42. // OTHER THREADS
  43. thread_extended_policy_data_t theFixedPolicy;
  44. thread_precedence_policy_data_t thePrecedencePolicy;
  45. SInt32 relativePriority;
  46. // [1] SET FIXED / NOT FIXED
  47. theFixedPolicy.timeshare = !inIsFixed;
  48. thread_policy_set(pthread_mach_thread_np(thread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
  49. // [2] SET PRECEDENCE
  50. // N.B.: We expect that if thread A created thread B, and the program wishes to change
  51. // the priority of thread B, then the call to change the priority of thread B must be
  52. // made by thread A.
  53. // This assumption allows us to use pthread_self() to correctly calculate the priority
  54. // of the feeder thread (since precedency policy's importance is relative to the
  55. // spawning thread's priority.)
  56. relativePriority = inPriority - GetThreadSetPriority(pthread_self());
  57. thePrecedencePolicy.importance = relativePriority;
  58. kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) &thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
  59. jack_log("JackMachThread::thread_policy_set res = %ld", res);
  60. return (res == KERN_SUCCESS) ? 0 : -1;
  61. }
  62. }
  63. // returns the thread's priority as it was last set by the API
  64. UInt32 JackMachThread::GetThreadSetPriority(jack_native_thread_t thread)
  65. {
  66. return GetThreadPriority(thread, THREAD_SET_PRIORITY);
  67. }
  68. // returns the thread's priority as it was last scheduled by the Kernel
  69. UInt32 JackMachThread::GetThreadScheduledPriority(jack_native_thread_t thread)
  70. {
  71. return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY);
  72. }
  73. UInt32 JackMachThread::GetThreadPriority(jack_native_thread_t thread, int inWhichPriority)
  74. {
  75. thread_basic_info_data_t threadInfo;
  76. policy_info_data_t thePolicyInfo;
  77. unsigned int count;
  78. // get basic info
  79. count = THREAD_BASIC_INFO_COUNT;
  80. thread_info(pthread_mach_thread_np(thread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
  81. switch (threadInfo.policy) {
  82. case POLICY_TIMESHARE:
  83. count = POLICY_TIMESHARE_INFO_COUNT;
  84. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
  85. if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) {
  86. return thePolicyInfo.ts.cur_priority;
  87. } else {
  88. return thePolicyInfo.ts.base_priority;
  89. }
  90. break;
  91. case POLICY_FIFO:
  92. count = POLICY_FIFO_INFO_COUNT;
  93. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
  94. if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
  95. return thePolicyInfo.fifo.depress_priority;
  96. }
  97. return thePolicyInfo.fifo.base_priority;
  98. break;
  99. case POLICY_RR:
  100. count = POLICY_RR_INFO_COUNT;
  101. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
  102. if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
  103. return thePolicyInfo.rr.depress_priority;
  104. }
  105. return thePolicyInfo.rr.base_priority;
  106. break;
  107. }
  108. return 0;
  109. }
  110. int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt64* computation, UInt64* constraint)
  111. {
  112. thread_time_constraint_policy_data_t theTCPolicy;
  113. mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
  114. boolean_t get_default = false;
  115. kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread),
  116. THREAD_TIME_CONSTRAINT_POLICY,
  117. (thread_policy_t) & theTCPolicy,
  118. &count,
  119. &get_default);
  120. if (res == KERN_SUCCESS) {
  121. #ifdef MY_TARGET_OS_IPHONE
  122. *period = CAHostTimeBase::ConvertToNanos(theTCPolicy.period);
  123. *computation = CAHostTimeBase::ConvertToNanos(theTCPolicy.computation);
  124. *constraint = CAHostTimeBase::ConvertToNanos(theTCPolicy.constraint);
  125. #else
  126. *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
  127. *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
  128. *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
  129. #endif
  130. jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f));
  131. return 0;
  132. } else {
  133. return -1;
  134. }
  135. }
  136. int JackMachThread::Kill()
  137. {
  138. if (fThread != (jack_native_thread_t)NULL) { // If thread has been started
  139. jack_log("JackMachThread::Kill");
  140. mach_port_t machThread = pthread_mach_thread_np(fThread);
  141. int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
  142. fStatus = kIdle;
  143. fThread = (jack_native_thread_t)NULL;
  144. return res;
  145. } else {
  146. return -1;
  147. }
  148. }
  149. int JackMachThread::AcquireRealTime()
  150. {
  151. jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
  152. long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
  153. return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
  154. }
  155. int JackMachThread::AcquireSelfRealTime()
  156. {
  157. jack_log("JackMachThread::AcquireSelfRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
  158. long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
  159. return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint);
  160. }
  161. int JackMachThread::AcquireRealTime(int priority)
  162. {
  163. fPriority = priority;
  164. return AcquireRealTime();
  165. }
  166. int JackMachThread::AcquireSelfRealTime(int priority)
  167. {
  168. fPriority = priority;
  169. return AcquireSelfRealTime();
  170. }
  171. int JackMachThread::AcquireRealTimeImp(jack_native_thread_t thread, UInt64 period, UInt64 computation, UInt64 constraint)
  172. {
  173. SetThreadToPriority(thread, 96, true, period, computation, constraint);
  174. return 0;
  175. }
  176. int JackMachThread::DropRealTime()
  177. {
  178. return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1;
  179. }
  180. int JackMachThread::DropSelfRealTime()
  181. {
  182. return DropRealTimeImp(pthread_self());
  183. }
  184. int JackMachThread::DropRealTimeImp(jack_native_thread_t thread)
  185. {
  186. SetThreadToPriority(thread, 63, false, 0, 0, 0);
  187. return 0;
  188. }
  189. void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint)
  190. {
  191. fPeriod = period;
  192. fComputation = computation;
  193. fConstraint = constraint;
  194. }
  195. } // end of namespace