Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreSemaphore
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreSemaphore which are only used by the implementation.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2006.
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 #ifndef _RTEMS_SCORE_CORESEMIMPL_H
0039 #define _RTEMS_SCORE_CORESEMIMPL_H
0040 
0041 #include <rtems/score/coresem.h>
0042 #include <rtems/score/objectimpl.h>
0043 #include <rtems/score/threaddispatch.h>
0044 #include <rtems/score/threadimpl.h>
0045 #include <rtems/score/threadqimpl.h>
0046 #include <rtems/score/statesimpl.h>
0047 #include <rtems/score/status.h>
0048 
0049 #ifdef __cplusplus
0050 extern "C" {
0051 #endif
0052 
0053 /**
0054  * @addtogroup RTEMSScoreSemaphore
0055  *
0056  * @{
0057  */
0058 
0059 /**
0060  * @brief Initializes the semaphore based on the parameters passed.
0061  *
0062  * This package is the implementation of the CORE Semaphore Handler.
0063  * This core object utilizes standard Dijkstra counting semaphores to provide
0064  * synchronization and mutual exclusion capabilities.
0065  *
0066  * This routine initializes the semaphore based on the parameters passed.
0067  *
0068  * @param[out] the_semaphore The semaphore to initialize.
0069  * @param initial_value The initial count of the semaphore.
0070  */
0071 void _CORE_semaphore_Initialize(
0072   CORE_semaphore_Control *the_semaphore,
0073   uint32_t                initial_value
0074 );
0075 
0076 /**
0077  * @brief Acquires the semaphore critical.
0078  *
0079  * This routine acquires the semaphore.
0080  *
0081  * @param[in, out] the_semaphore The semaphore to acquire.
0082  * @param queue_context The thread queue context.
0083  */
0084 static inline void _CORE_semaphore_Acquire_critical(
0085   CORE_semaphore_Control *the_semaphore,
0086   Thread_queue_Context   *queue_context
0087 )
0088 {
0089   _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, queue_context );
0090 }
0091 
0092 /**
0093  * @brief Releases the semaphore.
0094  *
0095  * This routine releases the semaphore.
0096  *
0097  * @param[in, out] the_semaphore The semaphore to release.
0098  * @param queue_context The thread queue context.
0099  */
0100 static inline void _CORE_semaphore_Release(
0101   CORE_semaphore_Control *the_semaphore,
0102   Thread_queue_Context   *queue_context
0103 )
0104 {
0105   _Thread_queue_Release( &the_semaphore->Wait_queue, queue_context );
0106 }
0107 
0108 /**
0109  * @brief Destroys the semaphore.
0110  *
0111  * This routine destroys the semaphore.
0112  *
0113  * @param[out] the_semaphore The semaphore to destroy.
0114  * @param operations The thread queue operations.
0115  * @param queue_context The thread queue context.
0116  */
0117 static inline void _CORE_semaphore_Destroy(
0118   CORE_semaphore_Control        *the_semaphore,
0119   const Thread_queue_Operations *operations,
0120   Thread_queue_Context          *queue_context
0121 )
0122 {
0123   _Thread_queue_Flush_critical(
0124     &the_semaphore->Wait_queue.Queue,
0125     operations,
0126     _Thread_queue_Flush_status_object_was_deleted,
0127     queue_context
0128   );
0129   _Thread_queue_Destroy( &the_semaphore->Wait_queue );
0130 }
0131 
0132 /**
0133  * @brief Surrenders a unit to the semaphore.
0134  *
0135  * This routine frees a unit to the semaphore.  If a task was blocked waiting
0136  * for a unit from this semaphore, then that task will be readied and the unit
0137  * given to that task.  Otherwise, the unit will be returned to the semaphore.
0138  *
0139  * @param[in, out] the_semaphore is the semaphore to surrender
0140  * @param operations The thread queue operations.
0141  * @param maximum_count The maximum number of units in the semaphore.
0142  * @param queue_context is a temporary variable used to contain the ISR
0143  *       disable level cookie.
0144  *
0145  * @retval STATUS_SUCCESSFUL The unit was successfully freed to the semaphore.
0146  * @retval STATUS_MAXIMUM_COUNT_EXCEEDED The maximum number of units was exceeded.
0147  */
0148 static inline Status_Control _CORE_semaphore_Surrender(
0149   CORE_semaphore_Control        *the_semaphore,
0150   const Thread_queue_Operations *operations,
0151   uint32_t                       maximum_count,
0152   Thread_queue_Context          *queue_context
0153 )
0154 {
0155   Status_Control      status;
0156   Thread_queue_Heads *heads;
0157 
0158   status = STATUS_SUCCESSFUL;
0159 
0160   _CORE_semaphore_Acquire_critical( the_semaphore, queue_context );
0161 
0162   heads = the_semaphore->Wait_queue.Queue.heads;
0163 
0164   if ( heads != NULL ) {
0165     _Thread_queue_Surrender_no_priority(
0166       &the_semaphore->Wait_queue.Queue,
0167       heads,
0168       queue_context,
0169       operations
0170     );
0171   } else {
0172     if ( the_semaphore->count < maximum_count )
0173       the_semaphore->count += 1;
0174     else
0175       status = STATUS_MAXIMUM_COUNT_EXCEEDED;
0176 
0177     _CORE_semaphore_Release( the_semaphore, queue_context );
0178   }
0179 
0180   return status;
0181 }
0182 
0183 /**
0184  * @brief Returns the current count associated with the semaphore.
0185  *
0186  * @param the_semaphore The semaphore to obtain the count of.
0187  *
0188  * @return the current count of this semaphore.
0189  */
0190 static inline uint32_t  _CORE_semaphore_Get_count(
0191   const CORE_semaphore_Control *the_semaphore
0192 )
0193 {
0194   return the_semaphore->count;
0195 }
0196 
0197 /**
0198  * @brief Seizes the semaphore
0199  *
0200  * This routine attempts to receive a unit from the_semaphore.
0201  * If a unit is available or if the wait flag is false, then the routine
0202  * returns.  Otherwise, the calling task is blocked until a unit becomes
0203  * available.
0204  *
0205  * @param[in, out] the_semaphore The semaphore to obtain.
0206  * @param operations The thread queue operations.
0207  * @param executing The currently executing thread.
0208  * @param wait Indicates whether the calling thread is willing to wait.
0209  * @param queue_context is a temporary variable used to contain the ISR
0210  *        disable level cookie.
0211  *
0212  * @retval STATUS_SUCCESSFUL The semaphore was successfully seized.
0213  * @retval STATUS_UNSATISFIED The semaphore is currently not free and the
0214  *      calling thread not willing to wait.
0215  * @retval STATUS_TIMEOUT A timeout occurred.
0216  */
0217 static inline Status_Control _CORE_semaphore_Seize(
0218   CORE_semaphore_Control        *the_semaphore,
0219   const Thread_queue_Operations *operations,
0220   Thread_Control                *executing,
0221   bool                           wait,
0222   Thread_queue_Context          *queue_context
0223 )
0224 {
0225   _Assert( _ISR_Get_level() != 0 );
0226 
0227   _CORE_semaphore_Acquire_critical( the_semaphore, queue_context );
0228   if ( the_semaphore->count != 0 ) {
0229     the_semaphore->count -= 1;
0230     _CORE_semaphore_Release( the_semaphore, queue_context );
0231     return STATUS_SUCCESSFUL;
0232   }
0233 
0234   if ( !wait ) {
0235     _CORE_semaphore_Release( the_semaphore, queue_context );
0236     return STATUS_UNSATISFIED;
0237   }
0238 
0239   _Thread_queue_Context_set_thread_state(
0240     queue_context,
0241     STATES_WAITING_FOR_SEMAPHORE
0242   );
0243   _Thread_queue_Enqueue(
0244     &the_semaphore->Wait_queue.Queue,
0245     operations,
0246     executing,
0247     queue_context
0248   );
0249   return _Thread_Wait_get_status( executing );
0250 }
0251 
0252 /** @} */
0253 
0254 #ifdef __cplusplus
0255 }
0256 #endif
0257 
0258 #endif
0259 /* end of include file */