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 RTEMSScoreUserExt
0007  *
0008  * @brief This source file contains the definition of ::_User_extensions_List
0009  *   and the implementation of _User_extensions_Fatal_visitor(),
0010  *   _User_extensions_Iterate(), _User_extensions_Thread_begin_visitor(),
0011  *   _User_extensions_Thread_create_visitor(),
0012  *   _User_extensions_Thread_delete_visitor(),
0013  *   _User_extensions_Thread_exitted_visitor(),
0014  *   _User_extensions_Thread_restart_visitor(),
0015  *   _User_extensions_Thread_start_visitor(), and
0016  *   _User_extensions_Thread_terminate_visitor().
0017  */
0018 
0019 /*
0020  * Copyright (C) 2012, 2019 embedded brains GmbH & Co. KG
0021  *
0022  * Redistribution and use in source and binary forms, with or without
0023  * modification, are permitted provided that the following conditions
0024  * are met:
0025  * 1. Redistributions of source code must retain the above copyright
0026  *    notice, this list of conditions and the following disclaimer.
0027  * 2. Redistributions in binary form must reproduce the above copyright
0028  *    notice, this list of conditions and the following disclaimer in the
0029  *    documentation and/or other materials provided with the distribution.
0030  *
0031  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0032  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0033  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0034  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0035  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0036  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0037  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0038  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0039  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0040  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0041  * POSSIBILITY OF SUCH DAMAGE.
0042  */
0043 
0044 #ifdef HAVE_CONFIG_H
0045 #include "config.h"
0046 #endif
0047 
0048 #include <rtems/score/userextimpl.h>
0049 
0050 User_extensions_List _User_extensions_List = {
0051   CHAIN_INITIALIZER_EMPTY( _User_extensions_List.Active ),
0052   CHAIN_ITERATOR_REGISTRY_INITIALIZER( _User_extensions_List.Iterators )
0053 #if defined(RTEMS_SMP)
0054   ,
0055   ISR_LOCK_INITIALIZER( "User Extensions List" )
0056 #endif
0057 };
0058 
0059 void _User_extensions_Thread_create_visitor(
0060   Thread_Control              *executing,
0061   void                        *arg,
0062   const User_extensions_Table *callouts
0063 )
0064 {
0065   User_extensions_thread_create_extension callout = callouts->thread_create;
0066 
0067   if ( callout != NULL ) {
0068     User_extensions_Thread_create_context *ctx = arg;
0069 
0070     ctx->ok = ctx->ok && (*callout)( executing, ctx->created );
0071   }
0072 }
0073 
0074 void _User_extensions_Thread_delete_visitor(
0075   Thread_Control              *executing,
0076   void                        *arg,
0077   const User_extensions_Table *callouts
0078 )
0079 {
0080   User_extensions_thread_delete_extension callout = callouts->thread_delete;
0081 
0082   if ( callout != NULL ) {
0083     (*callout)( executing, arg );
0084   }
0085 }
0086 
0087 void _User_extensions_Thread_start_visitor(
0088   Thread_Control              *executing,
0089   void                        *arg,
0090   const User_extensions_Table *callouts
0091 )
0092 {
0093   User_extensions_thread_start_extension callout = callouts->thread_start;
0094 
0095   if ( callout != NULL ) {
0096     (*callout)( executing, arg );
0097   }
0098 }
0099 
0100 void _User_extensions_Thread_restart_visitor(
0101   Thread_Control              *executing,
0102   void                        *arg,
0103   const User_extensions_Table *callouts
0104 )
0105 {
0106   User_extensions_thread_restart_extension callout = callouts->thread_restart;
0107 
0108   if ( callout != NULL ) {
0109     (*callout)( executing, arg );
0110   }
0111 }
0112 
0113 void _User_extensions_Thread_begin_visitor(
0114   Thread_Control              *executing,
0115   void                        *arg,
0116   const User_extensions_Table *callouts
0117 )
0118 {
0119   User_extensions_thread_begin_extension callout = callouts->thread_begin;
0120 
0121   (void) arg;
0122 
0123   if ( callout != NULL ) {
0124     (*callout)( executing );
0125   }
0126 }
0127 
0128 void _User_extensions_Thread_exitted_visitor(
0129   Thread_Control              *executing,
0130   void                        *arg,
0131   const User_extensions_Table *callouts
0132 )
0133 {
0134   User_extensions_thread_exitted_extension callout = callouts->thread_exitted;
0135 
0136   if ( callout != NULL ) {
0137     (*callout)( executing );
0138   }
0139 }
0140 
0141 void _User_extensions_Fatal_visitor(
0142   Thread_Control              *executing,
0143   void                        *arg,
0144   const User_extensions_Table *callouts
0145 )
0146 {
0147   User_extensions_fatal_extension callout = callouts->fatal;
0148 
0149   if ( callout != NULL ) {
0150     const User_extensions_Fatal_context *ctx = arg;
0151 
0152     (*callout)( ctx->source, false, ctx->error );
0153   }
0154 }
0155 
0156 void _User_extensions_Thread_terminate_visitor(
0157   Thread_Control              *executing,
0158   void                        *arg,
0159   const User_extensions_Table *callouts
0160 )
0161 {
0162   User_extensions_thread_terminate_extension callout =
0163     callouts->thread_terminate;
0164 
0165   if ( callout != NULL ) {
0166     (*callout)( executing );
0167   }
0168 }
0169 
0170 void _User_extensions_Iterate(
0171   void                     *arg,
0172   User_extensions_Visitor   visitor,
0173   Chain_Iterator_direction  direction
0174 )
0175 {
0176   Thread_Control              *executing;
0177   const User_extensions_Table *initial_current;
0178   const User_extensions_Table *initial_begin;
0179   const User_extensions_Table *initial_end;
0180   const Chain_Node            *end;
0181   Chain_Node                  *node;
0182   User_extensions_Iterator     iter;
0183   ISR_lock_Context             lock_context;
0184 
0185   executing = _Thread_Get_executing();
0186 
0187   initial_begin = _User_extensions_Initial_extensions;
0188   initial_end = initial_begin + _User_extensions_Initial_count;
0189 
0190   if ( direction == CHAIN_ITERATOR_FORWARD ) {
0191     initial_current = initial_begin;
0192 
0193     while ( initial_current != initial_end ) {
0194       (*visitor)( executing, arg, initial_current );
0195       ++initial_current;
0196     }
0197 
0198     end = _Chain_Immutable_tail( &_User_extensions_List.Active );
0199   } else {
0200     end = _Chain_Immutable_head( &_User_extensions_List.Active );
0201   }
0202 
0203   _User_extensions_Acquire( &lock_context );
0204 
0205   /*
0206    * Ignore this warning:
0207    *
0208    * - storing the address of local variable 'iter' ... [-Wdangling-pointer=]
0209    *
0210    * We store the local variable &iter.Iterator here on the
0211    * &User_extensions_List.Iterators, and then remove it from the list below
0212    * at the call to _Chain_Iterator_destroy(). So it is not left dangling.
0213    */
0214   #pragma GCC diagnostic push
0215   #pragma GCC diagnostic ignored "-Wdangling-pointer="
0216   _Chain_Iterator_initialize(
0217     &_User_extensions_List.Active,
0218     &_User_extensions_List.Iterators,
0219     &iter.Iterator,
0220     direction
0221   );
0222   #pragma GCC diagnostic pop
0223 
0224   if ( executing != NULL ) {
0225     iter.previous = executing->last_user_extensions_iterator;
0226     executing->last_user_extensions_iterator = &iter;
0227   }
0228 
0229   while ( ( node = _Chain_Iterator_next( &iter.Iterator ) ) != end ) {
0230     const User_extensions_Control *extension;
0231 
0232     _Chain_Iterator_set_position( &iter.Iterator, node );
0233 
0234     _User_extensions_Release( &lock_context );
0235 
0236     extension = (const User_extensions_Control *) node;
0237     ( *visitor )( executing, arg, &extension->Callouts );
0238 
0239     _User_extensions_Acquire( &lock_context );
0240   }
0241 
0242   if ( executing != NULL ) {
0243     executing->last_user_extensions_iterator = iter.previous;
0244   }
0245 
0246   _Chain_Iterator_destroy( &iter.Iterator );
0247 
0248   _User_extensions_Release( &lock_context );
0249 
0250   if ( direction == CHAIN_ITERATOR_BACKWARD ) {
0251     initial_current = initial_end;
0252 
0253     while ( initial_current != initial_begin ) {
0254       --initial_current;
0255       (*visitor)( executing, arg, initial_current );
0256     }
0257   }
0258 }