File indexing completed on 2025-05-11 08:24:12
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 #ifndef _RTEMS_POSIX_MUTEXIMPL_H
0038 #define _RTEMS_POSIX_MUTEXIMPL_H
0039
0040 #include <errno.h>
0041 #include <pthread.h>
0042
0043 #include <rtems/score/percpu.h>
0044 #include <rtems/score/muteximpl.h>
0045 #include <rtems/score/threadimpl.h>
0046
0047 #ifdef __cplusplus
0048 extern "C" {
0049 #endif
0050
0051 typedef struct {
0052 unsigned long flags;
0053 Mutex_recursive_Control Recursive;
0054 Priority_Node Priority_ceiling;
0055 const Scheduler_Control *scheduler;
0056 } POSIX_Mutex_Control;
0057
0058 #define POSIX_MUTEX_PROTOCOL_MASK 0x3UL
0059
0060 #define POSIX_MUTEX_RECURSIVE 0x4UL
0061
0062 #define POSIX_MUTEX_FLAGS_MASK 0x7UL
0063
0064 #define POSIX_MUTEX_MAGIC 0x961c13b8UL
0065
0066 #define POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
0067
0068 #define POSIX_MUTEX_PRIORITY_INHERIT_TQ_OPERATIONS \
0069 &_Thread_queue_Operations_priority_inherit
0070
0071 #define POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS \
0072 &_Thread_queue_Operations_priority
0073
0074
0075
0076
0077
0078
0079 typedef enum {
0080 POSIX_MUTEX_NO_PROTOCOL,
0081 POSIX_MUTEX_PRIORITY_INHERIT,
0082 POSIX_MUTEX_PRIORITY_CEILING
0083 } POSIX_Mutex_Protocol;
0084
0085
0086
0087
0088 extern const pthread_mutexattr_t _POSIX_Mutex_Default_attributes;
0089
0090 static inline Thread_Control *_POSIX_Mutex_Acquire(
0091 POSIX_Mutex_Control *the_mutex,
0092 Thread_queue_Context *queue_context
0093 )
0094 {
0095 ISR_Level level;
0096 Thread_Control *executing;
0097
0098 _Thread_queue_Context_initialize( queue_context );
0099 _Thread_queue_Context_ISR_disable( queue_context, level );
0100 _Thread_queue_Context_set_ISR_level( queue_context, level );
0101 executing = _Thread_Executing;
0102 _Thread_queue_Queue_acquire_critical(
0103 &the_mutex->Recursive.Mutex.Queue.Queue,
0104 &executing->Potpourri_stats,
0105 &queue_context->Lock_context.Lock_context
0106 );
0107
0108 return executing;
0109 }
0110
0111 static inline void _POSIX_Mutex_Release(
0112 POSIX_Mutex_Control *the_mutex,
0113 Thread_queue_Context *queue_context
0114 )
0115 {
0116 _Thread_queue_Queue_release(
0117 &the_mutex->Recursive.Mutex.Queue.Queue,
0118 &queue_context->Lock_context.Lock_context
0119 );
0120 }
0121
0122 static inline POSIX_Mutex_Protocol _POSIX_Mutex_Get_protocol(
0123 unsigned long flags
0124 )
0125 {
0126 return (POSIX_Mutex_Protocol) (flags & POSIX_MUTEX_PROTOCOL_MASK);
0127 }
0128
0129 static inline bool _POSIX_Mutex_Is_recursive(
0130 unsigned long flags
0131 )
0132 {
0133 return ( flags & POSIX_MUTEX_RECURSIVE ) != 0;
0134 }
0135
0136 static inline Thread_Control *_POSIX_Mutex_Get_owner(
0137 const POSIX_Mutex_Control *the_mutex
0138 )
0139 {
0140 return the_mutex->Recursive.Mutex.Queue.Queue.owner;
0141 }
0142
0143 static inline bool _POSIX_Mutex_Is_locked(
0144 const POSIX_Mutex_Control *the_mutex
0145 )
0146 {
0147 return _POSIX_Mutex_Get_owner( the_mutex ) != NULL;
0148 }
0149
0150 Status_Control _POSIX_Mutex_Seize_slow(
0151 POSIX_Mutex_Control *the_mutex,
0152 const Thread_queue_Operations *operations,
0153 Thread_Control *executing,
0154 const struct timespec *abstime,
0155 Thread_queue_Context *queue_context
0156 );
0157
0158 static inline void _POSIX_Mutex_Set_owner(
0159 POSIX_Mutex_Control *the_mutex,
0160 Thread_Control *owner
0161 )
0162 {
0163 the_mutex->Recursive.Mutex.Queue.Queue.owner = owner;
0164 }
0165
0166 static inline bool _POSIX_Mutex_Is_owner(
0167 const POSIX_Mutex_Control *the_mutex,
0168 const Thread_Control *the_thread
0169 )
0170 {
0171 return _POSIX_Mutex_Get_owner( the_mutex ) == the_thread;
0172 }
0173
0174 static Status_Control _POSIX_Mutex_Lock_nested(
0175 POSIX_Mutex_Control *the_mutex,
0176 unsigned long flags
0177 )
0178 {
0179
0180 if ( _POSIX_Mutex_Is_recursive( flags ) ) {
0181 ++the_mutex->Recursive.nest_level;
0182 return STATUS_SUCCESSFUL;
0183 } else {
0184 return STATUS_NESTING_NOT_ALLOWED;
0185 }
0186 }
0187
0188 static inline Status_Control _POSIX_Mutex_Seize(
0189 POSIX_Mutex_Control *the_mutex,
0190 unsigned long flags,
0191 const Thread_queue_Operations *operations,
0192 Thread_Control *executing,
0193 const struct timespec *abstime,
0194 Thread_queue_Context *queue_context
0195 )
0196 {
0197 Thread_Control *owner;
0198
0199 owner = _POSIX_Mutex_Get_owner( the_mutex );
0200
0201 if ( owner == NULL ) {
0202 _POSIX_Mutex_Set_owner( the_mutex, executing );
0203 _Thread_Resource_count_increment( executing );
0204 _POSIX_Mutex_Release( the_mutex, queue_context );
0205 return STATUS_SUCCESSFUL;
0206 }
0207
0208 if ( owner == executing ) {
0209 Status_Control status;
0210
0211 status = _POSIX_Mutex_Lock_nested( the_mutex, flags );
0212 _POSIX_Mutex_Release( the_mutex, queue_context );
0213 return status;
0214 }
0215
0216 return _POSIX_Mutex_Seize_slow(
0217 the_mutex,
0218 operations,
0219 executing,
0220 abstime,
0221 queue_context
0222 );
0223 }
0224
0225 static inline Status_Control _POSIX_Mutex_Surrender(
0226 POSIX_Mutex_Control *the_mutex,
0227 const Thread_queue_Operations *operations,
0228 Thread_Control *executing,
0229 Thread_queue_Context *queue_context
0230 )
0231 {
0232 unsigned int nest_level;
0233 Thread_queue_Heads *heads;
0234
0235 if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) {
0236 _POSIX_Mutex_Release( the_mutex, queue_context );
0237 return STATUS_NOT_OWNER;
0238 }
0239
0240 nest_level = the_mutex->Recursive.nest_level;
0241
0242 if ( nest_level > 0 ) {
0243 the_mutex->Recursive.nest_level = nest_level - 1;
0244 _POSIX_Mutex_Release( the_mutex, queue_context );
0245 return STATUS_SUCCESSFUL;
0246 }
0247
0248 _Thread_Resource_count_decrement( executing );
0249 _POSIX_Mutex_Set_owner( the_mutex, NULL );
0250
0251 heads = the_mutex->Recursive.Mutex.Queue.Queue.heads;
0252
0253 if ( heads == NULL ) {
0254 _POSIX_Mutex_Release( the_mutex, queue_context );
0255 return STATUS_SUCCESSFUL;
0256 }
0257
0258 _Thread_queue_Surrender(
0259 &the_mutex->Recursive.Mutex.Queue.Queue,
0260 heads,
0261 executing,
0262 queue_context,
0263 operations
0264 );
0265 return STATUS_SUCCESSFUL;
0266 }
0267
0268 static inline const Scheduler_Control *_POSIX_Mutex_Get_scheduler(
0269 const POSIX_Mutex_Control *the_mutex
0270 )
0271 {
0272 #if defined(RTEMS_SMP)
0273 return the_mutex->scheduler;
0274 #else
0275 return &_Scheduler_Table[ 0 ];
0276 #endif
0277 }
0278
0279 static inline void _POSIX_Mutex_Set_priority(
0280 POSIX_Mutex_Control *the_mutex,
0281 Priority_Control priority_ceiling,
0282 Thread_queue_Context *queue_context
0283 )
0284 {
0285 Thread_Control *owner;
0286
0287 owner = _POSIX_Mutex_Get_owner( the_mutex );
0288
0289 if ( owner != NULL ) {
0290 _Thread_Wait_acquire( owner, queue_context );
0291 _Thread_Priority_change(
0292 owner,
0293 &the_mutex->Priority_ceiling,
0294 priority_ceiling,
0295 PRIORITY_GROUP_LAST,
0296 queue_context
0297 );
0298 _Thread_Wait_release( owner, queue_context );
0299 } else {
0300 the_mutex->Priority_ceiling.priority = priority_ceiling;
0301 }
0302 }
0303
0304 static inline Priority_Control _POSIX_Mutex_Get_priority(
0305 const POSIX_Mutex_Control *the_mutex
0306 )
0307 {
0308 return the_mutex->Priority_ceiling.priority;
0309 }
0310
0311 static inline Status_Control _POSIX_Mutex_Ceiling_set_owner(
0312 POSIX_Mutex_Control *the_mutex,
0313 Thread_Control *owner,
0314 Thread_queue_Context *queue_context
0315 )
0316 {
0317 ISR_lock_Context lock_context;
0318 Scheduler_Node *scheduler_node;
0319 Per_CPU_Control *cpu_self;
0320
0321 _Thread_Wait_acquire_default_critical( owner, &lock_context );
0322
0323 scheduler_node = _Thread_Scheduler_get_home_node( owner );
0324
0325 if (
0326 _Priority_Get_priority( &scheduler_node->Wait.Priority )
0327 < the_mutex->Priority_ceiling.priority
0328 ) {
0329 _Thread_Wait_release_default_critical( owner, &lock_context );
0330 _POSIX_Mutex_Release( the_mutex, queue_context );
0331 return STATUS_MUTEX_CEILING_VIOLATED;
0332 }
0333
0334 _POSIX_Mutex_Set_owner( the_mutex, owner );
0335 _Thread_Resource_count_increment( owner );
0336 _Thread_Priority_add(
0337 owner,
0338 &the_mutex->Priority_ceiling,
0339 queue_context
0340 );
0341 _Thread_Wait_release_default_critical( owner, &lock_context );
0342
0343 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
0344 _POSIX_Mutex_Release( the_mutex, queue_context );
0345 _Thread_Priority_update( queue_context );
0346 _Thread_Dispatch_enable( cpu_self );
0347 return STATUS_SUCCESSFUL;
0348 }
0349
0350 static inline Status_Control _POSIX_Mutex_Ceiling_seize(
0351 POSIX_Mutex_Control *the_mutex,
0352 unsigned long flags,
0353 Thread_Control *executing,
0354 const struct timespec *abstime,
0355 Thread_queue_Context *queue_context
0356 )
0357 {
0358 Thread_Control *owner;
0359
0360 owner = _POSIX_Mutex_Get_owner( the_mutex );
0361
0362 if ( owner == NULL ) {
0363 #if defined(RTEMS_SMP)
0364 if (
0365 _Thread_Scheduler_get_home( executing )
0366 != _POSIX_Mutex_Get_scheduler( the_mutex )
0367 ) {
0368 _POSIX_Mutex_Release( the_mutex, queue_context );
0369 return STATUS_NOT_DEFINED;
0370 }
0371 #endif
0372
0373 _Thread_queue_Context_clear_priority_updates( queue_context );
0374 return _POSIX_Mutex_Ceiling_set_owner(
0375 the_mutex,
0376 executing,
0377 queue_context
0378 );
0379 }
0380
0381 if ( owner == executing ) {
0382 Status_Control status;
0383
0384 status = _POSIX_Mutex_Lock_nested( the_mutex, flags );
0385 _POSIX_Mutex_Release( the_mutex, queue_context );
0386 return status;
0387 }
0388
0389 return _POSIX_Mutex_Seize_slow(
0390 the_mutex,
0391 POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS,
0392 executing,
0393 abstime,
0394 queue_context
0395 );
0396 }
0397
0398 static inline Status_Control _POSIX_Mutex_Ceiling_surrender(
0399 POSIX_Mutex_Control *the_mutex,
0400 Thread_Control *executing,
0401 Thread_queue_Context *queue_context
0402 )
0403 {
0404 unsigned int nest_level;
0405
0406 if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) {
0407 _POSIX_Mutex_Release( the_mutex, queue_context );
0408 return STATUS_NOT_OWNER;
0409 }
0410
0411 nest_level = the_mutex->Recursive.nest_level;
0412
0413 if ( nest_level > 0 ) {
0414 the_mutex->Recursive.nest_level = nest_level - 1;
0415 _POSIX_Mutex_Release( the_mutex, queue_context );
0416 return STATUS_SUCCESSFUL;
0417 }
0418
0419 return _Thread_queue_Surrender_priority_ceiling(
0420 &the_mutex->Recursive.Mutex.Queue.Queue,
0421 executing,
0422 &the_mutex->Priority_ceiling,
0423 queue_context,
0424 POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS
0425 );
0426 }
0427
0428 #define POSIX_MUTEX_ABSTIME_TRY_LOCK ((uintptr_t) 1)
0429
0430 int _POSIX_Mutex_Lock_support(
0431 pthread_mutex_t *mutex,
0432 const struct timespec *abstime,
0433 Thread_queue_Enqueue_callout enqueue_callout
0434 );
0435
0436 static inline POSIX_Mutex_Control *_POSIX_Mutex_Get(
0437 pthread_mutex_t *mutex
0438 )
0439 {
0440 return (POSIX_Mutex_Control *) mutex;
0441 }
0442
0443 bool _POSIX_Mutex_Auto_initialization( POSIX_Mutex_Control *the_mutex );
0444
0445 #define POSIX_MUTEX_VALIDATE_OBJECT( the_mutex, flags ) \
0446 do { \
0447 if ( ( the_mutex ) == NULL ) { \
0448 return EINVAL; \
0449 } \
0450 flags = ( the_mutex )->flags; \
0451 if ( \
0452 ( ( (uintptr_t) ( the_mutex ) ^ POSIX_MUTEX_MAGIC ) \
0453 & ~POSIX_MUTEX_FLAGS_MASK ) \
0454 != ( flags & ~POSIX_MUTEX_FLAGS_MASK ) \
0455 ) { \
0456 if ( !_POSIX_Mutex_Auto_initialization( the_mutex ) ) { \
0457 return EINVAL; \
0458 } \
0459 } \
0460 } while ( 0 )
0461
0462 #ifdef __cplusplus
0463 }
0464 #endif
0465
0466 #endif
0467