diff --git a/hal/src/main/native/athena/Interrupts.cpp b/hal/src/main/native/athena/Interrupts.cpp index b9991e07e5..01b8a795d9 100644 --- a/hal/src/main/native/athena/Interrupts.cpp +++ b/hal/src/main/native/athena/Interrupts.cpp @@ -22,12 +22,6 @@ using namespace hal; namespace { - -struct Interrupt { - std::unique_ptr anInterrupt; - std::unique_ptr manager; -}; - // Safe thread to allow callbacks to run on their own thread class InterruptThread : public wpi::SafeThread { public: @@ -76,6 +70,13 @@ static void threadedInterruptHandler(uint32_t mask, void* param) { static_cast(param)->Notify(mask); } +struct Interrupt { + std::unique_ptr anInterrupt; + std::unique_ptr manager; + std::unique_ptr threadOwner = nullptr; + void* param = nullptr; +}; + static LimitedHandleResource* interruptHandles; @@ -110,8 +111,16 @@ HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher, return handle; } -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, int32_t* status) { +void* HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, + int32_t* status) { + auto anInterrupt = interruptHandles->Get(interruptHandle); interruptHandles->Free(interruptHandle); + if (anInterrupt == nullptr) { + return nullptr; + } + anInterrupt->manager->enable(status); + void* param = anInterrupt->param; + return param; } /** @@ -239,21 +248,29 @@ void HAL_AttachInterruptHandler(HAL_InterruptHandle interruptHandle, return; } anInterrupt->manager->registerHandler(handler, param, status); + anInterrupt->param = param; } void HAL_AttachInterruptHandlerThreaded(HAL_InterruptHandle interrupt_handle, HAL_InterruptHandlerFunction handler, void* param, int32_t* status) { - InterruptThreadOwner* intr = new InterruptThreadOwner; - intr->Start(); - intr->SetFunc(handler, param); + auto anInterrupt = interruptHandles->Get(interrupt_handle); + if (anInterrupt == nullptr) { + *status = HAL_HANDLE_ERROR; + return; + } - HAL_AttachInterruptHandler(interrupt_handle, threadedInterruptHandler, intr, - status); + anInterrupt->threadOwner = std::make_unique(); + anInterrupt->threadOwner->Start(); + anInterrupt->threadOwner->SetFunc(handler, param); + + HAL_AttachInterruptHandler(interrupt_handle, threadedInterruptHandler, + anInterrupt->threadOwner.get(), status); if (*status != 0) { - delete intr; + anInterrupt->threadOwner = nullptr; } + anInterrupt->param = param; } void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle, diff --git a/hal/src/main/native/cpp/jni/InterruptJNI.cpp b/hal/src/main/native/cpp/jni/InterruptJNI.cpp index 84bf58ed05..176f8e5f71 100644 --- a/hal/src/main/native/cpp/jni/InterruptJNI.cpp +++ b/hal/src/main/native/cpp/jni/InterruptJNI.cpp @@ -156,7 +156,11 @@ Java_edu_wpi_first_wpilibj_hal_InterruptJNI_cleanInterrupts << "Interrupt Handle = " << (HAL_InterruptHandle)interruptHandle; int32_t status = 0; - HAL_CleanInterrupts((HAL_InterruptHandle)interruptHandle, &status); + auto param = + HAL_CleanInterrupts((HAL_InterruptHandle)interruptHandle, &status); + if (param) { + delete static_cast(param); + } INTERRUPTJNI_LOG(logDEBUG) << "Status = " << status; diff --git a/hal/src/main/native/include/HAL/Interrupts.h b/hal/src/main/native/include/HAL/Interrupts.h index db522f955f..afdb4b7b8b 100644 --- a/hal/src/main/native/include/HAL/Interrupts.h +++ b/hal/src/main/native/include/HAL/Interrupts.h @@ -20,7 +20,7 @@ typedef void (*HAL_InterruptHandlerFunction)(uint32_t interruptAssertedMask, void* param); HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher, int32_t* status); -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, int32_t* status); +void* HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, int32_t* status); int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle, double timeout, HAL_Bool ignorePrevious, diff --git a/hal/src/main/native/sim/Interrupts.cpp b/hal/src/main/native/sim/Interrupts.cpp index c4ee964108..566a0d3db3 100644 --- a/hal/src/main/native/sim/Interrupts.cpp +++ b/hal/src/main/native/sim/Interrupts.cpp @@ -105,10 +105,15 @@ HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher, return handle; } -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, int32_t* status) { +void* HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, + int32_t* status) { HAL_DisableInterrupts(interruptHandle, status); - auto interrupt = interruptHandles->Get(interruptHandle); + auto anInterrupt = interruptHandles->Get(interruptHandle); interruptHandles->Free(interruptHandle); + if (anInterrupt == nullptr) { + return nullptr; + } + return anInterrupt->callbackParam; } static void ProcessInterruptDigitalSynchronous(const char* name, void* param,