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 RTEMSScoreSMPLock
0007  *
0008  * @brief This header file provides the interfaces of the
0009  *   @ref RTEMSScoreSMPLock related to ticket locks.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2013, 2016 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_SMPLOCKTICKET_H
0038 #define _RTEMS_SCORE_SMPLOCKTICKET_H
0039 
0040 #include <rtems/score/cpuopts.h>
0041 
0042 #if defined(RTEMS_SMP)
0043 
0044 #include <rtems/score/atomic.h>
0045 #include <rtems/score/smplockstats.h>
0046 
0047 #ifdef __cplusplus
0048 extern "C" {
0049 #endif /* __cplusplus */
0050 
0051 /**
0052  * @addtogroup RTEMSScoreSMPLock
0053  *
0054  * @{
0055  */
0056 
0057 /**
0058  * @brief SMP ticket lock control.
0059  */
0060 typedef struct {
0061   Atomic_Uint next_ticket;
0062   Atomic_Uint now_serving;
0063 } SMP_ticket_lock_Control;
0064 
0065 /**
0066  * @brief SMP ticket lock control initializer for static initialization.
0067  */
0068 #define SMP_TICKET_LOCK_INITIALIZER \
0069   { \
0070     ATOMIC_INITIALIZER_UINT( 0U ), \
0071     ATOMIC_INITIALIZER_UINT( 0U ) \
0072   }
0073 
0074 /**
0075  * @brief Initializes the SMP ticket lock.
0076  *
0077  * Concurrent initialization leads to unpredictable results.
0078  *
0079  * @param[in, out] lock The SMP ticket lock control.
0080  */
0081 static inline void _SMP_ticket_lock_Initialize(
0082   SMP_ticket_lock_Control *lock
0083 )
0084 {
0085   _Atomic_Init_uint( &lock->next_ticket, 0U );
0086   _Atomic_Init_uint( &lock->now_serving, 0U );
0087 }
0088 
0089 /**
0090  * @brief Destroys the SMP ticket lock.
0091  *
0092  * Concurrent destruction leads to unpredictable results.
0093  *
0094  * @param lock The SMP ticket lock control.
0095  */
0096 static inline void _SMP_ticket_lock_Destroy( SMP_ticket_lock_Control *lock )
0097 {
0098   (void) lock;
0099 }
0100 
0101 /**
0102  * @brief Acquires the SMP ticket lock.
0103  *
0104  * @param[in, out] lock The lock to acquire.
0105  * @param stats The SMP lock statistics.
0106  * @param[out] stats_context The context for the statistics.
0107  */
0108 static inline void _SMP_ticket_lock_Do_acquire(
0109   SMP_ticket_lock_Control *lock
0110 #if defined(RTEMS_PROFILING)
0111   ,
0112   SMP_lock_Stats          *stats,
0113   SMP_lock_Stats_context  *stats_context
0114 #endif
0115 )
0116 {
0117   unsigned int                   my_ticket;
0118   unsigned int                   now_serving;
0119 #if defined(RTEMS_PROFILING)
0120   unsigned int                   initial_queue_length;
0121   SMP_lock_Stats_acquire_context acquire_context;
0122 
0123   _SMP_lock_Stats_acquire_begin( &acquire_context );
0124 #endif
0125 
0126   my_ticket =
0127     _Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED );
0128 
0129 #if defined(RTEMS_PROFILING)
0130   now_serving =
0131     _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
0132   initial_queue_length = my_ticket - now_serving;
0133 
0134   if ( initial_queue_length > 0 ) {
0135 #endif
0136 
0137     do {
0138       now_serving =
0139         _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
0140     } while ( now_serving != my_ticket );
0141 
0142 #if defined(RTEMS_PROFILING)
0143   }
0144 
0145   _SMP_lock_Stats_acquire_end(
0146     &acquire_context,
0147     stats,
0148     stats_context,
0149     initial_queue_length
0150   );
0151 #endif
0152 }
0153 
0154 /**
0155  * @brief Acquires an SMP ticket lock.
0156  *
0157  * This function will not disable interrupts.  The caller must ensure that the
0158  * current thread of execution is not interrupted indefinite once it obtained
0159  * the SMP ticket lock.
0160  *
0161  * @param[in] lock The SMP ticket lock control.
0162  * @param[in] stats The SMP lock statistics.
0163  * @param[out] stats_context The SMP lock statistics context.
0164  */
0165 #if defined(RTEMS_PROFILING)
0166   #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
0167     _SMP_ticket_lock_Do_acquire( lock, stats, stats_context )
0168 #else
0169   #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
0170     _SMP_ticket_lock_Do_acquire( lock )
0171 #endif
0172 
0173 /**
0174  * @brief Releases the SMP ticket lock.
0175  *
0176  * @param[in, out] lock The SMP ticket lock to release.
0177  * @param[out] stats_context The SMP lock statistics context.
0178  */
0179 static inline void _SMP_ticket_lock_Do_release(
0180   SMP_ticket_lock_Control *lock
0181 #if defined(RTEMS_PROFILING)
0182   ,
0183   const SMP_lock_Stats_context *stats_context
0184 #endif
0185 )
0186 {
0187   unsigned int current_ticket =
0188     _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED );
0189   unsigned int next_ticket = current_ticket + 1U;
0190 
0191 #if defined(RTEMS_PROFILING)
0192   _SMP_lock_Stats_release_update( stats_context );
0193 #endif
0194 
0195   _Atomic_Store_uint( &lock->now_serving, next_ticket, ATOMIC_ORDER_RELEASE );
0196 }
0197 
0198 /**
0199  * @brief Releases an SMP ticket lock.
0200  *
0201  * @param[in] lock The SMP ticket lock control.
0202  * @param[in] stats_context The SMP lock statistics context.
0203  */
0204 #if defined(RTEMS_PROFILING)
0205   #define _SMP_ticket_lock_Release( lock, stats_context ) \
0206     _SMP_ticket_lock_Do_release( lock, stats_context )
0207 #else
0208   #define _SMP_ticket_lock_Release( lock, stats_context ) \
0209     _SMP_ticket_lock_Do_release( lock )
0210 #endif
0211 
0212 /** @} */
0213 
0214 #ifdef __cplusplus
0215 }
0216 #endif /* __cplusplus */
0217 
0218 #endif /* RTEMS_SMP */
0219 
0220 #endif /* _RTEMS_SCORE_SMPLOCKTICKET_H */