File indexing completed on 2025-05-11 08:24:26
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
0039
0040 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043
0044 #include <sys/lock.h>
0045 #include <errno.h>
0046
0047 #include <rtems/score/assert.h>
0048 #include <rtems/score/muteximpl.h>
0049 #include <rtems/score/threadimpl.h>
0050 #include <rtems/score/todimpl.h>
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 #define MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
0067
0068 RTEMS_STATIC_ASSERT(
0069 offsetof( Mutex_Control, Queue )
0070 == offsetof( struct _Mutex_Control, _Queue ),
0071 MUTEX_CONTROL_QUEUE
0072 );
0073
0074 RTEMS_STATIC_ASSERT(
0075 sizeof( Mutex_Control ) == sizeof( struct _Mutex_Control ),
0076 MUTEX_CONTROL_SIZE
0077 );
0078
0079 RTEMS_STATIC_ASSERT(
0080 offsetof( Mutex_recursive_Control, Mutex )
0081 == offsetof( struct _Mutex_recursive_Control, _Mutex ),
0082 MUTEX_RECURSIVE_CONTROL_MUTEX
0083 );
0084
0085 RTEMS_STATIC_ASSERT(
0086 offsetof( Mutex_recursive_Control, nest_level )
0087 == offsetof( struct _Mutex_recursive_Control, _nest_level ),
0088 MUTEX_RECURSIVE_CONTROL_NEST_LEVEL
0089 );
0090
0091 RTEMS_STATIC_ASSERT(
0092 sizeof( Mutex_recursive_Control )
0093 == sizeof( struct _Mutex_recursive_Control ),
0094 MUTEX_RECURSIVE_CONTROL_SIZE
0095 );
0096
0097 static Mutex_Control *_Mutex_Get( struct _Mutex_Control *_mutex )
0098 {
0099 return (Mutex_Control *) _mutex;
0100 }
0101
0102 static Thread_Control *_Mutex_Queue_acquire_critical(
0103 Mutex_Control *mutex,
0104 Thread_queue_Context *queue_context
0105 )
0106 {
0107 Thread_Control *executing;
0108
0109 executing = _Thread_Executing;
0110 _Thread_queue_Queue_acquire_critical(
0111 &mutex->Queue.Queue,
0112 &executing->Potpourri_stats,
0113 &queue_context->Lock_context.Lock_context
0114 );
0115
0116 return executing;
0117 }
0118
0119 static void _Mutex_Queue_release(
0120 Mutex_Control *mutex,
0121 ISR_Level level,
0122 Thread_queue_Context *queue_context
0123 )
0124 {
0125 _Thread_queue_Queue_release_critical(
0126 &mutex->Queue.Queue,
0127 &queue_context->Lock_context.Lock_context
0128 );
0129 _ISR_Local_enable( level );
0130 }
0131
0132 static void _Mutex_Acquire_slow(
0133 Mutex_Control *mutex,
0134 Thread_Control *owner,
0135 Thread_Control *executing,
0136 ISR_Level level,
0137 Thread_queue_Context *queue_context
0138 )
0139 {
0140 _Thread_queue_Context_set_thread_state(
0141 queue_context,
0142 STATES_WAITING_FOR_MUTEX
0143 );
0144 _Thread_queue_Context_set_deadlock_callout(
0145 queue_context,
0146 _Thread_queue_Deadlock_fatal
0147 );
0148 _Thread_queue_Context_set_ISR_level( queue_context, level );
0149 _Thread_queue_Enqueue(
0150 &mutex->Queue.Queue,
0151 MUTEX_TQ_OPERATIONS,
0152 executing,
0153 queue_context
0154 );
0155 }
0156
0157 static void _Mutex_Release_critical(
0158 Mutex_Control *mutex,
0159 Thread_Control *executing,
0160 ISR_Level level,
0161 Thread_queue_Context *queue_context
0162 )
0163 {
0164 Thread_queue_Heads *heads;
0165
0166 heads = mutex->Queue.Queue.heads;
0167 mutex->Queue.Queue.owner = NULL;
0168 _Thread_Resource_count_decrement( executing );
0169
0170 if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
0171 _Mutex_Queue_release( mutex, level, queue_context );
0172 } else {
0173 _Thread_queue_Context_set_ISR_level( queue_context, level );
0174 _Thread_queue_Surrender(
0175 &mutex->Queue.Queue,
0176 heads,
0177 executing,
0178 queue_context,
0179 MUTEX_TQ_OPERATIONS
0180 );
0181 }
0182 }
0183
0184 void _Mutex_Acquire( struct _Mutex_Control *_mutex )
0185 {
0186 Mutex_Control *mutex;
0187 Thread_queue_Context queue_context;
0188 ISR_Level level;
0189 Thread_Control *executing;
0190 Thread_Control *owner;
0191
0192 mutex = _Mutex_Get( _mutex );
0193 _Thread_queue_Context_initialize( &queue_context );
0194 _Thread_queue_Context_ISR_disable( &queue_context, level );
0195 executing = _Mutex_Queue_acquire_critical( mutex, &queue_context );
0196
0197 owner = mutex->Queue.Queue.owner;
0198
0199 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0200 mutex->Queue.Queue.owner = executing;
0201 _Thread_Resource_count_increment( executing );
0202 _Mutex_Queue_release( mutex, level, &queue_context );
0203 } else {
0204 _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
0205 _Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
0206 }
0207 }
0208
0209 int _Mutex_Acquire_timed(
0210 struct _Mutex_Control *_mutex,
0211 const struct timespec *abstime
0212 )
0213 {
0214 Mutex_Control *mutex;
0215 Thread_queue_Context queue_context;
0216 ISR_Level level;
0217 Thread_Control *executing;
0218 Thread_Control *owner;
0219
0220 mutex = _Mutex_Get( _mutex );
0221 _Thread_queue_Context_initialize( &queue_context );
0222 _Thread_queue_Context_ISR_disable( &queue_context, level );
0223 executing = _Mutex_Queue_acquire_critical( mutex, &queue_context );
0224
0225 owner = mutex->Queue.Queue.owner;
0226
0227 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0228 mutex->Queue.Queue.owner = executing;
0229 _Thread_Resource_count_increment( executing );
0230 _Mutex_Queue_release( mutex, level, &queue_context );
0231
0232 return 0;
0233 } else {
0234 _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
0235 &queue_context,
0236 abstime,
0237 true
0238 );
0239 _Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
0240
0241 return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
0242 }
0243 }
0244
0245 int _Mutex_Try_acquire( struct _Mutex_Control *_mutex )
0246 {
0247 Mutex_Control *mutex;
0248 Thread_queue_Context queue_context;
0249 ISR_Level level;
0250 Thread_Control *executing;
0251 Thread_Control *owner;
0252 int eno;
0253
0254 mutex = _Mutex_Get( _mutex );
0255 _Thread_queue_Context_initialize( &queue_context );
0256 _Thread_queue_Context_ISR_disable( &queue_context, level );
0257 executing = _Mutex_Queue_acquire_critical( mutex, &queue_context );
0258
0259 owner = mutex->Queue.Queue.owner;
0260
0261 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0262 mutex->Queue.Queue.owner = executing;
0263 _Thread_Resource_count_increment( executing );
0264 eno = 0;
0265 } else {
0266 eno = EBUSY;
0267 }
0268
0269 _Mutex_Queue_release( mutex, level, &queue_context );
0270
0271 return eno;
0272 }
0273
0274 void _Mutex_Release( struct _Mutex_Control *_mutex )
0275 {
0276 Mutex_Control *mutex;
0277 Thread_queue_Context queue_context;
0278 ISR_Level level;
0279 Thread_Control *executing;
0280
0281 mutex = _Mutex_Get( _mutex );
0282 _Thread_queue_Context_initialize( &queue_context );
0283 _Thread_queue_Context_ISR_disable( &queue_context, level );
0284 executing = _Mutex_Queue_acquire_critical( mutex, &queue_context );
0285
0286 _Assert( mutex->Queue.Queue.owner == executing );
0287
0288 _Mutex_Release_critical( mutex, executing, level, &queue_context );
0289 }
0290
0291 static Mutex_recursive_Control *_Mutex_recursive_Get(
0292 struct _Mutex_recursive_Control *_mutex
0293 )
0294 {
0295 return (Mutex_recursive_Control *) _mutex;
0296 }
0297
0298 void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
0299 {
0300 Mutex_recursive_Control *mutex;
0301 Thread_queue_Context queue_context;
0302 ISR_Level level;
0303 Thread_Control *executing;
0304 Thread_Control *owner;
0305
0306 mutex = _Mutex_recursive_Get( _mutex );
0307 _Thread_queue_Context_initialize( &queue_context );
0308 _Thread_queue_Context_ISR_disable( &queue_context, level );
0309 executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );
0310
0311 owner = mutex->Mutex.Queue.Queue.owner;
0312
0313 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0314 mutex->Mutex.Queue.Queue.owner = executing;
0315 _Thread_Resource_count_increment( executing );
0316 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0317 } else if ( owner == executing ) {
0318 ++mutex->nest_level;
0319 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0320 } else {
0321 _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
0322 _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
0323 }
0324 }
0325
0326 int _Mutex_recursive_Acquire_timed(
0327 struct _Mutex_recursive_Control *_mutex,
0328 const struct timespec *abstime
0329 )
0330 {
0331 Mutex_recursive_Control *mutex;
0332 Thread_queue_Context queue_context;
0333 ISR_Level level;
0334 Thread_Control *executing;
0335 Thread_Control *owner;
0336
0337 mutex = _Mutex_recursive_Get( _mutex );
0338 _Thread_queue_Context_initialize( &queue_context );
0339 _Thread_queue_Context_ISR_disable( &queue_context, level );
0340 executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );
0341
0342 owner = mutex->Mutex.Queue.Queue.owner;
0343
0344 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0345 mutex->Mutex.Queue.Queue.owner = executing;
0346 _Thread_Resource_count_increment( executing );
0347 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0348
0349 return 0;
0350 } else if ( owner == executing ) {
0351 ++mutex->nest_level;
0352 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0353
0354 return 0;
0355 } else {
0356 _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
0357 &queue_context,
0358 abstime,
0359 true
0360 );
0361 _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
0362
0363 return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
0364 }
0365 }
0366
0367 int _Mutex_recursive_Try_acquire( struct _Mutex_recursive_Control *_mutex )
0368 {
0369 Mutex_recursive_Control *mutex;
0370 Thread_queue_Context queue_context;
0371 ISR_Level level;
0372 Thread_Control *executing;
0373 Thread_Control *owner;
0374 int eno;
0375
0376 mutex = _Mutex_recursive_Get( _mutex );
0377 _Thread_queue_Context_initialize( &queue_context );
0378 _Thread_queue_Context_ISR_disable( &queue_context, level );
0379 executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );
0380
0381 owner = mutex->Mutex.Queue.Queue.owner;
0382
0383 if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
0384 mutex->Mutex.Queue.Queue.owner = executing;
0385 _Thread_Resource_count_increment( executing );
0386 eno = 0;
0387 } else if ( owner == executing ) {
0388 ++mutex->nest_level;
0389 eno = 0;
0390 } else {
0391 eno = EBUSY;
0392 }
0393
0394 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0395
0396 return eno;
0397 }
0398
0399 void _Mutex_recursive_Release( struct _Mutex_recursive_Control *_mutex )
0400 {
0401 Mutex_recursive_Control *mutex;
0402 Thread_queue_Context queue_context;
0403 ISR_Level level;
0404 Thread_Control *executing;
0405 unsigned int nest_level;
0406
0407 mutex = _Mutex_recursive_Get( _mutex );
0408 _Thread_queue_Context_initialize( &queue_context );
0409 _Thread_queue_Context_ISR_disable( &queue_context, level );
0410 executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );
0411
0412 _Assert( mutex->Mutex.Queue.Queue.owner == executing );
0413
0414 nest_level = mutex->nest_level;
0415
0416 if ( RTEMS_PREDICT_TRUE( nest_level == 0 ) ) {
0417 _Mutex_Release_critical( &mutex->Mutex, executing, level, &queue_context );
0418 } else {
0419 mutex->nest_level = nest_level - 1;
0420
0421 _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
0422 }
0423 }