summaryrefslogtreecommitdiff
path: root/ports_smp/linux/gnu/src
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-10-02 10:42:44 -0400
committerGitHub <[email protected]>2026-10-02 10:42:44 -0400
commit93387b0a60382a29579bbad5045c68328e3751df (patch)
tree42be790d602cb76f55090e5a7c418df7ea2b3428 /ports_smp/linux/gnu/src
parent44d7c95c582d415c4ad84527180b29c93c3bf664 (diff)
parent28281cd5647d4671236ca08d19bd18ed15b2265a (diff)
Merge pull request #783 from eclipse-threadx/devv6.5.2.202603_rel
Merged changes ahead of the v6.5.2.202603 release
Diffstat (limited to 'ports_smp/linux/gnu/src')
-rw-r--r--ports_smp/linux/gnu/src/tx_thread_schedule.c41
-rw-r--r--ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c15
-rw-r--r--ports_smp/linux/gnu/src/tx_thread_stack_build.c12
3 files changed, 61 insertions, 7 deletions
diff --git a/ports_smp/linux/gnu/src/tx_thread_schedule.c b/ports_smp/linux/gnu/src/tx_thread_schedule.c
index 0c3e8e32..0b6eba25 100644
--- a/ports_smp/linux/gnu/src/tx_thread_schedule.c
+++ b/ports_smp/linux/gnu/src/tx_thread_schedule.c
@@ -292,6 +292,8 @@ void _tx_linux_mutex_obtain(TX_LINUX_MUTEX *mutex)
TX_THREAD *thread_ptr;
pthread_t current_thread_id;
UINT i;
+INT linux_status;
+struct timespec ts;
/* Pickup the current thread ID. */
current_thread_id = pthread_self();
@@ -343,8 +345,43 @@ UINT i;
thread_ptr -> tx_thread_linux_mutex_access = TX_TRUE;
}
- /* Get the Linux mutex. */
- pthread_mutex_lock(&mutex -> tx_linux_mutex);
+ /* Get the Linux mutex. 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
+ release 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, which on this port deadlocks the whole process: the thread that
+ can resume the suspended one is the scheduler, and the scheduler takes
+ this mutex on every pass. 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. */
+ 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 -> tx_linux_mutex, &ts);
+
+ /* Anything but the deadline expiring is a real failure to obtain the
+ mutex, so stop retrying and record it. */
+ if ((linux_status != 0) && (linux_status != ETIMEDOUT))
+ {
+
+ /* Increment the system error counter. */
+ _tx_linux_system_error++;
+ break;
+ }
+
+ } while (linux_status != 0);
/* At this point we have the mutex. */
diff --git a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c
index 7428666f..2e0e7f1e 100644
--- a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c
+++ b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -124,11 +126,18 @@ pthread_t current_thread_id;
_tx_linux_debug_entry_insert("UNPROTECT-nested", __FILE__, __LINE__);
}
- /* Only release the critical section. */
- _tx_linux_mutex_release(&_tx_linux_mutex);
}
- /* Release the critical section. */
+ /* Release the critical section taken by the matching _tx_thread_smp_protect.
+ The protection and the critical section are separate counts, and this
+ release is owed whether or not the protection still names this core: the
+ protection can be cleared by another core while this one holds the
+ critical section it took. The critical section is only handed back to
+ Linux when its nesting count reaches zero, so a release skipped here is
+ never made up and the mutex stays locked for the life of the process. */
+ _tx_linux_mutex_release(&_tx_linux_mutex);
+
+ /* Release the critical section taken on entry. */
_tx_linux_mutex_release(&_tx_linux_mutex);
}
diff --git a/ports_smp/linux/gnu/src/tx_thread_stack_build.c b/ports_smp/linux/gnu/src/tx_thread_stack_build.c
index 1b491a3a..65b8e25c 100644
--- a/ports_smp/linux/gnu/src/tx_thread_stack_build.c
+++ b/ports_smp/linux/gnu/src/tx_thread_stack_build.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -80,6 +82,7 @@ void *_tx_linux_thread_entry(void *ptr);
/**************************************************************************/
VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
{
+ALIGN_TYPE fake_stack_ptr;
struct sched_param sp;
pthread_attr_t attrs;
@@ -120,8 +123,13 @@ pthread_attr_t attrs;
tx_interrupt_control nesting. */
thread_ptr -> tx_thread_linux_mutex_access = TX_FALSE;
- /* Setup a fake thread stack pointer. */
- thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
+ /* Setup a fake thread stack pointer. The stack end points at the last byte of the
+ thread's stack area and is therefore not necessarily aligned, so round the result
+ down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is
+ also the starting value of the stack checking logic's highest used pointer. */
+ fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8));
+ fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1)));
+ thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr);
/* Clear the first word of the stack. */
*(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;