Disable interrupts first when idling core #1883

Merged
GUVWAF merged 1 commits from disableInterrupts into master 2023-12-05 22:53:41 +03:00
GUVWAF commented 2023-12-05 20:53:14 +03:00 (Migrated from github.com)

I encountered an issue similar to the one in #1868, but this one is way more unlikely to happen. I believe what happens is similar to what you suspected in https://github.com/earlephilhower/arduino-pico/issues/1868#issuecomment-1836761063. When core0 wants to idle core1, it waits forever in while (!__otherCoreIdled) since at that time core1 is in an ISR, acquiring a lock (see the callstacks of both cores below). Therefore, I’ve moved portDISABLE_INTERRUPTS up in IdleThisCore and with this it’s been running for 11 hours straight without occurring.
I’m not sure if this guarantees that it cannot happen anymore, but it should at least lower the chance.

Callstack core0:

__freertos_idle_other_core@0x20000120 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/src/variantHooks.cpp:182)
_MFIFO::idleOtherCore@0x10039dc0 (~/.platformio/packages/framework-arduinopico/cores/rp2040/RP2040Support.h:97)
RP2040::idleOtherCore@0x1004cb88 (~/.platformio/packages/framework-arduinopico/cores/rp2040/RP2040Support.h:265)
__wrap_get_rand_64@0x1004cb88 (~/.platformio/packages/framework-arduinopico/cores/rp2040/_freertos.cpp:80)
__wrap_get_rand_32@0x1004cbb6 (~/.platformio/packages/framework-arduinopico/cores/rp2040/_freertos.cpp:92)
igmp_start_timer@0x1005e4ec (Unknown Source:695)
igmp_delaying_member@0x1005e4ec (Unknown Source:718)
igmp_delaying_member@0x1005e4ec (Unknown Source:713)
igmp_input@0x1005e6f2 (/igmp_input.dbgasm:103)
ip4_input@0x1005f45e (/ip4_input.dbgasm:305)
ethernet_input@0x1005f8ba (/ethernet_input.dbgasm:87)
__wrap_cyw43_cb_process_ethernet@0x1009b4de (~/.platformio/packages/framework-arduinopico/cores/rp2040/cyw43_wrappers.cpp:56)
cyw43_ll_process_packets@0x100603b0 (/cyw43_ll_process_packets.dbgasm:29)
cyw43_poll_func@0x100561fc (Unknown Source:238)
cyw43_poll_func@0x100561fc (Unknown Source:219)
cyw43_do_poll@0x100568ae (Unknown Source:90)
async_context_base_execute_once@0x1005722a (/async_context_base_execute_once.dbgasm:28)
process_under_lock@0x10056dfc (Unknown Source:251)
low_priority_irq_handler@0x10056f5e (Unknown Source:293)
<signal handler called>@0xfffffffd (Unknown Source:0)
vTaskSuspendAll@0x10049158 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/tasks.c:2938)

Callstack core1:

vPortRecursiveLock@0x10048ba6 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/portmacro.h:192)
vTaskSwitchContext@0x1004918a (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/tasks.c:3859)
isr_pendsv@0x1004a846 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/port.c:405)
I encountered an issue similar to the one in #1868, but this one is way more unlikely to happen. I believe what happens is similar to what you suspected in https://github.com/earlephilhower/arduino-pico/issues/1868#issuecomment-1836761063. When `core0` wants to idle `core1`, it waits forever in `while (!__otherCoreIdled)` since at that time `core1` is in an ISR, acquiring a lock (see the callstacks of both cores below). Therefore, I’ve moved `portDISABLE_INTERRUPTS` up in `IdleThisCore` and with this it’s been running for 11 hours straight without occurring. I’m not sure if this guarantees that it cannot happen anymore, but it should at least lower the chance. **Callstack `core0`:** ``` __freertos_idle_other_core@0x20000120 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/src/variantHooks.cpp:182) _MFIFO::idleOtherCore@0x10039dc0 (~/.platformio/packages/framework-arduinopico/cores/rp2040/RP2040Support.h:97) RP2040::idleOtherCore@0x1004cb88 (~/.platformio/packages/framework-arduinopico/cores/rp2040/RP2040Support.h:265) __wrap_get_rand_64@0x1004cb88 (~/.platformio/packages/framework-arduinopico/cores/rp2040/_freertos.cpp:80) __wrap_get_rand_32@0x1004cbb6 (~/.platformio/packages/framework-arduinopico/cores/rp2040/_freertos.cpp:92) igmp_start_timer@0x1005e4ec (Unknown Source:695) igmp_delaying_member@0x1005e4ec (Unknown Source:718) igmp_delaying_member@0x1005e4ec (Unknown Source:713) igmp_input@0x1005e6f2 (/igmp_input.dbgasm:103) ip4_input@0x1005f45e (/ip4_input.dbgasm:305) ethernet_input@0x1005f8ba (/ethernet_input.dbgasm:87) __wrap_cyw43_cb_process_ethernet@0x1009b4de (~/.platformio/packages/framework-arduinopico/cores/rp2040/cyw43_wrappers.cpp:56) cyw43_ll_process_packets@0x100603b0 (/cyw43_ll_process_packets.dbgasm:29) cyw43_poll_func@0x100561fc (Unknown Source:238) cyw43_poll_func@0x100561fc (Unknown Source:219) cyw43_do_poll@0x100568ae (Unknown Source:90) async_context_base_execute_once@0x1005722a (/async_context_base_execute_once.dbgasm:28) process_under_lock@0x10056dfc (Unknown Source:251) low_priority_irq_handler@0x10056f5e (Unknown Source:293) <signal handler called>@0xfffffffd (Unknown Source:0) vTaskSuspendAll@0x10049158 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/tasks.c:2938) ``` **Callstack `core1`:** ``` vPortRecursiveLock@0x10048ba6 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/portmacro.h:192) vTaskSwitchContext@0x1004918a (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/tasks.c:3859) isr_pendsv@0x1004a846 (~/.platformio/packages/framework-arduinopico/libraries/FreeRTOS/lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/port.c:405) ```
earlephilhower (Migrated from github.com) approved these changes 2023-12-05 22:53:35 +03:00
earlephilhower (Migrated from github.com) left a comment

Thanks. This all stems from the fact that the LWIP calls are happening in an IRQ and I've also got to freeze the other core while the HW random generator is being accessed. I'm going to push a change to remove the whole mess, but this change here seems good to keep anyway.

Thanks. This all stems from the fact that the LWIP calls are happening in an IRQ and I've also got to freeze the other core while the HW random generator is being accessed. I'm going to push a change to remove the whole mess, but this change here seems good to keep anyway.
Sign in to join this conversation.