clang+LTO makes USB Serial unacceptably slow #2464
Labels
No labels
bazel
bluetooth
board settings
boot_stage2
bug
build
c++
can't reproduce
clang
clib-interface
cmsis
code cleanliness
code size
compiler version issues
cyw43_driver
debug
discussion
documentation
duplicate
dynamic_clock
elf2uf2
enhancement
errata
filesystem
flash layout
floating point
FreeRTOS
hardware_adc
hardware_claim
hardware_clocks
hardware_dma
hardware_exception
hardware_flash
hardware_gpio
hardware_i2c
hardware_irq
hardware_pio
hardware_pwm
hardware_rcp
hardware_rtc
hardware_spi
hardware_sync
hardware_uart
hardware_vreg
hardware_watchdog
hardware_xosc
help wanted
host
IAR
installation
invalid
linker scripts
lto
lwip
mbedtls
missing API
needs reporter detail
networking
newlib
newlib-multicore
non-c
non-cmake
non-gcc
openocd
orphan PR
OS integration
pico_async_context
pico_base
pico_binary_info
pico_flash
picolibc
pico_lwip
pico_malloc
pico_multicore
pico_printf
pico_runtime
pico_stdio
pico_stdio_usb
pico_sync
pico_time
pico_util
pioasm
port
question
review
review2
rtos interop
runtime init
static library
svd
test
tinyusb
vscode
wifi integration
wontfix
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-raspberrypi/pico-sdk#2464
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
TL;DR
Enabling
-flto(orCMAKE_INTERPROCEDURAL_OPTIMIZATION ON) causes USB Serial to output only one "block" per second inReleasemode. The issue disappears inDebugbuilds.Detailed Description
Minimal Repro Code
Behavior with LTO:
stdio_printfwithprintfdoesn't make a differencestd::cout << "!!! " << cnt++ << std::endl;emits exactly one symbol per second.Issue only occurs with
CMAKE_BUILD_TYPE=Release. Debug builds work normally.How to Reproduce
main.cppabove.This issue on tinyusb repo: hathach/tinyusb#3120
Don't know if this should be considered a clang(*) or a pico-sdk bug: with LTO enabled the linker discards all the
auto_init_mutexmutexes; section ".mutex_array" is empty. In your case it'sprint_mutexin stdio.c that causes problems. I don't know what memoryprint_mutexnow occupies butmutex_try_enter_block_until()in functionstdout_serialize_begin()now times-out every time (1000 ms timeout). Removingstaticfrom macroauto_init_mutexor adding__attribute__((used))to it fixes the issue ... but I wouldn't be surprised if there will be other (hidden) issues ...Note that LTO with gcc also fails. -flto + -Wl,--wrap doesn't work due to a one or two decade old linker bug.
Maybe pico-sdk can detect whether LTO is enabled and then abort with an error instead.
(*) I used clang 20.1.0-ATfl
Declaring
mutex_tasvolatileinmutex.halso fixes the issue.It seems to me that mutexes should be volatile as they exist in order to sync code across different cores so it might be a good solution.
PS: I use
clang-18.1.3andLLVM-ET-Arm-18.1.3toolchain.See also https://github.com/raspberrypi/pico-sdk/issues?q=is%3Aissue%20lto
Does
#define auto_init_mutex(name) static _attribute_((section(".mutex_array"))) __used mutex_t name
help?