Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicSignal
0007  *
0008  * @brief This source file contains the implementation of
0009  *   rtems_signal_send().
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2014.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <rtems/rtems/signalimpl.h>
0043 #include <rtems/rtems/modesimpl.h>
0044 #include <rtems/rtems/tasksdata.h>
0045 #include <rtems/score/schedulerimpl.h>
0046 #include <rtems/score/threaddispatch.h>
0047 #include <rtems/score/threadimpl.h>
0048 
0049 #include <rtems/sysinit.h>
0050 
0051 static void _Signal_Action_handler(
0052   Thread_Control   *executing,
0053   Thread_Action    *action,
0054   ISR_lock_Context *lock_context
0055 )
0056 {
0057   RTEMS_API_Control        *api;
0058   ASR_Information          *asr;
0059   rtems_signal_set          signal_set;
0060   bool                      normal_is_preemptible;
0061   Thread_CPU_budget_control normal_cpu_budget;
0062   uint32_t                  normal_isr_level;
0063   uint32_t                  before_call_isr_level;
0064   bool                      after_call_is_preemptible;
0065   bool                      after_call_asr_is_enabled;
0066 
0067   (void) action;
0068 
0069   /*
0070    * For the variable names the following notation is used.  The prefix
0071    * "normal" specifies the mode associated with the normal task execution.
0072    * The prefix "before_call" specifies the mode set up right before the ASR
0073    * handler is called.  The prefix "after_call" specifies the mode after the
0074    * ASR handler call returned.  This mode may differ from the "before_call"
0075    * mode since an ASR handler is free to change the task mode.
0076    */
0077 
0078   api = executing->API_Extensions[ THREAD_API_RTEMS ];
0079   asr = &api->Signal;
0080 
0081   /* Get and clear the pending signals */
0082   signal_set = asr->signals_pending;
0083   _Assert( signal_set != 0 );
0084   asr->signals_pending = 0;
0085 
0086   /* Save normal mode */
0087 
0088   _Assert( asr->is_enabled );
0089   normal_is_preemptible = executing->is_preemptible;
0090   normal_cpu_budget = executing->CPU_budget;
0091 
0092   /* Set mode for ASR processing */
0093 
0094   executing->is_preemptible = _Modes_Is_preempt( asr->mode_set );
0095   asr->is_enabled = !_Modes_Is_asr_disabled( asr->mode_set );
0096   _Modes_Apply_timeslice_to_thread( asr->mode_set, executing );
0097   before_call_isr_level = _Modes_Get_interrupt_level( asr->mode_set );
0098 
0099   if ( executing->is_preemptible && !normal_is_preemptible ) {
0100     Per_CPU_Control *cpu_self;
0101 
0102     cpu_self = _Thread_Dispatch_disable_critical( lock_context );
0103     _Scheduler_Schedule( executing );
0104     _Thread_State_release( executing, lock_context );
0105     _Thread_Dispatch_direct( cpu_self );
0106   } else {
0107     _Thread_State_release( executing, lock_context );
0108   }
0109 
0110   normal_isr_level = _ISR_Get_level();
0111   _ISR_Set_level( before_call_isr_level );
0112 
0113   /* Call the ASR handler in the ASR processing mode */
0114   ( *asr->handler )( signal_set );
0115 
0116   /* Restore normal mode */
0117 
0118   _ISR_Set_level( normal_isr_level );
0119 
0120   _Thread_State_acquire( executing, lock_context );
0121 
0122   executing->CPU_budget = normal_cpu_budget;
0123   after_call_is_preemptible = executing->is_preemptible;
0124   executing->is_preemptible = normal_is_preemptible;
0125 
0126   /*
0127    * We do the best to avoid recursion in the ASR processing.  A well behaved
0128    * application will disable ASR processing during ASR processing.  In this
0129    * case, ASR processing is currently disabled.  We do now the thread dispatch
0130    * necessary due to a re-enabled preemption mode.  This helps to avoid doing
0131    * the next round of ASR processing recursively in _Thread_Dispatch_direct().
0132    */
0133   if ( normal_is_preemptible && !after_call_is_preemptible ) {
0134     Per_CPU_Control *cpu_self;
0135 
0136     cpu_self = _Thread_Dispatch_disable_critical( lock_context );
0137     _Scheduler_Schedule( executing );
0138     _Thread_State_release( executing, lock_context );
0139     _Thread_Dispatch_direct( cpu_self );
0140     _Thread_State_acquire( executing, lock_context );
0141   }
0142 
0143   /*
0144    * Restore the normal ASR processing mode.  If we enable ASR processing and
0145    * there are pending signals, then add us as a post-switch action.  The loop
0146    * in _Thread_Run_post_switch_actions() will continue after our return and
0147    * call us again.  This avoids a recursion.
0148    */
0149 
0150   after_call_asr_is_enabled = asr->is_enabled;
0151   asr->is_enabled = true;
0152 
0153   if ( !after_call_asr_is_enabled && asr->signals_pending != 0 ) {
0154     _Thread_Append_post_switch_action( executing, action );
0155   }
0156 }
0157 
0158 rtems_status_code rtems_signal_send(
0159   rtems_id          id,
0160   rtems_signal_set  signal_set
0161 )
0162 {
0163   Thread_Control    *the_thread;
0164   ISR_lock_Context   lock_context;
0165   RTEMS_API_Control *api;
0166   ASR_Information   *asr;
0167 
0168   if ( signal_set == 0 ) {
0169     return RTEMS_INVALID_NUMBER;
0170   }
0171 
0172   the_thread = _Thread_Get( id, &lock_context );
0173 
0174   if ( the_thread == NULL ) {
0175 #if defined(RTEMS_MULTIPROCESSING)
0176     return _Signal_MP_Send( id, signal_set );
0177 #else
0178     return RTEMS_INVALID_ID;
0179 #endif
0180   }
0181 
0182   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
0183   asr = &api->Signal;
0184 
0185   _Thread_State_acquire_critical( the_thread, &lock_context );
0186 
0187   if ( asr->handler == NULL ) {
0188     _Thread_State_release( the_thread, &lock_context );
0189     return RTEMS_NOT_DEFINED;
0190   }
0191 
0192   /* Make the signals of the set pending */
0193   asr->signals_pending |= signal_set;
0194 
0195   if ( asr->is_enabled ) {
0196     Per_CPU_Control *cpu_self;
0197 
0198     _Thread_Add_post_switch_action(
0199       the_thread,
0200       &api->Signal_action,
0201       _Signal_Action_handler
0202     );
0203     cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
0204     _Thread_State_release( the_thread, &lock_context );
0205     _Thread_Dispatch_enable( cpu_self );
0206   } else {
0207     _Thread_State_release( the_thread, &lock_context );
0208   }
0209 
0210   return RTEMS_SUCCESSFUL;
0211 }
0212 
0213 #if defined(RTEMS_MULTIPROCESSING)
0214 static void _Signal_MP_Initialize( void )
0215 {
0216   _MPCI_Register_packet_processor(
0217     MP_PACKET_SIGNAL,
0218     _Signal_MP_Process_packet
0219   );
0220 }
0221 
0222 RTEMS_SYSINIT_ITEM(
0223   _Signal_MP_Initialize,
0224   RTEMS_SYSINIT_CLASSIC_SIGNAL_MP,
0225   RTEMS_SYSINIT_ORDER_MIDDLE
0226 );
0227 #endif