From 173ecd3d020854db07f69edbe889a56ef842e4a4 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Mon, 6 Apr 2026 08:49:43 -0700 Subject: [PATCH] [hal] Refactor threads API (#8701) Since sched_setscheduler() requires non-RT priorities to be 0, we can use that as a sentinel value for disabling RT and condense the Java API to just two functions with fewer parameters. The thread priority setter is deprecated since only experts should use it. The HAL Notifier thread priority setter was replaced with setting the priority in the thread itself. The C++ Notifier non-RT and RT constructors were deduplicated. The real-time scheduler was changed from SCHED_FIFO to SCHED_RR, which is SCHED_FIFO with threads allowed to run for a maximum time quantum before yielding (100 ms by default). --- design-docs/real-time-thread-priorities.md | 6 ++ .../org/wpilib/hardware/hal/NotifierJNI.java | 16 ----- .../org/wpilib/hardware/hal/ThreadsJNI.java | 25 +++---- hal/src/main/native/cpp/jni/NotifierJNI.cpp | 19 +---- hal/src/main/native/cpp/jni/ThreadsJNI.cpp | 36 +++------- .../main/native/include/wpi/hal/Notifier.h | 19 ----- hal/src/main/native/include/wpi/hal/Threads.h | 70 +++++++++---------- hal/src/main/native/sim/Notifier.cpp | 6 -- hal/src/main/native/sim/Threads.cpp | 24 ++++--- hal/src/main/native/systemcore/CAN.cpp | 4 +- hal/src/main/native/systemcore/Notifier.cpp | 11 ++- hal/src/main/native/systemcore/Threads.cpp | 70 +++++++------------ hal/src/main/python/semiwrap/Notifier_c.yml | 1 - .../src/main/native/cpp/system/Notifier.cpp | 52 ++------------ .../src/main/native/cpp/system/Threads.cpp | 34 ++++----- wpilibc/src/main/native/cppcs/RobotBase.cpp | 5 -- .../include/wpi/framework/TimesliceRobot.hpp | 3 +- .../native/include/wpi/system/Notifier.hpp | 20 +----- .../native/include/wpi/system/Threads.hpp | 70 +++++++++++-------- wpilibc/src/main/python/semiwrap/Notifier.yml | 1 - wpilibc/src/main/python/wpilib/_impl/start.py | 5 -- .../main/python/wpilib/src/rpy/Notifier.cpp | 5 -- .../src/main/python/wpilib/src/rpy/Notifier.h | 17 ----- .../java/org/wpilib/framework/RobotBase.java | 5 -- .../org/wpilib/framework/TimesliceRobot.java | 4 +- .../main/java/org/wpilib/system/Notifier.java | 17 ----- .../main/java/org/wpilib/system/Threads.java | 31 ++++---- 27 files changed, 188 insertions(+), 388 deletions(-) create mode 100644 design-docs/real-time-thread-priorities.md diff --git a/design-docs/real-time-thread-priorities.md b/design-docs/real-time-thread-priorities.md new file mode 100644 index 0000000000..01b69c24df --- /dev/null +++ b/design-docs/real-time-thread-priorities.md @@ -0,0 +1,6 @@ +# Real-time thread priorities + +|Name |Location |Priority| +|-------------------|---------------------------------------------------------------------------------------------|--------| +|CAN HAL thread |[hal/src/main/native/systemcore/CAN.cpp](../hal/src/main/native/systemcore/CAN.cpp) |50 | +|Notifier HAL thread|[hal/src/main/native/systemcore/Notifier.cpp](../hal/src/main/native/systemcore/Notifier.cpp)|40 | diff --git a/hal/src/main/java/org/wpilib/hardware/hal/NotifierJNI.java b/hal/src/main/java/org/wpilib/hardware/hal/NotifierJNI.java index e904f0d444..53ac65b34b 100644 --- a/hal/src/main/java/org/wpilib/hardware/hal/NotifierJNI.java +++ b/hal/src/main/java/org/wpilib/hardware/hal/NotifierJNI.java @@ -24,22 +24,6 @@ public class NotifierJNI extends JNIWrapper { */ public static native int createNotifier(); - /** - * Sets the HAL notifier thread priority. - * - *

The HAL notifier thread is responsible for managing the system's notifier interrupt and - * waking up user's Notifiers when it's their time to run. Giving the HAL notifier thread - * real-time priority helps ensure the user's real-time Notifiers, if any, are notified to run in - * a timely manner. - * - * @param realTime Set to true to set a real-time priority, false for standard priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being - * highest. For non-real-time, this is forced to 0. See "man 7 sched" for more details. - * @return True on success. - * @see "HAL_SetNotifierThreadPriority" - */ - public static native boolean setHALThreadPriority(boolean realTime, int priority); - /** * Sets the name of the notifier. * diff --git a/hal/src/main/java/org/wpilib/hardware/hal/ThreadsJNI.java b/hal/src/main/java/org/wpilib/hardware/hal/ThreadsJNI.java index 1ce2bc2e0f..1998c3837b 100644 --- a/hal/src/main/java/org/wpilib/hardware/hal/ThreadsJNI.java +++ b/hal/src/main/java/org/wpilib/hardware/hal/ThreadsJNI.java @@ -11,32 +11,27 @@ package org.wpilib.hardware.hal; */ public class ThreadsJNI extends JNIWrapper { /** - * Gets the thread priority for the current thread. + * Gets the current thread's priority. * - * @return The current thread priority. For real-time, this is 1-99 with 99 being highest. For - * non-real-time, this is 0. See "man 7 sched" for details. + *

Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, and 99 is + * highest priority. See "man 7 sched" for details. + * + * @return The current thread's priority. * @see "HAL_GetCurrentThreadPriority" */ public static native int getCurrentThreadPriority(); /** - * Gets the real-time status for the current thread. + * Sets the current thread's priority. * - * @return Set to true if thread is real-time, otherwise false. - * @see "HAL_GetCurrentThreadPriority" - */ - public static native boolean getCurrentThreadIsRealTime(); - - /** - * Sets the thread priority for the current thread. + *

Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, and 99 is + * highest priority. See "man 7 sched" for details. * - * @param realTime Set to true to set a real-time priority, false for standard priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being - * highest. For non-real-time, this is forced to 0. See "man 7 sched" for more details. + * @param priority The priority. * @return True on success. * @see "HAL_SetCurrentThreadPriority" */ - public static native boolean setCurrentThreadPriority(boolean realTime, int priority); + public static native boolean setCurrentThreadPriority(int priority); /** Utility class. */ private ThreadsJNI() {} diff --git a/hal/src/main/native/cpp/jni/NotifierJNI.cpp b/hal/src/main/native/cpp/jni/NotifierJNI.cpp index e4dd9a5e00..92cefa1a20 100644 --- a/hal/src/main/native/cpp/jni/NotifierJNI.cpp +++ b/hal/src/main/native/cpp/jni/NotifierJNI.cpp @@ -3,9 +3,9 @@ // the WPILib BSD license file in the root directory of this project. #include +#include #include -#include #include "HALUtil.hpp" #include "org_wpilib_hardware_hal_NotifierJNI.h" @@ -33,20 +33,7 @@ Java_org_wpilib_hardware_hal_NotifierJNI_createNotifier return 0; // something went wrong in HAL } - return (jint)notifierHandle; -} - -/* - * Class: org_wpilib_hardware_hal_NotifierJNI - * Method: setHALThreadPriority - * Signature: (ZI)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_wpilib_hardware_hal_NotifierJNI_setHALThreadPriority - (JNIEnv* env, jclass, jboolean realTime, jint priority) -{ - int32_t status = 0; - return HAL_SetNotifierThreadPriority(realTime, priority, &status); + return static_cast(notifierHandle); } /* @@ -140,7 +127,7 @@ Java_org_wpilib_hardware_hal_NotifierJNI_getNotifierOverrun CheckStatus(env, status); - return (jint)count; + return static_cast(count); } } // extern "C" diff --git a/hal/src/main/native/cpp/jni/ThreadsJNI.cpp b/hal/src/main/native/cpp/jni/ThreadsJNI.cpp index 6f07a7e073..8ae4e334ea 100644 --- a/hal/src/main/native/cpp/jni/ThreadsJNI.cpp +++ b/hal/src/main/native/cpp/jni/ThreadsJNI.cpp @@ -3,6 +3,7 @@ // the WPILib BSD license file in the root directory of this project. #include +#include #include @@ -13,6 +14,7 @@ using namespace wpi::hal; extern "C" { + /* * Class: org_wpilib_hardware_hal_ThreadsJNI * Method: getCurrentThreadPriority @@ -22,43 +24,25 @@ JNIEXPORT jint JNICALL Java_org_wpilib_hardware_hal_ThreadsJNI_getCurrentThreadPriority (JNIEnv* env, jclass) { - int32_t status = 0; - HAL_Bool isRT = false; - auto ret = HAL_GetCurrentThreadPriority(&isRT, &status); + int32_t priority = 0; + HAL_Status status = HAL_GetCurrentThreadPriority(&priority); CheckStatus(env, status); - return static_cast(ret); -} - -/* - * Class: org_wpilib_hardware_hal_ThreadsJNI - * Method: getCurrentThreadIsRealTime - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL -Java_org_wpilib_hardware_hal_ThreadsJNI_getCurrentThreadIsRealTime - (JNIEnv* env, jclass) -{ - int32_t status = 0; - HAL_Bool isRT = false; - HAL_GetCurrentThreadPriority(&isRT, &status); - CheckStatus(env, status); - return static_cast(isRT); + return static_cast(priority); } /* * Class: org_wpilib_hardware_hal_ThreadsJNI * Method: setCurrentThreadPriority - * Signature: (ZI)Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_org_wpilib_hardware_hal_ThreadsJNI_setCurrentThreadPriority - (JNIEnv* env, jclass, jboolean realTime, jint priority) + (JNIEnv* env, jclass, jint priority) { - int32_t status = 0; - auto ret = HAL_SetCurrentThreadPriority( - static_cast(realTime), static_cast(priority), &status); + HAL_Status status = + HAL_SetCurrentThreadPriority(static_cast(priority)); CheckStatus(env, status, false); - return static_cast(ret); + return static_cast(status); } } // extern "C" diff --git a/hal/src/main/native/include/wpi/hal/Notifier.h b/hal/src/main/native/include/wpi/hal/Notifier.h index 9d6981e10e..c914bbdf49 100644 --- a/hal/src/main/native/include/wpi/hal/Notifier.h +++ b/hal/src/main/native/include/wpi/hal/Notifier.h @@ -30,25 +30,6 @@ extern "C" { */ HAL_NotifierHandle HAL_CreateNotifier(int32_t* status); -/** - * Sets the HAL notifier thread priority. - * - * The HAL notifier thread is responsible for managing the system's notifier - * interrupt and waking up user's Notifiers when it's their time to run. - * Giving the HAL notifier thread real-time priority helps ensure the user's - * real-time Notifiers, if any, are notified to run in a timely manner. - * - * @param[in] realTime Set to true to set a real-time priority, false for - * standard priority. - * @param[in] priority Priority to set the thread to. For real-time, this is - * 1-99 with 99 being highest. For non-real-time, this is - * forced to 0. See "man 7 sched" for more details. - * @param[out] status Error status variable. 0 on success. - * @return True on success. - */ -HAL_Bool HAL_SetNotifierThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status); - /** * Sets the name of a notifier. * diff --git a/hal/src/main/native/include/wpi/hal/Threads.h b/hal/src/main/native/include/wpi/hal/Threads.h index 3ae46ac410..106c999920 100644 --- a/hal/src/main/native/include/wpi/hal/Threads.h +++ b/hal/src/main/native/include/wpi/hal/Threads.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "wpi/hal/Types.h" /** @@ -19,58 +21,50 @@ extern "C" { #endif /** - * Gets the thread priority for the specified thread. + * Gets the specified thread's priority. * - * @param[in] handle Native handle pointer to the thread to get the - * priority for. - * @param[out] isRealTime Set to true if thread is real-time, otherwise false. - * @param[out] status Error status variable. 0 on success. - * @return The current thread priority. For real-time, this is 1-99 with 99 - * being highest. For non-real-time, this is 0. See "man 7 sched" for - * details. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param[in] handle Native thread handle. + * @param[out] priority The specified thread's priority. + * @return Error status variable. 0 on success. */ -int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime, - int32_t* status); +HAL_Status HAL_GetThreadPriority(NativeThreadHandle handle, int32_t* priority); /** - * Gets the thread priority for the current thread. + * Gets the current thread's priority. * - * @param[out] isRealTime Set to true if thread is real-time, otherwise false. - * @param[out] status Error status variable. 0 on success. - * @return The current thread priority. For real-time, this is 1-99 with 99 - * being highest. For non-real-time, this is 0. See "man 7 sched" for - * details. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param[out] priority The current thread's priority. + * @return Error status variable. 0 on success. */ -int32_t HAL_GetCurrentThreadPriority(HAL_Bool* isRealTime, int32_t* status); +HAL_Status HAL_GetCurrentThreadPriority(int32_t* priority); /** - * Sets the thread priority for the specified thread. + * Sets the specified thread's priority. * - * @param[in] handle Reference to the thread to set the priority of. - * @param[in] realTime Set to true to set a real-time priority, false for - * standard priority. - * @param[in] priority Priority to set the thread to. For real-time, this is - * 1-99 with 99 being highest. For non-real-time, this is - * forced to 0. See "man 7 sched" for more details. - * @param[out] status Error status variable. 0 on success. - * @return True on success. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param[in] handle The native thread handle. + * @param[in] priority The priority. + * @return Error status variable. 0 on success. */ -HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime, - int32_t priority, int32_t* status); +HAL_Status HAL_SetThreadPriority(NativeThreadHandle handle, int32_t priority); /** - * Sets the thread priority for the current thread. + * Sets the current thread's priority. * - * @param[in] realTime Set to true to set a real-time priority, false for - * standard priority. - * @param[in] priority Priority to set the thread to. For real-time, this is - * 1-99 with 99 being highest. For non-real-time, this is - * forced to 0. See "man 7 sched" for more details. - * @param[out] status Error status variable. 0 on success. - * @return True on success. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param[in] priority The priority. + * @return Error status variable. 0 on success. */ -HAL_Bool HAL_SetCurrentThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status); +HAL_Status HAL_SetCurrentThreadPriority(int32_t priority); #ifdef __cplusplus } // extern "C" diff --git a/hal/src/main/native/sim/Notifier.cpp b/hal/src/main/native/sim/Notifier.cpp index c079c8ddbc..e7f7066cc0 100644 --- a/hal/src/main/native/sim/Notifier.cpp +++ b/hal/src/main/native/sim/Notifier.cpp @@ -224,12 +224,6 @@ HAL_NotifierHandle HAL_CreateNotifier(int32_t* status) { return handle; } -HAL_Bool HAL_SetNotifierThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status) { - auto native = notifierInstance->owner.GetNativeThreadHandle(); - return HAL_SetThreadPriority(&native, realTime, priority, status); -} - void HAL_SetNotifierName(HAL_NotifierHandle notifierHandle, const WPI_String* name, int32_t* status) { auto thr = notifierInstance->owner.GetThread(); diff --git a/hal/src/main/native/sim/Threads.cpp b/hal/src/main/native/sim/Threads.cpp index bd982bdec6..37e504b685 100644 --- a/hal/src/main/native/sim/Threads.cpp +++ b/hal/src/main/native/sim/Threads.cpp @@ -4,22 +4,28 @@ #include "wpi/hal/Threads.h" +#include + +#include "wpi/hal/Types.h" + namespace wpi::hal::init { void InitializeThreads() {} } // namespace wpi::hal::init -int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime, - int32_t* status) { +HAL_Status HAL_GetThreadPriority(NativeThreadHandle handle, int32_t* priority) { + *priority = 0; return 0; } -int32_t HAL_GetCurrentThreadPriority(HAL_Bool* isRealTime, int32_t* status) { + +HAL_Status HAL_GetCurrentThreadPriority(int32_t* priority) { + *priority = 0; return 0; } -HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime, - int32_t priority, int32_t* status) { - return true; + +HAL_Status HAL_SetThreadPriority(NativeThreadHandle handle, int32_t priority) { + return 0; } -HAL_Bool HAL_SetCurrentThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status) { - return true; + +HAL_Status HAL_SetCurrentThreadPriority(int32_t priority) { + return 0; } diff --git a/hal/src/main/native/systemcore/CAN.cpp b/hal/src/main/native/systemcore/CAN.cpp index a7956f4e61..9583493551 100644 --- a/hal/src/main/native/systemcore/CAN.cpp +++ b/hal/src/main/native/systemcore/CAN.cpp @@ -149,9 +149,7 @@ void CANStreamStorage::CheckFrame(const HAL_CANStreamMessage& message) { bool SocketCanState::InitializeBuses() { bool success = true; readLoopRunner.ExecSync([this, &success](wpi::net::uv::Loop& loop) { - int32_t status = 0; - HAL_SetCurrentThreadPriority(true, 50, &status); - if (status != 0) { + if (HAL_SetCurrentThreadPriority(50) != 0) { wpi::util::print("Failed to set CAN thread priority\n"); } diff --git a/hal/src/main/native/systemcore/Notifier.cpp b/hal/src/main/native/systemcore/Notifier.cpp index 839204aa68..f80e220004 100644 --- a/hal/src/main/native/systemcore/Notifier.cpp +++ b/hal/src/main/native/systemcore/Notifier.cpp @@ -20,6 +20,7 @@ #include "wpi/hal/handles/UnlimitedHandleResource.hpp" #include "wpi/util/SafeThread.hpp" #include "wpi/util/Synchronization.hpp" +#include "wpi/util/print.hpp" #include "wpi/util/priority_queue.hpp" #include "wpi/util/string.hpp" @@ -74,6 +75,10 @@ void InitializeNotifier() { } // namespace wpi::hal::init void NotifierThread::Main() { + if (HAL_SetCurrentThreadPriority(40) != 0) { + wpi::util::print("Failed to set HAL Notifier thread priority\n"); + } + std::unique_lock lock(m_mutex); while (m_active) { if (m_alarmQueue.empty()) { @@ -150,12 +155,6 @@ HAL_NotifierHandle HAL_CreateNotifier(int32_t* status) { return handle; } -HAL_Bool HAL_SetNotifierThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status) { - auto native = notifierInstance->owner.GetNativeThreadHandle(); - return HAL_SetThreadPriority(&native, realTime, priority, status); -} - void HAL_SetNotifierName(HAL_NotifierHandle notifierHandle, const WPI_String* name, int32_t* status) { auto thr = notifierInstance->owner.GetThread(); diff --git a/hal/src/main/native/systemcore/Threads.cpp b/hal/src/main/native/systemcore/Threads.cpp index dd1a5ab6f8..1da3ad9c7d 100644 --- a/hal/src/main/native/systemcore/Threads.cpp +++ b/hal/src/main/native/systemcore/Threads.cpp @@ -4,10 +4,13 @@ #include "wpi/hal/Threads.h" +#include + #include #include #include "wpi/hal/Errors.h" +#include "wpi/hal/Types.h" namespace wpi::hal::init { void InitializeThreads() {} @@ -15,76 +18,55 @@ void InitializeThreads() {} extern "C" { -int32_t HAL_GetThreadPriority(NativeThreadHandle handle, HAL_Bool* isRealTime, - int32_t* status) { +HAL_Status HAL_GetThreadPriority(NativeThreadHandle handle, int32_t* priority) { + if (handle == nullptr) { + return NULL_PARAMETER; + } + sched_param sch; int policy; - int success = pthread_getschedparam( - *reinterpret_cast(handle), &policy, &sch); - if (success == 0) { - *status = 0; - } else { - *status = HAL_THREAD_PRIORITY_ERROR; - return -1; - } - if (policy == SCHED_FIFO || policy == SCHED_RR) { - *isRealTime = true; - return sch.sched_priority; - } else { - *isRealTime = false; - // 0 is the only supported priority for non-real-time + if (pthread_getschedparam(*reinterpret_cast(handle), + &policy, &sch) == 0) { + *priority = sch.sched_priority; return 0; + } else { + return HAL_THREAD_PRIORITY_ERROR; } } -int32_t HAL_GetCurrentThreadPriority(HAL_Bool* isRealTime, int32_t* status) { +HAL_Status HAL_GetCurrentThreadPriority(int32_t* priority) { auto thread = pthread_self(); - return HAL_GetThreadPriority(&thread, isRealTime, status); + return HAL_GetThreadPriority(&thread, priority); } -HAL_Bool HAL_SetThreadPriority(NativeThreadHandle handle, HAL_Bool realTime, - int32_t priority, int32_t* status) { +HAL_Status HAL_SetThreadPriority(NativeThreadHandle handle, int32_t priority) { if (handle == nullptr) { - *status = NULL_PARAMETER; - return false; + return NULL_PARAMETER; } - int scheduler = realTime ? SCHED_FIFO : SCHED_OTHER; - if (realTime) { - // We don't support setting priorities for non RT threads - // so we don't need to check for proper range - if (priority < sched_get_priority_min(scheduler) || - priority > sched_get_priority_max(scheduler)) { - *status = HAL_THREAD_PRIORITY_RANGE_ERROR; - return false; - } + if (priority < 0 || priority > 99) { + return HAL_THREAD_PRIORITY_RANGE_ERROR; } + int scheduler = priority > 0 ? SCHED_RR : SCHED_OTHER; + sched_param sch; int policy; pthread_getschedparam(*reinterpret_cast(handle), &policy, &sch); - if (scheduler == SCHED_FIFO || scheduler == SCHED_RR) { - sch.sched_priority = priority; - } else { - // Only need to set 0 priority for non RT thread - sch.sched_priority = 0; - } + sch.sched_priority = priority; if (pthread_setschedparam(*reinterpret_cast(handle), scheduler, &sch)) { - *status = HAL_THREAD_PRIORITY_ERROR; - return false; + return HAL_THREAD_PRIORITY_ERROR; } else { - *status = 0; - return true; + return 0; } } -HAL_Bool HAL_SetCurrentThreadPriority(HAL_Bool realTime, int32_t priority, - int32_t* status) { +HAL_Status HAL_SetCurrentThreadPriority(int32_t priority) { auto thread = pthread_self(); - return HAL_SetThreadPriority(&thread, realTime, priority, status); + return HAL_SetThreadPriority(&thread, priority); } } // extern "C" diff --git a/hal/src/main/python/semiwrap/Notifier_c.yml b/hal/src/main/python/semiwrap/Notifier_c.yml index 6bb7b0273f..d35d17f3aa 100644 --- a/hal/src/main/python/semiwrap/Notifier_c.yml +++ b/hal/src/main/python/semiwrap/Notifier_c.yml @@ -10,4 +10,3 @@ functions: HAL_CancelNotifierAlarm: HAL_GetNotifierOverrun: HAL_AcknowledgeNotifierAlarm: - HAL_SetNotifierThreadPriority: diff --git a/wpilibc/src/main/native/cpp/system/Notifier.cpp b/wpilibc/src/main/native/cpp/system/Notifier.cpp index 5cb975e56f..03bca34dc6 100644 --- a/wpilibc/src/main/native/cpp/system/Notifier.cpp +++ b/wpilibc/src/main/native/cpp/system/Notifier.cpp @@ -14,56 +14,20 @@ using namespace wpi; -Notifier::Notifier(std::function callback) { - if (!callback) { - throw WPILIB_MakeError(err::NullParameter, "callback"); - } - m_callback = callback; - int32_t status = 0; - m_notifier = HAL_CreateNotifier(&status); - WPILIB_CheckErrorStatus(status, "CreateNotifier"); - - m_thread = std::thread([=, this] { - for (;;) { - int32_t status = 0; - HAL_NotifierHandle notifier = m_notifier.load(); - if (notifier == 0) { - break; - } - if (WPI_WaitForObject(notifier) == 0) { - break; - } - - std::function callback; - { - std::scoped_lock lock(m_processMutex); - callback = m_callback; - } - - // Call callback - if (callback) { - callback(); - } - - // Ack notifier - HAL_AcknowledgeNotifierAlarm(notifier, &status); - WPILIB_CheckErrorStatus(status, "AcknowledgeNotifier"); - } - }); -} - Notifier::Notifier(int priority, std::function callback) { if (!callback) { throw WPILIB_MakeError(err::NullParameter, "callback"); } m_callback = callback; - int32_t status = 0; + HAL_Status status = 0; m_notifier = HAL_CreateNotifier(&status); WPILIB_CheckErrorStatus(status, "InitializeNotifier"); m_thread = std::thread([=, this] { - int32_t status = 0; - HAL_SetCurrentThreadPriority(true, priority, &status); + if (priority > 0 && HAL_SetCurrentThreadPriority(priority) != 0) { + WPILIB_ReportWarning("Setting Notifier priority to {} failed\n", + priority); + } for (;;) { HAL_NotifierHandle notifier = m_notifier.load(); if (notifier == 0) { @@ -99,6 +63,7 @@ Notifier::Notifier(int priority, std::function callback) { } // Ack notifier + HAL_Status status = 0; HAL_AcknowledgeNotifierAlarm(notifier, &status); WPILIB_CheckErrorStatus(status, "AcknowledgeNotifier"); } @@ -170,8 +135,3 @@ int32_t Notifier::GetOverrun() const { WPILIB_CheckErrorStatus(status, "GetNotifierOverrun"); return overrun; } - -bool Notifier::SetHALThreadPriority(bool realTime, int32_t priority) { - int32_t status = 0; - return HAL_SetNotifierThreadPriority(realTime, priority, &status); -} diff --git a/wpilibc/src/main/native/cpp/system/Threads.cpp b/wpilibc/src/main/native/cpp/system/Threads.cpp index 9f90af0459..9f1dcae4ba 100644 --- a/wpilibc/src/main/native/cpp/system/Threads.cpp +++ b/wpilibc/src/main/native/cpp/system/Threads.cpp @@ -9,38 +9,32 @@ namespace wpi { -int GetThreadPriority(std::thread& thread, bool* isRealTime) { - int32_t status = 0; - HAL_Bool rt = false; +int GetThreadPriority(std::thread& thread) { auto native = thread.native_handle(); - auto ret = HAL_GetThreadPriority(&native, &rt, &status); + int32_t priority = 0; + HAL_Status status = HAL_GetThreadPriority(&native, &priority); WPILIB_CheckErrorStatus(status, "GetThreadPriority"); - *isRealTime = rt; - return ret; + return priority; } -int GetCurrentThreadPriority(bool* isRealTime) { - int32_t status = 0; - HAL_Bool rt = false; - auto ret = HAL_GetCurrentThreadPriority(&rt, &status); +int GetCurrentThreadPriority() { + int32_t priority = 0; + HAL_Status status = HAL_GetCurrentThreadPriority(&priority); WPILIB_CheckErrorStatus(status, "GetCurrentThreadPriority"); - *isRealTime = rt; - return ret; + return priority; } -bool SetThreadPriority(std::thread& thread, bool realTime, int priority) { - int32_t status = 0; +bool SetThreadPriority(std::thread& thread, int priority) { auto native = thread.native_handle(); - auto ret = HAL_SetThreadPriority(&native, realTime, priority, &status); + HAL_Status status = HAL_SetThreadPriority(&native, priority); WPILIB_CheckErrorStatus(status, "SetThreadPriority"); - return ret; + return status != 0; } -bool SetCurrentThreadPriority(bool realTime, int priority) { - int32_t status = 0; - auto ret = HAL_SetCurrentThreadPriority(realTime, priority, &status); +bool SetCurrentThreadPriority(int priority) { + HAL_Status status = HAL_SetCurrentThreadPriority(priority); WPILIB_CheckErrorStatus(status, "SetCurrentThreadPriority"); - return ret; + return status != 0; } } // namespace wpi diff --git a/wpilibc/src/main/native/cppcs/RobotBase.cpp b/wpilibc/src/main/native/cppcs/RobotBase.cpp index d5ea33b083..58ae389394 100644 --- a/wpilibc/src/main/native/cppcs/RobotBase.cpp +++ b/wpilibc/src/main/native/cppcs/RobotBase.cpp @@ -24,7 +24,6 @@ #include "wpi/nt/NetworkTableInstance.hpp" #include "wpi/smartdashboard/SmartDashboard.hpp" #include "wpi/system/Errors.hpp" -#include "wpi/system/Notifier.hpp" #include "wpi/system/WPILibVersion.hpp" #include "wpi/util/print.hpp" #include "wpi/util/timestamp.hpp" @@ -51,10 +50,6 @@ int wpi::RunHALInitialization() { HAL_ReportUsage("Language", "C++"); HAL_ReportUsage("WPILibVersion", GetWPILibVersion()); - if (!wpi::Notifier::SetHALThreadPriority(true, 40)) { - WPILIB_ReportWarning("Setting HAL Notifier RT priority to 40 failed\n"); - } - std::puts("\n********** Robot program starting **********"); return 0; } diff --git a/wpilibc/src/main/native/include/wpi/framework/TimesliceRobot.hpp b/wpilibc/src/main/native/include/wpi/framework/TimesliceRobot.hpp index e68904f5ef..21a41c3c8f 100644 --- a/wpilibc/src/main/native/include/wpi/framework/TimesliceRobot.hpp +++ b/wpilibc/src/main/native/include/wpi/framework/TimesliceRobot.hpp @@ -75,7 +75,8 @@ namespace wpi { * If the robot periodic functions and the controller periodic functions have a * lot of scheduling jitter that cause them to occasionally overlap with later * timeslices, consider giving the main robot thread a real-time priority using - * wpi::SetCurrentThreadPriority(). An RT priority of 15 is a reasonable choice. + * wpi::SetCurrentThreadPriority(int). An RT priority of 15 is a reasonable + * choice. * * If you do enable RT though, make sure your periodic functions do not * block. If they do, the operating system will lock up, and you'll have to diff --git a/wpilibc/src/main/native/include/wpi/system/Notifier.hpp b/wpilibc/src/main/native/include/wpi/system/Notifier.hpp index d84b23c02e..169b55750f 100644 --- a/wpilibc/src/main/native/include/wpi/system/Notifier.hpp +++ b/wpilibc/src/main/native/include/wpi/system/Notifier.hpp @@ -36,7 +36,8 @@ class Notifier { * * @param callback The callback to run. */ - explicit Notifier(std::function callback); + explicit Notifier(std::function callback) + : Notifier(0, std::move(callback)) {} template Notifier(std::invocable auto&& callback, Arg&& arg, @@ -140,23 +141,6 @@ class Notifier { */ int32_t GetOverrun() const; - /** - * Sets the HAL notifier thread priority. - * - * The HAL notifier thread is responsible for managing the FPGA's notifier - * interrupt and waking up user's Notifiers when it's their time to run. - * Giving the HAL notifier thread real-time priority helps ensure the user's - * real-time Notifiers, if any, are notified to run in a timely manner. - * - * @param realTime Set to true to set a real-time priority, false for standard - * priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is forced to - * 0. See "man 7 sched" for more details. - * @return True on success. - */ - static bool SetHALThreadPriority(bool realTime, int32_t priority); - private: // The thread waiting on the HAL alarm std::thread m_thread; diff --git a/wpilibc/src/main/native/include/wpi/system/Threads.hpp b/wpilibc/src/main/native/include/wpi/system/Threads.hpp index b434a9a401..d758bc347f 100644 --- a/wpilibc/src/main/native/include/wpi/system/Threads.hpp +++ b/wpilibc/src/main/native/include/wpi/system/Threads.hpp @@ -9,49 +9,59 @@ namespace wpi { /** - * Get the thread priority for the specified thread. + * Gets the specified thread's priority. * - * @param thread Reference to the thread to get the priority for. - * @param isRealTime Set to true if thread is real-time, otherwise false. - * @return The current thread priority. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is 0. See - * "man 7 sched" for details. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param thread The thread. + * @return The specified thread's priority. */ -int GetThreadPriority(std::thread& thread, bool* isRealTime); +int GetThreadPriority(std::thread& thread); /** - * Get the thread priority for the current thread. + * Gets the current thread's priority. * - * @param isRealTime Set to true if thread is real-time, otherwise false. - * @return The current thread priority. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is 0. See - * "man 7 sched" for details. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @return The current thread's priority. */ -int GetCurrentThreadPriority(bool* isRealTime); +int GetCurrentThreadPriority(); /** - * Sets the thread priority for the specified thread. + * Sets the specified thread's priority. * - * @param thread Reference to the thread to set the priority of. - * @param realTime Set to true to set a real-time priority, false for standard - * priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is forced to - * 0. See "man 7 sched" for more details. - * @return True on success. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param thread The thread. + * @param priority The priority. + * @return True on success. + * @deprecated Incorrect usage of real-time priority can lead to system lockups. + * Only use this function if you are trained in real-time software + * development. */ -bool SetThreadPriority(std::thread& thread, bool realTime, int priority); +[[deprecated( + "Incorrect usage of real-time priority can lead to system lockups. Only " + "use this function if you are trained in real-time software development.")]] +bool SetThreadPriority(std::thread& thread, int priority); /** - * Sets the thread priority for the current thread. + * Sets the current thread's priority. * - * @param realTime Set to true to set a real-time priority, false for standard - * priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is forced to - * 0. See "man 7 sched" for more details. - * @return True on success. + * Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, + * and 99 is highest priority. See "man 7 sched" for details. + * + * @param priority The priority. + * @return True on success. + * @deprecated Incorrect usage of real-time priority can lead to system lockups. + * Only use this function if you are trained in real-time software + * development. */ -bool SetCurrentThreadPriority(bool realTime, int priority); +[[deprecated( + "Incorrect usage of real-time priority can lead to system lockups. Only " + "use this function if you are trained in real-time software development.")]] +bool SetCurrentThreadPriority(int priority); } // namespace wpi diff --git a/wpilibc/src/main/python/semiwrap/Notifier.yml b/wpilibc/src/main/python/semiwrap/Notifier.yml index 3f35b07c15..28f4fb2617 100644 --- a/wpilibc/src/main/python/semiwrap/Notifier.yml +++ b/wpilibc/src/main/python/semiwrap/Notifier.yml @@ -19,4 +19,3 @@ classes: wpi::units::second_t: Stop: GetOverrun: - SetHALThreadPriority: diff --git a/wpilibc/src/main/python/wpilib/_impl/start.py b/wpilibc/src/main/python/wpilib/_impl/start.py index 10c6af8086..eba991c0c3 100644 --- a/wpilibc/src/main/python/wpilib/_impl/start.py +++ b/wpilibc/src/main/python/wpilib/_impl/start.py @@ -157,11 +157,6 @@ class RobotStarter: def _start(self, robot_cls: wpilib.RobotBase) -> bool: hal.reportUsage("Language", "Python") - if not wpilib.Notifier.setHALThreadPriority(True, 40): - reportErrorInternal( - "Setting HAL Notifier RT priority to 40 failed", isWarning=True - ) - isSimulation = wpilib.RobotBase.isSimulation() # hack: initialize networktables before creating the robot diff --git a/wpilibc/src/main/python/wpilib/src/rpy/Notifier.cpp b/wpilibc/src/main/python/wpilib/src/rpy/Notifier.cpp index f87728a0c7..1ef0098086 100644 --- a/wpilibc/src/main/python/wpilib/src/rpy/Notifier.cpp +++ b/wpilibc/src/main/python/wpilib/src/rpy/Notifier.cpp @@ -155,8 +155,3 @@ int32_t PyNotifier::GetOverrun() const { WPILIB_CheckErrorStatus(status, "GetNotifierOverrun"); return overrun; } - -bool PyNotifier::SetHALThreadPriority(bool realTime, int32_t priority) { - int32_t status = 0; - return HAL_SetNotifierThreadPriority(realTime, priority, &status); -} diff --git a/wpilibc/src/main/python/wpilib/src/rpy/Notifier.h b/wpilibc/src/main/python/wpilib/src/rpy/Notifier.h index 80e22adc21..d008a819cd 100644 --- a/wpilibc/src/main/python/wpilib/src/rpy/Notifier.h +++ b/wpilibc/src/main/python/wpilib/src/rpy/Notifier.h @@ -101,23 +101,6 @@ class PyNotifier { */ int32_t GetOverrun() const; - /** - * Sets the HAL notifier thread priority. - * - * The HAL notifier thread is responsible for managing the FPGA's notifier - * interrupt and waking up user's Notifiers when it's their time to run. - * Giving the HAL notifier thread real-time priority helps ensure the user's - * real-time Notifiers, if any, are notified to run in a timely manner. - * - * @param realTime Set to true to set a real-time priority, false for standard - * priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 - * with 99 being highest. For non-real-time, this is forced to - * 0. See "man 7 sched" for more details. - * @return True on success. - */ - static bool SetHALThreadPriority(bool realTime, int32_t priority); - private: // The thread waiting on the HAL alarm py::object m_thread; diff --git a/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java b/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java index b4bb63fb52..ea66f5d094 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java +++ b/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java @@ -16,7 +16,6 @@ import org.wpilib.math.util.MathSharedStore; import org.wpilib.networktables.MultiSubscriber; import org.wpilib.networktables.NetworkTableEvent; import org.wpilib.networktables.NetworkTableInstance; -import org.wpilib.system.Notifier; import org.wpilib.system.RuntimeType; import org.wpilib.system.Timer; import org.wpilib.system.WPILibVersion; @@ -413,10 +412,6 @@ public abstract class RobotBase implements AutoCloseable { HAL.reportUsage("Language", "Java"); HAL.reportUsage("WPILibVersion", WPILibVersion.Version); - if (!Notifier.setHALThreadPriority(true, 40)) { - DriverStation.reportWarning("Setting HAL Notifier RT priority to 40 failed", false); - } - if (HAL.hasMain()) { Thread thread = new Thread( diff --git a/wpilibj/src/main/java/org/wpilib/framework/TimesliceRobot.java b/wpilibj/src/main/java/org/wpilib/framework/TimesliceRobot.java index 3644356972..4d98400468 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/TimesliceRobot.java +++ b/wpilibj/src/main/java/org/wpilib/framework/TimesliceRobot.java @@ -64,8 +64,8 @@ package org.wpilib.framework; *

If the robot periodic functions and the controller periodic functions have a lot of scheduling * jitter that cause them to occasionally overlap with later timeslices, consider giving the main * robot thread a real-time priority using {@link - * org.wpilib.system.Threads#setCurrentThreadPriority(boolean,int)}. An RT priority of 15 is a - * reasonable choice. + * org.wpilib.system.Threads#setCurrentThreadPriority(int)}. An RT priority of 15 is a reasonable + * choice. * *

If you do enable RT though, make sure your periodic functions do not block. If they do, * the operating system will lock up, and you'll have to boot the roboRIO into safe mode and delete diff --git a/wpilibj/src/main/java/org/wpilib/system/Notifier.java b/wpilibj/src/main/java/org/wpilib/system/Notifier.java index 8b661030dd..9f8cd4c030 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Notifier.java +++ b/wpilibj/src/main/java/org/wpilib/system/Notifier.java @@ -209,21 +209,4 @@ public class Notifier implements AutoCloseable { public void stop() { NotifierJNI.cancelNotifierAlarm(m_notifier.get(), false); } - - /** - * Sets the HAL notifier thread priority. - * - *

The HAL notifier thread is responsible for managing the FPGA's notifier interrupt and waking - * up user's Notifiers when it's their time to run. Giving the HAL notifier thread real-time - * priority helps ensure the user's real-time Notifiers, if any, are notified to run in a timely - * manner. - * - * @param realTime Set to true to set a real-time priority, false for standard priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being - * highest. For non-real-time, this is forced to 0. See "man 7 sched" for more details. - * @return True on success. - */ - public static boolean setHALThreadPriority(boolean realTime, int priority) { - return NotifierJNI.setHALThreadPriority(realTime, priority); - } } diff --git a/wpilibj/src/main/java/org/wpilib/system/Threads.java b/wpilibj/src/main/java/org/wpilib/system/Threads.java index cad90e7d8b..ca0c70aa7f 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Threads.java +++ b/wpilibj/src/main/java/org/wpilib/system/Threads.java @@ -9,34 +9,31 @@ import org.wpilib.hardware.hal.ThreadsJNI; /** Thread utility functions. */ public final class Threads { /** - * Get the thread priority for the current thread. + * Gets the current thread's priority. * - * @return The current thread priority. For real-time, this is 1-99 with 99 being highest. For - * non-real-time, this is 0. See "man 7 sched" for details. + *

Priorities range from 0 to 99 where 0 is non-real-time, and 1-99 are real-time, and 99 is + * highest priority. See "man 7 sched" for details. + * + * @return The current thread's priority. */ public static int getCurrentThreadPriority() { return ThreadsJNI.getCurrentThreadPriority(); } /** - * Get if the current thread is real-time. + * Sets the current thread's priority. * - * @return If the current thread is real-time. - */ - public static boolean getCurrentThreadIsRealTime() { - return ThreadsJNI.getCurrentThreadIsRealTime(); - } - - /** - * Sets the thread priority for the current thread. + *

Priorities range from 0 to 99 where 0 is non-real-time, 1-99 are real-time, and 99 is + * highest priority. See "man 7 sched" for details. * - * @param realTime Set to true to set a real-time priority, false for standard priority. - * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being - * highest. For non-real-time, this is forced to 0. See "man 7 sched" for details. + * @param priority The priority. * @return True on success. + * @deprecated Incorrect usage of real-time priority can lead to system lockups. Only use this + * function if you are trained in real-time software development. */ - public static boolean setCurrentThreadPriority(boolean realTime, int priority) { - return ThreadsJNI.setCurrentThreadPriority(realTime, priority); + @Deprecated + public static boolean setCurrentThreadPriority(int priority) { + return ThreadsJNI.setCurrentThreadPriority(priority); } private Threads() {}