Jack2 1.9.6
|
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 #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 jack_log("JackMachThread::thread_policy_set res = %ld", 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 jack_log("JackMachThread::thread_policy_set res = %ld", 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(pthread_t thread, 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(thread), 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 jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", 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 jack_log("JackMachThread::Kill"); 00147 00148 if (fThread != (pthread_t)NULL) { // If thread has been started 00149 mach_port_t machThread = pthread_mach_thread_np(fThread); 00150 int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1; 00151 fThread = (pthread_t)NULL; 00152 return res; 00153 } else { 00154 return -1; 00155 } 00156 } 00157 00158 int JackMachThread::AcquireRealTime() 00159 { 00160 jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00161 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00162 return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; 00163 } 00164 00165 int JackMachThread::AcquireSelfRealTime() 00166 { 00167 jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld", 00168 long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); 00169 return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint); 00170 } 00171 00172 int JackMachThread::AcquireRealTime(int priority) 00173 { 00174 fPriority = priority; 00175 return AcquireRealTime(); 00176 } 00177 00178 int JackMachThread::AcquireSelfRealTime(int priority) 00179 { 00180 fPriority = priority; 00181 return AcquireSelfRealTime(); 00182 } 00183 00184 int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) 00185 { 00186 SetThreadToPriority(thread, 96, true, period, computation, constraint); 00187 return 0; 00188 } 00189 00190 int JackMachThread::DropRealTime() 00191 { 00192 return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1; 00193 } 00194 00195 int JackMachThread::DropSelfRealTime() 00196 { 00197 return DropRealTimeImp(pthread_self()); 00198 } 00199 00200 int JackMachThread::DropRealTimeImp(pthread_t thread) 00201 { 00202 SetThreadToPriority(thread, 63, false, 0, 0, 0); 00203 return 0; 00204 } 00205 00206 void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint) 00207 { 00208 fPeriod = period; 00209 fComputation = computation; 00210 fConstraint = constraint; 00211 } 00212 00213 } // end of namespace 00214