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 RTEMSImplClassicSemaphore
0007  *
0008  * @brief This source file contains the implementation of
0009  *   rtems_semaphore_create() and the Semaphore Manager system initialization.
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/semimpl.h>
0043 #include <rtems/rtems/attrimpl.h>
0044 #include <rtems/rtems/statusimpl.h>
0045 #include <rtems/rtems/support.h>
0046 #include <rtems/rtems/tasksimpl.h>
0047 #include <rtems/score/schedulerimpl.h>
0048 #include <rtems/score/sysstate.h>
0049 #include <rtems/sysinit.h>
0050 
0051 #define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
0052   | RTEMS_PRIORITY_CEILING | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
0053 
0054 rtems_status_code rtems_semaphore_create(
0055   rtems_name           name,
0056   uint32_t             count,
0057   rtems_attribute      attribute_set,
0058   rtems_task_priority  priority_ceiling,
0059   rtems_id            *id
0060 )
0061 {
0062   Semaphore_Control       *the_semaphore;
0063   Thread_Control          *executing;
0064   Status_Control           status;
0065   rtems_attribute          maybe_global;
0066   rtems_attribute          mutex_with_protocol;
0067   Semaphore_Variant        variant;
0068   const Scheduler_Control *scheduler;
0069   bool                     valid;
0070   Priority_Control         priority;
0071   uintptr_t                flags;
0072 
0073   if ( !rtems_is_name_valid( name ) )
0074     return RTEMS_INVALID_NAME;
0075 
0076   if ( !id )
0077     return RTEMS_INVALID_ADDRESS;
0078 
0079 #if defined(RTEMS_MULTIPROCESSING)
0080   if ( !_System_state_Is_multiprocessing ) {
0081     attribute_set = _Attributes_Clear( attribute_set, RTEMS_GLOBAL );
0082   }
0083 #endif
0084 
0085   /* Attribute subset defining a potentially global semaphore variant */
0086   maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
0087 
0088   /* Attribute subset defining a mutex variant with a locking protocol */
0089   mutex_with_protocol =
0090     attribute_set & ( SEMAPHORE_KIND_MASK | RTEMS_GLOBAL | RTEMS_PRIORITY );
0091 
0092   if ( maybe_global == RTEMS_COUNTING_SEMAPHORE ) {
0093     variant = SEMAPHORE_VARIANT_COUNTING;
0094   } else if ( maybe_global == RTEMS_SIMPLE_BINARY_SEMAPHORE ) {
0095     variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
0096   } else if ( maybe_global == RTEMS_BINARY_SEMAPHORE ) {
0097     variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
0098   } else if (
0099     mutex_with_protocol
0100       == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY )
0101   ) {
0102     variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
0103   } else if (
0104     mutex_with_protocol
0105       == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING )
0106   ) {
0107     variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
0108   } else if (
0109     mutex_with_protocol == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY |
0110       RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
0111   ) {
0112 #if defined(RTEMS_SMP)
0113     variant = SEMAPHORE_VARIANT_MRSP;
0114 #else
0115     /*
0116      * On uni-processor configurations the Multiprocessor Resource Sharing
0117      * Protocol is equivalent to the Priority Ceiling Protocol.
0118      */
0119     variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
0120 #endif
0121   } else {
0122     return RTEMS_NOT_DEFINED;
0123   }
0124 
0125   if ( count > 1 && variant != SEMAPHORE_VARIANT_COUNTING ) {
0126     return RTEMS_INVALID_NUMBER;
0127   }
0128 
0129   the_semaphore = _Semaphore_Allocate();
0130 
0131   if ( !the_semaphore ) {
0132     _Objects_Allocator_unlock();
0133     return RTEMS_TOO_MANY;
0134   }
0135 
0136   flags = _Semaphore_Set_variant( 0, variant );
0137 
0138 #if defined(RTEMS_MULTIPROCESSING)
0139   if ( _Attributes_Is_global( attribute_set ) ) {
0140     bool ok;
0141 
0142     ok = _Objects_MP_Allocate_and_open(
0143       &_Semaphore_Information,
0144       name,
0145       the_semaphore->Object.id,
0146       false
0147     );
0148 
0149     if ( !ok ) {
0150       _Semaphore_Free( the_semaphore );
0151       _Objects_Allocator_unlock();
0152       return RTEMS_TOO_MANY;
0153     }
0154 
0155     flags = _Semaphore_Make_global( flags );
0156   }
0157 #endif
0158 
0159   if ( _Attributes_Is_priority( attribute_set ) ) {
0160     flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_PRIORITY );
0161   } else {
0162     flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_FIFO );
0163   }
0164 
0165   _Semaphore_Set_flags( the_semaphore, flags );
0166   executing = _Thread_Get_executing();
0167 
0168   switch ( variant ) {
0169     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
0170     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
0171       _CORE_recursive_mutex_Initialize(
0172         &the_semaphore->Core_control.Mutex.Recursive
0173       );
0174 
0175       if ( count == 0 ) {
0176         _CORE_mutex_Set_owner(
0177           &the_semaphore->Core_control.Mutex.Recursive.Mutex,
0178           executing
0179         );
0180         _Thread_Resource_count_increment( executing );
0181       }
0182 
0183       status = STATUS_SUCCESSFUL;
0184       break;
0185     case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
0186       scheduler = _Thread_Scheduler_get_home( executing );
0187       priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
0188 
0189       if ( valid ) {
0190         _CORE_ceiling_mutex_Initialize(
0191           &the_semaphore->Core_control.Mutex,
0192           scheduler,
0193           priority
0194         );
0195 
0196         if ( count == 0 ) {
0197           Thread_queue_Context queue_context;
0198 
0199           _Thread_queue_Context_initialize( &queue_context );
0200           _Thread_queue_Context_clear_priority_updates( &queue_context );
0201           _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
0202           _CORE_mutex_Acquire_critical(
0203             &the_semaphore->Core_control.Mutex.Recursive.Mutex,
0204             &queue_context
0205           );
0206           status = _CORE_ceiling_mutex_Set_owner(
0207             &the_semaphore->Core_control.Mutex,
0208             executing,
0209             &queue_context
0210           );
0211 
0212           if ( status != STATUS_SUCCESSFUL ) {
0213             _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
0214           }
0215         } else {
0216           status = STATUS_SUCCESSFUL;
0217         }
0218       } else {
0219         status = STATUS_INVALID_PRIORITY;
0220       }
0221 
0222       break;
0223 #if defined(RTEMS_SMP)
0224     case SEMAPHORE_VARIANT_MRSP:
0225       scheduler = _Thread_Scheduler_get_home( executing );
0226       priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
0227 
0228       if ( valid ) {
0229         status = _MRSP_Initialize(
0230           &the_semaphore->Core_control.MRSP,
0231           scheduler,
0232           priority,
0233           executing,
0234           count == 0
0235         );
0236       } else {
0237         status = STATUS_INVALID_PRIORITY;
0238       }
0239 
0240       break;
0241 #endif
0242     default:
0243       _Assert(
0244         variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
0245           || variant == SEMAPHORE_VARIANT_COUNTING
0246       );
0247       _CORE_semaphore_Initialize(
0248         &the_semaphore->Core_control.Semaphore,
0249         count
0250       );
0251       status = STATUS_SUCCESSFUL;
0252       break;
0253   }
0254 
0255   if ( status != STATUS_SUCCESSFUL ) {
0256     _Semaphore_Free( the_semaphore );
0257     _Objects_Allocator_unlock();
0258     return _Status_Get( status );
0259   }
0260 
0261   /*
0262    *  Whether we initialized it as a mutex or counting semaphore, it is
0263    *  now ready to be "offered" for use as a Classic API Semaphore.
0264    */
0265   *id = _Objects_Open_u32(
0266     &_Semaphore_Information,
0267     &the_semaphore->Object,
0268     name
0269   );
0270 
0271 #if defined(RTEMS_MULTIPROCESSING)
0272   if ( _Attributes_Is_global( attribute_set ) )
0273     _Semaphore_MP_Send_process_packet(
0274       SEMAPHORE_MP_ANNOUNCE_CREATE,
0275       the_semaphore->Object.id,
0276       name,
0277       0                          /* Not used */
0278     );
0279 #endif
0280   _Objects_Allocator_unlock();
0281   return RTEMS_SUCCESSFUL;
0282 }
0283 
0284 static void _Semaphore_Manager_initialization( void )
0285 {
0286   _Objects_Initialize_information( &_Semaphore_Information );
0287 }
0288 
0289 RTEMS_SYSINIT_ITEM(
0290   _Semaphore_Manager_initialization,
0291   RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
0292   RTEMS_SYSINIT_ORDER_MIDDLE
0293 );