File indexing completed on 2025-05-11 08:24:13
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_SCORE_MRSPIMPL_H
0038 #define _RTEMS_SCORE_MRSPIMPL_H
0039
0040 #include <rtems/score/mrsp.h>
0041
0042 #if defined(RTEMS_SMP)
0043
0044 #include <rtems/score/assert.h>
0045 #include <rtems/score/status.h>
0046 #include <rtems/score/threadqimpl.h>
0047 #include <rtems/score/watchdogimpl.h>
0048
0049 #ifdef __cplusplus
0050 extern "C" {
0051 #endif
0052
0053
0054
0055
0056
0057
0058
0059 #define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
0060
0061
0062
0063
0064
0065
0066
0067 static inline void _MRSP_Acquire_critical(
0068 MRSP_Control *mrsp,
0069 Thread_queue_Context *queue_context
0070 )
0071 {
0072 _Thread_queue_Acquire_critical( &mrsp->Wait_queue, queue_context );
0073 }
0074
0075
0076
0077
0078
0079
0080
0081 static inline void _MRSP_Release(
0082 MRSP_Control *mrsp,
0083 Thread_queue_Context *queue_context
0084 )
0085 {
0086 _Thread_queue_Release( &mrsp->Wait_queue, queue_context );
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096 static inline Thread_Control *_MRSP_Get_owner(
0097 const MRSP_Control *mrsp
0098 )
0099 {
0100 return mrsp->Wait_queue.Queue.owner;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109 static inline void _MRSP_Set_owner(
0110 MRSP_Control *mrsp,
0111 Thread_Control *owner
0112 )
0113 {
0114 mrsp->Wait_queue.Queue.owner = owner;
0115 }
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 static inline Priority_Control _MRSP_Get_priority(
0126 const MRSP_Control *mrsp,
0127 const Scheduler_Control *scheduler
0128 )
0129 {
0130 uint32_t scheduler_index;
0131
0132 scheduler_index = _Scheduler_Get_index( scheduler );
0133 _Assert( scheduler_index < _Scheduler_Count );
0134 return mrsp->ceiling_priorities[ scheduler_index ];
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144 static inline void _MRSP_Set_priority(
0145 MRSP_Control *mrsp,
0146 const Scheduler_Control *scheduler,
0147 Priority_Control new_priority
0148 )
0149 {
0150 uint32_t scheduler_index;
0151
0152 scheduler_index = _Scheduler_Get_index( scheduler );
0153 _Assert( scheduler_index < _Scheduler_Count );
0154 mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 static inline Status_Control _MRSP_Raise_priority(
0171 MRSP_Control *mrsp,
0172 Thread_Control *thread,
0173 Priority_Node *priority_node,
0174 Thread_queue_Context *queue_context
0175 )
0176 {
0177 Status_Control status;
0178 ISR_lock_Context lock_context;
0179 const Scheduler_Control *scheduler;
0180 Priority_Control ceiling_priority;
0181 Scheduler_Node *scheduler_node;
0182
0183 _Thread_queue_Context_clear_priority_updates( queue_context );
0184 _Thread_Wait_acquire_default_critical( thread, &lock_context );
0185
0186 scheduler = _Thread_Scheduler_get_home( thread );
0187 scheduler_node = _Thread_Scheduler_get_home_node( thread );
0188 ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
0189
0190 if (
0191 ceiling_priority
0192 <= _Priority_Get_priority( &scheduler_node->Wait.Priority )
0193 ) {
0194 _Priority_Node_initialize( priority_node, ceiling_priority );
0195 _Thread_Priority_add( thread, priority_node, queue_context );
0196 status = STATUS_SUCCESSFUL;
0197 } else {
0198 status = STATUS_MUTEX_CEILING_VIOLATED;
0199 }
0200
0201 _Thread_Wait_release_default_critical( thread, &lock_context );
0202 return status;
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 static inline void _MRSP_Remove_priority(
0213 Thread_Control *thread,
0214 Priority_Node *priority_node,
0215 Thread_queue_Context *queue_context
0216 )
0217 {
0218 ISR_lock_Context lock_context;
0219
0220 _Thread_queue_Context_clear_priority_updates( queue_context );
0221 _Thread_Wait_acquire_default_critical( thread, &lock_context );
0222 _Thread_Priority_remove( thread, priority_node, queue_context );
0223 _Thread_Wait_release_default_critical( thread, &lock_context );
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static inline void _MRSP_Replace_priority(
0235 MRSP_Control *mrsp,
0236 Thread_Control *thread,
0237 Priority_Node *ceiling_priority
0238 )
0239 {
0240 ISR_lock_Context lock_context;
0241
0242 _Thread_Wait_acquire_default( thread, &lock_context );
0243 _Thread_Priority_replace(
0244 thread,
0245 ceiling_priority,
0246 &mrsp->Ceiling_priority
0247 );
0248 _Thread_Wait_release_default( thread, &lock_context );
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 static inline Status_Control _MRSP_Claim_ownership(
0263 MRSP_Control *mrsp,
0264 Thread_Control *executing,
0265 Thread_queue_Context *queue_context
0266 )
0267 {
0268 Status_Control status;
0269 Per_CPU_Control *cpu_self;
0270
0271 status = _MRSP_Raise_priority(
0272 mrsp,
0273 executing,
0274 &mrsp->Ceiling_priority,
0275 queue_context
0276 );
0277
0278 if ( status != STATUS_SUCCESSFUL ) {
0279 _MRSP_Release( mrsp, queue_context );
0280 return status;
0281 }
0282
0283 _MRSP_Set_owner( mrsp, executing );
0284 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
0285 _MRSP_Release( mrsp, queue_context );
0286 _Thread_Priority_update_and_make_sticky( executing );
0287 _Thread_Dispatch_enable( cpu_self );
0288 return STATUS_SUCCESSFUL;
0289 }
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 static inline Status_Control _MRSP_Initialize(
0306 MRSP_Control *mrsp,
0307 const Scheduler_Control *scheduler,
0308 Priority_Control ceiling_priority,
0309 Thread_Control *executing,
0310 bool initially_locked
0311 )
0312 {
0313 Thread_queue_Context queue_context;
0314 ISR_Level level;
0315 size_t scheduler_count;
0316 size_t i;
0317 Status_Control status;
0318
0319 scheduler_count = _Scheduler_Count;
0320
0321 for ( i = 0 ; i < scheduler_count ; ++i ) {
0322 const Scheduler_Control *scheduler_of_index;
0323
0324 scheduler_of_index = &_Scheduler_Table[ i ];
0325
0326 if ( scheduler != scheduler_of_index ) {
0327 mrsp->ceiling_priorities[ i ] =
0328 _Scheduler_Map_priority( scheduler_of_index, 0 );
0329 } else {
0330 mrsp->ceiling_priorities[ i ] = ceiling_priority;
0331 }
0332 }
0333
0334 _Thread_queue_Object_initialize( &mrsp->Wait_queue );
0335
0336 if ( !initially_locked ) {
0337 return STATUS_SUCCESSFUL;
0338 }
0339
0340 _Thread_queue_Context_initialize( &queue_context );
0341 _Thread_queue_Context_ISR_disable( &queue_context, level );
0342 _Thread_queue_Context_set_ISR_level( &queue_context, level );
0343 _MRSP_Acquire_critical( mrsp, &queue_context );
0344 status = _MRSP_Claim_ownership( mrsp, executing, &queue_context );
0345
0346 if ( status != STATUS_SUCCESSFUL ) {
0347 _Thread_queue_Destroy( &mrsp->Wait_queue );
0348 }
0349
0350 return status;
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 static inline Status_Control _MRSP_Wait_for_ownership(
0367 MRSP_Control *mrsp,
0368 Thread_Control *executing,
0369 Thread_queue_Context *queue_context
0370 )
0371 {
0372 Status_Control status;
0373 Priority_Node ceiling_priority;
0374
0375 status = _MRSP_Raise_priority(
0376 mrsp,
0377 executing,
0378 &ceiling_priority,
0379 queue_context
0380 );
0381
0382 if ( status != STATUS_SUCCESSFUL ) {
0383 _MRSP_Release( mrsp, queue_context );
0384 return status;
0385 }
0386
0387 _Thread_queue_Context_set_deadlock_callout(
0388 queue_context,
0389 _Thread_queue_Deadlock_status
0390 );
0391 status = _Thread_queue_Enqueue_sticky(
0392 &mrsp->Wait_queue.Queue,
0393 MRSP_TQ_OPERATIONS,
0394 executing,
0395 queue_context
0396 );
0397
0398 if ( status == STATUS_SUCCESSFUL ) {
0399 _MRSP_Replace_priority( mrsp, executing, &ceiling_priority );
0400 } else {
0401 Per_CPU_Control *cpu_self;
0402
0403 _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
0404 _MRSP_Remove_priority( executing, &ceiling_priority, queue_context );
0405 cpu_self = _Thread_Dispatch_disable_critical(
0406 &queue_context->Lock_context.Lock_context
0407 );
0408 _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
0409
0410 if ( status != STATUS_DEADLOCK ) {
0411 _Thread_Priority_update_and_clean_sticky( executing );
0412 } else {
0413 _Thread_Priority_update_ignore_sticky( executing );
0414 }
0415
0416 _Thread_Dispatch_enable( cpu_self );
0417 }
0418
0419 return status;
0420 }
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 static inline Status_Control _MRSP_Seize(
0445 MRSP_Control *mrsp,
0446 Thread_Control *executing,
0447 bool wait,
0448 Thread_queue_Context *queue_context
0449 )
0450 {
0451 Status_Control status;
0452 Thread_Control *owner;
0453
0454 _MRSP_Acquire_critical( mrsp, queue_context );
0455
0456 owner = _MRSP_Get_owner( mrsp );
0457
0458 if ( owner == NULL ) {
0459 status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
0460 } else if ( owner == executing ) {
0461 _MRSP_Release( mrsp, queue_context );
0462 status = STATUS_DEADLOCK;
0463 } else if ( wait ) {
0464 status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context );
0465 } else {
0466 _MRSP_Release( mrsp, queue_context );
0467 status = STATUS_UNAVAILABLE;
0468 }
0469
0470 return status;
0471 }
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483 static inline Status_Control _MRSP_Surrender(
0484 MRSP_Control *mrsp,
0485 Thread_Control *executing,
0486 Thread_queue_Context *queue_context
0487 )
0488 {
0489 Thread_queue_Heads *heads;
0490
0491 if ( _MRSP_Get_owner( mrsp ) != executing ) {
0492 _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
0493 return STATUS_NOT_OWNER;
0494 }
0495
0496 _MRSP_Acquire_critical( mrsp, queue_context );
0497
0498 _MRSP_Set_owner( mrsp, NULL );
0499 _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
0500
0501 heads = mrsp->Wait_queue.Queue.heads;
0502
0503 if ( heads == NULL ) {
0504 Per_CPU_Control *cpu_self;
0505
0506 cpu_self = _Thread_Dispatch_disable_critical(
0507 &queue_context->Lock_context.Lock_context
0508 );
0509 _MRSP_Release( mrsp, queue_context );
0510 _Thread_Priority_update_and_clean_sticky( executing );
0511 _Thread_Dispatch_enable( cpu_self );
0512 return STATUS_SUCCESSFUL;
0513 }
0514
0515 _Thread_queue_Surrender_sticky(
0516 &mrsp->Wait_queue.Queue,
0517 heads,
0518 executing,
0519 queue_context,
0520 MRSP_TQ_OPERATIONS
0521 );
0522 return STATUS_SUCCESSFUL;
0523 }
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535 static inline Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp )
0536 {
0537 if ( _MRSP_Get_owner( mrsp ) != NULL ) {
0538 return STATUS_RESOURCE_IN_USE;
0539 }
0540
0541 return STATUS_SUCCESSFUL;
0542 }
0543
0544
0545
0546
0547
0548
0549
0550 static inline void _MRSP_Destroy(
0551 MRSP_Control *mrsp,
0552 Thread_queue_Context *queue_context
0553 )
0554 {
0555 _MRSP_Release( mrsp, queue_context );
0556 _Thread_queue_Destroy( &mrsp->Wait_queue );
0557 }
0558
0559
0560
0561 #ifdef __cplusplus
0562 }
0563 #endif
0564
0565 #endif
0566
0567 #endif