Correct wxThread::SetPriority() under Unix to hopefully work.

The old implementation was completely broken, the new should hopefully work if
pthread_setschedparam() behaviour really corresponds to its documentation.

Mapping of our priorities in 0..100 range to pthread 1..99 range remains ugly
but this seems to be unavoidable, unfortunately.

Closes #14985.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76116 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2014-03-11 16:04:17 +00:00
parent f4edf48ec8
commit 9a61ced717
2 changed files with 54 additions and 22 deletions

View File

@ -23,6 +23,7 @@ All:
- Allow iterating over wxCmdLineParser arguments in order (Armel Asselin).
- Add wxScopedArray ctor taking the number of elements to allocate.
- Add wxDynamicLibrary::GetModuleFromAddress() (Luca Bacci).
- Implement wxThread::SetPriority() for pthreads (Luca Bacci).
All (GUI):

View File

@ -1364,36 +1364,67 @@ void wxThread::SetPriority(unsigned int prio)
case STATE_RUNNING:
case STATE_PAUSED:
{
#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
#if defined(__LINUX__)
// On Linux, pthread_setschedparam with SCHED_OTHER does not allow
// a priority other than 0. Instead, we use the BSD setpriority
// which alllows us to set a 'nice' value between 20 to -20. Only
// super user can set a value less than zero (more negative yields
// higher priority). setpriority set the static priority of a
// process, but this is OK since Linux is configured as a thread
// per process.
//
// FIXME this is not true for 2.6!!
// We map our priority values to pthreads scheduling params as
// follows:
// 0..20 to SCHED_IDLE
// 21..40 to SCHED_BATCH
// 41..60 to SCHED_OTHER
// 61..80 to SCHED_RR
// 81..100 to SCHED_FIFO
//
// For the last two, we can also use the additional priority
// parameter which must be in 1..99 range under Linux (TODO:
// what should be used for the other systems?).
struct sched_param sparam = { 0 };
// map wx priorites 0..100 to Unix priorities 20..-20
if ( setpriority(PRIO_PROCESS, 0, -(2*(int)prio)/5 + 20) == -1 )
{
wxLogError(_("Failed to set thread priority %d."), prio);
}
#else // __LINUX__
{
struct sched_param sparam;
sparam.sched_priority = prio;
// The only scheduling policy guaranteed to be supported
// everywhere is this one.
int policy = SCHED_OTHER;
#ifdef SCHED_IDLE
if ( prio <= 20 )
policy = SCHED_IDLE;
#endif
#ifdef SCHED_BATCH
if ( 20 < prio && prio <= 40 )
policy = SCHED_BATCH;
#endif
#ifdef SCHED_RR
if ( 60 < prio && prio <= 80 )
policy = SCHED_RR;
#endif
#ifdef SCHED_FIFO
if ( 80 < prio )
policy = SCHED_FIFO;
#endif
// This test is not redundant as it takes care of the systems
// where neither SCHED_RR nor SCHED_FIFO are defined.
if ( prio > 60 && policy != SCHED_OTHER )
{
// There is no good way to map our 20 possible priorities
// (61..80 or 81..100) to the 99 pthread priorities, so we
// do the best that we can and ensure that the extremes of
// our range are mapped to the pthread extremes and all the
// rest fall in between.
// This gets us to 1..96 range.
sparam.sched_priority = ((prio - 61) % 20)*5 + 1;
// And we artificially increase our highest priority to the
// highest pthread one.
if ( sparam.sched_priority == 96 )
sparam.sched_priority = 99;
}
if ( pthread_setschedparam(m_internal->GetId(),
SCHED_OTHER, &sparam) != 0 )
policy, &sparam) != 0 )
{
wxLogError(_("Failed to set thread priority %d."), prio);
}
}
#endif // __LINUX__
#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
}
break;
case STATE_EXITED: