diff --git a/hal/build.gradle b/hal/build.gradle index d5af97f0ae..d697b4b303 100644 --- a/hal/build.gradle +++ b/hal/build.gradle @@ -18,6 +18,7 @@ model { binaries.all { tasks.withType(CppCompile) { cppCompiler.args "-DNAMESPACED_PRIORITY" + cppCompiler.args "-DCONFIG_ATHENA" addNiLibraryLinks(linker, targetPlatform) addWpiUtilLibraryLinks(it, linker, targetPlatform) } diff --git a/hal/include/HAL/handles/DigitalHandleResource.h b/hal/include/HAL/handles/DigitalHandleResource.h index ebe573cab7..c23db0afb3 100644 --- a/hal/include/HAL/handles/DigitalHandleResource.h +++ b/hal/include/HAL/handles/DigitalHandleResource.h @@ -33,7 +33,7 @@ namespace hal { * */ template -class DigitalHandleResource { +class DigitalHandleResource : public HandleBase { friend class DigitalHandleResourceTest; public: @@ -44,6 +44,7 @@ class DigitalHandleResource { THandle Allocate(int16_t index, HAL_HandleEnum enumValue, int32_t* status); std::shared_ptr Get(THandle handle, HAL_HandleEnum enumValue); void Free(THandle handle, HAL_HandleEnum enumValue); + void ResetHandles() override; private: std::array, size> m_structures; @@ -65,14 +66,14 @@ THandle DigitalHandleResource::Allocate( return HAL_kInvalidHandle; } m_structures[index] = std::make_shared(); - return static_cast(hal::createHandle(index, enumValue)); + return static_cast(hal::createHandle(index, enumValue, m_version)); } template std::shared_ptr DigitalHandleResource::Get( THandle handle, HAL_HandleEnum enumValue) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) { return nullptr; } @@ -86,10 +87,19 @@ template void DigitalHandleResource::Free( THandle handle, HAL_HandleEnum enumValue) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) return; // lock and deallocated handle std::lock_guard sync(m_handleMutexes[index]); m_structures[index].reset(); } + +template +void DigitalHandleResource::ResetHandles() { + for (int i = 0; i < size; i++) { + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i].reset(); + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/include/HAL/handles/HandlesInternal.h b/hal/include/HAL/handles/HandlesInternal.h index 27596dc3ee..9858564c46 100644 --- a/hal/include/HAL/handles/HandlesInternal.h +++ b/hal/include/HAL/handles/HandlesInternal.h @@ -13,7 +13,7 @@ /* General Handle Data Layout * Bits 0-15: Handle Index - * Bits 16-23: Unused + * Bits 16-23: 8 bit rolling reset detection * Bits 24-30: Handle Type * Bit 31: 1 if handle error, 0 if no error * @@ -23,6 +23,19 @@ namespace hal { +class HandleBase { + public: + HandleBase(); + ~HandleBase(); + HandleBase(const HandleBase&) = delete; + HandleBase& operator=(const HandleBase&) = delete; + virtual void ResetHandles(); + static void ResetGlobalHandles(); + + protected: + int16_t m_version; +}; + constexpr int16_t InvalidHandleIndex = -1; enum class HAL_HandleEnum { @@ -57,9 +70,16 @@ static inline HAL_HandleEnum getHandleType(HAL_Handle handle) { static inline bool isHandleType(HAL_Handle handle, HAL_HandleEnum handleType) { return handleType == getHandleType(handle); } +static inline bool isHandleCorrectVersion(HAL_Handle handle, int16_t version) { + return (((handle & 0xFF0000) >> 16) & version) == version; +} static inline int16_t getHandleTypedIndex(HAL_Handle handle, - HAL_HandleEnum enumType) { + HAL_HandleEnum enumType, + int16_t version) { if (!isHandleType(handle, enumType)) return InvalidHandleIndex; +#if !defined(CONFIG_ATHENA) + if (!isHandleCorrectVersion(handle, version)) return InvalidHandleIndex; +#endif return getHandleIndex(handle); } @@ -94,5 +114,6 @@ HAL_PortHandle createPortHandle(uint8_t channel, uint8_t module); HAL_PortHandle createPortHandleForSPI(uint8_t channel); -HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType); +HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType, + int16_t version); } // namespace hal diff --git a/hal/include/HAL/handles/IndexedClassedHandleResource.h b/hal/include/HAL/handles/IndexedClassedHandleResource.h index 8316ea186f..057b7ebe7a 100644 --- a/hal/include/HAL/handles/IndexedClassedHandleResource.h +++ b/hal/include/HAL/handles/IndexedClassedHandleResource.h @@ -35,7 +35,7 @@ namespace hal { */ template -class IndexedClassedHandleResource { +class IndexedClassedHandleResource : public HandleBase { friend class IndexedClassedHandleResourceTest; public: @@ -50,9 +50,8 @@ class IndexedClassedHandleResource { void Free(THandle handle); private: - // Dynamic array to shrink HAL file size. - std::unique_ptr[]> m_structures; - std::unique_ptr m_handleMutexes; + std::array[], size> m_structures; + std::array m_handleMutexes; }; template ::Allocate( return HAL_kInvalidHandle; } m_structures[index] = toSet; - return static_cast(hal::createHandle(index, enumValue)); + return static_cast(hal::createHandle(index, enumValue, m_version)); } template IndexedClassedHandleResource< THandle, TStruct, size, enumValue>::Get(THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) { return nullptr; } @@ -103,10 +102,21 @@ template ::Free( THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) return; // lock and deallocated handle std::lock_guard sync(m_handleMutexes[index]); m_structures[index].reset(); } + +template +void IndexedClassedHandleResource::ResetHandles() { + for (int i = 0; i < size; i++) { + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i].reset(); + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/include/HAL/handles/IndexedHandleResource.h b/hal/include/HAL/handles/IndexedHandleResource.h index 4b36e86d30..fa0c2b1d1d 100644 --- a/hal/include/HAL/handles/IndexedHandleResource.h +++ b/hal/include/HAL/handles/IndexedHandleResource.h @@ -34,7 +34,7 @@ namespace hal { */ template -class IndexedHandleResource { +class IndexedHandleResource : public HandleBase { friend class IndexedHandleResourceTest; public: @@ -45,6 +45,7 @@ class IndexedHandleResource { THandle Allocate(int16_t index, int32_t* status); std::shared_ptr Get(THandle handle); void Free(THandle handle); + void ResetHandles() override; private: std::array, size> m_structures; @@ -67,7 +68,7 @@ THandle IndexedHandleResource::Allocate( return HAL_kInvalidHandle; } m_structures[index] = std::make_shared(); - return static_cast(hal::createHandle(index, enumValue)); + return static_cast(hal::createHandle(index, enumValue, m_version)); } template IndexedHandleResource::Get(THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) { return nullptr; } @@ -90,10 +91,20 @@ template ::Free( THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) return; // lock and deallocated handle std::lock_guard sync(m_handleMutexes[index]); m_structures[index].reset(); } + +template +void IndexedHandleResource::ResetHandles() { + for (int i = 0; i < size; i++) { + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i].reset(); + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/include/HAL/handles/LimitedClassedHandleResource.h b/hal/include/HAL/handles/LimitedClassedHandleResource.h index 419dd95a1d..31537cc593 100644 --- a/hal/include/HAL/handles/LimitedClassedHandleResource.h +++ b/hal/include/HAL/handles/LimitedClassedHandleResource.h @@ -32,7 +32,7 @@ namespace hal { */ template -class LimitedClassedHandleResource { +class LimitedClassedHandleResource : public HandleBase { friend class LimitedClassedHandleResourceTest; public: @@ -44,6 +44,7 @@ class LimitedClassedHandleResource { THandle Allocate(std::shared_ptr toSet); std::shared_ptr Get(THandle handle); void Free(THandle handle); + void ResetHandles() override; private: std::array, size> m_structures; @@ -64,7 +65,7 @@ LimitedClassedHandleResource::Allocate( // and allocate it. std::lock_guard sync(m_handleMutexes[i]); m_structures[i] = toSet; - return static_cast(createHandle(i, enumValue)); + return static_cast(createHandle(i, enumValue, m_version)); } } return HAL_kInvalidHandle; @@ -75,7 +76,7 @@ template LimitedClassedHandleResource< THandle, TStruct, size, enumValue>::Get(THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) { return nullptr; } @@ -90,11 +91,25 @@ template ::Free( THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) return; // lock and deallocated handle std::lock_guard sync(m_allocateMutex); std::lock_guard lock(m_handleMutexes[index]); m_structures[index].reset(); } + +template +void LimitedClassedHandleResource::ResetHandles() { + { + std::lock_guard lock(m_allocateMutex); + for (int i = 0; i < size; i++) { + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i].reset(); + } + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/include/HAL/handles/LimitedHandleResource.h b/hal/include/HAL/handles/LimitedHandleResource.h index eb20cce874..7effac7ab9 100644 --- a/hal/include/HAL/handles/LimitedHandleResource.h +++ b/hal/include/HAL/handles/LimitedHandleResource.h @@ -31,7 +31,7 @@ namespace hal { */ template -class LimitedHandleResource { +class LimitedHandleResource : public HandleBase { friend class LimitedHandleResourceTest; public: @@ -42,6 +42,7 @@ class LimitedHandleResource { THandle Allocate(); std::shared_ptr Get(THandle handle); void Free(THandle handle); + void ResetHandles() override; private: std::array, size> m_structures; @@ -60,7 +61,7 @@ THandle LimitedHandleResource::Allocate() { // and allocate it. std::lock_guard sync(m_handleMutexes[i]); m_structures[i] = std::make_shared(); - return static_cast(createHandle(i, enumValue)); + return static_cast(createHandle(i, enumValue, m_version)); } } return HAL_kInvalidHandle; @@ -71,7 +72,7 @@ template LimitedHandleResource::Get(THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) { return nullptr; } @@ -86,11 +87,24 @@ template ::Free( THandle handle) { // get handle index, and fail early if index out of range or wrong handle - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); if (index < 0 || index >= size) return; // lock and deallocated handle std::lock_guard sync(m_allocateMutex); std::lock_guard lock(m_handleMutexes[index]); m_structures[index].reset(); } + +template +void LimitedHandleResource::ResetHandles() { + { + std::lock_guard lock(m_allocateMutex); + for (int i = 0; i < size; i++) { + std::lock_guard sync(m_handleMutexes[i]); + m_structures[i].reset(); + } + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/include/HAL/handles/UnlimitedHandleResource.h b/hal/include/HAL/handles/UnlimitedHandleResource.h index ba93176b8b..b93bf16316 100644 --- a/hal/include/HAL/handles/UnlimitedHandleResource.h +++ b/hal/include/HAL/handles/UnlimitedHandleResource.h @@ -33,7 +33,7 @@ namespace hal { * */ template -class UnlimitedHandleResource { +class UnlimitedHandleResource : public HandleBase { friend class UnlimitedHandleResourceTest; public: @@ -44,6 +44,7 @@ class UnlimitedHandleResource { THandle Allocate(std::shared_ptr structure); std::shared_ptr Get(THandle handle); void Free(THandle handle); + void ResetHandles() override; private: std::vector> m_structures; @@ -58,19 +59,20 @@ THandle UnlimitedHandleResource::Allocate( for (i = 0; i < m_structures.size(); i++) { if (m_structures[i] == nullptr) { m_structures[i] = structure; - return static_cast(createHandle(i, enumValue)); + return static_cast(createHandle(i, enumValue, m_version)); } } if (i >= INT16_MAX) return HAL_kInvalidHandle; m_structures.push_back(structure); - return static_cast(createHandle(static_cast(i), enumValue)); + return static_cast( + createHandle(static_cast(i), enumValue, m_version)); } template std::shared_ptr UnlimitedHandleResource::Get(THandle handle) { - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); std::lock_guard sync(m_handleMutex); if (index < 0 || index >= static_cast(m_structures.size())) return nullptr; @@ -80,9 +82,20 @@ UnlimitedHandleResource::Get(THandle handle) { template void UnlimitedHandleResource::Free( THandle handle) { - int16_t index = getHandleTypedIndex(handle, enumValue); + int16_t index = getHandleTypedIndex(handle, enumValue, m_version); std::lock_guard sync(m_handleMutex); if (index < 0 || index >= static_cast(m_structures.size())) return; m_structures[index].reset(); } + +template +void UnlimitedHandleResource::ResetHandles() { + { + std::lock_guard lock(m_handleMutex); + for (size_t i = 0; i < m_structures.size(); i++) { + m_structures[i].reset(); + } + } + HandleBase::ResetHandles(); +} } // namespace hal diff --git a/hal/lib/athena/Compressor.cpp b/hal/lib/athena/Compressor.cpp index 210becaca9..5a1b3e4eb0 100644 --- a/hal/lib/athena/Compressor.cpp +++ b/hal/lib/athena/Compressor.cpp @@ -28,7 +28,7 @@ HAL_CompressorHandle HAL_InitializeCompressor(int32_t module, int32_t* status) { // handle with the module number as the index. return (HAL_CompressorHandle)createHandle(static_cast(module), - HAL_HandleEnum::Compressor); + HAL_HandleEnum::Compressor, 0); } HAL_Bool HAL_CheckCompressorModule(int32_t module) { @@ -38,7 +38,7 @@ HAL_Bool HAL_CheckCompressorModule(int32_t module) { HAL_Bool HAL_GetCompressor(HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -53,7 +53,7 @@ HAL_Bool HAL_GetCompressor(HAL_CompressorHandle compressorHandle, void HAL_SetCompressorClosedLoopControl(HAL_CompressorHandle compressorHandle, HAL_Bool value, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return; @@ -65,7 +65,7 @@ void HAL_SetCompressorClosedLoopControl(HAL_CompressorHandle compressorHandle, HAL_Bool HAL_GetCompressorClosedLoopControl( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -80,7 +80,7 @@ HAL_Bool HAL_GetCompressorClosedLoopControl( HAL_Bool HAL_GetCompressorPressureSwitch(HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -95,7 +95,7 @@ HAL_Bool HAL_GetCompressorPressureSwitch(HAL_CompressorHandle compressorHandle, double HAL_GetCompressorCurrent(HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return 0; @@ -109,7 +109,7 @@ double HAL_GetCompressorCurrent(HAL_CompressorHandle compressorHandle, HAL_Bool HAL_GetCompressorCurrentTooHighFault( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -123,7 +123,7 @@ HAL_Bool HAL_GetCompressorCurrentTooHighFault( HAL_Bool HAL_GetCompressorCurrentTooHighStickyFault( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -137,7 +137,7 @@ HAL_Bool HAL_GetCompressorCurrentTooHighStickyFault( HAL_Bool HAL_GetCompressorShortedStickyFault( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -151,7 +151,7 @@ HAL_Bool HAL_GetCompressorShortedStickyFault( HAL_Bool HAL_GetCompressorShortedFault(HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -165,7 +165,7 @@ HAL_Bool HAL_GetCompressorShortedFault(HAL_CompressorHandle compressorHandle, HAL_Bool HAL_GetCompressorNotConnectedStickyFault( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; @@ -179,7 +179,7 @@ HAL_Bool HAL_GetCompressorNotConnectedStickyFault( HAL_Bool HAL_GetCompressorNotConnectedFault( HAL_CompressorHandle compressorHandle, int32_t* status) { int16_t index = - getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor); + getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0); if (index == InvalidHandleIndex) { *status = HAL_HANDLE_ERROR; return false; diff --git a/hal/lib/shared/handles/HandlesInternal.cpp b/hal/lib/shared/handles/HandlesInternal.cpp index 26441d3748..a1e9c2e5f7 100644 --- a/hal/lib/shared/handles/HandlesInternal.cpp +++ b/hal/lib/shared/handles/HandlesInternal.cpp @@ -7,7 +7,51 @@ #include "HAL/handles/HandlesInternal.h" +#include + +#include "HAL/cpp/priority_mutex.h" +#include "llvm/SmallVector.h" + namespace hal { +static llvm::SmallVector globalHandles; +static priority_mutex globalHandleMutex; + +HandleBase::HandleBase() { + std::lock_guard lock(globalHandleMutex); + auto index = std::find(globalHandles.begin(), globalHandles.end(), this); + if (index == globalHandles.end()) { + globalHandles.push_back(this); + } else { + *index = this; + } +} + +HandleBase::~HandleBase() { + std::lock_guard lock(globalHandleMutex); + auto index = std::find(globalHandles.begin(), globalHandles.end(), this); + if (index != globalHandles.end()) { + *index = nullptr; + } +} + +void HandleBase::ResetHandles() { + m_version++; + if (m_version > 255) { + m_version = 0; + } +} + +void HandleBase::ResetGlobalHandles() { + std::unique_lock lock(globalHandleMutex); + for (auto&& i : globalHandles) { + if (i != nullptr) { + lock.unlock(); + i->ResetHandles(); + lock.lock(); + } + } +} + HAL_PortHandle createPortHandle(uint8_t channel, uint8_t module) { // set last 8 bits, then shift to first 8 bits HAL_PortHandle handle = static_cast(HAL_HandleEnum::Port); @@ -36,13 +80,16 @@ HAL_PortHandle createPortHandleForSPI(uint8_t channel) { return handle; } -HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType) { +HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType, + int16_t version) { if (index < 0) return HAL_kInvalidHandle; uint8_t hType = static_cast(handleType); if (hType == 0 || hType > 127) return HAL_kInvalidHandle; // set last 8 bits, then shift to first 8 bits HAL_Handle handle = hType; - handle = handle << 24; + handle = handle << 8; + handle += static_cast(version); + handle = handle << 16; // add index to set last 16 bits handle += index; return handle;