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.

193 lines
7.4KB

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