Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2001 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License as published by 00007 the Free Software Foundation; either version 2.1 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 00019 */ 00020 00021 00022 #include "JackMachThread.h" 00023 #include "JackError.h" 00024 00025 #ifdef MY_TARGET_OS_IPHONE 00026 #include "/Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.h" 00027 #endif 00028 00029 namespace Jack 00030 { 00031 00032 int JackMachThread::SetThreadToPriority(jack_native_thread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint) 00033 { 00034 if (inPriority == 96) { 00035 // REAL-TIME / TIME-CONSTRAINT THREAD 00036 thread_time_constraint_policy_data_t theTCPolicy; 00037 00038 #ifdef MY_TARGET_OS_IPHONE 00039 theTCPolicy.period = CAHostTimeBase::ConvertFromNanos(period); 00040 theTCPolicy.computation = CAHostTimeBase::ConvertFromNanos(computation); 00041 theTCPolicy.constraint = CAHostTimeBase::ConvertFromNanos(constraint); 00042 #else 00043 theTCPolicy.period = AudioConvertNanosToHostTime(period); 00044 theTCPolicy.computation = AudioConvertNanosToHostTime(computation); 00045 theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint); 00046 #endif 00047 theTCPolicy.preemptible = true; 00048 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); 00049 jack_log("JackMachThread::thread_policy_set res = %ld", res); 00050 return (res == KERN_SUCCESS) ? 0 : -1; 00051 } else { 00052 // OTHER THREADS 00053 thread_extended_policy_data_t theFixedPolicy; 00054 thread_precedence_policy_data_t thePrecedencePolicy; 00055 SInt32 relativePriority; 00056 00057 // [1] SET FIXED / NOT FIXED 00058 theFixedPolicy.timeshare = !inIsFixed; 00059 thread_policy_set(pthread_mach_thread_np(thread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); 00060 00061 // [2] SET PRECEDENCE 00062 // N.B.: We expect that if thread A created thread B, and the program wishes to change 00063 // the priority of thread B, then the call to change the priority of thread B must be 00064 // made by thread A. 00065 // This assumption allows us to use pthread_self() to correctly calculate the priority 00066 // of the feeder thread (since precedency policy's importance is relative to the 00067 // spawning thread's priority.) 00068 relativePriority = inPriority - GetThreadSetPriority(pthread_self()); 00069 00070 thePrecedencePolicy.importance = relativePriority; 00071 kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) &thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); 00072 jack_log("JackMachThread::thread_policy_set res = %ld", res); 00073 return (res == KERN_SUCCESS) ? 0 : -1; 00074 } 00075 } 00076 00077 // returns the thread's priority as it was last set by the API 00078 UInt32 JackMachThread::GetThreadSetPriority(jack_native_thread_t thread) 00079 { 00080 return GetThreadPriority(thread, THREAD_SET_PRIORITY); 00081 } 00082 00083 // returns the thread's priority as it was last scheduled by the Kernel 00084 UInt32 JackMachThread::GetThreadScheduledPriority(jack_native_thread_t thread) 00085 { 00086 return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY); 00087 } 00088 00089 UInt32 JackMachThread::GetThreadPriority(jack_native_thread_t thread, int inWhichPriority) 00090 { 00091 thread_basic_info_data_t threadInfo; 00092 policy_info_data_t thePolicyInfo; 00093 unsigned int count; 00094 00095 // get basic info 00096 count = THREAD_BASIC_INFO_COUNT; 00097 thread_info(pthread_mach_thread_np(thread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count); 00098 00099 switch (threadInfo.policy) { 00100 case POLICY_TIMESHARE: 00101 count = POLICY_TIMESHARE_INFO_COUNT; 00102 thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count); 00103 if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) { 00104 return thePolicyInfo.ts.cur_priority; 00105 } else { 00106 return thePolicyInfo.ts.base_priority; 00107 } 00108 break; 00109 00110 case POLICY_FIFO: 00111 count = POLICY_FIFO_INFO_COUNT; 00112 thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count); 00113 if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { 00114 return thePolicyInfo.fifo.depress_priority; 00115 } 00116 return thePolicyInfo.fifo.base_priority; 00117 break; 00118 00119 case POLICY_RR: 00120 count = POLICY_RR_INFO_COUNT; 00121 thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count); 00122 if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { 00123 return thePolicyInfo.rr.depress_priority; 00124 } 00125 return thePolicyInfo.rr.base_priority; 00126 break; 00127 } 00128 00129 return 0; 00130 } 00131 00132 int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt64* computation, UInt64* constraint) 00133 { 00134 thread_time_constraint_policy_data_t theTCPolicy; 00135 mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT; 00136 boolean_t get_default = false; 00137 00138 kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread), 00139 THREAD_TIME_CONSTRAINT_POLICY, 00140 (thread_policy_t) & theTCPolicy, 00141 &count, 00142 &get_default); 00143 if (res == KERN_SUCCESS) { 00144 #ifdef MY_TARGET_OS_IPHONE 00145 *period = CAHostTimeBase::ConvertToNanos(theTCPolicy.period); 00146 *computation = CAHostTimeBase::ConvertToNanos(theTCPolicy.computation); 00147 *constraint = CAHostTimeBase::ConvertToNanos(theTCPolicy.constraint); 00148 #else 00149 *period = AudioConvertHostTimeToNanos(theTCPolicy.period); 00150 *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation); 00151 *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint); 00152 #endif 00153 00154 jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f)); 00155 return 0; 00156 } else { 00157 return -1; 00158 } 00159 } 00160 00161 int JackMachThread::Kill() 00162 { 00163 if (fThread != (jack_native_thread_t)NULL) { // If thread has been started 00164 jack_log("JackMachThread::Kill"); 00165 mach_port_t machThread = pthread_mach_thread_np(fThread); 00166 int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1; 00167 fStatus = kIdle; 00168 fThread = (jack_native_thread_t)NULL; 00169 return res; 00170 } else { 00171 return -1; 00172 } 00173 } 00174 00175 int JackMachThread::AcquireRealTime() 00176 { 00177 jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00178 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00179 return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; 00180 } 00181 00182 int JackMachThread::AcquireSelfRealTime() 00183 { 00184 jack_log("JackMachThread::AcquireSelfRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00185 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00186 return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint); 00187 } 00188 00189 int JackMachThread::AcquireRealTime(int priority) 00190 { 00191 fPriority = priority; 00192 return AcquireRealTime(); 00193 } 00194 00195 int JackMachThread::AcquireSelfRealTime(int priority) 00196 { 00197 fPriority = priority; 00198 return AcquireSelfRealTime(); 00199 } 00200 00201 int JackMachThread::AcquireRealTimeImp(jack_native_thread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) 00202 { 00203 SetThreadToPriority(thread, 96, true, period, computation, constraint); 00204 return 0; 00205 } 00206 00207 int JackMachThread::DropRealTime() 00208 { 00209 return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; 00210 } 00211 00212 int JackMachThread::DropSelfRealTime() 00213 { 00214 return DropRealTimeImp(pthread_self()); 00215 } 00216 00217 int JackMachThread::DropRealTimeImp(jack_native_thread_t thread) 00218 { 00219 SetThreadToPriority(thread, 63, false, 0, 0, 0); 00220 return 0; 00221 } 00222 00223 void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint) 00224 { 00225 fPeriod = period; 00226 fComputation = computation; 00227 fConstraint = constraint; 00228 } 00229 00230 } // end of namespace 00231