From 74d9e3937fa913380fdfdd902e528411c661ea3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 15:10:15 -0400 Subject: [PATCH] Reverted the Linux port mutex retry on this branch The backport fixes a real deadlock and is right in itself, but on this branch it reproducibly breaks the NetX Duo nx_secure suite: nx_secure_tls_coverage_test segfaults in 8 of 19 configurations on one run and 9 of 19 on a re-run of the same commit, against four consecutive runs with none before it. Whether the retry causes that or merely exposes something latent is not known. The first guess, a kernel object outliving its stack frame, is wrong: that test's sessions are file scope and its creates and deletes balance. The deadlock the retry cures costs one configuration's coverage data at roughly 0.4% of test instances, which the union absorbs, so the branch is measurably worse with it than without while the interaction is unexplained. This is a deferral, not a dismissal. The diagnosis stands, the reproduction is recorded, and re-applying is one cherry-pick. The upstream fix is unaffected. This reverts commit ac95c32c. Assisted-by: Claude Code (Opus 5) --- ports/linux/gnu/inc/tx_port.h | 13 +------ ports/linux/gnu/src/tx_thread_schedule.c | 45 ------------------------ 2 files changed, 1 insertion(+), 57 deletions(-) diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h index 70a9fb9d..dc39b5f9 100644 --- a/ports/linux/gnu/inc/tx_port.h +++ b/ports/linux/gnu/inc/tx_port.h @@ -525,7 +525,7 @@ VOID _tx_thread_interrupt_restore(UINT previous_posture); #define TX_RESTORE _tx_linux_debug_entry_insert("RESTORE", __FILE__, __LINE__); \ _tx_thread_interrupt_restore(tx_saved_posture); #endif /* TX_LINUX_DEBUG_ENABLE */ -#define tx_linux_mutex_lock(p) _tx_linux_mutex_lock_retry(&p) +#define tx_linux_mutex_lock(p) pthread_mutex_lock(&p) #define tx_linux_mutex_unlock(p) pthread_mutex_unlock(&p) #define tx_linux_mutex_recursive_unlock(p) {\ int _recursive_count = (int)tx_linux_mutex_recursive_count;\ @@ -566,17 +566,6 @@ extern CHAR _tx_version_id[]; /* Define externals for the Linux port of ThreadX. */ extern pthread_mutex_t _tx_linux_mutex; - -/* Define how long a thread waits on the Linux mutex before retrying. A thread - parked on the mutex can be suspended by the port's signal handler and so never - act on the wake-up the next unlock sends it, which leaves the wake-up lost and - every other waiter parked on a mutex that is free. */ - -#ifndef TX_LINUX_MUTEX_RETRY_NSEC -#define TX_LINUX_MUTEX_RETRY_NSEC 1000000 -#endif - -void _tx_linux_mutex_lock_retry(pthread_mutex_t *mutex); extern sem_t _tx_linux_semaphore; extern sem_t _tx_linux_semaphore_no_idle; extern ULONG _tx_linux_global_int_disabled_flag; diff --git a/ports/linux/gnu/src/tx_thread_schedule.c b/ports/linux/gnu/src/tx_thread_schedule.c index c66aa891..d65104a1 100644 --- a/ports/linux/gnu/src/tx_thread_schedule.c +++ b/ports/linux/gnu/src/tx_thread_schedule.c @@ -8,8 +8,6 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Portions of this file were generated with AI assistance. - /**************************************************************************/ /**************************************************************************/ @@ -208,49 +206,6 @@ struct timespec ts; } } -/* Define the ThreadX Linux mutex lock function. The wait is timed and retried - rather than left to pthread_mutex_lock, because a thread can be signalled into - the port's suspend handler while it is parked on this mutex. That handler does - not return until the thread is resumed, so the wake-up the next unlock sends is - delivered to a thread that never retries and is lost. Any other thread parked - on the mutex then waits on a mutex that is free. Retrying on a timeout costs - nothing when the mutex is handed over normally, and turns that lost wake-up into - a delay of at most the retry period. */ - -void _tx_linux_mutex_lock_retry(pthread_mutex_t *mutex) -{ - -INT linux_status; -struct timespec ts; - - - do - { - - /* Set the deadline for this attempt. */ - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_nsec = ts.tv_nsec + TX_LINUX_MUTEX_RETRY_NSEC; - if (ts.tv_nsec >= 1000000000) - { - - ts.tv_nsec = ts.tv_nsec - 1000000000; - ts.tv_sec++; - } - - linux_status = pthread_mutex_timedlock(mutex, &ts); - - /* Anything but the deadline expiring is a real failure to obtain the - mutex, so stop retrying. */ - if ((linux_status != 0) && (linux_status != ETIMEDOUT)) - { - - break; - } - - } while (linux_status != 0); -} - - void _tx_thread_delete_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture) { INT linux_status;