summaryrefslogtreecommitdiff
path: root/ports/linux/gnu/src/tx_thread_schedule.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/linux/gnu/src/tx_thread_schedule.c')
-rw-r--r--ports/linux/gnu/src/tx_thread_schedule.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/ports/linux/gnu/src/tx_thread_schedule.c b/ports/linux/gnu/src/tx_thread_schedule.c
index eeff680f..405ef4b8 100644
--- a/ports/linux/gnu/src/tx_thread_schedule.c
+++ b/ports/linux/gnu/src/tx_thread_schedule.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -201,6 +203,49 @@ 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;