Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:27

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreThreadQueue
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _Thread_queue_Flush_default_filter(),
0010  *   _Thread_queue_Flush_status_object_was_deleted(),
0011  *   _Thread_queue_Flush_status_unavailable(), and
0012  *   _Thread_queue_Flush_critical().
0013  */
0014 
0015 /*
0016  *  COPYRIGHT (c) 1989-2008.
0017  *  On-Line Applications Research Corporation (OAR).
0018  *
0019  * Redistribution and use in source and binary forms, with or without
0020  * modification, are permitted provided that the following conditions
0021  * are met:
0022  * 1. Redistributions of source code must retain the above copyright
0023  *    notice, this list of conditions and the following disclaimer.
0024  * 2. Redistributions in binary form must reproduce the above copyright
0025  *    notice, this list of conditions and the following disclaimer in the
0026  *    documentation and/or other materials provided with the distribution.
0027  *
0028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0029  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0030  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0031  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0032  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0033  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0034  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0035  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0036  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0037  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0038  * POSSIBILITY OF SUCH DAMAGE.
0039  */
0040 
0041 #ifdef HAVE_CONFIG_H
0042 #include "config.h"
0043 #endif
0044 
0045 #include <rtems/score/threadimpl.h>
0046 #include <rtems/score/schedulerimpl.h>
0047 #include <rtems/score/status.h>
0048 
0049 Thread_Control *_Thread_queue_Flush_default_filter(
0050   Thread_Control       *the_thread,
0051   Thread_queue_Queue   *queue,
0052   Thread_queue_Context *queue_context
0053 )
0054 {
0055   (void) queue;
0056   (void) queue_context;
0057   return the_thread;
0058 }
0059 
0060 Thread_Control *_Thread_queue_Flush_status_object_was_deleted(
0061   Thread_Control       *the_thread,
0062   Thread_queue_Queue   *queue,
0063   Thread_queue_Context *queue_context
0064 )
0065 {
0066   the_thread->Wait.return_code = STATUS_OBJECT_WAS_DELETED;
0067 
0068   (void) queue;
0069   (void) queue_context;
0070   return the_thread;
0071 }
0072 
0073 Thread_Control *_Thread_queue_Flush_status_unavailable(
0074   Thread_Control       *the_thread,
0075   Thread_queue_Queue   *queue,
0076   Thread_queue_Context *queue_context
0077 )
0078 {
0079   the_thread->Wait.return_code = STATUS_UNAVAILABLE;
0080 
0081   (void) queue;
0082   (void) queue_context;
0083   return the_thread;
0084 }
0085 
0086 size_t _Thread_queue_Flush_critical(
0087   Thread_queue_Queue            *queue,
0088   const Thread_queue_Operations *operations,
0089   Thread_queue_Flush_filter      filter,
0090   Thread_queue_Context          *queue_context
0091 )
0092 {
0093   size_t        flushed;
0094   size_t        priority_updates;
0095   Chain_Control unblock;
0096   Chain_Node   *node;
0097   Chain_Node   *tail;
0098 
0099   flushed = 0;
0100   priority_updates = 0;
0101   _Chain_Initialize_empty( &unblock );
0102 
0103   while ( true ) {
0104     Thread_queue_Heads *heads;
0105     Thread_Control     *first;
0106     bool                do_unblock;
0107 
0108     heads = queue->heads;
0109     if ( heads == NULL ) {
0110       break;
0111     }
0112 
0113     first = ( *operations->first )( heads );
0114     first = ( *filter )( first, queue, queue_context );
0115     if ( first == NULL ) {
0116       break;
0117     }
0118 
0119     /*
0120      * We do not have enough space in the queue context to collect all priority
0121      * updates, so clear it each time and accumulate the priority updates.
0122      */
0123     _Thread_queue_Context_clear_priority_updates( queue_context );
0124 
0125     do_unblock = _Thread_queue_Extract_locked(
0126       queue,
0127       operations,
0128       first,
0129       queue_context
0130     );
0131     if ( do_unblock ) {
0132       Scheduler_Node *scheduler_node;
0133 
0134       scheduler_node = _Thread_Scheduler_get_home_node( first );
0135       _Chain_Append_unprotected(
0136         &unblock,
0137         &scheduler_node->Wait.Priority.Node.Node.Chain
0138       );
0139     }
0140 
0141     priority_updates +=
0142       _Thread_queue_Context_get_priority_updates( queue_context );
0143     ++flushed;
0144   }
0145 
0146   node = _Chain_First( &unblock );
0147   tail = _Chain_Tail( &unblock );
0148 
0149   if ( node != tail ) {
0150     Per_CPU_Control *cpu_self;
0151 
0152     cpu_self = _Thread_queue_Dispatch_disable( queue_context );
0153     _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
0154 
0155     do {
0156       Scheduler_Node *scheduler_node;
0157       Thread_Control *the_thread;
0158       Chain_Node     *next;
0159 
0160       next = _Chain_Next( node );
0161       scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node );
0162       the_thread = _Scheduler_Node_get_owner( scheduler_node );
0163       _Thread_Remove_timer_and_unblock( the_thread, queue );
0164 
0165       node = next;
0166     } while ( node != tail );
0167 
0168     if ( priority_updates != 0 ) {
0169       Thread_Control  *owner;
0170       ISR_lock_Context lock_context;
0171 
0172       owner = queue->owner;
0173       _Assert( owner != NULL );
0174       _Thread_State_acquire( owner, &lock_context );
0175       _Scheduler_Update_priority( owner );
0176       _Thread_State_release( owner, &lock_context );
0177     }
0178 
0179     _Thread_Dispatch_enable( cpu_self );
0180   } else {
0181     _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
0182   }
0183 
0184   return flushed;
0185 }