File indexing completed on 2025-05-11 08:24:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
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
0086 maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
0087
0088
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
0117
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
0263
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
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 );