summaryrefslogtreecommitdiffstats
path: root/cpukit/score
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
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')
-rw-r--r--cpukit/score/Makefile.am1
-rw-r--r--cpukit/score/include/rtems/score/thread.h5
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h22
-rw-r--r--cpukit/score/src/threadtimeout.c74
4 files changed, 102 insertions, 0 deletions
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 3eb2caa902..35470972af 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -290,6 +290,7 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \
src/threadstartmultitasking.c src/iterateoverthreads.c
libscore_a_SOURCES += src/threadglobalconstruction.c
+libscore_a_SOURCES += src/threadtimeout.c
libscore_a_SOURCES += src/threadyield.c
if HAS_SMP
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 112bd22e63..1a73fdaa8a 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -354,6 +354,11 @@ typedef struct {
*/
uint32_t return_code;
+ /**
+ * @brief Code to set the timeout return code in _Thread_Timeout().
+ */
+ uint32_t timeout_code;
+
/** This field points to the thread queue on which this thread is blocked. */
Thread_queue_Control *queue;
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 3577a7493b..c266a9cce3 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -1257,6 +1257,28 @@ RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change(
return success;
}
+/**
+ * @brief Sets the thread wait timeout code.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] timeout_code The new thread wait timeout code.
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Wait_set_timeout_code(
+ Thread_Control *the_thread,
+ uint32_t timeout_code
+)
+{
+ the_thread->Wait.timeout_code = timeout_code;
+}
+
+/**
+ * @brief General purpose thread wait timeout.
+ *
+ * @param[in] id Unused.
+ * @param[in] arg The thread.
+ */
+void _Thread_Timeout( Objects_Id id, void *arg );
+
RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor(
Thread_Control *the_thread,
Per_CPU_Control *cpu
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 );
+ }
+}