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
{
ma_log_proc logCallback;
ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
struct
......@@ -3343,6 +3344,7 @@ struct ma_context
ma_backend backend; /* DirectSound, ALSA, etc. */
ma_log_proc logCallback;
ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
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) {
return ma_result_from_GetLastError(GetLastError());
}
......@@ -7966,7 +7968,7 @@ static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore)
#include <sched.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;
pthread_attr_t* pAttr = NULL;
......@@ -7994,6 +7996,10 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
#endif
}
if (stackSize > 0) {
pthread_attr_setstacksize(&attr, stackSize);
}
if (scheduler != -1) {
int priorityMin = sched_get_priority_min(scheduler);
int priorityMax = sched_get_priority_max(scheduler);
......@@ -8210,17 +8216,17 @@ static ma_result ma_semaphore_release__posix(ma_semaphore* pSemaphore)
}
#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) {
return MA_FALSE;
}
#ifdef MA_WIN32
return ma_thread_create__win32(pThread, priority, entryProc, pData);
return ma_thread_create__win32(pThread, priority, stackSize, entryProc, pData);
#endif
#ifdef MA_POSIX
return ma_thread_create__posix(pThread, priority, entryProc, pData);
return ma_thread_create__posix(pThread, priority, stackSize, entryProc, pData);
#endif
}
......@@ -8253,31 +8259,27 @@ static void ma_sleep(ma_uint32 milliseconds)
#if !defined(MA_EMSCRIPTEN)
static MA_INLINE void ma_yield()
{
#ifdef MA_POSIX
posix_yield();
#else
#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
/* x86/x64 */
#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();
#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
/* x86/x64 */
#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER >= 1400
_mm_pause();
#else
__asm__ __volatile__ ("yield");
__asm pause;
#endif
#else
/* Unknown or unsupported architecture. No-op. */
__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
__asm__ __volatile__ ("yield");
#endif
#else
/* Unknown or unsupported architecture. No-op. */
#endif
}
#endif
......@@ -9897,7 +9899,7 @@ static ma_result ma_device_init__null(ma_context* pContext, const ma_device_conf
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) {
return result;
}
......@@ -30129,9 +30131,10 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
config = ma_context_config_init();
}
pContext->logCallback = config.logCallback;
pContext->threadPriority = config.threadPriority;
pContext->pUserData = config.pUserData;
pContext->logCallback = config.logCallback;
pContext->threadPriority = config.threadPriority;
pContext->threadStackSize = config.threadStackSize;
pContext->pUserData = config.pUserData;
result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &config.allocationCallbacks);
if (result != MA_SUCCESS) {
......@@ -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. */
if (!ma_context_is_backend_asynchronous(pContext)) {
/* 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) {
ma_device_uninit(pDevice);
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)
#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);
if (result != MA_SUCCESS) {
printf("Failed to load sound: %s\n", argv[1]);
ma_engine_uninit(&engine);
return -1;
}
......
......@@ -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. */
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) {
ma_mutex_uninit(&pResourceManager->dataBufferLock);
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:
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 ma_uint32 ma_get_accumulation_bytes_per_frame(ma_format format, ma_uint32 channels);
MA_API size_t ma_get_accumulation_bytes_per_sample(ma_format format);
MA_API size_t ma_get_accumulation_bytes_per_frame(ma_format format, ma_uint32 channels);
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