diff options
author | falkTX <falktx@gmail.com> | 2019-01-24 11:49:56 +0100 |
---|---|---|
committer | falkTX <falktx@gmail.com> | 2019-01-24 11:49:56 +0100 |
commit | f73640618c6b9dde4854b1f847f10fdcb5c5b52f (patch) | |
tree | a9e0b165cc512c3986b1cce3bdec521545066a35 /distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp | |
parent | 9f8ff46e7ddef2224fcf432bc4dc410e4b3d003e (diff) |
Add CoreAudio 10.6 files
Signed-off-by: falkTX <falktx@gmail.com>
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp')
-rwxr-xr-x | distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp b/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp new file mode 100755 index 00000000..6c5563a2 --- /dev/null +++ b/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp @@ -0,0 +1,375 @@ +/* Copyright © 2007 Apple Inc. All Rights Reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +//============================================================================= +// Includes +//============================================================================= + +// Self Include +#include "CAPThread.h" + +// PublicUtility Includes +#include "CADebugMacros.h" +#include "CAException.h" + +// System Includes +#if TARGET_OS_MAC + #include <mach/mach.h> +#endif + +// Standard Library Includes +#include <stdio.h> + +//================================================================================================== +// CAPThread +//================================================================================================== + +// returns the thread's priority as it was last set by the API +#define CAPTHREAD_SET_PRIORITY 0 +// returns the thread's priority as it was last scheduled by the Kernel +#define CAPTHREAD_SCHEDULED_PRIORITY 1 + +//#define Log_SetPriority 1 + +CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority, bool inAutoDelete) +: +#if TARGET_OS_MAC + mPThread(0), + mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)), +#elif TARGET_OS_WIN32 + mThreadHandle(NULL), + mThreadID(0), +#endif + mThreadRoutine(inThreadRoutine), + mThreadParameter(inParameter), + mPriority(inPriority), + mPeriod(0), + mComputation(0), + mConstraint(0), + mIsPreemptible(true), + mTimeConstraintSet(false), + mFixedPriority(inFixedPriority), + mAutoDelete(inAutoDelete) +{ +} + +CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete) +: +#if TARGET_OS_MAC + mPThread(0), + mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)), +#elif TARGET_OS_WIN32 + mThreadHandle(NULL), + mThreadID(0), +#endif + mThreadRoutine(inThreadRoutine), + mThreadParameter(inParameter), + mPriority(kDefaultThreadPriority), + mPeriod(inPeriod), + mComputation(inComputation), + mConstraint(inConstraint), + mIsPreemptible(inIsPreemptible), + mTimeConstraintSet(true), + mFixedPriority(false), + mAutoDelete(inAutoDelete) +{ +} + +CAPThread::~CAPThread() +{ +} + +UInt32 CAPThread::GetScheduledPriority() +{ +#if TARGET_OS_MAC + return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY ); +#elif TARGET_OS_WIN32 + UInt32 theAnswer = 0; + if(mThreadHandle != NULL) + { + theAnswer = GetThreadPriority(mThreadHandle); + } + return theAnswer; +#endif +} + +void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority) +{ + mPriority = inPriority; + mTimeConstraintSet = false; + mFixedPriority = inFixedPriority; +#if TARGET_OS_MAC + if(mPThread != 0) + { + kern_return_t theError = 0; + + // set whether or not this is a fixed priority thread + if (mFixedPriority) + { + thread_extended_policy_data_t theFixedPolicy = { false }; + theError = thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); + AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the fixed-priority policy"); + } + + // set the thread's absolute priority which is relative to the priority on which thread_policy_set() is called + UInt32 theCurrentThreadPriority = getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY); + thread_precedence_policy_data_t thePrecedencePolicy = { mPriority - theCurrentThreadPriority }; + theError = thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); + AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the precedence policy"); + + #if Log_SetPriority + DebugMessageN4("CAPThread::SetPriority: requsted: %lu spawning: %lu current: %lu assigned: %d", mPriority, mSpawningThreadPriority, theCurrentThreadPriority, thePrecedencePolicy.importance); + #endif + } +#elif TARGET_OS_WIN32 + if(mThreadHandle != NULL) + { + SetThreadPriority(mThreadHandle, mPriority); + } +#endif +} + +void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible) +{ + mPeriod = inPeriod; + mComputation = inComputation; + mConstraint = inConstraint; + mIsPreemptible = inIsPreemptible; + mTimeConstraintSet = true; +#if TARGET_OS_MAC + if(mPThread != 0) + { + thread_time_constraint_policy_data_t thePolicy; + thePolicy.period = mPeriod; + thePolicy.computation = mComputation; + thePolicy.constraint = mConstraint; + thePolicy.preemptible = mIsPreemptible; + 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"); + } +#elif TARGET_OS_WIN32 + if(mThreadHandle != NULL) + { + SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL); + } +#endif +} + +void CAPThread::Start() +{ +#if TARGET_OS_MAC + Assert(mPThread == 0, "CAPThread::Start: can't start because the thread is already running"); + if(mPThread == 0) + { + OSStatus theResult; + pthread_attr_t theThreadAttributes; + + theResult = pthread_attr_init(&theThreadAttributes); + ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created."); + + theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED); + ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state."); + + theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this); + ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread."); + + pthread_attr_destroy(&theThreadAttributes); + + } +#elif TARGET_OS_WIN32 + Assert(mThreadID == 0, "CAPThread::Start: can't start because the thread is already running"); + if(mThreadID == 0) + { + // clean up the existing thread handle + if(mThreadHandle != NULL) + { + CloseHandle(mThreadHandle); + mThreadHandle = NULL; + } + + // create a new thread + mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID); + ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread."); + } +#endif +} + +#if TARGET_OS_MAC + +void* CAPThread::Entry(CAPThread* inCAPThread) +{ + void* theAnswer = NULL; + + try + { + if(inCAPThread->mTimeConstraintSet) + { + inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible); + } + else + { + inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority); + } + + if(inCAPThread->mThreadRoutine != NULL) + { + theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter); + } + } + catch (...) + { + // what should be done here? + } + inCAPThread->mPThread = 0; + if (inCAPThread->mAutoDelete) + delete inCAPThread; + return theAnswer; +} + +UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind) +{ + thread_basic_info_data_t threadInfo; + policy_info_data_t thePolicyInfo; + unsigned int count; + + if (inThread == NULL) + return 0; + + // get basic info + count = THREAD_BASIC_INFO_COUNT; + thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count); + + switch (threadInfo.policy) { + case POLICY_TIMESHARE: + count = POLICY_TIMESHARE_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count); + if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) { + return thePolicyInfo.ts.cur_priority; + } + return thePolicyInfo.ts.base_priority; + break; + + case POLICY_FIFO: + count = POLICY_FIFO_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count); + if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) { + return thePolicyInfo.fifo.depress_priority; + } + return thePolicyInfo.fifo.base_priority; + break; + + case POLICY_RR: + count = POLICY_RR_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count); + if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) { + return thePolicyInfo.rr.depress_priority; + } + return thePolicyInfo.rr.base_priority; + break; + } + + return 0; +} + +#elif TARGET_OS_WIN32 + +UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread) +{ + UInt32 theAnswer = 0; + + try + { + if(inCAPThread->mTimeConstraintSet) + { + inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible); + } + else + { + inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority); + } + + if(inCAPThread->mThreadRoutine != NULL) + { + theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter)); + } + inCAPThread->mThreadID = 0; + } + catch (...) + { + // what should be done here? + } + CloseHandle(inCAPThread->mThreadHandle); + inCAPThread->mThreadHandle = NULL; + if (inCAPThread->mAutoDelete) + delete inCAPThread; + return theAnswer; +} + +extern "C" +Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr) +{ + return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue; +} + +#endif + +#if CoreAudio_Debug +void CAPThread::DebugPriority(const char *label) +{ +#if !TARGET_OS_WIN32 + if (mTimeConstraintSet) + printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, + (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1); + else + printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", + (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1); +#else + if (mTimeConstraintSet) + { + printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, + (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1); + } + else + { + printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", + (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1); + } +#endif +} +#endif |