[Threading/Linux] Add fallback to nice values
SCHED_FIFO requires CAP_SYS_NICE or root, try SCHED_FIFO first for real-time priority control, then fall back to setpriority() nice values if permission is denied.
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -611,6 +612,7 @@ class PosixCondition<Thread> final : public PosixConditionBase {
|
|||||||
/// Thread::GetCurrentThread() on the main thread
|
/// Thread::GetCurrentThread() on the main thread
|
||||||
explicit PosixCondition(pthread_t thread)
|
explicit PosixCondition(pthread_t thread)
|
||||||
: thread_(thread),
|
: thread_(thread),
|
||||||
|
tid_(static_cast<pid_t>(syscall(SYS_gettid))),
|
||||||
signaled_(false),
|
signaled_(false),
|
||||||
exit_code_(0),
|
exit_code_(0),
|
||||||
state_(State::kRunning),
|
state_(State::kRunning),
|
||||||
@@ -742,31 +744,48 @@ class PosixCondition<Thread> final : public PosixConditionBase {
|
|||||||
|
|
||||||
int priority() const {
|
int priority() const {
|
||||||
WaitStarted();
|
WaitStarted();
|
||||||
int policy;
|
if (!fifo_failed_) {
|
||||||
sched_param param{};
|
int policy;
|
||||||
int ret = pthread_getschedparam(thread_, &policy, ¶m);
|
sched_param param{};
|
||||||
if (ret != 0) {
|
int ret = pthread_getschedparam(thread_, &policy, ¶m);
|
||||||
return -1;
|
if (ret != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return param.sched_priority;
|
||||||
}
|
}
|
||||||
|
// When using nice values, map back to the SCHED_FIFO range (1-32)
|
||||||
return param.sched_priority;
|
// so callers see a consistent priority space.
|
||||||
|
int nice_val = getpriority(PRIO_PROCESS, tid_);
|
||||||
|
// nice -19..19 → fifo 32..1
|
||||||
|
return 16 - nice_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_priority(int new_priority) const {
|
void set_priority(int new_priority) const {
|
||||||
WaitStarted();
|
WaitStarted();
|
||||||
sched_param param{};
|
if (!fifo_failed_) {
|
||||||
param.sched_priority = new_priority;
|
// Try real-time SCHED_FIFO for best priority control.
|
||||||
int res = pthread_setschedparam(thread_, SCHED_FIFO, ¶m);
|
sched_param param{};
|
||||||
if (res != 0) {
|
param.sched_priority = new_priority;
|
||||||
switch (res) {
|
int res = pthread_setschedparam(thread_, SCHED_FIFO, ¶m);
|
||||||
case EPERM:
|
if (res == 0) {
|
||||||
XELOGW("Permission denied while setting priority");
|
return;
|
||||||
break;
|
|
||||||
case EINVAL:
|
|
||||||
assert_always();
|
|
||||||
default:
|
|
||||||
XELOGW("Unknown error while setting priority");
|
|
||||||
}
|
}
|
||||||
|
if (res == EPERM) {
|
||||||
|
fifo_failed_ = true;
|
||||||
|
} else {
|
||||||
|
XELOGW("Unexpected error {} while setting SCHED_FIFO priority", res);
|
||||||
|
fifo_failed_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall back to nice values under SCHED_OTHER.
|
||||||
|
// Map SCHED_FIFO range (1-32) to nice range (19 to -19).
|
||||||
|
// Center: fifo 16 → nice 0.
|
||||||
|
int nice_val = 16 - new_priority;
|
||||||
|
// Clamp to valid nice range.
|
||||||
|
if (nice_val < -20) nice_val = -20;
|
||||||
|
if (nice_val > 19) nice_val = 19;
|
||||||
|
if (tid_ > 0) {
|
||||||
|
setpriority(PRIO_PROCESS, tid_, nice_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -930,6 +949,8 @@ class PosixCondition<Thread> final : public PosixConditionBase {
|
|||||||
sem_destroy(&suspend_sem_);
|
sem_destroy(&suspend_sem_);
|
||||||
}
|
}
|
||||||
pthread_t thread_;
|
pthread_t thread_;
|
||||||
|
pid_t tid_ = 0; // Kernel TID for setpriority() fallback
|
||||||
|
mutable bool fifo_failed_ = false; // True after SCHED_FIFO was rejected
|
||||||
bool signaled_;
|
bool signaled_;
|
||||||
int exit_code_;
|
int exit_code_;
|
||||||
State state_; // Protected by state_mutex_
|
State state_; // Protected by state_mutex_
|
||||||
@@ -1243,6 +1264,7 @@ void* PosixCondition<Thread>::ThreadStartRoutine(void* parameter) {
|
|||||||
delete start_data;
|
delete start_data;
|
||||||
|
|
||||||
current_thread_ = thread;
|
current_thread_ = thread;
|
||||||
|
thread->handle_.tid_ = static_cast<pid_t>(syscall(SYS_gettid));
|
||||||
{
|
{
|
||||||
std::unique_lock lock(thread->handle_.state_mutex_);
|
std::unique_lock lock(thread->handle_.state_mutex_);
|
||||||
thread->handle_.state_ =
|
thread->handle_.state_ =
|
||||||
|
|||||||
Reference in New Issue
Block a user