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) <noreply@anthropic.com>
This commit is contained in:
Frédéric Desbiens
2026-09-30 15:10:15 -04:00
parent ac95c32c3e
commit 74d9e3937f
2 changed files with 1 additions and 57 deletions
+1 -12
View File
@@ -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;
-45
View File
@@ -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;