Jack2 1.9.8

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     // 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