Commit 4b6c8f55 authored by David Reid's avatar David Reid

Add support for configuring thread stack sizes and fix GCC errors.

The thread priority can be set via ma_thread_create() and can be set in
the context config along side the thread priority for configuring the
size of the stack for the audio thread.
parent d4cdee82
...@@ -3292,6 +3292,7 @@ typedef struct ...@@ -3292,6 +3292,7 @@ typedef struct
{ {
ma_log_proc logCallback; ma_log_proc logCallback;
ma_thread_priority threadPriority; ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData; void* pUserData;
ma_allocation_callbacks allocationCallbacks; ma_allocation_callbacks allocationCallbacks;
struct struct
...@@ -3343,6 +3344,7 @@ struct ma_context ...@@ -3343,6 +3344,7 @@ struct ma_context
ma_backend backend; /* DirectSound, ALSA, etc. */ ma_backend backend; /* DirectSound, ALSA, etc. */
ma_log_proc logCallback; ma_log_proc logCallback;
ma_thread_priority threadPriority; ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData; void* pUserData;
ma_allocation_callbacks allocationCallbacks; ma_allocation_callbacks allocationCallbacks;
ma_mutex deviceEnumLock; /* Used to make ma_context_get_devices() thread safe. */ ma_mutex deviceEnumLock; /* Used to make ma_context_get_devices() thread safe. */
...@@ -7832,9 +7834,9 @@ static int ma_thread_priority_to_win32(ma_thread_priority priority) ...@@ -7832,9 +7834,9 @@ static int ma_thread_priority_to_win32(ma_thread_priority priority)
} }
} }
static ma_result ma_thread_create__win32(ma_thread* pThread, ma_thread_priority priority, ma_thread_entry_proc entryProc, void* pData) static ma_result ma_thread_create__win32(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
{ {
*pThread = CreateThread(NULL, 0, entryProc, pData, 0, NULL); *pThread = CreateThread(NULL, stackSize, entryProc, pData, 0, NULL);
if (*pThread == NULL) { if (*pThread == NULL) {
return ma_result_from_GetLastError(GetLastError()); return ma_result_from_GetLastError(GetLastError());
} }
...@@ -7966,7 +7968,7 @@ static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore) ...@@ -7966,7 +7968,7 @@ static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore)
#include <sched.h> #include <sched.h>
#include <sys/time.h> #include <sys/time.h>
static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority priority, ma_thread_entry_proc entryProc, void* pData) static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
{ {
int result; int result;
pthread_attr_t* pAttr = NULL; pthread_attr_t* pAttr = NULL;
...@@ -7994,6 +7996,10 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority ...@@ -7994,6 +7996,10 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
#endif #endif
} }
if (stackSize > 0) {
pthread_attr_setstacksize(&attr, stackSize);
}
if (scheduler != -1) { if (scheduler != -1) {
int priorityMin = sched_get_priority_min(scheduler); int priorityMin = sched_get_priority_min(scheduler);
int priorityMax = sched_get_priority_max(scheduler); int priorityMax = sched_get_priority_max(scheduler);
...@@ -8210,17 +8216,17 @@ static ma_result ma_semaphore_release__posix(ma_semaphore* pSemaphore) ...@@ -8210,17 +8216,17 @@ static ma_result ma_semaphore_release__posix(ma_semaphore* pSemaphore)
} }
#endif #endif
static ma_result ma_thread_create(ma_thread* pThread, ma_thread_priority priority, ma_thread_entry_proc entryProc, void* pData) static ma_result ma_thread_create(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
{ {
if (pThread == NULL || entryProc == NULL) { if (pThread == NULL || entryProc == NULL) {
return MA_FALSE; return MA_FALSE;
} }
#ifdef MA_WIN32 #ifdef MA_WIN32
return ma_thread_create__win32(pThread, priority, entryProc, pData); return ma_thread_create__win32(pThread, priority, stackSize, entryProc, pData);
#endif #endif
#ifdef MA_POSIX #ifdef MA_POSIX
return ma_thread_create__posix(pThread, priority, entryProc, pData); return ma_thread_create__posix(pThread, priority, stackSize, entryProc, pData);
#endif #endif
} }
...@@ -8253,31 +8259,27 @@ static void ma_sleep(ma_uint32 milliseconds) ...@@ -8253,31 +8259,27 @@ static void ma_sleep(ma_uint32 milliseconds)
#if !defined(MA_EMSCRIPTEN) #if !defined(MA_EMSCRIPTEN)
static MA_INLINE void ma_yield() static MA_INLINE void ma_yield()
{ {
#ifdef MA_POSIX #if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
posix_yield(); /* x86/x64 */
#else #if defined(_MSC_VER) && !defined(__clang__)
#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) #if _MSC_VER >= 1400
/* x86/x64 */ _mm_pause();
#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER >= 1400
_mm_pause();
#else
__asm pause;
#endif
#else
__asm__ __volatile__ ("pause");
#endif
#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 6) || (defined(_M_ARM) && _M_ARM >= 6)
/* ARM */
#if defined(_MSC_VER)
/* Apparently there is a __yield() intrinsic that's compatible with ARM, but I cannot find documentation for it nor can I find where it's declared. */
__yield();
#else #else
__asm__ __volatile__ ("yield"); __asm pause;
#endif #endif
#else #else
/* Unknown or unsupported architecture. No-op. */ __asm__ __volatile__ ("pause");
#endif #endif
#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 6) || (defined(_M_ARM) && _M_ARM >= 6)
/* ARM */
#if defined(_MSC_VER)
/* Apparently there is a __yield() intrinsic that's compatible with ARM, but I cannot find documentation for it nor can I find where it's declared. */
__yield();
#else
__asm__ __volatile__ ("yield");
#endif
#else
/* Unknown or unsupported architecture. No-op. */
#endif #endif
} }
#endif #endif
...@@ -9897,7 +9899,7 @@ static ma_result ma_device_init__null(ma_context* pContext, const ma_device_conf ...@@ -9897,7 +9899,7 @@ static ma_result ma_device_init__null(ma_context* pContext, const ma_device_conf
return result; return result;
} }
result = ma_thread_create(&pDevice->thread, pContext->threadPriority, ma_device_thread__null, pDevice); result = ma_thread_create(&pDevice->thread, pContext->threadPriority, 0, ma_device_thread__null, pDevice);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
...@@ -30129,9 +30131,10 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC ...@@ -30129,9 +30131,10 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
config = ma_context_config_init(); config = ma_context_config_init();
} }
pContext->logCallback = config.logCallback; pContext->logCallback = config.logCallback;
pContext->threadPriority = config.threadPriority; pContext->threadPriority = config.threadPriority;
pContext->pUserData = config.pUserData; pContext->threadStackSize = config.threadStackSize;
pContext->pUserData = config.pUserData;
result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &config.allocationCallbacks); result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &config.allocationCallbacks);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -30683,7 +30686,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC ...@@ -30683,7 +30686,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
/* Some backends don't require the worker thread. */ /* Some backends don't require the worker thread. */
if (!ma_context_is_backend_asynchronous(pContext)) { if (!ma_context_is_backend_asynchronous(pContext)) {
/* The worker thread. */ /* The worker thread. */
result = ma_thread_create(&pDevice->thread, pContext->threadPriority, ma_worker_thread, pDevice); result = ma_thread_create(&pDevice->thread, pContext->threadPriority, pContext->threadStackSize, ma_worker_thread, pDevice);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_device_uninit(pDevice); ma_device_uninit(pDevice);
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread.", result); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread.", result);
...@@ -36,6 +36,7 @@ int main(int argc, char** argv) ...@@ -36,6 +36,7 @@ int main(int argc, char** argv)
#if 1 #if 1
result = ma_engine_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE | MA_DATA_SOURCE_FLAG_ASYNC | MA_DATA_SOURCE_FLAG_STREAM, NULL, &sound); result = ma_engine_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE | MA_DATA_SOURCE_FLAG_ASYNC | MA_DATA_SOURCE_FLAG_STREAM, NULL, &sound);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to load sound: %s\n", argv[1]);
ma_engine_uninit(&engine); ma_engine_uninit(&engine);
return -1; return -1;
} }
......
...@@ -1332,7 +1332,7 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon ...@@ -1332,7 +1332,7 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon
/* Create the resource thread last to ensure the new thread has access to valid data. */ /* Create the resource thread last to ensure the new thread has access to valid data. */
result = ma_thread_create(&pResourceManager->asyncThread, ma_thread_priority_normal, ma_resource_manager_resource_thread, pResourceManager); result = ma_thread_create(&pResourceManager->asyncThread, ma_thread_priority_normal, 0, ma_resource_manager_resource_thread, pResourceManager);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_mutex_uninit(&pResourceManager->dataBufferLock); ma_mutex_uninit(&pResourceManager->dataBufferLock);
ma_resource_manager_message_queue_uninit(&pResourceManager->messageQueue); ma_resource_manager_message_queue_uninit(&pResourceManager->messageQueue);
......
...@@ -253,8 +253,8 @@ Below a summary of some things to keep in mind for high performance mixing: ...@@ -253,8 +253,8 @@ Below a summary of some things to keep in mind for high performance mixing:
of your data sources to 48000Hz before mixing may be unnecessarily inefficient because it'll need to perform mixing on a greater number of samples. of your data sources to 48000Hz before mixing may be unnecessarily inefficient because it'll need to perform mixing on a greater number of samples.
*/ */
MA_API ma_uint32 ma_get_accumulation_bytes_per_sample(ma_format format); MA_API size_t ma_get_accumulation_bytes_per_sample(ma_format format);
MA_API ma_uint32 ma_get_accumulation_bytes_per_frame(ma_format format, ma_uint32 channels); MA_API size_t ma_get_accumulation_bytes_per_frame(ma_format format, ma_uint32 channels);
typedef struct typedef struct
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment