diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-10-19 13:47:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-10-24 10:19:05 +0200 |
commit | c31058947491ca319c901040219be39e4f8155b6 (patch) | |
tree | 435bf0887bd77e3d344b31275853a6e52fca8dd8 /cpukit/score/src/threadqtimeout.c | |
parent | score: Rename function threadq support function (diff) | |
download | rtems-c31058947491ca319c901040219be39e4f8155b6.tar.bz2 |
score: Move thread queue timeout handling
Update #3117.
Update #3182.
Diffstat (limited to '')
-rw-r--r-- | cpukit/score/src/threadqtimeout.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/cpukit/score/src/threadqtimeout.c b/cpukit/score/src/threadqtimeout.c new file mode 100644 index 0000000000..3f052fcf6f --- /dev/null +++ b/cpukit/score/src/threadqtimeout.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016, 2017 embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/threadqimpl.h> +#include <rtems/score/threadimpl.h> +#include <rtems/score/watchdogimpl.h> + +void _Thread_queue_Add_timeout_ticks( + Thread_queue_Queue *queue, + Thread_Control *the_thread, + Per_CPU_Control *cpu_self, + Thread_queue_Context *queue_context +) +{ + Watchdog_Interval ticks; + + ticks = queue_context->Timeout.ticks; + + if ( ticks != WATCHDOG_NO_TIMEOUT ) { + _Thread_Add_timeout_ticks( + the_thread, + cpu_self, + queue_context->Timeout.ticks + ); + } +} + +static bool _Thread_queue_Lazy_insert_monotonic_timespec( + Thread_Control *the_thread, + Per_CPU_Control *cpu_self, + const struct timespec *abstime +) +{ + uint64_t expire; + ISR_lock_Context lock_context; + bool insert; + + if ( abstime->tv_sec < 0 ) { + expire = 0; + } else if ( _Watchdog_Is_far_future_monotonic_timespec( abstime ) ) { + expire = WATCHDOG_MAXIMUM_TICKS; + } else { + expire = _Watchdog_Monotonic_from_timespec( abstime ); + } + + _ISR_lock_ISR_disable_and_acquire( + &the_thread->Timer.Lock, + &lock_context + ); + + the_thread->Timer.header = + &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ]; + the_thread->Timer.Watchdog.routine = _Thread_Timeout; + insert = _Watchdog_Per_CPU_lazy_insert_monotonic( + &the_thread->Timer.Watchdog, + cpu_self, + expire + ); + + _ISR_lock_Release_and_ISR_enable( + &the_thread->Timer.Lock, + &lock_context + ); + return insert; +} + +void _Thread_queue_Add_timeout_monotonic_timespec( + Thread_queue_Queue *queue, + Thread_Control *the_thread, + Per_CPU_Control *cpu_self, + Thread_queue_Context *queue_context +) +{ + const struct timespec *abstime; + + abstime = queue_context->Timeout.arg; + + if ( _Watchdog_Is_valid_timespec( abstime ) ) { + if ( + !_Thread_queue_Lazy_insert_monotonic_timespec( + the_thread, + cpu_self, + abstime + ) + ) { + _Thread_Continue( the_thread, STATUS_TIMEOUT ); + } + } else { + _Thread_Continue( the_thread, STATUS_INVALID_NUMBER ); + } +} + +void _Thread_queue_Add_timeout_realtime_timespec( + Thread_queue_Queue *queue, + Thread_Control *the_thread, + Per_CPU_Control *cpu_self, + Thread_queue_Context *queue_context +) +{ + const struct timespec *abstime; + + abstime = queue_context->Timeout.arg; + + if ( _Watchdog_Is_valid_timespec( abstime ) ) { + uint64_t expire; + struct timespec now; + + if ( abstime->tv_sec < 0 ) { + expire = 0; + } else if ( _Watchdog_Is_far_future_realtime_timespec( abstime ) ) { + expire = WATCHDOG_MAXIMUM_TICKS; + } else { + expire = _Watchdog_Realtime_from_timespec( abstime ); + } + + _Timecounter_Getnanotime( &now ); + + if ( expire > _Watchdog_Realtime_from_timespec( &now ) ) { + ISR_lock_Context lock_context; + + _ISR_lock_ISR_disable_and_acquire( + &the_thread->Timer.Lock, + &lock_context + ); + + the_thread->Timer.header = + &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ]; + the_thread->Timer.Watchdog.routine = _Thread_Timeout; + _Watchdog_Per_CPU_insert_realtime( + &the_thread->Timer.Watchdog, + cpu_self, + expire + ); + + _ISR_lock_Release_and_ISR_enable( + &the_thread->Timer.Lock, + &lock_context + ); + } else { + _Thread_Continue( the_thread, STATUS_TIMEOUT ); + } + } else { + _Thread_Continue( the_thread, STATUS_INVALID_NUMBER ); + } +} |