summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-19 13:47:57 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-24 10:19:05 +0200
commitc31058947491ca319c901040219be39e4f8155b6 (patch)
tree435bf0887bd77e3d344b31275853a6e52fca8dd8 /cpukit/score
parentscore: Rename function threadq support function (diff)
downloadrtems-c31058947491ca319c901040219be39e4f8155b6.tar.bz2
score: Move thread queue timeout handling
Update #3117. Update #3182.
Diffstat (limited to '')
-rw-r--r--cpukit/score/Makefile.am2
-rw-r--r--cpukit/score/include/rtems/score/coresemimpl.h1
-rw-r--r--cpukit/score/include/rtems/score/threadq.h33
-rw-r--r--cpukit/score/include/rtems/score/threadqimpl.h110
-rw-r--r--cpukit/score/include/rtems/score/todimpl.h40
-rw-r--r--cpukit/score/include/rtems/score/watchdog.h31
-rw-r--r--cpukit/score/include/rtems/score/watchdogimpl.h5
-rw-r--r--cpukit/score/src/apimutexlock.c2
-rw-r--r--cpukit/score/src/condition.c88
-rw-r--r--cpukit/score/src/corebarrierwait.c1
-rw-r--r--cpukit/score/src/coremsgseize.c1
-rw-r--r--cpukit/score/src/coremsgsubmit.c1
-rw-r--r--cpukit/score/src/coremutexseize.c1
-rw-r--r--cpukit/score/src/corerwlockobtainread.c1
-rw-r--r--cpukit/score/src/corerwlockobtainwrite.c1
-rw-r--r--cpukit/score/src/coretodabsolutetimeout.c82
-rw-r--r--cpukit/score/src/futex.c1
-rw-r--r--cpukit/score/src/mutex.c43
-rw-r--r--cpukit/score/src/semaphore.c1
-rw-r--r--cpukit/score/src/threadqenqueue.c54
-rw-r--r--cpukit/score/src/threadqtimeout.c154
-rw-r--r--cpukit/score/src/threadrestart.c2
22 files changed, 342 insertions, 313 deletions
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index f0c927b294..7ff1f41684 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -305,6 +305,7 @@ libscore_a_SOURCES += src/threadq.c \
src/threadqextractwithproxy.c src/threadqfirst.c \
src/threadqflush.c
libscore_a_SOURCES += src/threadqops.c
+libscore_a_SOURCES += src/threadqtimeout.c
## TIMESPEC_C_FILES
libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
@@ -316,7 +317,6 @@ libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
libscore_a_SOURCES += src/coretod.c src/coretodset.c \
src/coretodtickspersec.c \
src/coretodadjust.c
-libscore_a_SOURCES += src/coretodabsolutetimeout.c
## WATCHDOG_C_FILES
libscore_a_SOURCES += src/watchdoginsert.c
diff --git a/cpukit/score/include/rtems/score/coresemimpl.h b/cpukit/score/include/rtems/score/coresemimpl.h
index aa053d7acd..00f77e61dd 100644
--- a/cpukit/score/include/rtems/score/coresemimpl.h
+++ b/cpukit/score/include/rtems/score/coresemimpl.h
@@ -188,7 +188,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_semaphore_Seize(
queue_context,
STATES_WAITING_FOR_SEMAPHORE
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_semaphore->Wait_queue.Queue,
operations,
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index c4742ba05c..3e618bf5af 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -57,14 +57,16 @@ typedef struct Thread_queue_Operations Thread_queue_Operations;
*
* @param[in] queue The actual thread queue.
* @param[in] the_thread The thread to enqueue.
+ * @param[in] cpu_self The current processor.
* @param[in] queue_context The thread queue context of the lock acquire.
*
* @see _Thread_queue_Context_set_enqueue_callout().
*/
typedef void ( *Thread_queue_Enqueue_callout )(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Thread_queue_Context *queue_context
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ struct Per_CPU_Control *cpu_self,
+ Thread_queue_Context *queue_context
);
/**
@@ -202,22 +204,31 @@ struct Thread_queue_Context {
* @brief The enqueue callout for _Thread_queue_Enqueue().
*
* The callout is invoked after the release of the thread queue lock with
- * thread dispatching disabled. Afterwards the thread is blocked.
+ * thread dispatching disabled. Afterwards the thread is blocked. This
+ * callout must be used to install the thread watchdog for timeout handling.
*
* @see _Thread_queue_Enqueue_do_nothing_extra().
+ * _Thread_queue_Add_timeout_ticks(), and
+ * _Thread_queue_Add_timeout_realtime_timespec().
*/
Thread_queue_Enqueue_callout enqueue_callout;
/**
- * @brief The clock discipline for the interval timeout.
- * Use WATCHDOG_NO_TIMEOUT to block indefinitely.
- */
- Watchdog_Discipline timeout_discipline;
-
- /**
* @brief Interval to wait.
+ *
+ * May be used by the enqueue callout to register a timeout handler.
*/
- uint64_t timeout;
+ union {
+ /**
+ * @brief The timeout in ticks.
+ */
+ Watchdog_Interval ticks;
+
+ /**
+ * @brief The timeout argument, e.g. pointer to struct timespec.
+ */
+ const void *arg;
+ } Timeout;
#if defined(RTEMS_SMP)
/**
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index f74db96129..ecbd8fd42f 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -65,6 +65,28 @@ typedef struct {
void _Thread_queue_Enqueue_do_nothing_extra(
Thread_queue_Queue *queue,
Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
+ Thread_queue_Context *queue_context
+);
+
+void _Thread_queue_Add_timeout_ticks(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
+ Thread_queue_Context *queue_context
+);
+
+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
+);
+
+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
);
@@ -118,6 +140,40 @@ _Thread_queue_Context_set_thread_state(
}
/**
+ * @brief Sets the timeout ticks in the thread queue context.
+ *
+ * @param queue_context The thread queue context.
+ * @param ticks The timeout in ticks.
+ *
+ * @see _Thread_queue_Enqueue().
+ */
+RTEMS_INLINE_ROUTINE void
+_Thread_queue_Context_set_timeout_ticks(
+ Thread_queue_Context *queue_context,
+ Watchdog_Interval ticks
+)
+{
+ queue_context->Timeout.ticks = ticks;
+}
+
+/**
+ * @brief Sets the timeout argument in the thread queue context.
+ *
+ * @param queue_context The thread queue context.
+ * @param arg The timeout argument.
+ *
+ * @see _Thread_queue_Enqueue().
+ */
+RTEMS_INLINE_ROUTINE void
+_Thread_queue_Context_set_timeout_argument(
+ Thread_queue_Context *queue_context,
+ const void *arg
+)
+{
+ queue_context->Timeout.arg = arg;
+}
+
+/**
* @brief Sets the enqueue callout in the thread queue context.
*
* @param queue_context The thread queue context.
@@ -150,55 +206,61 @@ _Thread_queue_Context_set_enqueue_do_nothing_extra(
}
/**
- * @brief Sets an indefinite timeout interval in the thread queue context.
+ * @brief Sets the enqueue callout to add a relative monotonic timeout in
+ * ticks.
*
* @param queue_context The thread queue context.
- * @param timeout The new timeout.
+ * @param ticks The timeout in ticks.
*
* @see _Thread_queue_Enqueue().
*/
RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_no_timeout(
- Thread_queue_Context *queue_context
+_Thread_queue_Context_set_enqueue_timeout_ticks(
+ Thread_queue_Context *queue_context,
+ Watchdog_Interval ticks
)
{
- queue_context->timeout_discipline = WATCHDOG_NO_TIMEOUT;
+ queue_context->Timeout.ticks = ticks;
+ queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks;
}
/**
- * @brief Sets a relative timeout in the thread queue context.
+ * @brief Sets the enqueue callout to add an absolute monotonic timeout in
+ * timespec format.
*
* @param queue_context The thread queue context.
- * @param discipline The clock discipline to use for the timeout.
+ * @param abstime The absolute monotonic timeout.
*
* @see _Thread_queue_Enqueue().
*/
RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_relative_timeout(
- Thread_queue_Context *queue_context,
- Watchdog_Interval timeout
+_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
+ Thread_queue_Context *queue_context,
+ const struct timespec *abstime
)
{
- queue_context->timeout_discipline = WATCHDOG_RELATIVE;
- queue_context->timeout = timeout;
+ queue_context->Timeout.arg = abstime;
+ queue_context->enqueue_callout =
+ _Thread_queue_Add_timeout_monotonic_timespec;
}
/**
- * @brief Sets an absolute timeout in the thread queue context.
+ * @brief Sets the enqueue callout to add an absolute realtime timeout in
+ * timespec format.
*
* @param queue_context The thread queue context.
- * @param discipline The clock discipline to use for the timeout.
+ * @param abstime The absolute realtime timeout.
*
* @see _Thread_queue_Enqueue().
*/
RTEMS_INLINE_ROUTINE void
-_Thread_queue_Context_set_absolute_timeout(
- Thread_queue_Context *queue_context,
- uint64_t timeout
+_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+ Thread_queue_Context *queue_context,
+ const struct timespec *abstime
)
{
- queue_context->timeout_discipline = WATCHDOG_ABSOLUTE;
- queue_context->timeout = timeout;
+ queue_context->Timeout.arg = abstime;
+ queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec;
}
/**
@@ -615,11 +677,10 @@ Thread_Control *_Thread_queue_Do_dequeue(
* - _Thread_queue_Context_set_thread_state(),
*
* - _Thread_queue_Context_set_enqueue_callout() or
- * _Thread_queue_Context_set_enqueue_do_nothing_extra(),
- *
- * - _Thread_queue_Context_set_no_timeout() or
- * _Thread_queue_Context_set_relative_timeout() or
- * _Thread_queue_Context_set_absolute_timeout(), and
+ * _Thread_queue_Context_set_enqueue_do_nothing_extra() or
+ * _Thread_queue_Context_set_enqueue_timeout_ticks() or
+ * _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or
+ * _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(),
*
* - _Thread_queue_Context_set_deadlock_callout().
*
@@ -652,7 +713,6 @@ Thread_Control *_Thread_queue_Do_dequeue(
* STATES_WAITING_FOR_MUTEX
* );
* _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
- * _Thread_queue_Context_set_no_timeout( &queue_context );
* _Thread_queue_Context_set_deadlock_callout(
* queue_context,
* _Thread_queue_Deadlock_fatal
diff --git a/cpukit/score/include/rtems/score/todimpl.h b/cpukit/score/include/rtems/score/todimpl.h
index de4dc93430..e3a1a8f58c 100644
--- a/cpukit/score/include/rtems/score/todimpl.h
+++ b/cpukit/score/include/rtems/score/todimpl.h
@@ -298,46 +298,6 @@ RTEMS_INLINE_ROUTINE bool _TOD_Is_set( void )
return _TOD.is_set;
}
-/**
- * @brief Absolute timeout conversion results.
- *
- * This enumeration defines the possible results of converting
- * an absolute time used for timeouts to POSIX blocking calls to
- * a number of ticks for example.
- */
-typedef enum {
- /** The timeout is invalid. */
- TOD_ABSOLUTE_TIMEOUT_INVALID,
- /** The timeout represents a time that is in the past. */
- TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST,
- /** The timeout represents a time that is equal to the current time. */
- TOD_ABSOLUTE_TIMEOUT_IS_NOW,
- /** The timeout represents a time that is in the future. */
- TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
-} TOD_Absolute_timeout_conversion_results;
-
-/**
- * @brief Convert absolute timeout to ticks.
- *
- * This method takes an absolute time being used as a timeout
- * to a blocking directive, validates it and returns the number
- * of corresponding clock ticks for use by the SuperCore.
- *
- * @param[in] abstime is a pointer to the timeout
- * @param[in] clock is the time source to use for the timeout
- * @param[out] ticks_out will contain the number of ticks
- *
- * @return This method returns the number of ticks in @a ticks_out
- * and a status value indicating whether the absolute time
- * is valid, in the past, equal to the current time or in
- * the future as it should be.
- */
-TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
- const struct timespec *abstime,
- clockid_t clock,
- Watchdog_Interval *ticks_out
-);
-
/**@}*/
#ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
index a379bf7a23..dbb092bbef 100644
--- a/cpukit/score/include/rtems/score/watchdog.h
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -53,36 +53,9 @@ typedef struct Watchdog_Control Watchdog_Control;
typedef uint32_t Watchdog_Interval;
/**
- * @brief The clock discipline to use for the Watchdog timeout interval.
+ * @brief Special watchdog ticks value to indicate an infinite wait.
*/
-typedef enum {
-
- /**
- * @brief Indefinite wait.
- *
- * This is to indicate there is no timeout and not to use a watchdog. It
- * must be equal to 0, which is an illegal relative clock interval, so that
- * it may be used as a Watchdog_Interval value with WATCHDOG_RELATIVE to
- * express an indefinite wait.
- */
- WATCHDOG_NO_TIMEOUT = 0,
-
- /**
- * @brief Relative clock.
- *
- * The reference time point for the watchdog is current ticks value
- * during insert. Time is measured in clock ticks.
- */
- WATCHDOG_RELATIVE,
-
- /**
- * @brief Absolute clock.
- *
- * The reference time point for this header is the POSIX Epoch. Time is
- * measured in nanoseconds since POSIX Epoch.
- */
- WATCHDOG_ABSOLUTE
-} Watchdog_Discipline;
+#define WATCHDOG_NO_TIMEOUT 0
/**
* @brief Return type from a Watchdog Service Routine.
diff --git a/cpukit/score/include/rtems/score/watchdogimpl.h b/cpukit/score/include/rtems/score/watchdogimpl.h
index 1fa67f3961..7866c0ce44 100644
--- a/cpukit/score/include/rtems/score/watchdogimpl.h
+++ b/cpukit/score/include/rtems/score/watchdogimpl.h
@@ -284,6 +284,11 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
}
}
+/**
+ * @brief The maximum watchdog ticks value for the far future.
+ */
+#define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
+
#define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
/**
diff --git a/cpukit/score/src/apimutexlock.c b/cpukit/score/src/apimutexlock.c
index 879562d9f0..312dcc2993 100644
--- a/cpukit/score/src/apimutexlock.c
+++ b/cpukit/score/src/apimutexlock.c
@@ -33,7 +33,7 @@ void _API_Mutex_Lock( API_Mutex_Control *the_mutex )
_Thread_queue_Context_initialize( &queue_context );
_ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
- _Thread_queue_Context_set_no_timeout( &queue_context );
+ _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
_CORE_recursive_mutex_Seize(
&the_mutex->Mutex,
CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
diff --git a/cpukit/score/src/condition.c b/cpukit/score/src/condition.c
index bbbeb901db..9913d86d34 100644
--- a/cpukit/score/src/condition.c
+++ b/cpukit/score/src/condition.c
@@ -84,16 +84,38 @@ typedef struct {
struct _Mutex_Control *mutex;
} Condition_Enqueue_context;
-static void _Condition_Enqueue_callout(
+static void _Condition_Mutex_release( Thread_queue_Context *queue_context )
+{
+ Condition_Enqueue_context *context;
+
+ context = (Condition_Enqueue_context *) queue_context;
+ _Mutex_Release( context->mutex );
+}
+
+static void _Condition_Enqueue_no_timeout(
Thread_queue_Queue *queue,
Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
Thread_queue_Context *queue_context
)
{
- Condition_Enqueue_context *context;
+ _Condition_Mutex_release( queue_context );
+}
- context = (Condition_Enqueue_context *) queue_context;
- _Mutex_Release( context->mutex );
+static void _Condition_Enqueue_with_timeout(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
+ Thread_queue_Context *queue_context
+)
+{
+ _Thread_queue_Add_timeout_realtime_timespec(
+ queue,
+ the_thread,
+ cpu_self,
+ queue_context
+ );
+ _Condition_Mutex_release( queue_context );
}
static Thread_Control *_Condition_Do_wait(
@@ -107,15 +129,12 @@ static Thread_Control *_Condition_Do_wait(
context->mutex = _mutex;
condition = _Condition_Get( _condition );
+ _ISR_lock_ISR_disable( &context->Base.Lock_context.Lock_context );
executing = _Condition_Queue_acquire_critical( condition, &context->Base );
_Thread_queue_Context_set_thread_state(
&context->Base,
STATES_WAITING_FOR_CONDITION_VARIABLE
);
- _Thread_queue_Context_set_enqueue_callout(
- &context->Base,
- _Condition_Enqueue_callout
- );
_Thread_queue_Enqueue(
&condition->Queue.Queue,
CONDITION_TQ_OPERATIONS,
@@ -134,8 +153,10 @@ void _Condition_Wait(
Condition_Enqueue_context context;
_Thread_queue_Context_initialize( &context.Base );
- _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
- _Thread_queue_Context_set_no_timeout( &context.Base );
+ _Thread_queue_Context_set_enqueue_callout(
+ &context.Base,
+ _Condition_Enqueue_no_timeout
+ );
_Condition_Do_wait( _condition, _mutex, &context );
_Mutex_Acquire( _mutex );
}
@@ -149,24 +170,13 @@ int _Condition_Wait_timed(
Condition_Enqueue_context context;
Thread_Control *executing;
int eno;
- Watchdog_Interval ticks;
_Thread_queue_Context_initialize( &context.Base );
- _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-
- switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
- case TOD_ABSOLUTE_TIMEOUT_INVALID:
- _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
- return EINVAL;
- case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
- case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
- _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
- return ETIMEDOUT;
- default:
- break;
- }
-
- _Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
+ _Thread_queue_Context_set_enqueue_callout(
+ &context.Base,
+ _Condition_Enqueue_with_timeout
+ );
+ _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
executing = _Condition_Do_wait( _condition, _mutex, &context );
eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
_Mutex_Acquire( _mutex );
@@ -195,8 +205,10 @@ void _Condition_Wait_recursive(
unsigned int nest_level;
_Thread_queue_Context_initialize( &context.Base );
- _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
- _Thread_queue_Context_set_no_timeout( &context.Base );
+ _Thread_queue_Context_set_enqueue_callout(
+ &context.Base,
+ _Condition_Enqueue_no_timeout
+ );
nest_level = _Condition_Unnest_mutex( _mutex );
_Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
_Mutex_recursive_Acquire( _mutex );
@@ -213,23 +225,13 @@ int _Condition_Wait_recursive_timed(
Thread_Control *executing;
int eno;
unsigned int nest_level;
- Watchdog_Interval ticks;
_Thread_queue_Context_initialize( &context.Base );
- _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
-
- switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
- case TOD_ABSOLUTE_TIMEOUT_INVALID:
- _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
- return EINVAL;
- case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
- case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
- _ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
- return ETIMEDOUT;
- default:
- break;
- }
- _Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
+ _Thread_queue_Context_set_enqueue_callout(
+ &context.Base,
+ _Condition_Enqueue_with_timeout
+ );
+ _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
nest_level = _Condition_Unnest_mutex( _mutex );
executing = _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c
index 5093e02bc0..08acce9d86 100644
--- a/cpukit/score/src/corebarrierwait.c
+++ b/cpukit/score/src/corebarrierwait.c
@@ -48,7 +48,6 @@ Status_Control _CORE_barrier_Seize(
queue_context,
STATES_WAITING_FOR_BARRIER
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_barrier->Wait_queue.Queue,
CORE_BARRIER_TQ_OPERATIONS,
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
index 5d0b95b9e5..e3d8842831 100644
--- a/cpukit/score/src/coremsgseize.c
+++ b/cpukit/score/src/coremsgseize.c
@@ -117,7 +117,6 @@ Status_Control _CORE_message_queue_Seize(
queue_context,
STATES_WAITING_FOR_MESSAGE
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_message_queue->Wait_queue.Queue,
the_message_queue->operations,
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
index 6040f76eb3..49c90256cd 100644
--- a/cpukit/score/src/coremsgsubmit.c
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -135,7 +135,6 @@ Status_Control _CORE_message_queue_Submit(
queue_context,
STATES_WAITING_FOR_MESSAGE
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_message_queue->Wait_queue.Queue,
the_message_queue->operations,
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
index 173c495d3c..e07458573d 100644
--- a/cpukit/score/src/coremutexseize.c
+++ b/cpukit/score/src/coremutexseize.c
@@ -36,7 +36,6 @@ Status_Control _CORE_mutex_Seize_slow(
queue_context,
STATES_WAITING_FOR_MUTEX
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Context_set_deadlock_callout(
queue_context,
_Thread_queue_Deadlock_status
diff --git a/cpukit/score/src/corerwlockobtainread.c b/cpukit/score/src/corerwlockobtainread.c
index 88853ebfb3..6969486f28 100644
--- a/cpukit/score/src/corerwlockobtainread.c
+++ b/cpukit/score/src/corerwlockobtainread.c
@@ -77,7 +77,6 @@ Status_Control _CORE_RWLock_Seize_for_reading(
queue_context,
STATES_WAITING_FOR_RWLOCK
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_rwlock->Queue.Queue,
CORE_RWLOCK_TQ_OPERATIONS,
diff --git a/cpukit/score/src/corerwlockobtainwrite.c b/cpukit/score/src/corerwlockobtainwrite.c
index 6145fc3c4c..7b296169d9 100644
--- a/cpukit/score/src/corerwlockobtainwrite.c
+++ b/cpukit/score/src/corerwlockobtainwrite.c
@@ -71,7 +71,6 @@ Status_Control _CORE_RWLock_Seize_for_writing(
queue_context,
STATES_WAITING_FOR_RWLOCK
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Enqueue(
&the_rwlock->Queue.Queue,
CORE_RWLOCK_TQ_OPERATIONS,
diff --git a/cpukit/score/src/coretodabsolutetimeout.c b/cpukit/score/src/coretodabsolutetimeout.c
deleted file mode 100644
index d67b7c33c7..0000000000
--- a/cpukit/score/src/coretodabsolutetimeout.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file
- *
- * @brief Convert Absolute Timeout to Ticks
- * @ingroup ScoreTOD
- */
-
-/*
- * 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/todimpl.h>
-
-/*
- * The abstime is a walltime. We turn it into an interval.
- */
-TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
- const struct timespec *abstime,
- clockid_t clock,
- Watchdog_Interval *ticks_out
-)
-{
- struct timespec current_time;
- struct timespec difference;
-
- /*
- * Make sure there is always a value returned.
- */
- *ticks_out = 0;
-
- /*
- * Is the absolute time even valid?
- */
- if ( !_Timespec_Is_valid(abstime) )
- return TOD_ABSOLUTE_TIMEOUT_INVALID;
-
- /*
- * Is the absolute time in the past?
- */
- if ( clock == CLOCK_REALTIME ) {
- _TOD_Get( &current_time );
- } else {
- _Assert( clock == CLOCK_MONOTONIC );
- _TOD_Get_zero_based_uptime_as_timespec( &current_time );
- }
-
- if ( _Timespec_Less_than( abstime, &current_time ) )
- return TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST;
-
- /*
- * How long until the requested absolute time?
- */
- _Timespec_Subtract( &current_time, abstime, &difference );
-
- /*
- * Internally the SuperCore uses ticks, so convert to them.
- */
- *ticks_out = _Timespec_To_ticks( &difference );
-
- /*
- * If the difference was 0, then the future is now. It is so bright
- * we better wear shades.
- */
- if ( !*ticks_out )
- return TOD_ABSOLUTE_TIMEOUT_IS_NOW;
-
- /*
- * This is the case we were expecting and it took this long to
- * get here.
- */
- return TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
-}
-
diff --git a/cpukit/score/src/futex.c b/cpukit/score/src/futex.c
index c5b4f197c3..6487882819 100644
--- a/cpukit/score/src/futex.c
+++ b/cpukit/score/src/futex.c
@@ -95,7 +95,6 @@ int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
STATES_WAITING_FOR_FUTEX
);
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
- _Thread_queue_Context_set_no_timeout( &queue_context );
_Thread_queue_Context_set_ISR_level( &queue_context, level );
_Thread_queue_Enqueue(
&futex->Queue.Queue,
diff --git a/cpukit/score/src/mutex.c b/cpukit/score/src/mutex.c
index 1c793ad633..e2f5bb52fc 100644
--- a/cpukit/score/src/mutex.c
+++ b/cpukit/score/src/mutex.c
@@ -102,7 +102,6 @@ static void _Mutex_Acquire_slow(
queue_context,
STATES_WAITING_FOR_MUTEX
);
- _Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
_Thread_queue_Context_set_deadlock_callout(
queue_context,
_Thread_queue_Deadlock_fatal
@@ -163,7 +162,7 @@ void _Mutex_Acquire( struct _Mutex_Control *_mutex )
_Thread_Resource_count_increment( executing );
_Mutex_Queue_release( mutex, level, &queue_context );
} else {
- _Thread_queue_Context_set_no_timeout( &queue_context );
+ _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
_Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
}
}
@@ -193,21 +192,10 @@ int _Mutex_Acquire_timed(
return 0;
} else {
- Watchdog_Interval ticks;
-
- switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
- case TOD_ABSOLUTE_TIMEOUT_INVALID:
- _Mutex_Queue_release( mutex, level, &queue_context );
- return EINVAL;
- case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
- case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
- _Mutex_Queue_release( mutex, level, &queue_context );
- return ETIMEDOUT;
- default:
- break;
- }
-
- _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+ _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+ &queue_context,
+ abstime
+ );
_Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
@@ -290,7 +278,7 @@ void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
++mutex->nest_level;
_Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
} else {
- _Thread_queue_Context_set_no_timeout( &queue_context );
+ _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
_Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
}
}
@@ -325,21 +313,10 @@ int _Mutex_recursive_Acquire_timed(
return 0;
} else {
- Watchdog_Interval ticks;
-
- switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
- case TOD_ABSOLUTE_TIMEOUT_INVALID:
- _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
- return EINVAL;
- case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
- case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
- _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
- return ETIMEDOUT;
- default:
- break;
- }
-
- _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
+ _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
+ &queue_context,
+ abstime
+ );
_Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c
index a912fbc4d2..4edd25a387 100644
--- a/cpukit/score/src/semaphore.c
+++ b/cpukit/score/src/semaphore.c
@@ -61,7 +61,6 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem )
STATES_WAITING_FOR_SEMAPHORE
);
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
- _Thread_queue_Context_set_no_timeout( &queue_context );
_Thread_queue_Context_set_ISR_level( &queue_context, level );
_Thread_queue_Enqueue(
&sem->Queue.Queue,
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 40fb69bbd3..62d3671222 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -359,6 +359,7 @@ bool _Thread_queue_Path_acquire_critical(
void _Thread_queue_Enqueue_do_nothing_extra(
Thread_queue_Queue *queue,
Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
Thread_queue_Context *queue_context
)
{
@@ -375,36 +376,6 @@ void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread )
_Internal_error( INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK );
}
-static void _Thread_queue_Timeout(
- Thread_Control *the_thread,
- Per_CPU_Control *cpu_self,
- Thread_queue_Context *queue_context
-)
-{
- switch ( queue_context->timeout_discipline ) {
- case WATCHDOG_RELATIVE:
- /* A relative timeout of 0 is a special case indefinite (no) timeout */
- if ( queue_context->timeout != 0 ) {
- _Thread_Add_timeout_ticks(
- the_thread,
- cpu_self,
- (Watchdog_Interval) queue_context->timeout
- );
- }
- break;
- case WATCHDOG_ABSOLUTE:
- _Thread_Timer_insert_realtime(
- the_thread,
- cpu_self,
- _Thread_Timeout,
- queue_context->timeout
- );
- break;
- default:
- break;
- }
-}
-
void _Thread_queue_Enqueue(
Thread_queue_Queue *queue,
const Thread_queue_Operations *operations,
@@ -416,7 +387,6 @@ void _Thread_queue_Enqueue(
bool success;
_Assert( queue_context->enqueue_callout != NULL );
- _Assert( (uint8_t) queue_context->timeout_discipline != 0x7f );
#if defined(RTEMS_MULTIPROCESSING)
if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
@@ -447,7 +417,12 @@ void _Thread_queue_Enqueue(
cpu_self = _Thread_queue_Dispatch_disable( queue_context );
_Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
- ( *queue_context->enqueue_callout )( queue, the_thread, queue_context );
+ ( *queue_context->enqueue_callout )(
+ queue,
+ the_thread,
+ cpu_self,
+ queue_context
+ );
/*
* Set the blocking state for this thread queue in the thread.
@@ -455,11 +430,6 @@ void _Thread_queue_Enqueue(
_Thread_Set_state( the_thread, queue_context->thread_state );
/*
- * If the thread wants to timeout, then schedule its timer.
- */
- _Thread_queue_Timeout( the_thread, cpu_self, queue_context );
-
- /*
* At this point thread dispatching is disabled, however, we already released
* the thread queue lock. Thus, interrupts or threads on other processors
* may already changed our state with respect to the thread queue object.
@@ -491,6 +461,8 @@ Status_Control _Thread_queue_Enqueue_sticky(
{
Per_CPU_Control *cpu_self;
+ _Assert( queue_context->enqueue_callout != NULL );
+
_Thread_Wait_claim( the_thread, queue );
if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
@@ -519,7 +491,13 @@ Status_Control _Thread_queue_Enqueue_sticky(
);
}
- _Thread_queue_Timeout( the_thread, cpu_self, queue_context );
+ ( *queue_context->enqueue_callout )(
+ queue,
+ the_thread,
+ cpu_self,
+ queue_context
+ );
+
_Thread_Priority_update( queue_context );
_Thread_Priority_and_sticky_update( the_thread, 1 );
_Thread_Dispatch_enable( cpu_self );
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 );
+ }
+}
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 7ee1f880c4..0430ca0407 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -514,6 +514,7 @@ void _Thread_Cancel(
static void _Thread_Close_enqueue_callout(
Thread_queue_Queue *queue,
Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
Thread_queue_Context *queue_context
)
{
@@ -534,7 +535,6 @@ void _Thread_Close(
&context->Base,
_Thread_Close_enqueue_callout
);
- _Thread_queue_Context_set_no_timeout( &context->Base );
_Thread_State_acquire_critical(
the_thread,
&context->Base.Lock_context.Lock_context