Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreISRLocks
0007  *
0008  * @brief This header file provides the interfaces of the
0009  *   @ref RTEMSScoreISRLocks.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2013, 2024 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifndef _RTEMS_SCORE_ISR_LOCK_H
0038 #define _RTEMS_SCORE_ISR_LOCK_H
0039 
0040 #include <rtems/score/isrlevel.h>
0041 #include <rtems/score/smplock.h>
0042 
0043 #ifdef __cplusplus
0044 extern "C" {
0045 #endif
0046 
0047 /**
0048  * @defgroup RTEMSScoreISRLocks ISR Locks
0049  *
0050  * @ingroup RTEMSScoreISR
0051  *
0052  * @brief This group contains the ISR locks implementation.
0053  *
0054  * The ISR locks are low-level locks to protect critical sections accessed by
0055  * threads and interrupt service routines.
0056  *
0057  * In uniprocessor configurations the ISR locks degrade to simple ISR
0058  * disable/enable sequences.  No additional storage or objects are required.
0059  *
0060  * This synchronization primitive is supported in SMP configurations.  Here SMP
0061  * locks are used.
0062  *
0063  * @{
0064  */
0065 
0066 /**
0067  * @brief If this define has a non-zero value, then the interrupt lock
0068  *   operations require an object of type ::ISR_lock_Control, otherwise no
0069  *   lock object is required.
0070  *
0071  * @par Notes
0072  * This indication can be used to avoid the space overhead for lock objects
0073  * when they are not needed.  In this case, the lock operations will not use a
0074  * lock objects parameter.
0075  */
0076 #if defined( RTEMS_SMP )
0077   #define ISR_LOCK_NEEDS_OBJECT 1
0078 #else
0079   #define ISR_LOCK_NEEDS_OBJECT 0
0080 #endif
0081 
0082 #if ISR_LOCK_NEEDS_OBJECT
0083 /**
0084  * @brief ISR lock control.
0085  */
0086 typedef struct {
0087   SMP_lock_Control Lock;
0088 } ISR_lock_Control;
0089 #endif
0090 
0091 /**
0092  * @brief Local ISR lock context for acquire and release pairs.
0093  */
0094 typedef struct {
0095 #if defined( RTEMS_SMP )
0096   SMP_lock_Context Lock_context;
0097 #else
0098   ISR_Level isr_level;
0099 #endif
0100 #if defined( RTEMS_PROFILING )
0101   /**
0102    * @brief The last interrupt disable instant in CPU counter ticks.
0103    */
0104   CPU_Counter_ticks ISR_disable_instant;
0105 #endif
0106 } ISR_lock_Context;
0107 
0108 #if ISR_LOCK_NEEDS_OBJECT
0109   /**
0110    * @brief Initializer for static initialization of ISR locks.
0111    *
0112    * @param _name The name for the interrupt lock.  It must be a string.  The
0113    * name is only used if profiling is enabled.
0114    */
0115   #define ISR_LOCK_INITIALIZER( _name ) { SMP_LOCK_INITIALIZER( _name ) }
0116 #endif
0117 
0118 /**
0119  * @brief Sets the ISR level in the ISR lock context.
0120  *
0121  * @param[out] context The ISR lock context.
0122  * @param level The ISR level.
0123  */
0124 static inline void _ISR_lock_Context_set_level(
0125   ISR_lock_Context *context,
0126   ISR_Level         level
0127 )
0128 {
0129 #if defined( RTEMS_SMP )
0130   context->Lock_context.isr_level = level;
0131 #else
0132   context->isr_level = level;
0133 #endif
0134 }
0135 
0136 /**
0137  * @brief Initializes an ISR lock.
0138  *
0139  * Concurrent initialization leads to unpredictable results.
0140  *
0141  * @param[in] _lock The ISR lock control.
0142  * @param[in] _name The name for the ISR lock.  This name must be a
0143  * string persistent throughout the life time of this lock.  The name is only
0144  * used if profiling is enabled.
0145  */
0146 #if defined( RTEMS_SMP )
0147   #define _ISR_lock_Initialize( _lock, _name ) \
0148     _SMP_lock_Initialize( &( _lock )->Lock, _name )
0149 #else
0150   #define _ISR_lock_Initialize( _lock, _name ) \
0151     do { (void) _name; } while (0)
0152 #endif
0153 
0154 /**
0155  * @brief Destroys an ISR lock.
0156  *
0157  * Concurrent destruction leads to unpredictable results.
0158  *
0159  * @param[in] _lock The ISR lock control.
0160  */
0161 #if defined( RTEMS_SMP )
0162   #define _ISR_lock_Destroy( _lock ) \
0163     _SMP_lock_Destroy( &( _lock )->Lock )
0164 #else
0165   #define _ISR_lock_Destroy( _lock )
0166 #endif
0167 
0168 /**
0169  * @brief Sets the name of an ISR lock.
0170  *
0171  * @param[out] _lock The ISR lock control.
0172  * @param _name The name for the ISR lock.  This name must be a string
0173  *   persistent throughout the life time of this lock.  The name is only used
0174  *   if profiling is enabled.
0175  */
0176 #if defined( RTEMS_SMP )
0177   #define _ISR_lock_Set_name( _lock, _name ) \
0178     _SMP_lock_Set_name( &( _lock )->Lock, _name )
0179 #else
0180   #define _ISR_lock_Set_name( _lock, _name )
0181 #endif
0182 
0183 /**
0184  * @brief Acquires an ISR lock.
0185  *
0186  * Interrupts will be disabled.  On SMP configurations this function acquires
0187  * an SMP lock.
0188  *
0189  * This function can be used in thread and interrupt context.
0190  *
0191  * @param[in] _lock The ISR lock control.
0192  * @param[in] _context The local ISR lock context for an acquire and release
0193  * pair.
0194  *
0195  * @see _ISR_lock_Release_and_ISR_enable().
0196  */
0197 #if defined( RTEMS_SMP )
0198   #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
0199     _SMP_lock_ISR_disable_and_acquire( \
0200       &( _lock )->Lock, \
0201       &( _context )->Lock_context \
0202     )
0203 #else
0204   #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
0205     _ISR_Local_disable( ( _context )->isr_level )
0206 #endif
0207 
0208 /**
0209  * @brief Releases an ISR lock.
0210  *
0211  * The interrupt status will be restored.  On SMP configurations this function
0212  * releases an SMP lock.
0213  *
0214  * This function can be used in thread and interrupt context.
0215  *
0216  * @param[in] _lock The ISR lock control.
0217  * @param[in] _context The local ISR lock context for an acquire and release
0218  * pair.
0219  *
0220  * @see _ISR_lock_ISR_disable_and_acquire().
0221  */
0222 #if defined( RTEMS_SMP )
0223   #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
0224     _SMP_lock_Release_and_ISR_enable( \
0225       &( _lock )->Lock, \
0226       &( _context )->Lock_context \
0227     )
0228 #else
0229   #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
0230     _ISR_Local_enable( ( _context )->isr_level )
0231 #endif
0232 
0233 /**
0234  * @brief Acquires an ISR lock inside an ISR disabled section.
0235  *
0236  * The interrupt status will remain unchanged.  On SMP configurations this
0237  * function acquires an SMP lock.
0238  *
0239  * In case the executing context can be interrupted by higher priority
0240  * interrupts and these interrupts enter the critical section protected by this
0241  * lock, then the result is unpredictable.
0242  *
0243  * @param[in] _lock The ISR lock control.
0244  * @param[in] _context The local ISR lock context for an acquire and release
0245  * pair.
0246  *
0247  * @see _ISR_lock_Release().
0248  */
0249 #if defined( RTEMS_SMP )
0250   #define _ISR_lock_Acquire( _lock, _context ) \
0251     do { \
0252       _Assert( _ISR_Get_level() != 0 ); \
0253       _SMP_lock_Acquire( \
0254         &( _lock )->Lock, \
0255         &( _context )->Lock_context \
0256       ); \
0257     } while ( 0 )
0258 #else
0259   #define _ISR_lock_Acquire( _lock, _context ) \
0260     do { (void) _context; } while ( 0 )
0261 #endif
0262 
0263 /**
0264  * @brief Releases an ISR lock inside an ISR disabled section.
0265  *
0266  * The interrupt status will remain unchanged.  On SMP configurations this
0267  * function releases an SMP lock.
0268  *
0269  * @param[in] _lock The ISR lock control.
0270  * @param[in] _context The local ISR lock context for an acquire and release
0271  * pair.
0272  *
0273  * @see _ISR_lock_Acquire().
0274  */
0275 #if defined( RTEMS_SMP )
0276   #define _ISR_lock_Release( _lock, _context ) \
0277     _SMP_lock_Release( \
0278       &( _lock )->Lock, \
0279       &( _context )->Lock_context \
0280     )
0281 #else
0282   #define _ISR_lock_Release( _lock, _context ) \
0283     do { (void) _context; } while ( 0 )
0284 #endif
0285 
0286 /**
0287  * @brief Acquires an ISR lock inside an ISR disabled section (inline).
0288  *
0289  * @see _ISR_lock_Acquire().
0290  */
0291 #if defined( RTEMS_SMP )
0292   #define _ISR_lock_Acquire_inline( _lock, _context ) \
0293     do { \
0294       _Assert( _ISR_Get_level() != 0 ); \
0295       _SMP_lock_Acquire_inline( \
0296         &( _lock )->Lock, \
0297         &( _context )->Lock_context \
0298       ); \
0299     } while ( 0 )
0300 #else
0301   #define _ISR_lock_Acquire_inline( _lock, _context ) \
0302     do { (void) _context; } while ( 0 )
0303 #endif
0304 
0305 /**
0306  * @brief Releases an ISR lock inside an ISR disabled section (inline).
0307  *
0308  * @see _ISR_lock_Release().
0309  */
0310 #if defined( RTEMS_SMP )
0311   #define _ISR_lock_Release_inline( _lock, _context ) \
0312     _SMP_lock_Release_inline( \
0313       &( _lock )->Lock, \
0314       &( _context )->Lock_context \
0315     )
0316 #else
0317   #define _ISR_lock_Release_inline( _lock, _context ) \
0318     do { (void) _context; } while ( 0 )
0319 #endif
0320 
0321 #if defined( RTEMS_DEBUG )
0322   /**
0323    * @brief Returns true, if the ISR lock is owned by the current processor,
0324    * otherwise false.
0325    *
0326    * On uni-processor configurations, this function returns true, if interrupts
0327    * are disabled, otherwise false.
0328    *
0329    * @param[in] _lock The ISR lock control.
0330    */
0331   #if defined( RTEMS_SMP )
0332     #define _ISR_lock_Is_owner( _lock ) \
0333       _SMP_lock_Is_owner( &( _lock )->Lock )
0334   #else
0335     #define _ISR_lock_Is_owner( _lock ) \
0336       ( _ISR_Get_level() != 0 )
0337   #endif
0338 #endif
0339 
0340 #if defined( RTEMS_PROFILING )
0341   #define _ISR_lock_ISR_disable_profile( _context ) \
0342     ( _context )->ISR_disable_instant = _CPU_Counter_read();
0343 #else
0344   #define _ISR_lock_ISR_disable_profile( _context )
0345 #endif
0346 
0347 /**
0348  * @brief Disables interrupts and saves the previous interrupt state in the ISR
0349  * lock context.
0350  *
0351  * This function can be used in thread and interrupt context.
0352  *
0353  * @param[in] _context The local ISR lock context to store the interrupt state.
0354  *
0355  * @see _ISR_lock_ISR_enable().
0356  */
0357 #if defined( RTEMS_SMP )
0358   #define _ISR_lock_ISR_disable( _context ) \
0359     do { \
0360       _ISR_Local_disable( ( _context )->Lock_context.isr_level ); \
0361       _ISR_lock_ISR_disable_profile( _context ) \
0362     } while ( 0 )
0363 #else
0364   #define _ISR_lock_ISR_disable( _context ) \
0365     do { \
0366       _ISR_Local_disable( ( _context )->isr_level ); \
0367       _ISR_lock_ISR_disable_profile( _context ) \
0368     } while ( 0 )
0369 #endif
0370 
0371 /**
0372  * @brief Restores the saved interrupt state of the ISR lock context.
0373  *
0374  * This function can be used in thread and interrupt context.
0375  *
0376  * @param[in] _context The local ISR lock context containing the saved
0377  * interrupt state.
0378  *
0379  * @see _ISR_lock_ISR_disable().
0380  */
0381 #if defined( RTEMS_SMP )
0382   #define _ISR_lock_ISR_enable( _context ) \
0383     _ISR_Local_enable( ( _context )->Lock_context.isr_level )
0384 #else
0385   #define _ISR_lock_ISR_enable( _context ) \
0386     _ISR_Local_enable( ( _context )->isr_level )
0387 #endif
0388 
0389 /** @} */
0390 
0391 #ifdef __cplusplus
0392 }
0393 #endif
0394 
0395 #endif /* _RTEMS_SCORE_ISR_LOCK_H */