46 #include "CAPThread.h"
49 #include "CADebugMacros.h"
50 #include "CAException.h"
54 #include <mach/mach.h>
65 #define CAPTHREAD_SET_PRIORITY 0
67 #define CAPTHREAD_SCHEDULED_PRIORITY 1
71 CAPThread::CAPThread(ThreadRoutine inThreadRoutine,
void* inParameter, UInt32 inPriority,
bool inFixedPriority,
bool inAutoDelete)
75 mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
80 mThreadRoutine(inThreadRoutine),
81 mThreadParameter(inParameter),
82 mPriority(inPriority),
87 mTimeConstraintSet(false),
88 mFixedPriority(inFixedPriority),
89 mAutoDelete(inAutoDelete)
93 CAPThread::CAPThread(ThreadRoutine inThreadRoutine,
void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint,
bool inIsPreemptible,
bool inAutoDelete)
97 mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
102 mThreadRoutine(inThreadRoutine),
103 mThreadParameter(inParameter),
104 mPriority(kDefaultThreadPriority),
106 mComputation(inComputation),
107 mConstraint(inConstraint),
108 mIsPreemptible(inIsPreemptible),
109 mTimeConstraintSet(true),
110 mFixedPriority(false),
111 mAutoDelete(inAutoDelete)
115 CAPThread::~CAPThread()
119 UInt32 CAPThread::GetScheduledPriority()
122 return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY );
123 #elif TARGET_OS_WIN32
124 UInt32 theAnswer = 0;
125 if(mThreadHandle != NULL)
127 theAnswer = GetThreadPriority(mThreadHandle);
133 void CAPThread::SetPriority(UInt32 inPriority,
bool inFixedPriority)
135 mPriority = inPriority;
136 mTimeConstraintSet =
false;
137 mFixedPriority = inFixedPriority;
141 kern_return_t theError = 0;
146 thread_extended_policy_data_t theFixedPolicy = {
false };
147 theError = thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
148 AssertNoKernelError(theError,
"CAPThread::SetPriority: failed to set the fixed-priority policy");
152 UInt32 theCurrentThreadPriority = getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY);
153 thread_precedence_policy_data_t thePrecedencePolicy = { mPriority - theCurrentThreadPriority };
154 theError = thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
155 AssertNoKernelError(theError,
"CAPThread::SetPriority: failed to set the precedence policy");
158 DebugMessageN4(
"CAPThread::SetPriority: requsted: %lu spawning: %lu current: %lu assigned: %d", mPriority, mSpawningThreadPriority, theCurrentThreadPriority, thePrecedencePolicy.importance);
161 #elif TARGET_OS_WIN32
162 if(mThreadHandle != NULL)
164 SetThreadPriority(mThreadHandle, mPriority);
169 void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint,
bool inIsPreemptible)
172 mComputation = inComputation;
173 mConstraint = inConstraint;
174 mIsPreemptible = inIsPreemptible;
175 mTimeConstraintSet =
true;
179 thread_time_constraint_policy_data_t thePolicy;
180 thePolicy.period = mPeriod;
181 thePolicy.computation = mComputation;
182 thePolicy.constraint = mConstraint;
183 thePolicy.preemptible = mIsPreemptible;
184 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");
186 #elif TARGET_OS_WIN32
187 if(mThreadHandle != NULL)
189 SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
194 void CAPThread::Start()
197 Assert(mPThread == 0,
"CAPThread::Start: can't start because the thread is already running");
201 pthread_attr_t theThreadAttributes;
203 theResult = pthread_attr_init(&theThreadAttributes);
204 ThrowIf(theResult != 0, CAException(theResult),
"CAPThread::Start: Thread attributes could not be created.");
206 theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED);
207 ThrowIf(theResult != 0, CAException(theResult),
"CAPThread::Start: A thread could not be created in the detached state.");
209 theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry,
this);
210 ThrowIf(theResult != 0 || !mPThread, CAException(theResult),
"CAPThread::Start: Could not create a thread.");
212 pthread_attr_destroy(&theThreadAttributes);
215 #elif TARGET_OS_WIN32
216 Assert(mThreadID == 0,
"CAPThread::Start: can't start because the thread is already running");
220 if(mThreadHandle != NULL)
222 CloseHandle(mThreadHandle);
223 mThreadHandle = NULL;
227 mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry,
this, 0, &mThreadID);
228 ThrowIf(mThreadHandle == NULL, CAException(GetLastError()),
"CAPThread::Start: Could not create a thread.");
235 void* CAPThread::Entry(CAPThread* inCAPThread)
237 void* theAnswer = NULL;
241 if(inCAPThread->mTimeConstraintSet)
243 inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
247 inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
250 if(inCAPThread->mThreadRoutine != NULL)
252 theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter);
259 inCAPThread->mPThread = 0;
260 if (inCAPThread->mAutoDelete)
265 UInt32 CAPThread::getScheduledPriority(pthread_t inThread,
int inPriorityKind)
267 thread_basic_info_data_t threadInfo;
268 policy_info_data_t thePolicyInfo;
271 if (inThread == NULL)
275 count = THREAD_BASIC_INFO_COUNT;
276 thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
278 switch (threadInfo.policy) {
279 case POLICY_TIMESHARE:
280 count = POLICY_TIMESHARE_INFO_COUNT;
281 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
282 if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) {
283 return thePolicyInfo.ts.cur_priority;
285 return thePolicyInfo.ts.base_priority;
289 count = POLICY_FIFO_INFO_COUNT;
290 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
291 if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
292 return thePolicyInfo.fifo.depress_priority;
294 return thePolicyInfo.fifo.base_priority;
298 count = POLICY_RR_INFO_COUNT;
299 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
300 if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
301 return thePolicyInfo.rr.depress_priority;
303 return thePolicyInfo.rr.base_priority;
310 #elif TARGET_OS_WIN32
312 UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread)
314 UInt32 theAnswer = 0;
318 if(inCAPThread->mTimeConstraintSet)
320 inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
324 inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
327 if(inCAPThread->mThreadRoutine != NULL)
329 theAnswer =
reinterpret_cast<UInt32
>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
331 inCAPThread->mThreadID = 0;
337 CloseHandle(inCAPThread->mThreadHandle);
338 inCAPThread->mThreadHandle = NULL;
339 if (inCAPThread->mAutoDelete)
345 Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
347 return InterlockedCompareExchange((
volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
353 void CAPThread::DebugPriority(
const char *label)
356 if (mTimeConstraintSet)
357 printf(
"CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label,
this,
358 (
int)mSpawningThreadPriority, (mPThread != NULL) ? (
int)GetScheduledPriority() : -1);
360 printf(
"CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label,
this, (
int)mPriority, mFixedPriority ?
" fixed" :
"",
361 (
int)mSpawningThreadPriority, (mPThread != NULL) ? (
int)GetScheduledPriority() : -1);
363 if (mTimeConstraintSet)
365 printf(
"CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label,
this,
366 (
int)mPriority, (mThreadHandle != NULL) ? (
int)GetScheduledPriority() : -1);
370 printf(
"CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label,
this, (
int)mPriority, mFixedPriority ?
" fixed" :
"",
371 (
int)mPriority, (mThreadHandle != NULL) ? (
int)GetScheduledPriority() : -1);