Jack2  1.9.10
JackMachThread.cpp
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