summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-08-31 11:03:57 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-09-01 20:24:57 +0200
commitd9249c9bffe4238e3853996d1f0758d9f55fbe67 (patch)
tree95e948656a5ca4c639cda76d0c34728d7af98fe0 /cpukit/score
parentscore: Fix priority discipline handling (diff)
downloadrtems-d9249c9bffe4238e3853996d1f0758d9f55fbe67.tar.bz2
score: Fix blocking message queue receive
In order to ensure FIFO fairness across schedulers, the thread queue surrender operation must be used to dequeue a thread from the thread queue. The thread queue extract operation is intended for timeouts. Add _Thread_queue_Resume() which may be used to make extracted or surrendered threads ready again. Remove the now unused _Thread_queue_Extract_critical() function. Close #4509.
Diffstat (limited to 'cpukit/score')
-rw-r--r--cpukit/score/src/coremsgseize.c20
-rw-r--r--cpukit/score/src/threadqenqueue.c45
2 files changed, 37 insertions, 28 deletions
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
index e44538ee17..148e9dbb3c 100644
--- a/cpukit/score/src/coremsgseize.c
+++ b/cpukit/score/src/coremsgseize.c
@@ -56,7 +56,8 @@ Status_Control _CORE_message_queue_Seize(
return STATUS_SUCCESSFUL;
#else
{
- Thread_Control *the_thread;
+ Thread_queue_Heads *heads;
+ Thread_Control *the_thread;
/*
* There could be a thread waiting to send a message. If there
@@ -65,11 +66,8 @@ Status_Control _CORE_message_queue_Seize(
* NOTE: If we note that the queue was not full before this receive,
* then we can avoid this dequeue.
*/
- the_thread = _Thread_queue_First_locked(
- &the_message_queue->Wait_queue,
- the_message_queue->operations
- );
- if ( the_thread == NULL ) {
+ heads = the_message_queue->Wait_queue.Queue.heads;
+ if ( heads == NULL ) {
_CORE_message_queue_Free_message_buffer(
the_message_queue,
the_message
@@ -78,6 +76,13 @@ Status_Control _CORE_message_queue_Seize(
return STATUS_SUCCESSFUL;
}
+ the_thread = ( *the_message_queue->operations->surrender )(
+ &the_message_queue->Wait_queue.Queue,
+ heads,
+ NULL,
+ queue_context
+ );
+
/*
* There was a thread waiting to send a message. This code
* puts the messages in the message queue on behalf of the
@@ -90,9 +95,8 @@ Status_Control _CORE_message_queue_Seize(
(size_t) the_thread->Wait.option,
(CORE_message_queue_Submit_types) the_thread->Wait.count
);
- _Thread_queue_Extract_critical(
+ _Thread_queue_Resume(
&the_message_queue->Wait_queue.Queue,
- the_message_queue->operations,
the_thread,
queue_context
);
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index d165e30da7..833d37ee61 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -7,9 +7,10 @@
* _Thread_queue_Deadlock_fatal(), _Thread_queue_Deadlock_status(),
* _Thread_queue_Do_dequeue(), _Thread_queue_Enqueue(),
* _Thread_queue_Enqueue_do_nothing_extra(), _Thread_queue_Enqueue_sticky(),
- * _Thread_queue_Extract(), _Thread_queue_Extract_critical(),
- * _Thread_queue_Extract_locked(), _Thread_queue_Path_acquire_critical(),
- * _Thread_queue_Path_release_critical(), _Thread_queue_Surrender(),
+ * _Thread_queue_Extract(), _Thread_queue_Extract_locked(),
+ * _Thread_queue_Path_acquire_critical(),
+ * _Thread_queue_Path_release_critical(),
+ * _Thread_queue_Resume(),_Thread_queue_Surrender(),
* _Thread_queue_Surrender_sticky(), and _Thread_queue_Unblock_critical().
*/
@@ -604,28 +605,32 @@ void _Thread_queue_Unblock_critical(
}
}
-void _Thread_queue_Extract_critical(
- Thread_queue_Queue *queue,
- const Thread_queue_Operations *operations,
- Thread_Control *the_thread,
- Thread_queue_Context *queue_context
+void _Thread_queue_Resume(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
bool unblock;
- unblock = _Thread_queue_Extract_locked(
- queue,
- operations,
- the_thread,
- queue_context
- );
+ unblock = _Thread_queue_Make_ready_again( the_thread );
- _Thread_queue_Unblock_critical(
- unblock,
- queue,
- the_thread,
- &queue_context->Lock_context.Lock_context
- );
+ if ( unblock ) {
+ Per_CPU_Control *cpu_self;
+
+ cpu_self = _Thread_queue_Dispatch_disable( queue_context );
+ _Thread_queue_Queue_release(
+ queue, &queue_context->Lock_context.Lock_context
+ );
+
+ _Thread_Remove_timer_and_unblock( the_thread, queue );
+
+ _Thread_Dispatch_enable( cpu_self );
+ } else {
+ _Thread_queue_Queue_release(
+ queue, &queue_context->Lock_context.Lock_context
+ );
+ }
}
void _Thread_queue_Extract( Thread_Control *the_thread )