felomousa opened a new issue, #21499: URL: https://github.com/apache/nuttx/issues/21499
### Description / Steps to reproduce the issue ## Description Inserting a task into `g_readytorun` is a linear walk done with interrupts disabled. Each ready task at or above the new task's priority adds a fixed cost to the critical section. On an ESP32 at 240 MHz, a `sem_post()` from the timer interrupt took 324 cycles with no other ready tasks and 3460 cycles (14.4 µs) with 224 ready tasks at the same priority. The interrupt latency of the system therefore depends on how many tasks are ready, not only on the code that runs in interrupt handlers. ## Root cause [`nxsched_add_prioritized()`](https://github.com/apache/nuttx/blob/437306409e8a553ad82a08e6e8cafa382ee77c15/sched/sched/sched.h#L493-L494) walks the list from the head while `sched_priority <= next->sched_priority`. It is called from [`nxsched_add_readytorun()`](https://github.com/apache/nuttx/blob/437306409e8a553ad82a08e6e8cafa382ee77c15/sched/sched/sched_addreadytorun.c#L94), which callers such as [`nxsem_post_slow()`](https://github.com/apache/nuttx/blob/437306409e8a553ad82a08e6e8cafa382ee77c15/sched/semaphore/sem_post.c#L89) must call inside `enter_critical_section()`, because the list is shared with interrupt handlers. The `<=` keeps FIFO order among equal priorities, so the walk passes every ready task of equal or higher priority. The same path runs for a `sem_post()` from a thread and for a priority change. ## Reproduction Measurement code: - nuttx: https://github.com/felomousa/nuttx/tree/readylist-measure - nuttx-apps: https://github.com/felomousa/nuttx-apps/tree/readylist-measure ``` ./tools/configure.sh esp32-devkitc:readylist # or sim:readylist make -j && make flash ESPTOOL_PORT=<port> ESPTOOL_BINDIR=./ nsh> readylist -n 224 -s 56 -i 200 -c -w 210 # baseline: woken task above every ready task nsh> readylist -n 224 -s 32 -i 200 -c # worst case: ready tasks at the woken task's priority ``` The app keeps N tasks ready, wakes a task from a watchdog callback in the timer interrupt, and reports the cycles spent in `sem_post()`. With `CONFIG_SCHED_READYLIST_STATS` it also reports the number of list entries passed. ## Benchmark results ESP32-D0WD-V3 (rev 3.1), single core, 240 MHz, `CCOUNT` cycle counter. 200 wake-ups for each row. Ready tasks at the woken task's priority: | N ready tasks | Entries passed | Cycles in `sem_post()` | |---:|---:|---:| | 0 | 1 | 324 | | 32 | 33 | 772 | | 64 | 65 | 1220 | | 128 | 129 | 2116 | | 192 | 193 | 3012 | | 224 | 225 | 3460 | - In this configuration, each entry cost 14.0 cycles (58 ns). The minimum, median and maximum were the same in every row. - The entries-passed count matched a full scan of the list on every wake-up. `sim:readylist` gave the same counts. - Ready tasks below the woken task's priority, blocked tasks, and a woken task above every ready task did not change the cost: 324 cycles at every N up to 224. We used Claude (Anthropic) to help trace the code and write the measurement tools; all measurements are from an ESP32-WROOM-32E ### On which OS does this issue occur? [OS: Mac] ### What is the version of your OS? macOS 27.2 (Darwin 27.2.0), arm64 ### NuttX Version master ### Issue Architecture [Arch: xtensa], [Arch: simulator] ### Issue Area [Area: Kernel] ### Host information <details><summary>make host_info (esp32-devkitc:readylist, ESP32-WROOM-32E connected)</summary> ``` NuttX configuration options: CONFIG_HOST_MACOS=y CONFIG_APPS_DIR="../apps" CONFIG_BASE_DEFCONFIG="esp32-devkitc:readylist" CONFIG_BUILD_FLAT=y CONFIG_INTELHEX_BINARY=y CONFIG_OUTPUT_STRIP_PATHS=y CONFIG_ARCH_HAVE_STDARG_H=y CONFIG_ARCH_HAVE_SETJMP=y CONFIG_ARCH_NONE_DEBUG_H=y CONFIG_FORTIFY_SOURCE=0 CONFIG_NDEBUG=y CONFIG_DEBUG_ALERT=y CONFIG_SCHED_DUMP_TASKS=y CONFIG_SCHED_DUMP_STACK=y CONFIG_ARCH_HAVE_STACKCHECK=y CONFIG_STACK_USAGE_WARNING=0 CONFIG_ARCH_HAVE_CUSTOMOPT=y CONFIG_DEBUG_FULLOPT=y CONFIG_LTO_NONE=y CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y CONFIG_DEBUG_LINK_MAP=y CONFIG_ARCH_XTENSA=y CONFIG_ARCH="xtensa" CONFIG_ARCH_CHIP="esp32" CONFIG_ESPRESSIF_CHIP_SERIES="esp32" CONFIG_ESPRESSIF_NUM_CPUS=2 CONFIG_ESPRESSIF_LOG_LEVEL_NONE=y CONFIG_ESPRESSIF_LOG_LEVEL=0 CONFIG_ESPRESSIF_SIMPLE_BOOT=y CONFIG_ESPRESSIF_FLASH_MODE_DIO=y CONFIG_ESPRESSIF_FLASH_FREQ_40M=y CONFIG_ESPRESSIF_FLASH_FREQ="40m" CONFIG_ARCH_CHIP_ESP32=y CONFIG_ARCH_FAMILY_LX6=y CONFIG_XTENSA_CP_INITSET=0x0001 CONFIG_XTENSA_TOOLCHAIN_ESP=y CONFIG_ARCH_CHIP_ESP32WROVER=y CONFIG_ESP32_DUAL_CPU=y CONFIG_ESP32_FLASH_4M=y CONFIG_ESP32_FLASH_DETECT=y CONFIG_ESP32_PSRAM_8M=y CONFIG_ESP32_ESP32DXWDXX=y CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 CONFIG_ESP32_XTAL_40MZ=y CONFIG_ESP_PHY_IRQSTATE_FLAGS_NUMBER=3 CONFIG_ESP32_UART=y CONFIG_ESP32_RTC=y CONFIG_ESP32_UART0=y CONFIG_ESP32_BT_RESERVE_DRAM=0 CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0 CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 CONFIG_ESP32_UART0_TXPIN=1 CONFIG_ESP32_UART0_RXPIN=3 CONFIG_ESP32_UART_RXFIFO_FULL_THRHD=112 CONFIG_ESP32_FLASH_MODE_DIO=y CONFIG_ESP32_FLASH_FREQ_40M=y CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y CONFIG_ARCH_TOOLCHAIN_GNU=y CONFIG_ARCH_VECNOTIRQ=y CONFIG_ARCH_HAVE_TEXT_HEAP=y CONFIG_ARCH_HAVE_MULTICPU=y CONFIG_ARCH_HAVE_VFORK=y CONFIG_ARCH_HAVE_FPU=y CONFIG_ARCH_HAVE_MPU=y CONFIG_ARCH_HAVE_RESET=y CONFIG_ARCH_HAVE_THREAD_LOCAL=y CONFIG_ARCH_HAVE_SYSCALL_HOOKS=y CONFIG_ARCH_HAVE_BACKTRACE=y CONFIG_ARCH_HAVE_DEBUG=y CONFIG_ARCH_HAVE_PERF_EVENTS=y CONFIG_ARCH_PERF_EVENTS=y CONFIG_ARCH_HAVE_BOOTLOADER=y CONFIG_ARCH_HAVE_CPUINFO=y CONFIG_ARCH_CPUINFO_FREQ_KHZ=0 CONFIG_ARCH_HAVE_TCBINFO=y CONFIG_ARCH_FPU=y CONFIG_NCPUS=1 CONFIG_ARCH_STACKDUMP=y CONFIG_ARCH_STACKDUMP_MAX_LENGTH=0 CONFIG_ARCH_MINIMAL_VECTORTABLE=y CONFIG_ARCH_MINIMAL_VECTORTABLE_DYNAMIC=y CONFIG_ARCH_IRQ_TO_NDX=y CONFIG_ARCH_NUSER_INTERRUPTS=2 CONFIG_BOARD_LOOPSPERMSEC=16717 CONFIG_ARCH_HAVE_INTERRUPTSTACK=y CONFIG_ARCH_INTERRUPTSTACK=0 CONFIG_BOOT_RUNFROMFLASH=y CONFIG_RAM_START=0x20000000 CONFIG_RAM_SIZE=114688 CONFIG_FLASH_START=0x0 CONFIG_FLASH_SIZE=0 CONFIG_ARCH_BOARD_ESP32_DEVKITC=y CONFIG_ARCH_BOARD="esp32-devkitc" CONFIG_ARCH_HAVE_LEDS=y CONFIG_ARCH_HAVE_BUTTONS=y CONFIG_ARCH_BOARD_COMMON=y CONFIG_BOARD_CRASHDUMP_NONE=y CONFIG_BOARDCTL=y CONFIG_BOARDCTL_MKRD=y CONFIG_BOARD_MEMORY_RANGE="" CONFIG_DISABLE_OS_API=y CONFIG_USEC_PER_TICK=10000 CONFIG_TIMER_ADJUST_USEC=0 CONFIG_START_YEAR=2011 CONFIG_START_MONTH=12 CONFIG_START_DAY=6 CONFIG_PREALLOC_TIMERS=4 CONFIG_IRQ_NWORKS=8 CONFIG_IRQ_WORK_SECTION="" CONFIG_IRQ_WORK_STACKSIZE=2048 CONFIG_INIT_ENTRY=y CONFIG_INIT_ARGS="" CONFIG_INIT_STACKSIZE=3072 CONFIG_INIT_PRIORITY=100 CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INIT_ENTRYNAME="nsh_main" CONFIG_RR_INTERVAL=200 CONFIG_TASK_NAME_SIZE=31 CONFIG_SCHED_WAITPID=y CONFIG_PTHREAD_MUTEX_BOTH=y CONFIG_PTHREAD_MUTEX_DEFAULT_UNSAFE=y CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_NONE=y CONFIG_SCHED_IRQMONITOR=y CONFIG_SCHED_READYLIST_STATS=y CONFIG_SCHED_CPULOAD_NONE=y CONFIG_SCHED_CPULOAD_TICKSPERSEC=100 CONFIG_SCHED_PROFILE_TICKSPERSEC=1000 CONFIG_SCHED_STACK_RECORD=0 CONFIG_DEV_CONSOLE=y CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=8 CONFIG_FILE_STREAM=y CONFIG_BOARD_LATE_INITIALIZE=y CONFIG_BOARD_INITTHREAD_STACKSIZE=2048 CONFIG_BOARD_INITTHREAD_PRIORITY=240 CONFIG_ENABLE_ALL_SIGNALS=y CONFIG_SIG_PREALLOC_IRQ_ACTIONS=8 CONFIG_SIG_PREALLOC_ACTIONS=4 CONFIG_SIG_ALLOC_ACTIONS=1 CONFIG_PREALLOC_MQ_MSGS=8 CONFIG_PREALLOC_MQ_IRQ_MSGS=8 CONFIG_MQ_MAXMSGSIZE=32 CONFIG_DEFAULT_TASK_STACKSIZE=2048 CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_PTHREAD_STACK_MIN=256 CONFIG_PTHREAD_STACK_DEFAULT=2048 CONFIG_PTHREAD_GUARDSIZE_DEFAULT=0 CONFIG_PID_INITIAL_COUNT=16 CONFIG_ARCH_HAVE_I2CRESET=y CONFIG_DEV_NULL=y CONFIG_DEV_ZERO=y CONFIG_DEV_OPTEE_NONE=y CONFIG_DRVR_MKRD=y CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y CONFIG_SERIAL=y CONFIG_SERIAL_CONSOLE=y CONFIG_MCU_SERIAL=y CONFIG_STANDARD_SERIAL=y CONFIG_SERIAL_NPOLLWAITERS=4 CONFIG_SERIAL_TXBULK=y CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_UART0_SERIALDRIVER=y CONFIG_UART0_RXBUFSIZE=256 CONFIG_UART0_TXBUFSIZE=256 CONFIG_UART0_BAUD=115200 CONFIG_UART0_BITS=8 CONFIG_UART0_PARITY=0 CONFIG_UART0_2STOP=0 CONFIG_SYSLOG=y CONFIG_SYSLOG_DEFAULT_MASK=0xff CONFIG_SYSLOG_CRLF=y CONFIG_SYSLOG_MAX_CHANNELS=1 CONFIG_SYSLOG_BUFFER=y CONFIG_SYSLOG_BUFSIZE=64 CONFIG_SYSLOG_DEVPATH="/dev/ttyS1" CONFIG_SYSLOG_DEFAULT=y CONFIG_FS_NEPOLL_DESCRIPTORS=8 CONFIG_FS_LOCK_BUCKET_SIZE=0 CONFIG_SENDFILE_BUFSIZE=512 CONFIG_FS_BACKTRACE=0 CONFIG_FS_AIO_LISTIO_MAX=256 CONFIG_FS_MQUEUE_VFS_PATH="/var/mqueue" CONFIG_FS_MQUEUE_NPOLLWAITERS=4 CONFIG_FS_ANONMAP=y CONFIG_FS_PROCFS=y CONFIG_NXFONTS_PACKEDMSFIRST=y CONFIG_MM_DEFAULT_MANAGER=y CONFIG_MM_DEFAULT_ALIGNMENT=8 CONFIG_MM_NODE_GUARDSIZE=0 CONFIG_MM_REGIONS=3 CONFIG_MM_MAP_COUNT_MAX=1024 CONFIG_MM_BACKTRACE=-1 CONFIG_MM_FREE_DELAYCOUNT_MAX=0 CONFIG_MM_HEAP_BIGGEST_COUNT=30 CONFIG_MM_HEAP_MEMPOOL_THRESHOLD=-1 CONFIG_BINFMT_ELF_RELOCATABLE=y CONFIG_STDIO_BUFFER_SIZE=64 CONFIG_STDIO_LINEBUFFER=y CONFIG_NUNGET_CHARS=2 CONFIG_LIBC_FLOATINGPOINT=y CONFIG_LIBC_ATOMIC_TOOLCHAIN=y CONFIG_ARCH_LOWPUTC=y CONFIG_LIBC_ARCH_MEMCHR=y CONFIG_LIBC_ARCH_MEMCPY=y CONFIG_LIBC_ARCH_MEMCMP=y CONFIG_LIBC_ARCH_MEMMOVE=y CONFIG_LIBC_ARCH_MEMSET=y CONFIG_LIBC_ARCH_STRCHR=y CONFIG_LIBC_ARCH_STRCMP=y CONFIG_LIBC_ARCH_STRCPY=y CONFIG_LIBC_ARCH_STRLCPY=y CONFIG_LIBC_ARCH_STRNCPY=y CONFIG_LIBC_ARCH_STRLEN=y CONFIG_LIBC_ARCH_STRNLEN=y CONFIG_LIBC_PREVENT_STRING_KERNEL=y CONFIG_LIBC_PREVENT_MEMCHR_KERNEL=y CONFIG_LIBC_PREVENT_MEMCMP_KERNEL=y CONFIG_LIBC_PREVENT_MEMCPY_KERNEL=y CONFIG_LIBC_PREVENT_MEMMOVE_KERNEL=y CONFIG_LIBC_PREVENT_MEMSET_KERNEL=y CONFIG_LIBC_PREVENT_STRCAT_KERNEL=y CONFIG_LIBC_PREVENT_STRCASECMP_KERNEL=y CONFIG_LIBC_PREVENT_STRCHR_KERNEL=y CONFIG_LIBC_PREVENT_STRCHRNUL_KERNEL=y CONFIG_LIBC_PREVENT_STRCMP_KERNEL=y CONFIG_LIBC_PREVENT_STRCPY_KERNEL=y CONFIG_LIBC_PREVENT_STRLCAT_KERNEL=y CONFIG_LIBC_PREVENT_STRLEN_KERNEL=y CONFIG_LIBC_PREVENT_STRLCPY_KERNEL=y CONFIG_LIBC_PREVENT_STRNCASECMP_KERNEL=y CONFIG_LIBC_PREVENT_STRNCAT_KERNEL=y CONFIG_LIBC_PREVENT_STRNLEN_KERNEL=y CONFIG_LIBC_PREVENT_STRNCMP_KERNEL=y CONFIG_LIBC_PREVENT_STRNCPY_KERNEL=y CONFIG_LIBC_PREVENT_STRRCHR_KERNEL=y CONFIG_LIBC_HOMEDIR="/" CONFIG_LIBC_TMPDIR="/tmp" CONFIG_LIBC_MAX_TMPFILE=32 CONFIG_LIBC_MAX_EXITFUNS=0 CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_LIBC_HOSTNAME="" CONFIG_LIBC_OPEN_MAX=256 CONFIG_NAME_MAX=32 CONFIG_PATH_MAX=256 CONFIG_LINE_MAX=64 CONFIG_LIBC_STRERROR_ERRNUM=y CONFIG_LIBC_STRSIGNAL=y CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS=y CONFIG_LIBC_STRFTIME_POSIX_FORMATS=y CONFIG_LIBC_STRFTIME_NONSTANDARD_FORMATS=y CONFIG_TLS_NELEM=0 CONFIG_TLS_TASK_NELEM=0 CONFIG_TLS_NCLEANUP=0 CONFIG_LIBC_GAISTRERROR_ERRNUM=y CONFIG_LIBC_FTOK_VFS_PATH="/var/ftok" CONFIG_LIBC_MEMFD_ERROR=y CONFIG_LIBC_TEMPBUFFER=y CONFIG_LIBC_MAX_TEMPBUFFER=2 CONFIG_LIBC_TEMPBUFFER_MALLOC=y CONFIG_LIBC_MUTEX_BACKTRACE=0 CONFIG_BUILTIN=y CONFIG_APP_REGISTRY=y CONFIG_STREAM_OUT_BUFFER_SIZE=64 CONFIG_STREAM_HEXDUMP_BUFFER_SIZE=128 CONFIG_STREAM_BASE64_BUFFER_SIZE=128 CONFIG_LIBC_INLINE_QUEUE=y CONFIG_LIBM_TOOLCHAIN=y CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_LIBCXXNONE=y CONFIG_LIBMINIABI=y CONFIG_CXX_STANDARD="gnu++17" CONFIG_CXX_NO_LOCALIZATION=y CONFIG_BUILTIN_TOOLCHAIN=y CONFIG_COVERAGE_NONE=y CONFIG_COVERAGE_DEFAULT_PREFIX_STRIP="0" CONFIG_COVERAGE_DEFAULT_PREFIX="/data" CONFIG_PROFILE_NONE=y CONFIG_NSH_LIBRARY=y CONFIG_NSH_PROMPT_STRING="nsh> " CONFIG_NSH_PROMPT_MAX=32 CONFIG_NSH_PROMPT_ENV="PS1" CONFIG_NSH_PROMPT_SUFFIX="> " CONFIG_NSH_READLINE=y CONFIG_NSH_MAXARGUMENTS=12 CONFIG_NSH_NESTDEPTH=3 CONFIG_NSH_ALIAS=y CONFIG_NSH_ALIAS_MAX_AMOUNT=1 CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_DISABLE_DATE=y CONFIG_NSH_DISABLE_LOSMART=y CONFIG_NSH_DISABLE_LOMTD=y CONFIG_NSH_DISABLE_MB=y CONFIG_NSH_DISABLE_MH=y CONFIG_NSH_DISABLE_MW=y CONFIG_NSH_DISABLE_TIMEDATECTL=y CONFIG_NSH_CODECS_BUFSIZE=128 CONFIG_NSH_PROC_MOUNTPOINT="/proc" CONFIG_NSH_FILEIOSIZE=512 CONFIG_NSH_SYSINITSCRIPT="init.d/rc.sysinit" CONFIG_NSH_INITSCRIPT="init.d/rcS" CONFIG_NSH_SCRIPT_REDIRECT_PATH="" CONFIG_NSH_CONSOLE=y CONFIG_SYSTEM_DD=y CONFIG_SYSTEM_DD_PROGNAME="dd" CONFIG_SYSTEM_DD_PRIORITY=100 CONFIG_SYSTEM_DD_STACKSIZE=2048 CONFIG_SYSTEM_DD_STATS=y CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_NSH_PRIORITY=100 CONFIG_SYSTEM_NSH_STACKSIZE=2048 CONFIG_SYSTEM_NSH_PROGNAME="nsh" CONFIG_SYSTEM_READLINE=y CONFIG_READLINE_HAVE_EXTMATCH=y CONFIG_READLINE_ECHO=y CONFIG_READLINE_EDIT=y CONFIG_TESTING_READYLIST=y CONFIG_TESTING_READYLIST_PRIORITY=100 CONFIG_TESTING_READYLIST_STACKSIZE=2048 CONFIG_TESTING_READYLIST_FILLER_STACKSIZE=1024 Host system OS: macOS 27.2 Darwin <host> 27.2.0 Darwin Kernel Version 27.2.0: Wed Oct 14 23:48:16 PDT 2026; root:xnu-13432.41.4~25/RELEASE_ARM64_T8112 arm64 arm Host system PATH: /Users/felomousa/nuttxspace/.venv/bin /Users/felomousa/nuttxspace/toolchains/xtensa-esp-elf/bin /opt/homebrew/bin /usr/bin /bin Espressif specific information: Toolchain version: esp32: Bootloader image not found esp32s2: Bootloader image not found esp32s3: Bootloader image not found esp32c2: Bootloader image not found esp32c3: Bootloader image not found esp32c6: Bootloader image not found esp32h2: Bootloader image not found Toolchain version: clang: Apple clang version 17.0.0 (clang-1700.0.13.5) gcc: Apple clang version 17.0.0 (clang-1700.0.13.5) xtensa-esp32-elf-gcc: xtensa-esp-elf-gcc (crosstool-NG esp-14.2.0_20241119) 14.2.0 xtensa-esp32s2-elf-gcc: xtensa-esp-elf-gcc (crosstool-NG esp-14.2.0_20241119) 14.2.0 xtensa-esp32s3-elf-gcc: xtensa-esp-elf-gcc (crosstool-NG esp-14.2.0_20241119) 14.2.0 riscv-none-elf-gcc: Not found riscv32-esp-elf-gcc: Not found riscv64-unknown-elf-gcc: Not found Esptool version: 5.6.0 HAL version: Not found CHIP ID: Not found Flash ID: Manufacturer: 5e Device: 4016 Security information: Not found Flash status: Not found MAC address: <hidden> ``` </details> ### Verification - [x] I have verified before submitting the report. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
