[hal] Set HAL Notifier thread as RT by default (#3482)

This PR gives the Notifier HAL thread RT priority 40 in RobotBase after
HAL initialization and before the user code is run. This drastically
improves scheduling jitter for TimedRobot's AddPeriodic() functions (in
3512's experience).

It's too risky to set user code as RT because badly behaved code
will lock up the Rio (potentially requiring safe mode to recover).

This needs the user program to be setuid admin to succeed.
This commit is contained in:
Tyler Veness
2021-08-14 11:42:35 -07:00
committed by GitHub
parent 192d251ee8
commit 5d9ae3cdb4
8 changed files with 182 additions and 14 deletions

View File

@@ -6,9 +6,42 @@
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
#include <system_error>
#include <fmt/format.h>
#include "hal/Errors.h"
namespace {
class UidSetter {
public:
explicit UidSetter(uid_t uid) {
m_uid = geteuid();
if (uid == 0 && setuid(uid) == -1) {
throw std::system_error(errno, std::generic_category(),
fmt::format("setuid({}) failed", uid));
} else if (uid != 0 && seteuid(uid) == -1) {
throw std::system_error(errno, std::generic_category(),
fmt::format("seteuid({}) failed", uid));
}
}
~UidSetter() noexcept(false) {
if (seteuid(m_uid) == -1) {
throw std::system_error(errno, std::generic_category(),
fmt::format("seteuid({}) failed", m_uid));
}
}
private:
uid_t m_uid;
};
} // namespace
namespace hal::init {
void InitializeThreads() {}
} // namespace hal::init
@@ -70,13 +103,21 @@ HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime,
// Only need to set 0 priority for non RT thread
sch.sched_priority = 0;
}
if (pthread_setschedparam(*reinterpret_cast<const pthread_t*>(handle),
scheduler, &sch)) {
*status = HAL_THREAD_PRIORITY_ERROR;
try {
UidSetter uidSetter{0};
if (pthread_setschedparam(*reinterpret_cast<const pthread_t*>(handle),
scheduler, &sch)) {
*status = HAL_THREAD_PRIORITY_ERROR;
return false;
} else {
*status = 0;
return true;
}
} catch (const std::system_error& e) {
*status = HAL_SETUID_ERROR;
return false;
} else {
*status = 0;
return true;
}
}