On 16/06/16 08:09, Sebastian Huber wrote:
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h
b/cpukit/score/include/rtems/score/threadqimpl.h
index 73d4de2..f59a334 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -349,6 +349,7 @@ Thread_Control *_Thread_queue_Do_dequeue(
* executing,
* STATES_WAITING_FOR_MUTEX,
* WATCHDOG_NO_TIMEOUT,
+ * WATCHDOG_RELATIVE,
* 0,
* &queue_context
* );
@@ -362,6 +363,7 @@ Thread_Control *_Thread_queue_Do_dequeue(
* @param[in] state The new state of the thread.
* @param[in] timeout Interval to wait. Use WATCHDOG_NO_TIMEOUT to
block
* potentially forever.
+ * @param[in] clock The kind of clock used for the interval.
* @param[in] queue_context The thread queue context of the lock
acquire.
*/
void _Thread_queue_Enqueue_critical(
@@ -370,6 +372,7 @@ void _Thread_queue_Enqueue_critical(
Thread_Control *the_thread,
States_Control state,
Watchdog_Interval timeout,
+ Watchdog_Clock clock,
Thread_queue_Context *queue_context
);
We already have a lot of parameters for the
_Thread_queue_Enqueue_critical(). I would rather move the timeout
parameters to the queue_context, since this is more efficient.
The Watchdog_Interval is 32-bit, thus not suitable for the absolute
timeouts.
A value of 0 is valid for absolute timeouts, see what happens if you
get that wrong
https://www.wired.com/2016/02/dont-set-your-iphone-back-to-1970-no-matter-what/
So, I would move the WATCHDOG_NO_TIMEOUT to your new Watchdog_Clock.
[...]
From IRC log:
[19:44] <gedare> sebhub: Does it make sense to you to redefine
Watchdog_Interval as a struct containing a union for the interval and an
enum for the Clock "Discipline" (relative/absolute)?
[19:45] <gedare> ^the union for uint32_t relative, uint64_t absolute--or
else we make all intervals 64-bit
No, I would not change Watchdog_Interval. We should keep the ticks based
services as is. The problem is that _Thread_queue_Enqueue_critical()
doesn't support absolute timeouts currently. I would do something like
the attached.
We have
void _Thread_queue_Enqueue_critical(
Thread_queue_Queue *queue,
const Thread_queue_Operations *operations,
Thread_Control *the_thread,
States_Control state,
Thread_queue_Context *queue_context
)
{
Per_CPU_Control *cpu_self;
bool success;
#if defined(RTEMS_MULTIPROCESSING)
if ( _Thread_MP_Is_receive( the_thread ) &&
the_thread->receive_packet ) {
the_thread = _Thread_MP_Allocate_proxy( state );
}
#endif
_Thread_Lock_set( the_thread, &queue->Lock );
the_thread->Wait.return_code = STATUS_SUCCESSFUL;
_Thread_Wait_set_queue( the_thread, queue );
_Thread_Wait_set_operations( the_thread, operations );
( *operations->enqueue )( queue, the_thread );
Thus, we would have to store the timeout related parameters to the stack
anyway, since ( *operations->enqueue )( queue, the_thread ) is a
function call which cannot be optimized way (except maybe through
link-time optimization). So, there is no overhead due to the use of the
queue context.
--
Sebastian Huber, embedded brains GmbH
Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone : +49 89 189 47 41-16
Fax : +49 89 189 47 41-09
E-Mail : sebastian.hu...@embedded-brains.de
PGP : Public key available on request.
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
>From 62fa4b43ecdf560c6f5f1e397e25c06ded5bfc63 Mon Sep 17 00:00:00 2001
From: Sebastian Huber <sebastian.hu...@embedded-brains.de>
Date: Tue, 21 Jun 2016 07:45:19 +0200
Subject: [PATCH] score: _Thread_queue_Enqueue_critical()
Support absolute timeouts in _Thread_queue_Enqueue_critical().
---
cpukit/score/include/rtems/score/threadq.h | 5 +++++
cpukit/score/include/rtems/score/threadqimpl.h | 28 ++++++++++++++++++--------
cpukit/score/include/rtems/score/watchdog.h | 20 +++++++++++-------
cpukit/score/src/threadqenqueue.c | 27 +++++++++++++++++--------
4 files changed, 57 insertions(+), 23 deletions(-)
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index a4e5292..f0ebf13 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -24,6 +24,7 @@
#include <rtems/score/object.h>
#include <rtems/score/priority.h>
#include <rtems/score/rbtree.h>
+#include <rtems/score/watchdog.h>
#ifdef __cplusplus
extern "C" {
@@ -78,6 +79,10 @@ typedef struct {
*/
uint32_t expected_thread_dispatch_disable_level;
+ Watchdog_Dicipline timeout_discipline;
+
+ uint64_t timeout_interval;
+
/**
* @brief Callout to unblock the thread in case it is actually a thread
* proxy.
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index 73d4de2..48cb9d6 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -62,16 +62,34 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Context_initialize(
Thread_queue_Context *queue_context
)
{
+ queue_context->timeout_discipline = WATCHDOG_NO_TIMEOUT;
+
#if defined(RTEMS_DEBUG)
queue_context->expected_thread_dispatch_disable_level = 0xdeadbeef;
#if defined(RTEMS_MULTIPROCESSING)
queue_context->mp_callout = NULL;
#endif
-#else
- (void) queue_context;
#endif
}
+RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_relative_timeout(
+ Thread_queue_Context *queue_context,
+ Watchdog_Interval timeout
+)
+{
+ queue_context->timeout_discipline = WATCHDOG_RELATIVE;
+ queue_context->timeout_interval = timeout;
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_absolute_timeout(
+ Thread_queue_Context *queue_context,
+ uint64_t timeout
+)
+{
+ queue_context->timeout_discipline = WATCHDOG_ABSOLUTE;
+ queue_context->timeout_interval = timeout;
+}
+
/**
* @brief Sets the expected thread dispatch disable level in the thread queue
* context.
@@ -348,8 +366,6 @@ Thread_Control *_Thread_queue_Do_dequeue(
* MUTEX_TQ_OPERATIONS,
* executing,
* STATES_WAITING_FOR_MUTEX,
- * WATCHDOG_NO_TIMEOUT,
- * 0,
* &queue_context
* );
* }
@@ -360,8 +376,6 @@ Thread_Control *_Thread_queue_Do_dequeue(
* @param[in] operations The thread queue operations.
* @param[in] the_thread The thread to enqueue.
* @param[in] state The new state of the thread.
- * @param[in] timeout Interval to wait. Use WATCHDOG_NO_TIMEOUT to block
- * potentially forever.
* @param[in] queue_context The thread queue context of the lock acquire.
*/
void _Thread_queue_Enqueue_critical(
@@ -369,7 +383,6 @@ void _Thread_queue_Enqueue_critical(
const Thread_queue_Operations *operations,
Thread_Control *the_thread,
States_Control state,
- Watchdog_Interval timeout,
Thread_queue_Context *queue_context
);
@@ -382,7 +395,6 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue(
const Thread_queue_Operations *operations,
Thread_Control *the_thread,
States_Control state,
- Watchdog_Interval timeout,
uint32_t expected_level
)
{
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
index c582dbd..1bf7d5c 100644
--- a/cpukit/score/include/rtems/score/watchdog.h
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -67,13 +67,19 @@ typedef void Watchdog_Service_routine;
typedef Watchdog_Service_routine
( *Watchdog_Service_routine_entry )( Watchdog_Control * );
-/**
- * @brief The constant for indefinite wait.
- *
- * This is the constant for indefinite wait. It is actually an
- * illegal interval.
- */
-#define WATCHDOG_NO_TIMEOUT 0
+typedef struct {
+ /**
+ * @brief The constant for indefinite wait.
+ *
+ * This is the constant for indefinite wait. It is actually an
+ * illegal interval.
+ */
+ WATCHDOG_NO_TIMEOUT,
+
+ WATCHDOG_RELATIVE,
+
+ WATCHDOG_ABSOLUTE
+} Watchdog_Dicipline;
/**
* @brief The watchdog header to manage scheduled watchdogs.
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 8bd1905..cbec7c7 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -39,7 +39,6 @@ void _Thread_queue_Enqueue_critical(
const Thread_queue_Operations *operations,
Thread_Control *the_thread,
States_Control state,
- Watchdog_Interval timeout,
Thread_queue_Context *queue_context
)
{
@@ -83,13 +82,25 @@ void _Thread_queue_Enqueue_critical(
/*
* If the thread wants to timeout, then schedule its timer.
*/
- if ( timeout != WATCHDOG_NO_TIMEOUT ) {
- _Thread_Timer_insert_relative(
- the_thread,
- cpu_self,
- _Thread_Timeout,
- timeout
- );
+ switch ( queue_context->timeout_discipline ) {
+ case WATCHDOG_RELATIVE:
+ _Thread_Timer_insert_relative(
+ the_thread,
+ cpu_self,
+ _Thread_Timeout,
+ (Watchdog_Interval) queue_context->timeout_interval
+ );
+ break;
+ case WATCHDOG_ABSOLUTE:
+ _Thread_Timer_insert_absolute(
+ the_thread,
+ cpu_self,
+ _Thread_Timeout,
+ queue_context->timeout_interval
+ );
+ break;
+ default:
+ break;
}
/*
--
1.8.4.5
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel