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 General Public License as published by
00007 the Free Software Foundation; either version 2 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 General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 */
00020 
00021 #include "JackMachThread.h"
00022 #include "JackError.h"
00023 
00024 namespace Jack
00025 {
00026 
00027 int JackMachThread::SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint)
00028 {
00029     if (inPriority == 96) {
00030         // REAL-TIME / TIME-CONSTRAINT THREAD
00031         thread_time_constraint_policy_data_t    theTCPolicy;
00032 
00033         theTCPolicy.period = AudioConvertNanosToHostTime(period);
00034         theTCPolicy.computation = AudioConvertNanosToHostTime(computation);
00035         theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint);
00036         theTCPolicy.preemptible = true;
00037         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);
00038         JackLog("JackMachThread::thread_policy_set %ld\n", res);
00039         return (res == KERN_SUCCESS) ? 0 : -1;
00040     } else {
00041         // OTHER THREADS
00042         thread_extended_policy_data_t theFixedPolicy;
00043         thread_precedence_policy_data_t thePrecedencePolicy;
00044         SInt32 relativePriority;
00045 
00046         // [1] SET FIXED / NOT FIXED
00047         theFixedPolicy.timeshare = !inIsFixed;
00048         thread_policy_set(pthread_mach_thread_np(thread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
00049 
00050         // [2] SET PRECEDENCE
00051         // N.B.: We expect that if thread A created thread B, and the program wishes to change
00052         // the priority of thread B, then the call to change the priority of thread B must be
00053         // made by thread A.
00054         // This assumption allows us to use pthread_self() to correctly calculate the priority
00055         // of the feeder thread (since precedency policy's importance is relative to the
00056         // spawning thread's priority.)
00057         relativePriority = inPriority - GetThreadSetPriority(pthread_self());
00058 
00059         thePrecedencePolicy.importance = relativePriority;
00060         kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) & thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
00061         JackLog("JackMachThread::thread_policy_set %ld\n", res);
00062         return (res == KERN_SUCCESS) ? 0 : -1;
00063     }
00064 }
00065 
00066 // returns the thread's priority as it was last set by the API
00067 UInt32 JackMachThread::GetThreadSetPriority(pthread_t thread)
00068 {
00069     return GetThreadPriority(thread, THREAD_SET_PRIORITY);
00070 }
00071 
00072 // returns the thread's priority as it was last scheduled by the Kernel
00073 UInt32 JackMachThread::GetThreadScheduledPriority(pthread_t thread)
00074 {
00075     return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY);
00076 }
00077 
00078 UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority)
00079 {
00080     thread_basic_info_data_t threadInfo;
00081     policy_info_data_t thePolicyInfo;
00082     unsigned int count;
00083 
00084     // get basic info
00085     count = THREAD_BASIC_INFO_COUNT;
00086     thread_info(pthread_mach_thread_np(thread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
00087 
00088     switch (threadInfo.policy) {
00089         case POLICY_TIMESHARE:
00090             count = POLICY_TIMESHARE_INFO_COUNT;
00091             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
00092             if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) {
00093                 return thePolicyInfo.ts.cur_priority;
00094             } else {
00095                 return thePolicyInfo.ts.base_priority;
00096             }
00097             break;
00098 
00099         case POLICY_FIFO:
00100             count = POLICY_FIFO_INFO_COUNT;
00101             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
00102             if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
00103                 return thePolicyInfo.fifo.depress_priority;
00104             }
00105             return thePolicyInfo.fifo.base_priority;
00106             break;
00107 
00108         case POLICY_RR:
00109             count = POLICY_RR_INFO_COUNT;
00110             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
00111             if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
00112                 return thePolicyInfo.rr.depress_priority;
00113             }
00114             return thePolicyInfo.rr.base_priority;
00115             break;
00116     }
00117 
00118     return 0;
00119 }
00120 
00121 int JackMachThread::GetParams(UInt64* period, UInt64* computation, UInt64* constraint)
00122 {
00123     thread_time_constraint_policy_data_t theTCPolicy;
00124     mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
00125     boolean_t get_default = false;
00126 
00127     kern_return_t res = thread_policy_get(pthread_mach_thread_np(pthread_self()),
00128                                           THREAD_TIME_CONSTRAINT_POLICY,
00129                                           (thread_policy_t) & theTCPolicy,
00130                                           &count,
00131                                           &get_default);
00132     if (res == KERN_SUCCESS) {
00133         *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
00134         *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
00135         *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
00136         JackLog("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld\n", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f));
00137         return 0;
00138     } else {
00139         return -1;
00140     }
00141 }
00142 
00143 int JackMachThread::Kill()
00144 {
00145     // pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER)
00146 
00147     if (fThread) { // If thread has been started
00148         mach_port_t machThread = pthread_mach_thread_np(fThread);
00149         return (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
00150     } else {
00151         return -1;
00152     }
00153 }
00154 
00155 int JackMachThread::AcquireRealTime()
00156 {
00157     JackLog("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld\n",
00158             long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
00159 
00160         return (fThread) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
00161 }
00162 
00163 int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint)
00164 {
00165         SetThreadToPriority(thread, 96, true, period, computation, constraint);
00166         UInt64 int_period;
00167         UInt64 int_computation;
00168         UInt64 int_constraint;
00169         GetParams(&int_period, &int_computation, &int_constraint);
00170         return 0;
00171 }
00172 
00173 int JackMachThread::DropRealTime()
00174 {
00175     return (fThread) ? DropRealTimeImp(fThread) : -1;
00176 }
00177 
00178 int JackMachThread::DropRealTimeImp(pthread_t thread)
00179 {
00180         SetThreadToPriority(thread, 63, false, 0, 0, 0);
00181         return 0;
00182 }
00183 
00184 void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint)
00185 {
00186     fPeriod = period;
00187     fComputation = computation;
00188     fConstraint = constraint;
00189 }
00190 
00191 } // end of namespace
00192 

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1