Don't change thread priority if it is default under Unix

Skip all the code dealing with the priority/scheduling parameters if the
priority is just wxPRIORITY_DEFAULT anyhow, as it's unnecessary to do
anything in this case and it can result in spurious errors.

Also extract this code into a separate SetThreadPriority() function to
make wxThreadInternal::Create() itself shorter and more clear.

Closes #18195.
This commit is contained in:
Vadim Zeitlin
2018-08-16 12:58:10 +02:00
parent 29c218f1b4
commit 51c8496087
2 changed files with 74 additions and 51 deletions

View File

@@ -96,6 +96,7 @@ All:
- Make wxList and wxVector iterators conform to input iterator requirements.
- Fix MT-safety problem when reading and writing from wxSocket (jkubalik).
- Fix build issues under HaikuOS (mill-j).
- Avoid spurious errors on thread creation under NetBSD.
All (GUI):

View File

@@ -987,6 +987,74 @@ wxThreadInternal::~wxThreadInternal()
{
}
static bool SetThreadPriority(pthread_attr_t& attr, int prio)
{
if ( prio == wxPRIORITY_DEFAULT )
{
// Don't even try to do anything, there is no need for it and it could
// result in failures if we don't handle setting the priority correctly
// under the current platform, see e.g. #18195.
return true;
}
#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
int policy;
if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 )
{
wxLogError(_("Cannot retrieve thread scheduling policy."));
return false;
}
#ifdef __VMS__
/* the pthread.h contains too many spaces. This is a work-around */
# undef sched_get_priority_max
#undef sched_get_priority_min
#define sched_get_priority_max(_pol_) \
(_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX)
#define sched_get_priority_min(_pol_) \
(_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN)
#endif
int max_prio = sched_get_priority_max(policy),
min_prio = sched_get_priority_min(policy);
if ( min_prio == -1 || max_prio == -1 )
{
wxLogError(_("Cannot get priority range for scheduling policy %d."),
policy);
return false;
}
if ( max_prio == min_prio )
{
// notify the programmer that this doesn't work here
wxLogWarning(_("Thread priority setting is ignored."));
return false;
}
struct sched_param sp;
if ( pthread_attr_getschedparam(&attr, &sp) != 0 )
{
wxFAIL_MSG(wxT("pthread_attr_getschedparam() failed"));
return false;
}
sp.sched_priority = min_prio + (prio*(max_prio - min_prio))/100;
if ( pthread_attr_setschedparam(&attr, &sp) != 0 )
{
wxFAIL_MSG(wxT("pthread_attr_setschedparam(priority) failed"));
return false;
}
return true;
#else // !HAVE_THREAD_PRIORITY_FUNCTIONS
wxUnusedVar(attr);
return false;
#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
}
wxThreadError wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
{
if ( GetState() != STATE_NEW )
@@ -1006,60 +1074,14 @@ wxThreadError wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
wxUnusedVar(stackSize);
#endif
#ifdef HAVE_THREAD_PRIORITY_FUNCTIONS
int policy;
if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 )
if ( !SetThreadPriority(attr, GetPriority()) )
{
wxLogError(_("Cannot retrieve thread scheduling policy."));
// We currently ignore the failure to set the thread priority as it
// seems better to create a thread with default priority than to
// not create one at all.
wxLogDebug("Failed to set thread priority to %d", GetPriority());
}
#ifdef __VMS__
/* the pthread.h contains too many spaces. This is a work-around */
# undef sched_get_priority_max
#undef sched_get_priority_min
#define sched_get_priority_max(_pol_) \
(_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX)
#define sched_get_priority_min(_pol_) \
(_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN)
#endif
int max_prio = sched_get_priority_max(policy),
min_prio = sched_get_priority_min(policy),
prio = GetPriority();
if ( min_prio == -1 || max_prio == -1 )
{
wxLogError(_("Cannot get priority range for scheduling policy %d."),
policy);
}
else if ( max_prio == min_prio )
{
if ( prio != wxPRIORITY_DEFAULT )
{
// notify the programmer that this doesn't work here
wxLogWarning(_("Thread priority setting is ignored."));
}
//else: we have default priority, so don't complain
// anyhow, don't do anything because priority is just ignored
}
else
{
struct sched_param sp;
if ( pthread_attr_getschedparam(&attr, &sp) != 0 )
{
wxFAIL_MSG(wxT("pthread_attr_getschedparam() failed"));
}
sp.sched_priority = min_prio + (prio*(max_prio - min_prio))/100;
if ( pthread_attr_setschedparam(&attr, &sp) != 0 )
{
wxFAIL_MSG(wxT("pthread_attr_setschedparam(priority) failed"));
}
}
#endif // HAVE_THREAD_PRIORITY_FUNCTIONS
#ifdef HAVE_PTHREAD_ATTR_SETSCOPE
// this will make the threads created by this process really concurrent
if ( pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0 )