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.

203 lines
7.6KB

  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. #if defined(HAVE_CONFIG_H)
  17. #include "config.h"
  18. #endif
  19. #include "JackMachThread.h"
  20. #include "JackError.h"
  21. namespace Jack
  22. {
  23. int JackMachThread::SetThreadToPriority(pthread_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. theTCPolicy.period = AudioConvertNanosToHostTime(period);
  29. theTCPolicy.computation = AudioConvertNanosToHostTime(computation);
  30. theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint);
  31. theTCPolicy.preemptible = true;
  32. 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);
  33. jack_log("JackMachThread::thread_policy_set %ld", res);
  34. return (res == KERN_SUCCESS) ? 0 : -1;
  35. } else {
  36. // OTHER THREADS
  37. thread_extended_policy_data_t theFixedPolicy;
  38. thread_precedence_policy_data_t thePrecedencePolicy;
  39. SInt32 relativePriority;
  40. // [1] SET FIXED / NOT FIXED
  41. theFixedPolicy.timeshare = !inIsFixed;
  42. thread_policy_set(pthread_mach_thread_np(thread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
  43. // [2] SET PRECEDENCE
  44. // N.B.: We expect that if thread A created thread B, and the program wishes to change
  45. // the priority of thread B, then the call to change the priority of thread B must be
  46. // made by thread A.
  47. // This assumption allows us to use pthread_self() to correctly calculate the priority
  48. // of the feeder thread (since precedency policy's importance is relative to the
  49. // spawning thread's priority.)
  50. relativePriority = inPriority - GetThreadSetPriority(pthread_self());
  51. thePrecedencePolicy.importance = relativePriority;
  52. kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) & thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
  53. jack_log("JackMachThread::thread_policy_set %ld", res);
  54. return (res == KERN_SUCCESS) ? 0 : -1;
  55. }
  56. }
  57. // returns the thread's priority as it was last set by the API
  58. UInt32 JackMachThread::GetThreadSetPriority(pthread_t thread)
  59. {
  60. return GetThreadPriority(thread, THREAD_SET_PRIORITY);
  61. }
  62. // returns the thread's priority as it was last scheduled by the Kernel
  63. UInt32 JackMachThread::GetThreadScheduledPriority(pthread_t thread)
  64. {
  65. return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY);
  66. }
  67. UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority)
  68. {
  69. thread_basic_info_data_t threadInfo;
  70. policy_info_data_t thePolicyInfo;
  71. unsigned int count;
  72. // get basic info
  73. count = THREAD_BASIC_INFO_COUNT;
  74. thread_info(pthread_mach_thread_np(thread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
  75. switch (threadInfo.policy) {
  76. case POLICY_TIMESHARE:
  77. count = POLICY_TIMESHARE_INFO_COUNT;
  78. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
  79. if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) {
  80. return thePolicyInfo.ts.cur_priority;
  81. } else {
  82. return thePolicyInfo.ts.base_priority;
  83. }
  84. break;
  85. case POLICY_FIFO:
  86. count = POLICY_FIFO_INFO_COUNT;
  87. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
  88. if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
  89. return thePolicyInfo.fifo.depress_priority;
  90. }
  91. return thePolicyInfo.fifo.base_priority;
  92. break;
  93. case POLICY_RR:
  94. count = POLICY_RR_INFO_COUNT;
  95. thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
  96. if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
  97. return thePolicyInfo.rr.depress_priority;
  98. }
  99. return thePolicyInfo.rr.base_priority;
  100. break;
  101. }
  102. return 0;
  103. }
  104. int JackMachThread::GetParams(UInt64* period, UInt64* computation, UInt64* constraint)
  105. {
  106. thread_time_constraint_policy_data_t theTCPolicy;
  107. mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
  108. boolean_t get_default = false;
  109. kern_return_t res = thread_policy_get(pthread_mach_thread_np(pthread_self()),
  110. THREAD_TIME_CONSTRAINT_POLICY,
  111. (thread_policy_t) & theTCPolicy,
  112. &count,
  113. &get_default);
  114. if (res == KERN_SUCCESS) {
  115. *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
  116. *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
  117. *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
  118. jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f));
  119. return 0;
  120. } else {
  121. return -1;
  122. }
  123. }
  124. int JackMachThread::Kill()
  125. {
  126. // pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER)
  127. jack_log("JackMachThread::Kill");
  128. if (fThread) { // If thread has been started
  129. mach_port_t machThread = pthread_mach_thread_np(fThread);
  130. return (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
  131. } else {
  132. return -1;
  133. }
  134. }
  135. int JackMachThread::AcquireRealTime()
  136. {
  137. jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
  138. long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
  139. return (fThread) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
  140. }
  141. int JackMachThread::AcquireRealTime(int priority)
  142. {
  143. fPriority = priority;
  144. return AcquireRealTime();
  145. }
  146. int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint)
  147. {
  148. SetThreadToPriority(thread, 96, true, period, computation, constraint);
  149. UInt64 int_period;
  150. UInt64 int_computation;
  151. UInt64 int_constraint;
  152. GetParams(&int_period, &int_computation, &int_constraint);
  153. return 0;
  154. }
  155. int JackMachThread::DropRealTime()
  156. {
  157. return (fThread) ? DropRealTimeImp(fThread) : -1;
  158. }
  159. int JackMachThread::DropRealTimeImp(pthread_t thread)
  160. {
  161. SetThreadToPriority(thread, 63, false, 0, 0, 0);
  162. return 0;
  163. }
  164. void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint)
  165. {
  166. fPeriod = period;
  167. fComputation = computation;
  168. fConstraint = constraint;
  169. }
  170. } // end of namespace