Jack2
1.9.8
|
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 // pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER) 00164 jack_log("JackMachThread::Kill"); 00165 00166 if (fThread != (jack_native_thread_t)NULL) { // If thread has been started 00167 mach_port_t machThread = pthread_mach_thread_np(fThread); 00168 int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1; 00169 fThread = (jack_native_thread_t)NULL; 00170 return res; 00171 } else { 00172 return -1; 00173 } 00174 } 00175 00176 int JackMachThread::AcquireRealTime() 00177 { 00178 jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00179 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00180 return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; 00181 } 00182 00183 int JackMachThread::AcquireSelfRealTime() 00184 { 00185 jack_log("JackMachThread::AcquireSelfRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00186 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00187 return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint); 00188 } 00189 00190 int JackMachThread::AcquireRealTime(int priority) 00191 { 00192 fPriority = priority; 00193 return AcquireRealTime(); 00194 } 00195 00196 int JackMachThread::AcquireSelfRealTime(int priority) 00197 { 00198 fPriority = priority; 00199 return AcquireSelfRealTime(); 00200 } 00201 00202 int JackMachThread::AcquireRealTimeImp(jack_native_thread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) 00203 { 00204 SetThreadToPriority(thread, 96, true, period, computation, constraint); 00205 return 0; 00206 } 00207 00208 int JackMachThread::DropRealTime() 00209 { 00210 return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; 00211 } 00212 00213 int JackMachThread::DropSelfRealTime() 00214 { 00215 return DropRealTimeImp(pthread_self()); 00216 } 00217 00218 int JackMachThread::DropRealTimeImp(jack_native_thread_t thread) 00219 { 00220 SetThreadToPriority(thread, 63, false, 0, 0, 0); 00221 return 0; 00222 } 00223 00224 void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint) 00225 { 00226 fPeriod = period; 00227 fComputation = computation; 00228 fConstraint = constraint; 00229 } 00230 00231 } // end of namespace 00232