root/jack2/branches/libjacknet/macosx/JackMachThread.cpp

Revision 3814, 8.4 kB (checked in by sletz, 10 months ago)

rebase from trunk 3684:3813

  • Property svn:eol-style set to native
Line 
1 /*
2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2004-2008 Grame
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #include "JackMachThread.h"
23 #include "JackError.h"
24
25 namespace Jack
26 {
27
28 int JackMachThread::SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint)
29 {
30     if (inPriority == 96) {
31         // REAL-TIME / TIME-CONSTRAINT THREAD
32         thread_time_constraint_policy_data_t    theTCPolicy;
33
34 #ifdef TARGET_OS_IPHONE
35         theTCPolicy.period =  0;
36         theTCPolicy.computation = 0;
37         theTCPolicy.constraint =  0;
38 #else
39         theTCPolicy.period = AudioConvertNanosToHostTime(period);
40         theTCPolicy.computation = AudioConvertNanosToHostTime(computation);
41         theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint);
42
43 #endif
44         theTCPolicy.preemptible = true;
45         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);
46         jack_log("JackMachThread::thread_policy_set res = %ld", res);
47         return (res == KERN_SUCCESS) ? 0 : -1;
48     } else {
49         // OTHER THREADS
50         thread_extended_policy_data_t theFixedPolicy;
51         thread_precedence_policy_data_t thePrecedencePolicy;
52         SInt32 relativePriority;
53
54         // [1] SET FIXED / NOT FIXED
55         theFixedPolicy.timeshare = !inIsFixed;
56         thread_policy_set(pthread_mach_thread_np(thread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
57
58         // [2] SET PRECEDENCE
59         // N.B.: We expect that if thread A created thread B, and the program wishes to change
60         // the priority of thread B, then the call to change the priority of thread B must be
61         // made by thread A.
62         // This assumption allows us to use pthread_self() to correctly calculate the priority
63         // of the feeder thread (since precedency policy's importance is relative to the
64         // spawning thread's priority.)
65         relativePriority = inPriority - GetThreadSetPriority(pthread_self());
66
67         thePrecedencePolicy.importance = relativePriority;
68         kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) & thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
69         jack_log("JackMachThread::thread_policy_set res = %ld", res);
70         return (res == KERN_SUCCESS) ? 0 : -1;
71     }
72 }
73
74 // returns the thread's priority as it was last set by the API
75 UInt32 JackMachThread::GetThreadSetPriority(pthread_t thread)
76 {
77     return GetThreadPriority(thread, THREAD_SET_PRIORITY);
78 }
79
80 // returns the thread's priority as it was last scheduled by the Kernel
81 UInt32 JackMachThread::GetThreadScheduledPriority(pthread_t thread)
82 {
83     return GetThreadPriority(thread, THREAD_SCHEDULED_PRIORITY);
84 }
85
86 UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority)
87 {
88     thread_basic_info_data_t threadInfo;
89     policy_info_data_t thePolicyInfo;
90     unsigned int count;
91
92     // get basic info
93     count = THREAD_BASIC_INFO_COUNT;
94     thread_info(pthread_mach_thread_np(thread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
95
96     switch (threadInfo.policy) {
97         case POLICY_TIMESHARE:
98             count = POLICY_TIMESHARE_INFO_COUNT;
99             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
100             if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) {
101                 return thePolicyInfo.ts.cur_priority;
102             } else {
103                 return thePolicyInfo.ts.base_priority;
104             }
105             break;
106
107         case POLICY_FIFO:
108             count = POLICY_FIFO_INFO_COUNT;
109             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
110             if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
111                 return thePolicyInfo.fifo.depress_priority;
112             }
113             return thePolicyInfo.fifo.base_priority;
114             break;
115
116         case POLICY_RR:
117             count = POLICY_RR_INFO_COUNT;
118             thread_info(pthread_mach_thread_np(thread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
119             if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) {
120                 return thePolicyInfo.rr.depress_priority;
121             }
122             return thePolicyInfo.rr.base_priority;
123             break;
124     }
125
126     return 0;
127 }
128
129 int JackMachThread::GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint)
130 {
131     thread_time_constraint_policy_data_t theTCPolicy;
132     mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
133     boolean_t get_default = false;
134
135     kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread),
136                                           THREAD_TIME_CONSTRAINT_POLICY,
137                                           (thread_policy_t) & theTCPolicy,
138                                           &count,
139                                           &get_default);
140     if (res == KERN_SUCCESS) {
141     #ifdef TARGET_OS_IPHONE
142         *period = 0;
143         *computation = 0;
144         *constraint = 0;
145     #else
146         *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
147         *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
148         *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
149     #endif
150      
151         jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f));
152         return 0;
153     } else {
154         return -1;
155     }
156 }
157
158 int JackMachThread::Kill()
159 {
160     // pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER)
161     jack_log("JackMachThread::Kill");
162    
163     if (fThread != (pthread_t)NULL)  { // If thread has been started
164         mach_port_t machThread = pthread_mach_thread_np(fThread);
165         int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
166         fThread = (pthread_t)NULL;
167         return res;
168     } else {
169         return -1;
170     }
171 }
172
173 int JackMachThread::AcquireRealTime()
174 {
175     jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
176              long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
177     return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
178 }
179
180 int JackMachThread::AcquireSelfRealTime()
181 {
182     jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
183              long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
184     return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint);
185 }
186
187 int JackMachThread::AcquireRealTime(int priority)
188 {
189     fPriority = priority;
190     return AcquireRealTime();
191 }
192
193 int JackMachThread::AcquireSelfRealTime(int priority)
194 {
195     fPriority = priority;
196     return AcquireSelfRealTime();
197 }
198
199 int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint)
200 {
201     SetThreadToPriority(thread, 96, true, period, computation, constraint);
202     return 0;
203 }
204
205 int JackMachThread::DropRealTime()
206 {
207     return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1;
208 }
209
210 int JackMachThread::DropSelfRealTime()
211 {
212     return DropRealTimeImp(pthread_self());
213 }
214
215 int JackMachThread::DropRealTimeImp(pthread_t thread)
216 {
217     SetThreadToPriority(thread, 63, false, 0, 0, 0);
218     return 0;
219 }
220
221 void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint)
222 {
223     fPeriod = period;
224     fComputation = computation;
225     fConstraint = constraint;
226 }
227
228 } // end of namespace
229
Note: See TracBrowser for help on using the browser.