d3ffeb40a7
In order to turn longjmp context-switch safe, it's necessary to disable interrupts before modifying windowbase and windowstart. Otherwise, after a context switch, windowstart and windowbase would be different, leading to a wrongly set windowstart bit due to longjmp writing it based on the windowbase before the context switch. This corrupts the registers at the next window overflow reaching that wrongly set bit. *Background:* This PR is related to an issue first observed on ESP-IDF https://github.com/espressif/esp-idf/issues/5229 and it was, then, checked on NuttX using a test application. *The test application:* To check if the problem affects ESP32, ESP32-S2 and ESP32-S3 on NuttX, it was created an application based on: https://en.cppreference.com/w/c/program/longjmp The application creates 16 tasks (`#define NUMBER_OF_TASKS 16`) that implements the following daemon: ``` static int setjmp_longjmp_daemon(int argc, char *argv[]) { for (int i = 0; i < NUMBER_OF_TASKS * 2; i++) { jmp_buf env; volatile int count = 0; if (setjmp(env) != UINT16_MAX) { foo(&env, ++count); } } sem_post(&g_sem); return EXIT_SUCCESS; } ``` The main function also initializes a semaphore to avoid application exiting before tasks return successfully: ``` sem_init(&g_sem, 0, -NUMBER_OF_TASKS); ``` Finally, the round-robin interval was lowered to 1ms to raise the chances of the longjmp being interrupted by a context switch (`CONFIG_RR_INTERVAL=1). This setup was able to reproduce the problem prior to this patch being applied. |
||
---|---|---|
.. | ||
arch_elf.c | ||
arch_memcpy.S | ||
arch_memmove.S | ||
arch_memset.S | ||
arch_setjmp.S | ||
arch_strcmp.S | ||
arch_strcpy.S | ||
arch_strlen.S | ||
arch_strncpy.S | ||
Kconfig | ||
Make.defs | ||
xtensa_asm.h |