77// ===----------------------------------------------------------------------===//
88
99// ============================================================================
10- // CRITICAL SAFETY WARNING - READ BEFORE USE
10+ // EXCEPTION STORAGE IMPLEMENTATION FOR NUTTX
1111// ============================================================================
1212//
13- // This implementation uses a SINGLE GLOBAL exception state without any
14- // synchronization mechanism. It is ONLY safe under these conditions:
13+ // This implementation provides THREAD-SAFE per-task exception storage using
14+ // NuttX Task Local Storage (TLS). It is safe for use in multi-tasking RTOS
15+ // environments.
1516//
16- // 1. Single-threaded execution (no RTOS task switching during exception
17- // handling )
18- // 2. No interrupt-based exception throwing
19- // 3. No concurrent exception handling across tasks
20- // 4. _LIBCPP_HAS_NO_THREADS must be defined at compile time
17+ // SAFETY FEATURES:
18+ // 1. Per-task exception state using NuttX TLS (no shared global state )
19+ // 2. Interrupt-safe initialization using enter_critical_section()
20+ // 3. Automatic cleanup on task exit via TLS destructor
21+ // 4. Double-checked locking pattern for initialization
2122//
22- // UNSAFE SCENARIOS (will cause data corruption) :
23+ // SAFE SCENARIOS:
2324// - Multiple RTOS tasks throwing exceptions simultaneously
24- // - Exception thrown from ISR while task is handling exception
25- // - Nested exceptions across different execution contexts
25+ // - Task preemption during exception handling
26+ // - Nested exceptions within the same task
2627//
27- // FOR MULTI-THREADED SYSTEMS:
28- // Implement per-task exception storage using NuttX TLS or task-local storage.
28+ // LIMITATIONS:
29+ // - Exception thrown from ISR context is NOT supported (use error codes)
30+ // - Requires CONFIG_TLS_TASK_NELEM >= 1 for TLS storage
2931//
30- // RECOMMENDED FOR CRITICAL SYSTEMS:
31- // Disable C++ exceptions entirely (CONFIG_CXX_EXCEPTION=n) and use
32- // error codes instead.
32+ // MEMORY USAGE PER TASK:
33+ // - sizeof(__cxa_eh_globals) bytes allocated on first exception (typically ~48
34+ // bytes)
35+ // - Automatically freed when task exits
3336// ============================================================================
3437
3538#include " ../libcxxabi/src/cxa_exception.h"
3841#include < cstring>
3942
4043// Use NuttX Task Local Storage for per-task exception state
44+ #include < nuttx/irq.h>
4145#include < nuttx/tls.h>
4246
4347// Compile-time safety check: ensure threading is disabled for libcxx
@@ -50,20 +54,37 @@ namespace __cxxabiv1 {
5054
5155// Per-task exception storage using NuttX TLS
5256// This is THREAD-SAFE and works correctly with NuttX RTOS task switching
53- static int tls_key = -1 ;
57+ static volatile int tls_key = -1 ;
5458
55- // Initialize TLS key on first use (lazy initialization)
59+ // Initialize TLS key on first use (lazy initialization with interrupt
60+ // protection) SAFETY: Uses interrupt disabling to prevent race conditions
61+ // during initialization
5662static void init_tls_key () {
63+ // Fast path: key already initialized (no locking needed for reads)
64+ if (tls_key >= 0 ) {
65+ return ;
66+ }
67+
68+ // Critical section: disable interrupts to prevent race condition
69+ irqstate_t flags = enter_critical_section ();
70+
71+ // Double-check: another task might have initialized while we waited
5772 if (tls_key == -1 ) {
5873 // Allocate TLS slot with destructor to free memory on task exit
59- tls_key = task_tls_alloc ([](void *ptr) {
74+ int new_key = task_tls_alloc ([](void *ptr) {
6075 if (ptr) {
6176 free (ptr);
6277 }
6378 });
64- // Verify allocation succeeded
65- assert (tls_key >= 0 && " Failed to allocate TLS key for exception storage" );
79+
80+ // Verify allocation succeeded before storing
81+ assert (new_key >= 0 && " Failed to allocate TLS key for exception storage" );
82+
83+ // Atomic write: store the key (volatile ensures visibility)
84+ tls_key = new_key;
6685 }
86+
87+ leave_critical_section (flags);
6788}
6889
6990extern __cxa_eh_globals *__cxa_get_globals () {
0 commit comments