this repo has no description
1/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved.
2
3 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
4 ("Apple") in consideration of your agreement to the following terms, and your
5 use, installation, modification or redistribution of this Apple software
6 constitutes acceptance of these terms. If you do not agree with these terms,
7 please do not use, install, modify or redistribute this Apple software.
8
9 In consideration of your agreement to abide by the following terms, and subject
10 to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
11 copyrights in this original Apple software (the "Apple Software"), to use,
12 reproduce, modify and redistribute the Apple Software, with or without
13 modifications, in source and/or binary forms; provided that if you redistribute
14 the Apple Software in its entirety and without modifications, you must retain
15 this notice and the following text and disclaimers in all such redistributions of
16 the Apple Software. Neither the name, trademarks, service marks or logos of
17 Apple Computer, Inc. may be used to endorse or promote products derived from the
18 Apple Software without specific prior written permission from Apple. Except as
19 expressly stated in this notice, no other rights or licenses, express or implied,
20 are granted by Apple herein, including but not limited to any patent rights that
21 may be infringed by your derivative works or by other works in which the Apple
22 Software may be incorporated.
23
24 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
25 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
26 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
28 COMBINATION WITH YOUR PRODUCTS.
29
30 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
32 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
34 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
35 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
36 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*/
38/*=============================================================================
39 CAPThread.cp
40
41=============================================================================*/
42
43//=============================================================================
44// Includes
45//=============================================================================
46
47// Self Include
48#include "CAPThread.h"
49
50// PublicUtility Includes
51#include "CADebugMacros.h"
52#include "CAException.h"
53
54// System Includes
55#if TARGET_OS_MAC
56 #include <mach/mach.h>
57#endif
58
59// Standard Library Includes
60#include <stdio.h>
61
62//==================================================================================================
63// CAPThread
64//==================================================================================================
65
66// returns the thread's priority as it was last set by the API
67#define CAPTHREAD_SET_PRIORITY 0
68// returns the thread's priority as it was last scheduled by the Kernel
69#define CAPTHREAD_SCHEDULED_PRIORITY 1
70
71CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority)
72:
73#if TARGET_OS_MAC
74 mPThread(0),
75 mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
76#elif TARGET_OS_WIN32
77 mThreadHandle(NULL),
78 mThreadID(0),
79#endif
80 mThreadRoutine(inThreadRoutine),
81 mThreadParameter(inParameter),
82 mPriority(inPriority),
83 mPeriod(0),
84 mComputation(0),
85 mConstraint(0),
86 mIsPreemptible(true),
87 mTimeConstraintSet(false),
88 mFixedPriority(inFixedPriority)
89{
90}
91
92CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
93:
94#if TARGET_OS_MAC
95 mPThread(0),
96 mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
97#elif TARGET_OS_WIN32
98 mThreadHandle(NULL),
99 mThreadID(0),
100#endif
101 mThreadRoutine(inThreadRoutine),
102 mThreadParameter(inParameter),
103 mPriority(kDefaultThreadPriority),
104 mPeriod(inPeriod),
105 mComputation(inComputation),
106 mConstraint(inConstraint),
107 mIsPreemptible(inIsPreemptible),
108 mTimeConstraintSet(true),
109 mFixedPriority(false)
110{
111}
112
113CAPThread::~CAPThread()
114{
115}
116
117UInt32 CAPThread::GetScheduledPriority()
118{
119#if TARGET_OS_MAC
120 return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY );
121#elif TARGET_OS_WIN32
122 UInt32 theAnswer = 0;
123 if(mThreadHandle != NULL)
124 {
125 theAnswer = GetThreadPriority(mThreadHandle);
126 }
127 return theAnswer;
128#endif
129}
130
131void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority)
132{
133 mPriority = inPriority;
134 mTimeConstraintSet = false;
135 mFixedPriority = inFixedPriority;
136#if TARGET_OS_MAC
137 if(mPThread != 0)
138 {
139
140 if (mFixedPriority)
141 {
142 thread_extended_policy_data_t theFixedPolicy;
143 theFixedPolicy.timeshare = false; // set to true for a non-fixed thread
144 AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT), "CAPThread::SetPriority: failed to set the fixed-priority policy");
145 }
146 // We keep a reference to the spawning thread's priority around (initialized in the constructor),
147 // and set the importance of the child thread relative to the spawning thread's priority.
148 thread_precedence_policy_data_t thePrecedencePolicy;
149
150 thePrecedencePolicy.importance = mPriority - mSpawningThreadPriority;
151 AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT), "CAPThread::SetPriority: failed to set the precedence policy");
152 }
153#elif TARGET_OS_WIN32
154 if(mThreadHandle != NULL)
155 {
156 SetThreadPriority(mThreadHandle, mPriority);
157 }
158#endif
159}
160
161void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
162{
163 mPeriod = inPeriod;
164 mComputation = inComputation;
165 mConstraint = inConstraint;
166 mIsPreemptible = inIsPreemptible;
167 mTimeConstraintSet = true;
168#if TARGET_OS_MAC
169 if(mPThread != 0)
170 {
171 thread_time_constraint_policy_data_t thePolicy;
172 thePolicy.period = mPeriod;
173 thePolicy.computation = mComputation;
174 thePolicy.constraint = mConstraint;
175 thePolicy.preemptible = mIsPreemptible;
176 AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thePolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT), "CAPThread::SetTimeConstraints: thread_policy_set failed");
177 }
178#elif TARGET_OS_WIN32
179 if(mThreadHandle != NULL)
180 {
181 SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
182 }
183#endif
184}
185
186void CAPThread::Start()
187{
188#if TARGET_OS_MAC
189 if(mPThread == 0)
190 {
191 OSStatus theResult;
192 pthread_attr_t theThreadAttributes;
193
194 theResult = pthread_attr_init(&theThreadAttributes);
195 ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created.");
196
197 theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED);
198 ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state.");
199
200 theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this);
201 ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread.");
202
203 pthread_attr_destroy(&theThreadAttributes);
204
205 }
206#elif TARGET_OS_WIN32
207 if(mThreadID == 0)
208 {
209 // clean up the existing thread handle
210 if(mThreadHandle != NULL)
211 {
212 CloseHandle(mThreadHandle);
213 mThreadHandle = NULL;
214 }
215
216 // create a new thread
217 mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID);
218 ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread.");
219 }
220#endif
221}
222
223#if TARGET_OS_MAC
224
225void* CAPThread::Entry(CAPThread* inCAPThread)
226{
227 void* theAnswer = NULL;
228
229 try
230 {
231 if(inCAPThread->mTimeConstraintSet)
232 {
233 inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
234 }
235 else
236 {
237 inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
238 }
239
240 if(inCAPThread->mThreadRoutine != NULL)
241 {
242 theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter);
243 }
244 }
245 catch (...)
246 {
247 // what should be done here?
248 }
249 inCAPThread->mPThread = 0;
250 return theAnswer;
251}
252
253UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind)
254{
255 thread_basic_info_data_t threadInfo;
256 policy_info_data_t thePolicyInfo;
257 unsigned int count;
258
259 if (inThread == NULL)
260 return 0;
261
262 // get basic info
263 count = THREAD_BASIC_INFO_COUNT;
264 thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
265
266 switch (threadInfo.policy) {
267 case POLICY_TIMESHARE:
268 count = POLICY_TIMESHARE_INFO_COUNT;
269 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
270 if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) {
271 return thePolicyInfo.ts.cur_priority;
272 }
273 return thePolicyInfo.ts.base_priority;
274 break;
275
276 case POLICY_FIFO:
277 count = POLICY_FIFO_INFO_COUNT;
278 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
279 if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
280 return thePolicyInfo.fifo.depress_priority;
281 }
282 return thePolicyInfo.fifo.base_priority;
283 break;
284
285 case POLICY_RR:
286 count = POLICY_RR_INFO_COUNT;
287 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
288 if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
289 return thePolicyInfo.rr.depress_priority;
290 }
291 return thePolicyInfo.rr.base_priority;
292 break;
293 }
294
295 return 0;
296}
297
298#elif TARGET_OS_WIN32
299
300UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread)
301{
302 UInt32 theAnswer = 0;
303
304 try
305 {
306 if(inCAPThread->mTimeConstraintSet)
307 {
308 inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
309 }
310 else
311 {
312 inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
313 }
314
315 if(inCAPThread->mThreadRoutine != NULL)
316 {
317 theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
318 }
319 inCAPThread->mThreadID = 0;
320 }
321 catch (...)
322 {
323 // what should be done here?
324 }
325 return theAnswer;
326}
327
328// a definition of this function here for now
329extern "C"
330Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
331{
332 return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
333}
334
335#endif