From c49ab1b841d2020df31b314eb0eccc934fe906c0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 25 Mar 2011 12:44:06 -0700 Subject: [PATCH] The API sets the priority for the current thread, not an arbitrary thread. Implemented thread priority as the 'nice' value on Linux. High priority threads require root permissions (you shouldn't give your game root permissions though!) --- include/SDL_thread.h | 4 ++-- src/audio/SDL_audio.c | 4 +++- src/thread/SDL_systhread.h | 4 ++-- src/thread/SDL_thread.c | 8 ++------ src/thread/beos/SDL_systhread.c | 10 +++++---- src/thread/generic/SDL_systhread.c | 2 +- src/thread/nds/SDL_systhread.c | 2 +- src/thread/pthread/SDL_systhread.c | 33 +++++++++++++++++++++++++----- src/thread/windows/SDL_systhread.c | 12 +++++------ 9 files changed, 51 insertions(+), 28 deletions(-) diff --git a/include/SDL_thread.h b/include/SDL_thread.h index 66a7f8dec..25e7194d5 100644 --- a/include/SDL_thread.h +++ b/include/SDL_thread.h @@ -157,9 +157,9 @@ extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void); extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); /** - * Set the thread priority + * Set the priority for the current thread */ -extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority); +extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); /** * Wait for a thread to finish. diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index ad4bc02e8..c7c14f81b 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -329,6 +329,9 @@ SDL_RunAudio(void *devicep) int silence; Uint32 delay; + /* The audio mixing is always a high priority thread */ + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); + /* For streaming when the buffer sizes don't match up */ Uint8 *istream; int istream_len = 0; @@ -974,7 +977,6 @@ open_audio_device(const char *devname, int iscapture, SDL_SetError("Couldn't create audio thread"); return 0; } - SDL_SetThreadPriority(device->thread, SDL_THREAD_PRIORITY_HIGH); } return id + 1; diff --git a/src/thread/SDL_systhread.h b/src/thread/SDL_systhread.h index f520ddd79..684547e57 100644 --- a/src/thread/SDL_systhread.h +++ b/src/thread/SDL_systhread.h @@ -43,8 +43,8 @@ extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args); /* This function does any necessary setup in the child thread */ extern void SDL_SYS_SetupThread(void); -/* This function sets thread priority */ -extern int SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority); +/* This function sets the current thread priority */ +extern int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority); /* This function waits for the thread to finish and frees any data allocated by SDL_SYS_CreateThread() diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index 349e7b49e..a51e506f3 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -295,13 +295,9 @@ SDL_GetThreadID(SDL_Thread * thread) } int -SDL_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) +SDL_SetThreadPriority(SDL_ThreadPriority priority) { - if (!thread) { - SDL_SetError("SDL_SetThreadPriority() passed NULL thread"); - return -1; - } - return SDL_SYS_SetThreadPriority(thread, priority); + return SDL_SYS_SetThreadPriority(priority); } void diff --git a/src/thread/beos/SDL_systhread.c b/src/thread/beos/SDL_systhread.c index 235bcae88..ffc077d22 100644 --- a/src/thread/beos/SDL_systhread.c +++ b/src/thread/beos/SDL_systhread.c @@ -93,14 +93,16 @@ SDL_ThreadID(void) int SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) { - int32 new_priority = B_NORMAL_PRIORITY; + int32 value; if (priority == SDL_THREAD_PRIORITY_LOW) { - new_priority = B_LOW_PRIORITY; + value = B_LOW_PRIORITY; } else if (priority == SDL_THREAD_PRIORITY_HIGH) { - new_priority = B_URGENT_DISPLAY_PRIORITY; + value = B_URGENT_DISPLAY_PRIORITY; + } else { + value = B_NORMAL_PRIORITY; } - set_thread_priority(thread->handle, new_priority); + set_thread_priority(find_thread(NULL), value); return 0; } diff --git a/src/thread/generic/SDL_systhread.c b/src/thread/generic/SDL_systhread.c index e59f3a945..5201d9477 100644 --- a/src/thread/generic/SDL_systhread.c +++ b/src/thread/generic/SDL_systhread.c @@ -46,7 +46,7 @@ SDL_ThreadID(void) } int -SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) +SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) { return (0); } diff --git a/src/thread/nds/SDL_systhread.c b/src/thread/nds/SDL_systhread.c index ad5bf9bed..8dd829f70 100644 --- a/src/thread/nds/SDL_systhread.c +++ b/src/thread/nds/SDL_systhread.c @@ -57,7 +57,7 @@ SDL_SYS_WaitThread(SDL_Thread * thread) } int -SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) +SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) { return (0); } diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index 42e60f3f0..4711b1c49 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -23,6 +23,11 @@ #include #include +#ifdef linux +#include +#include +#include +#endif #include "SDL_thread.h" #include "../SDL_thread_c.h" @@ -34,6 +39,7 @@ static const int sig_list[] = { SIGVTALRM, SIGPROF, 0 }; + static void * RunThread(void *data) { @@ -92,12 +98,29 @@ SDL_ThreadID(void) } int -SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) +SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) { +#ifdef linux + int value; + + if (priority == SDL_THREAD_PRIORITY_LOW) { + value = 19; + } else if (priority == SDL_THREAD_PRIORITY_HIGH) { + value = -20; + } else { + value = 0; + } + if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) { + SDL_SetError("setpriority() failed"); + return -1; + } + return 0; +#else struct sched_param sched; int policy; + pthread_t thread = pthread_self(); - if (pthread_getschedparam(thread->handle, &policy, &sched) < 0) { + if (pthread_getschedparam(thread, &policy, &sched) < 0) { SDL_SetError("pthread_getschedparam() failed"); return -1; } @@ -108,14 +131,14 @@ SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) } else { int min_priority = sched_get_priority_min(policy); int max_priority = sched_get_priority_max(policy); - int priority = (min_priority + (max_priority - min_priority) / 2); - sched.sched_priority = priority; + sched.sched_priority = (min_priority + (max_priority - min_priority) / 2); } - if (pthread_setschedparam(thread->handle, policy, &sched) < 0) { + if (pthread_setschedparam(thread, policy, &sched) < 0) { SDL_SetError("pthread_setschedparam() failed"); return -1; } return 0; +#endif /* linux */ } void diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c index 058ff93f0..26d994e00 100644 --- a/src/thread/windows/SDL_systhread.c +++ b/src/thread/windows/SDL_systhread.c @@ -156,18 +156,18 @@ SDL_ThreadID(void) } int -SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority) +SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) { - BOOL result; + int value; if (priority == SDL_THREAD_PRIORITY_LOW) { - result = SetThreadPriority(thread->handle, THREAD_PRIORITY_LOWEST); + value = THREAD_PRIORITY_LOWEST; } else if (priority == SDL_THREAD_PRIORITY_HIGH) { - result = SetThreadPriority(thread->handle, THREAD_PRIORITY_HIGHEST); + value = THREAD_PRIORITY_HIGHEST; } else { - result = SetThreadPriority(thread->handle, THREAD_PRIORITY_NORMAL); + value = THREAD_PRIORITY_NORMAL; } - if (!result) { + if (!SetThreadPriority(GetCurrentThread(), value)) { WIN_SetError("SetThreadPriority()"); return -1; }