summaryrefslogtreecommitdiff
path: root/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp
diff options
context:
space:
mode:
authorfalkTX <falktx@gmail.com>2019-01-24 11:49:56 +0100
committerfalkTX <falktx@gmail.com>2019-01-24 11:49:56 +0100
commitf73640618c6b9dde4854b1f847f10fdcb5c5b52f (patch)
treea9e0b165cc512c3986b1cce3bdec521545066a35 /distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp
parent9f8ff46e7ddef2224fcf432bc4dc410e4b3d003e (diff)
Add CoreAudio 10.6 files
Signed-off-by: falkTX <falktx@gmail.com>
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp')
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPThread.cpp375
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