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.
This commit is contained in:
David Reid
2020-06-14 19:27:02 +10:00
parent d4cdee82b5
commit 4b6c8f555b
4 changed files with 39 additions and 35 deletions
+15 -12
View File
@@ -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
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)
} }
} }
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)
#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
#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)
} }
#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,9 +8259,6 @@ 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
posix_yield();
#else
#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) #if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
/* x86/x64 */ /* x86/x64 */
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
@@ -8278,7 +8281,6 @@ static MA_INLINE void ma_yield()
#else #else
/* Unknown or unsupported architecture. No-op. */ /* Unknown or unsupported architecture. No-op. */
#endif #endif
#endif
} }
#endif #endif
@@ -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;
} }
@@ -30131,6 +30133,7 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
pContext->logCallback = config.logCallback; pContext->logCallback = config.logCallback;
pContext->threadPriority = config.threadPriority; pContext->threadPriority = config.threadPriority;
pContext->threadStackSize = config.threadStackSize;
pContext->pUserData = config.pUserData; pContext->pUserData = config.pUserData;
result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &config.allocationCallbacks); result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &config.allocationCallbacks);
@@ -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);
+1
View File
@@ -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;
} }
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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
{ {