summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadtimeout.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-04-22 10:06:05 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-19 12:00:45 +0200
commit08fe84b5d7072b7809581b1a25954a3b221497a5 (patch)
tree79a1ea39b1ea24ca25bf9f450a726efe80dd6257 /cpukit/score/src/threadtimeout.c
parentscore: Reduce thread wait states (diff)
downloadrtems-08fe84b5d7072b7809581b1a25954a3b221497a5.tar.bz2
score: Generalize _Event_Timeout()
Add a thread wait timeout code. Replace _Event_Timeout() with a general purpose _Thread_Timeout() watchdog handler. Update #2273.
Diffstat (limited to 'cpukit/score/src/threadtimeout.c')
-rw-r--r--cpukit/score/src/threadtimeout.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/cpukit/score/src/threadtimeout.c b/cpukit/score/src/threadtimeout.c
new file mode 100644
index 0000000000..b6ce2d7362
--- /dev/null
+++ b/cpukit/score/src/threadtimeout.c
@@ -0,0 +1,74 @@
+/**
+ * @file
+ *
+ * @brief Thread Wait Timeout
+ *
+ * @ingroup ScoreThread
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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/threadimpl.h>
+
+static void _Thread_Do_timeout( Thread_Control *the_thread )
+{
+ the_thread->Wait.return_code = the_thread->Wait.timeout_code;
+ _Thread_Lock_restore_default( the_thread );
+}
+
+void _Thread_Timeout( Objects_Id id, void *arg )
+{
+ Thread_Control *the_thread;
+ ISR_lock_Control *thread_lock;
+ ISR_lock_Context lock_context;
+ Thread_Wait_flags wait_flags;
+ Thread_Wait_flags wait_class;
+ Thread_Wait_flags intend_to_block;
+ Thread_Wait_flags blocked;
+ bool success;
+ bool unblock;
+
+ the_thread = arg;
+ thread_lock = _Thread_Lock_acquire( the_thread, &lock_context );
+
+ wait_flags = _Thread_Wait_flags_get( the_thread );
+ wait_class = wait_flags & THREAD_WAIT_CLASS_MASK;
+ intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
+ blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
+ success = _Thread_Wait_flags_try_change_critical(
+ the_thread,
+ intend_to_block,
+ wait_class | THREAD_WAIT_STATE_READY_AGAIN
+ );
+
+ if ( success ) {
+ _Thread_Do_timeout( the_thread );
+ unblock = false;
+ } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
+ _Thread_Wait_flags_set(
+ the_thread,
+ wait_class | THREAD_WAIT_STATE_READY_AGAIN
+ );
+ _Thread_Do_timeout( the_thread );
+ unblock = true;
+ } else {
+ unblock = false;
+ }
+
+ _Thread_Lock_release( thread_lock, &lock_context );
+
+ if ( unblock ) {
+ _Thread_Unblock( the_thread );
+ }
+}