mirror of https://github.com/ARMmbed/mbed-os.git
Fix potential race condition in critical section HAL API
Call underlying HAL implementation to enter critical section/disable interrupts before incrementing the global critical section counter. Modify HAL implementations to track first entrances to the critical section and only update the saved state on first enter.pull/5346/head
parent
a07c07fa63
commit
e14bee5209
|
@ -28,11 +28,13 @@ static union {
|
|||
} _state = {0};
|
||||
|
||||
static bool _use_softdevice_routine = false;
|
||||
static bool _state_saved = false;
|
||||
|
||||
void hal_critical_section_enter(void)
|
||||
{
|
||||
// Fetch the current state of interrupts
|
||||
uint32_t primask = __get_PRIMASK();
|
||||
uint8_t temp_state = 0;
|
||||
|
||||
// If interrupts are enabled, try to use the soft device
|
||||
uint8_t sd_enabled;
|
||||
|
@ -40,8 +42,12 @@ void hal_critical_section_enter(void)
|
|||
(sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) &&
|
||||
(sd_enabled == 1)) {
|
||||
// If the softdevice can be used, use it.
|
||||
sd_nvic_critical_region_enter(&_state._sd_state);
|
||||
sd_nvic_critical_region_enter(&temp_state);
|
||||
_use_softdevice_routine = true;
|
||||
|
||||
if (_state_saved == false) {
|
||||
_state._sd_state = temp_state;
|
||||
}
|
||||
} else {
|
||||
// If interrupts are enabled, disable them.
|
||||
if (primask == 0) {
|
||||
|
@ -50,13 +56,20 @@ void hal_critical_section_enter(void)
|
|||
|
||||
// Store PRIMASK state, it will be restored when exiting critical
|
||||
// section.
|
||||
_state._PRIMASK_state = primask;
|
||||
_use_softdevice_routine = false;
|
||||
|
||||
if (_state_saved == false) {
|
||||
_state._PRIMASK_state = primask;
|
||||
}
|
||||
}
|
||||
|
||||
_state_saved = true;
|
||||
}
|
||||
|
||||
void hal_critical_section_exit(void)
|
||||
{
|
||||
_state_saved = false;
|
||||
|
||||
// Restore the state as it was prior to entering the critical section.
|
||||
if (_use_softdevice_routine) {
|
||||
sd_nvic_critical_region_exit(_state._sd_state)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
static volatile bool critical_interrupts_enabled = false;
|
||||
static volatile bool state_saved = false;
|
||||
|
||||
static bool are_interrupts_enabled(void)
|
||||
{
|
||||
|
@ -34,17 +35,25 @@ static bool are_interrupts_enabled(void)
|
|||
|
||||
MBED_WEAK void hal_critical_section_enter(void)
|
||||
{
|
||||
critical_interrupts_enabled = are_interrupts_enabled();
|
||||
const bool interrupt_state = are_interrupts_enabled();
|
||||
|
||||
__disable_irq();
|
||||
}
|
||||
|
||||
if (state_saved == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
critical_interrupts_enabled = interrupt_state;
|
||||
state_saved = true;
|
||||
}
|
||||
|
||||
MBED_WEAK void hal_critical_section_exit()
|
||||
{
|
||||
// Interrupts must be disabled on invoking an exit from a critical section
|
||||
MBED_ASSERT(!are_interrupts_enabled());
|
||||
|
||||
state_saved = false;
|
||||
|
||||
// Restore the IRQs to their state prior to entering the critical section
|
||||
if (critical_interrupts_enabled == true) {
|
||||
__enable_irq();
|
||||
|
|
|
@ -66,11 +66,9 @@ void core_util_critical_section_enter(void)
|
|||
MBED_ASSERT(critical_section_reentrancy_counter < UINT32_MAX);
|
||||
#endif /* FEATURE_UVISOR */
|
||||
|
||||
if (critical_section_reentrancy_counter == 0) {
|
||||
hal_critical_section_enter();
|
||||
}
|
||||
hal_critical_section_enter();
|
||||
|
||||
critical_section_reentrancy_counter++;
|
||||
++critical_section_reentrancy_counter;
|
||||
}
|
||||
|
||||
void core_util_critical_section_exit(void)
|
||||
|
@ -85,7 +83,7 @@ void core_util_critical_section_exit(void)
|
|||
return;
|
||||
}
|
||||
|
||||
critical_section_reentrancy_counter--;
|
||||
--critical_section_reentrancy_counter;
|
||||
|
||||
if (critical_section_reentrancy_counter == 0) {
|
||||
hal_critical_section_exit();
|
||||
|
|
|
@ -16,16 +16,28 @@
|
|||
*/
|
||||
#include "nrf_nvic.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h> // uint32_t, UINT32_MAX
|
||||
|
||||
static uint8_t _sd_state = 0;
|
||||
static volatile bool _state_saved = false;
|
||||
|
||||
void hal_critical_section_enter(void)
|
||||
{
|
||||
sd_nvic_critical_region_enter(&_sd_state);
|
||||
uint8_t temp_state = 0;
|
||||
sd_nvic_critical_region_enter(&temp_state);
|
||||
|
||||
if (_state_saved == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
_sd_state = temp_state;
|
||||
_state_saved = true;
|
||||
}
|
||||
|
||||
void hal_critical_section_exit(void)
|
||||
{
|
||||
_state_saved = false;
|
||||
|
||||
sd_nvic_critical_region_exit(_sd_state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue