Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreObjectMP
0007  *
0008  * @brief This source file contains the definition of
0009  *   ::_Objects_Local_node, ::_Objects_Maximum_nodes,
0010  *   ::_Objects_MP_Maximum_global_objects and the implementation of
0011  *   _Objects_MP_Handler_early_initialization(),
0012  *   _Objects_MP_Handler_initialization(), _Objects_MP_Open(),
0013  *   _Objects_MP_Allocate_and_open(), _Objects_MP_Close(),
0014  *   _Objects_MP_Global_name_search(), _Objects_MP_Is_remote(),
0015  *   _Objects_MP_Allocate_global_object(), and
0016  *   _Objects_MP_Free_global_object().
0017  */
0018 
0019 /*
0020  *  COPYRIGHT (c) 1989-1999.
0021  *  On-Line Applications Research Corporation (OAR).
0022  *
0023  * Redistribution and use in source and binary forms, with or without
0024  * modification, are permitted provided that the following conditions
0025  * are met:
0026  * 1. Redistributions of source code must retain the above copyright
0027  *    notice, this list of conditions and the following disclaimer.
0028  * 2. Redistributions in binary form must reproduce the above copyright
0029  *    notice, this list of conditions and the following disclaimer in the
0030  *    documentation and/or other materials provided with the distribution.
0031  *
0032  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0033  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0034  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0035  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0036  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0037  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0038  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0039  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0040  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0041  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0042  * POSSIBILITY OF SUCH DAMAGE.
0043  */
0044 
0045 #ifdef HAVE_CONFIG_H
0046 #include "config.h"
0047 #endif
0048 
0049 #include <rtems/score/objectimpl.h>
0050 #include <rtems/score/interr.h>
0051 #include <rtems/score/isrlock.h>
0052 #include <rtems/config.h>
0053 
0054 #define OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( node ) \
0055   RTEMS_CONTAINER_OF( node, Objects_MP_Control, Nodes.Active.Id_lookup )
0056 
0057 #define OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( node ) \
0058   RTEMS_CONTAINER_OF( node, Objects_MP_Control, Nodes.Active.Name_lookup )
0059 
0060 typedef struct {
0061   uint32_t name;
0062   uint32_t node;
0063 } Objects_MP_Name_and_node;
0064 
0065 uint16_t _Objects_Local_node;
0066 
0067 uint16_t _Objects_Maximum_nodes;
0068 
0069 uint32_t _Objects_MP_Maximum_global_objects;
0070 
0071 static CHAIN_DEFINE_EMPTY( _Objects_MP_Inactive_global_objects );
0072 
0073 #if ISR_LOCK_NEEDS_OBJECT
0074 static ISR_lock_Control _Objects_MP_Global_lock =
0075   ISR_LOCK_INITIALIZER( "MP Objects" );
0076 #endif
0077 
0078 static void _Objects_MP_Global_acquire( ISR_lock_Context *lock_context )
0079 {
0080   _ISR_lock_ISR_disable_and_acquire( &_Objects_MP_Global_lock, lock_context );
0081 }
0082 
0083 static void _Objects_MP_Global_release( ISR_lock_Context *lock_context )
0084 {
0085   _ISR_lock_Release_and_ISR_enable( &_Objects_MP_Global_lock, lock_context );
0086 }
0087 
0088 static bool _Objects_MP_Id_equal(
0089   const void        *left,
0090   const RBTree_Node *right
0091 )
0092 {
0093   const Objects_Id         *the_left;
0094   const Objects_MP_Control *the_right;
0095 
0096   the_left = left;
0097   the_right = OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( right );
0098 
0099   return *the_left == the_right->id;
0100 }
0101 
0102 static bool _Objects_MP_Id_less(
0103   const void        *left,
0104   const RBTree_Node *right
0105 )
0106 {
0107   const Objects_Id         *the_left;
0108   const Objects_MP_Control *the_right;
0109 
0110   the_left = left;
0111   the_right = OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( right );
0112 
0113   return *the_left < the_right->id;
0114 }
0115 
0116 static void *_Objects_MP_Id_map( RBTree_Node *node )
0117 {
0118   return OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( node );
0119 }
0120 
0121 static bool _Objects_MP_Name_equal(
0122   const void        *left,
0123   const RBTree_Node *right
0124 )
0125 {
0126   const uint32_t           *the_left;
0127   const Objects_MP_Control *the_right;
0128 
0129   the_left = left;
0130   the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
0131 
0132   return *the_left == the_right->name;
0133 }
0134 
0135 static bool _Objects_MP_Name_less(
0136   const void        *left,
0137   const RBTree_Node *right
0138 )
0139 {
0140   const uint32_t           *the_left;
0141   const Objects_MP_Control *the_right;
0142 
0143   the_left = left;
0144   the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
0145 
0146   return *the_left < the_right->name;
0147 }
0148 
0149 static void *_Objects_MP_Name_map( RBTree_Node *node )
0150 {
0151   return OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( node );
0152 }
0153 
0154 static bool _Objects_MP_Name_and_node_equal(
0155   const void        *left,
0156   const RBTree_Node *right
0157 )
0158 {
0159   const Objects_MP_Name_and_node *the_left;
0160   const Objects_MP_Control       *the_right;
0161 
0162   the_left = left;
0163   the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
0164 
0165   return the_left->name == the_right->name
0166     && the_left->node == _Objects_Get_node( the_right->id );
0167 }
0168 
0169 static bool _Objects_MP_Name_and_node_less(
0170   const void        *left,
0171   const RBTree_Node *right
0172 )
0173 {
0174   const Objects_MP_Name_and_node *the_left;
0175   const Objects_MP_Control       *the_right;
0176 
0177   the_left = left;
0178   the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
0179 
0180   /*
0181    * Use > for the node to find smaller numbered nodes first in case of equal
0182    * names.
0183    */
0184   return the_left->name < the_right->name
0185     || ( the_left->name == the_right->name
0186       && the_left->node > _Objects_Get_node( the_right->id ) );
0187 }
0188 
0189 void _Objects_MP_Handler_early_initialization(void)
0190 {
0191   uint32_t   node;
0192   uint32_t   maximum_nodes;
0193 
0194   node                   = _MPCI_Configuration.node;
0195   maximum_nodes          = _MPCI_Configuration.maximum_nodes;
0196 
0197   if ( node < 1 || node > maximum_nodes )
0198     _Internal_error( INTERNAL_ERROR_INVALID_NODE );
0199 
0200   _Objects_Local_node    = node;
0201   _Objects_Maximum_nodes = maximum_nodes;
0202 }
0203 
0204 void _Objects_MP_Handler_initialization( void )
0205 {
0206   uint32_t maximum_global_objects;
0207 
0208   maximum_global_objects = _MPCI_Configuration.maximum_global_objects;
0209 
0210   _Objects_MP_Maximum_global_objects = maximum_global_objects;
0211 
0212   if ( maximum_global_objects == 0 ) {
0213     return;
0214   }
0215 
0216   _Chain_Initialize(
0217     &_Objects_MP_Inactive_global_objects,
0218     &_Objects_MP_Controls[ 0 ],
0219     maximum_global_objects,
0220     sizeof( _Objects_MP_Controls[ 0 ] )
0221   );
0222 }
0223 
0224 void _Objects_MP_Open (
0225   Objects_Information *information,
0226   Objects_MP_Control  *the_global_object,
0227   uint32_t             the_name,      /* XXX -- wrong for variable */
0228   Objects_Id           the_id
0229 )
0230 {
0231   Objects_MP_Name_and_node name_and_node;
0232   ISR_lock_Context         lock_context;
0233 
0234   the_global_object->id = the_id;
0235   the_global_object->name = the_name;
0236 
0237   name_and_node.name = the_name;
0238   name_and_node.node = _Objects_Get_node( the_id );
0239 
0240   _Objects_MP_Global_acquire( &lock_context );
0241 
0242   _RBTree_Insert_inline(
0243     &information->Global_by_id,
0244     &the_global_object->Nodes.Active.Id_lookup,
0245     &the_id,
0246     _Objects_MP_Id_less
0247   );
0248   _RBTree_Insert_inline(
0249     &information->Global_by_name,
0250     &the_global_object->Nodes.Active.Name_lookup,
0251     &name_and_node,
0252     _Objects_MP_Name_and_node_less
0253   );
0254 
0255   _Objects_MP_Global_release( &lock_context );
0256 }
0257 
0258 bool _Objects_MP_Allocate_and_open (
0259   Objects_Information *information,
0260   uint32_t             the_name,      /* XXX -- wrong for variable */
0261   Objects_Id           the_id,
0262   bool                 is_fatal_error
0263 )
0264 {
0265   Objects_MP_Control *the_global_object;
0266 
0267   the_global_object = _Objects_MP_Allocate_global_object();
0268 
0269   if ( the_global_object == NULL ) {
0270     if ( !is_fatal_error ) {
0271       return false;
0272     }
0273 
0274     _Internal_error( INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS );
0275   }
0276 
0277   _Objects_MP_Open( information, the_global_object, the_name, the_id );
0278 
0279   return true;
0280 }
0281 
0282 void _Objects_MP_Close (
0283   Objects_Information *information,
0284   Objects_Id           the_id
0285 )
0286 {
0287   Objects_MP_Control *the_global_object;
0288   ISR_lock_Context    lock_context;
0289 
0290   _Objects_MP_Global_acquire( &lock_context );
0291 
0292   the_global_object = _RBTree_Find_inline(
0293     &information->Global_by_id,
0294     &the_id,
0295     _Objects_MP_Id_equal,
0296     _Objects_MP_Id_less,
0297     _Objects_MP_Id_map
0298   );
0299 
0300   if ( the_global_object != NULL ) {
0301     _RBTree_Extract(
0302       &information->Global_by_id,
0303       &the_global_object->Nodes.Active.Id_lookup
0304     );
0305     _RBTree_Extract(
0306       &information->Global_by_name,
0307       &the_global_object->Nodes.Active.Name_lookup
0308     );
0309     _Objects_MP_Free_global_object( the_global_object );
0310     _Objects_MP_Global_release( &lock_context );
0311   } else {
0312     _Objects_MP_Global_release( &lock_context );
0313 
0314     _Internal_error( INTERNAL_ERROR_INVALID_GLOBAL_ID );
0315   }
0316 }
0317 
0318 Status_Control _Objects_MP_Global_name_search(
0319   const Objects_Information *information,
0320   Objects_Name               the_name,
0321   uint32_t                   nodes_to_search,
0322   Objects_Id                *the_id
0323 )
0324 {
0325   Status_Control      status;
0326   Objects_MP_Control *the_global_object;
0327   ISR_lock_Context    lock_context;
0328 
0329   if ( nodes_to_search > _Objects_Maximum_nodes ) {
0330     return STATUS_INVALID_NODE;
0331   }
0332 
0333   _Objects_MP_Global_acquire( &lock_context );
0334 
0335   if ( nodes_to_search == OBJECTS_SEARCH_ALL_NODES ) {
0336     the_global_object = _RBTree_Find_inline(
0337       &information->Global_by_name,
0338       &the_name.name_u32,
0339       _Objects_MP_Name_equal,
0340       _Objects_MP_Name_less,
0341       _Objects_MP_Name_map
0342     );
0343   } else {
0344     Objects_MP_Name_and_node name_and_node;
0345 
0346     name_and_node.name = the_name.name_u32;
0347     name_and_node.node = nodes_to_search;
0348 
0349     the_global_object = _RBTree_Find_inline(
0350       &information->Global_by_name,
0351       &name_and_node,
0352       _Objects_MP_Name_and_node_equal,
0353       _Objects_MP_Name_and_node_less,
0354       _Objects_MP_Name_map
0355     );
0356   }
0357 
0358   if ( the_global_object != NULL ) {
0359     *the_id = the_global_object->id;
0360     _Assert( the_global_object->name != 0 );
0361     status = STATUS_SUCCESSFUL;
0362   } else {
0363     status = STATUS_INVALID_NAME;
0364   }
0365 
0366   _Objects_MP_Global_release( &lock_context );
0367 
0368   return status;
0369 }
0370 
0371 bool _Objects_MP_Is_remote(
0372   Objects_Id                 the_id,
0373   const Objects_Information *information
0374 )
0375 {
0376   Objects_MP_Control *the_global_object;
0377   ISR_lock_Context    lock_context;
0378 
0379   _Objects_MP_Global_acquire( &lock_context );
0380 
0381   the_global_object = _RBTree_Find_inline(
0382     &information->Global_by_id,
0383     &the_id,
0384     _Objects_MP_Id_equal,
0385     _Objects_MP_Id_less,
0386     _Objects_MP_Id_map
0387   );
0388 
0389   _Objects_MP_Global_release( &lock_context );
0390 
0391   return the_global_object != NULL;
0392 }
0393 
0394 Objects_MP_Control *_Objects_MP_Allocate_global_object( void )
0395 {
0396   Objects_MP_Control *the_global_object;
0397   ISR_lock_Context    lock_context;
0398 
0399   _Objects_MP_Global_acquire( &lock_context );
0400 
0401   the_global_object = (Objects_MP_Control *)
0402     _Chain_Get_unprotected( &_Objects_MP_Inactive_global_objects );
0403 
0404   _Objects_MP_Global_release( &lock_context );
0405   return the_global_object;
0406 }
0407 
0408 void _Objects_MP_Free_global_object( Objects_MP_Control *the_global_object )
0409 {
0410   ISR_lock_Context lock_context;
0411 
0412   _Objects_MP_Global_acquire( &lock_context );
0413 
0414   _Chain_Initialize_node( &the_global_object->Nodes.Inactive );
0415   _Chain_Append_unprotected(
0416     &_Objects_MP_Inactive_global_objects,
0417     &the_global_object->Nodes.Inactive
0418   );
0419 
0420   _Objects_MP_Global_release( &lock_context );
0421 }