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 RTEMSScoreThreadMP
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _Thread_MP_Handler_initialization(), _Thread_MP_Allocate_proxy(),
0010  *   _Thread_MP_Find_proxy(), _Thread_MP_Free_proxy().
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 1989-2006.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <rtems/score/threadimpl.h>
0044 #include <rtems/score/isrlock.h>
0045 #include <rtems/score/schedulerimpl.h>
0046 
0047 #include <string.h>
0048 
0049 static RBTREE_DEFINE_EMPTY( _Thread_MP_Active_proxies );
0050 
0051 static CHAIN_DEFINE_EMPTY( _Thread_MP_Inactive_proxies );
0052 
0053 #if ISR_LOCK_NEEDS_OBJECT
0054 static ISR_lock_Control _Thread_MP_Proxies_lock =
0055   ISR_LOCK_INITIALIZER( "Thread MP Proxies" );
0056 #endif
0057 
0058 static void _Thread_MP_Proxies_acquire( ISR_lock_Context *lock_context )
0059 {
0060   _ISR_lock_ISR_disable_and_acquire( &_Thread_MP_Proxies_lock, lock_context );
0061 }
0062 
0063 static void _Thread_MP_Proxies_release( ISR_lock_Context *lock_context )
0064 {
0065   _ISR_lock_Release_and_ISR_enable( &_Thread_MP_Proxies_lock, lock_context );
0066 }
0067 
0068 void _Thread_MP_Handler_initialization (
0069   uint32_t    maximum_proxies
0070 )
0071 {
0072   size_t    proxy_size;
0073   char     *proxies;
0074   uint32_t  i;
0075 
0076   if ( maximum_proxies == 0 ) {
0077     return;
0078   }
0079 
0080   proxy_size = sizeof( Thread_Proxy_control ) + _Thread_queue_Heads_size;
0081   proxies = (char *) _Thread_MP_Proxies;
0082 
0083   _Chain_Initialize(
0084     &_Thread_MP_Inactive_proxies,
0085     proxies,
0086     maximum_proxies,
0087     proxy_size
0088   );
0089 
0090   for ( i = 0 ; i < maximum_proxies ; ++i ) {
0091     Thread_Proxy_control *proxy;
0092 
0093     proxy = (Thread_Proxy_control *) ( proxies + i * proxy_size );
0094 
0095     _Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) );
0096     _RBTree_Initialize_node( &proxy->Active );
0097 
0098     proxy->Scheduler.nodes = &proxy->Scheduler_node;
0099     _Scheduler_Node_do_initialize(
0100       &_Scheduler_Table[ 0 ],
0101       &proxy->Scheduler_node,
0102       (Thread_Control *) proxy,
0103       0
0104     );
0105 
0106     proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ];
0107     _Thread_queue_Heads_initialize( proxy->Wait.spare_heads );
0108   }
0109 }
0110 
0111 #define THREAD_MP_PROXY_OF_ACTIVE_NODE( the_node ) \
0112   RTEMS_CONTAINER_OF( the_node, Thread_Proxy_control, Active )
0113 
0114 static bool _Thread_MP_Proxy_equal(
0115   const void        *left,
0116   const RBTree_Node *right
0117 )
0118 {
0119   const Objects_Id           *the_left;
0120   const Thread_Proxy_control *the_right;
0121 
0122   the_left = left;
0123   the_right = THREAD_MP_PROXY_OF_ACTIVE_NODE( right );
0124 
0125   return *the_left == the_right->Object.id;
0126 }
0127 
0128 static bool _Thread_MP_Proxy_less(
0129   const void        *left,
0130   const RBTree_Node *right
0131 )
0132 {
0133   const Objects_Id           *the_left;
0134   const Thread_Proxy_control *the_right;
0135 
0136   the_left = left;
0137   the_right = THREAD_MP_PROXY_OF_ACTIVE_NODE( right );
0138 
0139   return *the_left < the_right->Object.id;
0140 }
0141 
0142 static void *_Thread_MP_Proxy_map( RBTree_Node *node )
0143 {
0144   return THREAD_MP_PROXY_OF_ACTIVE_NODE( node );
0145 }
0146 
0147 Thread_Control *_Thread_MP_Allocate_proxy (
0148   States_Control  the_state
0149 )
0150 {
0151   Thread_Proxy_control *the_proxy;
0152   ISR_lock_Context      lock_context;
0153 
0154   _Thread_MP_Proxies_acquire( &lock_context );
0155 
0156   the_proxy = (Thread_Proxy_control *)
0157     _Chain_Get_unprotected( &_Thread_MP_Inactive_proxies );
0158   if ( the_proxy != NULL ) {
0159     Thread_Control   *executing;
0160     MP_packet_Prefix *receive_packet;
0161     Objects_Id        source_tid;
0162 
0163     executing = _Thread_Executing;
0164     receive_packet = _MPCI_Receive_server_tcb->receive_packet;
0165     source_tid = receive_packet->source_tid;
0166 
0167     executing->Wait.return_code = STATUS_PROXY_BLOCKING;
0168 
0169     the_proxy->receive_packet = receive_packet;
0170     the_proxy->Object.id = source_tid;
0171     the_proxy->Real_priority.priority = receive_packet->source_priority;
0172     the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
0173 
0174     the_proxy->Wait.count                   = executing->Wait.count;
0175     the_proxy->Wait.return_argument         = executing->Wait.return_argument;
0176     the_proxy->Wait.return_argument_second  = executing->Wait.return_argument_second;
0177     the_proxy->Wait.option                  = executing->Wait.option;
0178     the_proxy->Wait.return_code             = executing->Wait.return_code;
0179 
0180     the_proxy->thread_queue_callout = _Thread_queue_MP_callout_do_nothing;
0181 
0182     _RBTree_Insert_inline(
0183       &_Thread_MP_Active_proxies,
0184       &the_proxy->Active,
0185       &source_tid,
0186       _Thread_MP_Proxy_less
0187     );
0188 
0189     _Thread_MP_Proxies_release( &lock_context );
0190 
0191     return (Thread_Control *) the_proxy;
0192   }
0193 
0194   _Thread_MP_Proxies_release( &lock_context );
0195 
0196   _Internal_error( INTERNAL_ERROR_OUT_OF_PROXIES );
0197 
0198   /*
0199    *  NOTE: The following return ensures that the compiler will
0200    *        think that all paths return a value.
0201    */
0202 
0203   return NULL;
0204 }
0205 
0206 Thread_Control *_Thread_MP_Find_proxy (
0207   Objects_Id  the_id
0208 )
0209 {
0210   Thread_Proxy_control *the_proxy;
0211   ISR_lock_Context      lock_context;
0212 
0213   _Thread_MP_Proxies_acquire( &lock_context );
0214 
0215   the_proxy = _RBTree_Find_inline(
0216     &_Thread_MP_Active_proxies,
0217     &the_id,
0218     _Thread_MP_Proxy_equal,
0219     _Thread_MP_Proxy_less,
0220     _Thread_MP_Proxy_map
0221   );
0222 
0223   _Thread_MP_Proxies_release( &lock_context );
0224 
0225   return (Thread_Control *) the_proxy;
0226 }
0227 
0228 void _Thread_MP_Free_proxy( Thread_Control *the_thread )
0229 {
0230   Thread_Proxy_control *the_proxy;
0231   ISR_lock_Context      lock_context;
0232 
0233   the_proxy = (Thread_Proxy_control *) the_thread;
0234 
0235   _Thread_MP_Proxies_acquire( &lock_context );
0236 
0237   _RBTree_Extract( &_Thread_MP_Active_proxies, &the_proxy->Active );
0238   _Chain_Append_unprotected(
0239     &_Thread_MP_Inactive_proxies,
0240     &the_proxy->Object.Node
0241   );
0242 
0243   _Thread_MP_Proxies_release( &lock_context );
0244 }