[f9d533a5] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @brief Private Inlined Routines for POSIX Mutex's. |
---|
[c5b7942] | 5 | * |
---|
| 6 | * This include file contains the static inline implementation of the private |
---|
[f9d533a5] | 7 | * inlined routines for POSIX mutex's. |
---|
| 8 | */ |
---|
| 9 | |
---|
[4600bd7c] | 10 | /* COPYRIGHT (c) 1989-2013. |
---|
[f9d533a5] | 11 | * On-Line Applications Research Corporation (OAR). |
---|
| 12 | * |
---|
| 13 | * The license and distribution terms for this file may be |
---|
| 14 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 15 | * http://www.rtems.org/license/LICENSE. |
---|
[f9d533a5] | 16 | */ |
---|
| 17 | |
---|
[b8bdced1] | 18 | #ifndef _RTEMS_POSIX_MUTEXIMPL_H |
---|
| 19 | #define _RTEMS_POSIX_MUTEXIMPL_H |
---|
| 20 | |
---|
[9728ef3] | 21 | #include <errno.h> |
---|
[b8bdced1] | 22 | #include <pthread.h> |
---|
[f9d533a5] | 23 | |
---|
[de59c065] | 24 | #include <rtems/score/percpu.h> |
---|
| 25 | #include <rtems/score/muteximpl.h> |
---|
| 26 | #include <rtems/score/threadimpl.h> |
---|
| 27 | |
---|
[f9d533a5] | 28 | #ifdef __cplusplus |
---|
| 29 | extern "C" { |
---|
| 30 | #endif |
---|
| 31 | |
---|
[de59c065] | 32 | typedef struct { |
---|
| 33 | unsigned long flags; |
---|
| 34 | Mutex_recursive_Control Recursive; |
---|
| 35 | Priority_Node Priority_ceiling; |
---|
| 36 | const Scheduler_Control *scheduler; |
---|
| 37 | } POSIX_Mutex_Control; |
---|
| 38 | |
---|
| 39 | #define POSIX_MUTEX_PROTOCOL_MASK 0x3UL |
---|
| 40 | |
---|
| 41 | #define POSIX_MUTEX_RECURSIVE 0x4UL |
---|
| 42 | |
---|
| 43 | #define POSIX_MUTEX_FLAGS_MASK 0x7UL |
---|
| 44 | |
---|
| 45 | #define POSIX_MUTEX_MAGIC 0x961c13b8UL |
---|
| 46 | |
---|
[5a598ac] | 47 | #define POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS &_Thread_queue_Operations_FIFO |
---|
| 48 | |
---|
[de59c065] | 49 | #define POSIX_MUTEX_PRIORITY_INHERIT_TQ_OPERATIONS \ |
---|
| 50 | &_Thread_queue_Operations_priority_inherit |
---|
| 51 | |
---|
| 52 | #define POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS \ |
---|
| 53 | &_Thread_queue_Operations_priority |
---|
| 54 | |
---|
[5a598ac] | 55 | /** |
---|
| 56 | * @brief Supported POSIX mutex protocols. |
---|
| 57 | * |
---|
| 58 | * Must be in synchronization with POSIX_Mutex_Control::protocol. |
---|
| 59 | */ |
---|
| 60 | typedef enum { |
---|
| 61 | POSIX_MUTEX_NO_PROTOCOL, |
---|
| 62 | POSIX_MUTEX_PRIORITY_INHERIT, |
---|
| 63 | POSIX_MUTEX_PRIORITY_CEILING |
---|
| 64 | } POSIX_Mutex_Protocol; |
---|
| 65 | |
---|
[4600bd7c] | 66 | /** |
---|
[f9d533a5] | 67 | * The default mutex attributes structure. |
---|
| 68 | */ |
---|
[2df7fcf] | 69 | extern const pthread_mutexattr_t _POSIX_Mutex_Default_attributes; |
---|
[f9d533a5] | 70 | |
---|
[de59c065] | 71 | RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Mutex_Acquire( |
---|
[5a598ac] | 72 | POSIX_Mutex_Control *the_mutex, |
---|
| 73 | Thread_queue_Context *queue_context |
---|
| 74 | ) |
---|
| 75 | { |
---|
[de59c065] | 76 | ISR_Level level; |
---|
| 77 | Thread_Control *executing; |
---|
| 78 | |
---|
| 79 | _Thread_queue_Context_initialize( queue_context ); |
---|
| 80 | _Thread_queue_Context_ISR_disable( queue_context, level ); |
---|
| 81 | _Thread_queue_Context_set_ISR_level( queue_context, level ); |
---|
| 82 | executing = _Thread_Executing; |
---|
| 83 | _Thread_queue_Queue_acquire_critical( |
---|
| 84 | &the_mutex->Recursive.Mutex.Queue.Queue, |
---|
| 85 | &executing->Potpourri_stats, |
---|
| 86 | &queue_context->Lock_context.Lock_context |
---|
[5a598ac] | 87 | ); |
---|
[de59c065] | 88 | |
---|
| 89 | return executing; |
---|
[5a598ac] | 90 | } |
---|
| 91 | |
---|
| 92 | RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Release( |
---|
| 93 | POSIX_Mutex_Control *the_mutex, |
---|
| 94 | Thread_queue_Context *queue_context |
---|
| 95 | ) |
---|
| 96 | { |
---|
[de59c065] | 97 | _Thread_queue_Queue_release( |
---|
| 98 | &the_mutex->Recursive.Mutex.Queue.Queue, |
---|
| 99 | &queue_context->Lock_context.Lock_context |
---|
| 100 | ); |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | RTEMS_INLINE_ROUTINE POSIX_Mutex_Protocol _POSIX_Mutex_Get_protocol( |
---|
| 104 | unsigned long flags |
---|
| 105 | ) |
---|
| 106 | { |
---|
[c5b7942] | 107 | return (POSIX_Mutex_Protocol) (flags & POSIX_MUTEX_PROTOCOL_MASK); |
---|
[de59c065] | 108 | } |
---|
| 109 | |
---|
| 110 | RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_recursive( |
---|
| 111 | unsigned long flags |
---|
| 112 | ) |
---|
| 113 | { |
---|
| 114 | return ( flags & POSIX_MUTEX_RECURSIVE ) != 0; |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Mutex_Get_owner( |
---|
| 118 | const POSIX_Mutex_Control *the_mutex |
---|
| 119 | ) |
---|
| 120 | { |
---|
| 121 | return the_mutex->Recursive.Mutex.Queue.Queue.owner; |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_locked( |
---|
| 125 | const POSIX_Mutex_Control *the_mutex |
---|
| 126 | ) |
---|
| 127 | { |
---|
| 128 | return _POSIX_Mutex_Get_owner( the_mutex ) != NULL; |
---|
| 129 | } |
---|
| 130 | |
---|
| 131 | Status_Control _POSIX_Mutex_Seize_slow( |
---|
| 132 | POSIX_Mutex_Control *the_mutex, |
---|
| 133 | const Thread_queue_Operations *operations, |
---|
| 134 | Thread_Control *executing, |
---|
[c3105894] | 135 | const struct timespec *abstime, |
---|
[de59c065] | 136 | Thread_queue_Context *queue_context |
---|
| 137 | ); |
---|
| 138 | |
---|
| 139 | RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Set_owner( |
---|
| 140 | POSIX_Mutex_Control *the_mutex, |
---|
| 141 | Thread_Control *owner |
---|
| 142 | ) |
---|
| 143 | { |
---|
| 144 | the_mutex->Recursive.Mutex.Queue.Queue.owner = owner; |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_owner( |
---|
| 148 | const POSIX_Mutex_Control *the_mutex, |
---|
| 149 | const Thread_Control *the_thread |
---|
| 150 | ) |
---|
| 151 | { |
---|
| 152 | return _POSIX_Mutex_Get_owner( the_mutex ) == the_thread; |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | static Status_Control _POSIX_Mutex_Lock_nested( |
---|
| 156 | POSIX_Mutex_Control *the_mutex, |
---|
| 157 | unsigned long flags |
---|
| 158 | ) |
---|
| 159 | { |
---|
| 160 | |
---|
| 161 | if ( _POSIX_Mutex_Is_recursive( flags ) ) { |
---|
| 162 | ++the_mutex->Recursive.nest_level; |
---|
| 163 | return STATUS_SUCCESSFUL; |
---|
| 164 | } else { |
---|
| 165 | return STATUS_NESTING_NOT_ALLOWED; |
---|
| 166 | } |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize( |
---|
| 170 | POSIX_Mutex_Control *the_mutex, |
---|
| 171 | unsigned long flags, |
---|
| 172 | const Thread_queue_Operations *operations, |
---|
| 173 | Thread_Control *executing, |
---|
[c3105894] | 174 | const struct timespec *abstime, |
---|
[de59c065] | 175 | Thread_queue_Context *queue_context |
---|
| 176 | ) |
---|
| 177 | { |
---|
| 178 | Thread_Control *owner; |
---|
| 179 | |
---|
| 180 | owner = _POSIX_Mutex_Get_owner( the_mutex ); |
---|
| 181 | |
---|
| 182 | if ( owner == NULL ) { |
---|
| 183 | _POSIX_Mutex_Set_owner( the_mutex, executing ); |
---|
| 184 | _Thread_Resource_count_increment( executing ); |
---|
| 185 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 186 | return STATUS_SUCCESSFUL; |
---|
| 187 | } |
---|
| 188 | |
---|
| 189 | if ( owner == executing ) { |
---|
| 190 | Status_Control status; |
---|
| 191 | |
---|
| 192 | status = _POSIX_Mutex_Lock_nested( the_mutex, flags ); |
---|
| 193 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 194 | return status; |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | return _POSIX_Mutex_Seize_slow( |
---|
| 198 | the_mutex, |
---|
| 199 | operations, |
---|
| 200 | executing, |
---|
[c3105894] | 201 | abstime, |
---|
[5a598ac] | 202 | queue_context |
---|
| 203 | ); |
---|
| 204 | } |
---|
| 205 | |
---|
[de59c065] | 206 | RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Surrender( |
---|
| 207 | POSIX_Mutex_Control *the_mutex, |
---|
| 208 | const Thread_queue_Operations *operations, |
---|
| 209 | Thread_Control *executing, |
---|
| 210 | Thread_queue_Context *queue_context |
---|
| 211 | ) |
---|
[4600bd7c] | 212 | { |
---|
[de59c065] | 213 | unsigned int nest_level; |
---|
| 214 | Thread_queue_Heads *heads; |
---|
| 215 | |
---|
| 216 | if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) { |
---|
| 217 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 218 | return STATUS_NOT_OWNER; |
---|
| 219 | } |
---|
| 220 | |
---|
| 221 | nest_level = the_mutex->Recursive.nest_level; |
---|
| 222 | |
---|
| 223 | if ( nest_level > 0 ) { |
---|
| 224 | the_mutex->Recursive.nest_level = nest_level - 1; |
---|
| 225 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 226 | return STATUS_SUCCESSFUL; |
---|
| 227 | } |
---|
| 228 | |
---|
| 229 | _Thread_Resource_count_decrement( executing ); |
---|
| 230 | _POSIX_Mutex_Set_owner( the_mutex, NULL ); |
---|
| 231 | |
---|
| 232 | heads = the_mutex->Recursive.Mutex.Queue.Queue.heads; |
---|
| 233 | |
---|
| 234 | if ( heads == NULL ) { |
---|
| 235 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 236 | return STATUS_SUCCESSFUL; |
---|
| 237 | } |
---|
| 238 | |
---|
| 239 | _Thread_queue_Surrender( |
---|
| 240 | &the_mutex->Recursive.Mutex.Queue.Queue, |
---|
| 241 | heads, |
---|
| 242 | executing, |
---|
| 243 | queue_context, |
---|
| 244 | operations |
---|
| 245 | ); |
---|
| 246 | return STATUS_SUCCESSFUL; |
---|
[4600bd7c] | 247 | } |
---|
[f9d533a5] | 248 | |
---|
[de59c065] | 249 | RTEMS_INLINE_ROUTINE const Scheduler_Control *_POSIX_Mutex_Get_scheduler( |
---|
| 250 | const POSIX_Mutex_Control *the_mutex |
---|
[4600bd7c] | 251 | ) |
---|
| 252 | { |
---|
[de59c065] | 253 | #if defined(RTEMS_SMP) |
---|
| 254 | return the_mutex->scheduler; |
---|
| 255 | #else |
---|
| 256 | return &_Scheduler_Table[ 0 ]; |
---|
| 257 | #endif |
---|
| 258 | } |
---|
| 259 | |
---|
| 260 | RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Set_priority( |
---|
| 261 | POSIX_Mutex_Control *the_mutex, |
---|
| 262 | Priority_Control priority_ceiling, |
---|
| 263 | Thread_queue_Context *queue_context |
---|
| 264 | ) |
---|
| 265 | { |
---|
| 266 | Thread_Control *owner; |
---|
| 267 | |
---|
| 268 | owner = _POSIX_Mutex_Get_owner( the_mutex ); |
---|
| 269 | |
---|
| 270 | if ( owner != NULL ) { |
---|
| 271 | _Thread_Wait_acquire( owner, queue_context ); |
---|
| 272 | _Thread_Priority_change( |
---|
| 273 | owner, |
---|
| 274 | &the_mutex->Priority_ceiling, |
---|
| 275 | priority_ceiling, |
---|
| 276 | false, |
---|
| 277 | queue_context |
---|
| 278 | ); |
---|
| 279 | _Thread_Wait_release( owner, queue_context ); |
---|
| 280 | } else { |
---|
| 281 | the_mutex->Priority_ceiling.priority = priority_ceiling; |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | RTEMS_INLINE_ROUTINE Priority_Control _POSIX_Mutex_Get_priority( |
---|
| 286 | const POSIX_Mutex_Control *the_mutex |
---|
| 287 | ) |
---|
| 288 | { |
---|
| 289 | return the_mutex->Priority_ceiling.priority; |
---|
| 290 | } |
---|
| 291 | |
---|
| 292 | RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_set_owner( |
---|
| 293 | POSIX_Mutex_Control *the_mutex, |
---|
| 294 | Thread_Control *owner, |
---|
| 295 | Thread_queue_Context *queue_context |
---|
| 296 | ) |
---|
| 297 | { |
---|
| 298 | ISR_lock_Context lock_context; |
---|
| 299 | Scheduler_Node *scheduler_node; |
---|
| 300 | Per_CPU_Control *cpu_self; |
---|
| 301 | |
---|
| 302 | _Thread_Wait_acquire_default_critical( owner, &lock_context ); |
---|
| 303 | |
---|
| 304 | scheduler_node = _Thread_Scheduler_get_home_node( owner ); |
---|
| 305 | |
---|
| 306 | if ( |
---|
| 307 | _Priority_Get_priority( &scheduler_node->Wait.Priority ) |
---|
| 308 | < the_mutex->Priority_ceiling.priority |
---|
| 309 | ) { |
---|
| 310 | _Thread_Wait_release_default_critical( owner, &lock_context ); |
---|
| 311 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 312 | return STATUS_MUTEX_CEILING_VIOLATED; |
---|
| 313 | } |
---|
| 314 | |
---|
| 315 | _POSIX_Mutex_Set_owner( the_mutex, owner ); |
---|
| 316 | _Thread_Resource_count_increment( owner ); |
---|
| 317 | _Thread_Priority_add( |
---|
| 318 | owner, |
---|
| 319 | &the_mutex->Priority_ceiling, |
---|
| 320 | queue_context |
---|
| 321 | ); |
---|
| 322 | _Thread_Wait_release_default_critical( owner, &lock_context ); |
---|
| 323 | |
---|
[db3a3de] | 324 | cpu_self = _Thread_queue_Dispatch_disable( queue_context ); |
---|
[de59c065] | 325 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 326 | _Thread_Priority_update( queue_context ); |
---|
| 327 | _Thread_Dispatch_enable( cpu_self ); |
---|
| 328 | return STATUS_SUCCESSFUL; |
---|
| 329 | } |
---|
| 330 | |
---|
| 331 | RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize( |
---|
[c3105894] | 332 | POSIX_Mutex_Control *the_mutex, |
---|
| 333 | unsigned long flags, |
---|
| 334 | Thread_Control *executing, |
---|
| 335 | const struct timespec *abstime, |
---|
| 336 | Thread_queue_Context *queue_context |
---|
[de59c065] | 337 | ) |
---|
| 338 | { |
---|
| 339 | Thread_Control *owner; |
---|
| 340 | |
---|
| 341 | owner = _POSIX_Mutex_Get_owner( the_mutex ); |
---|
| 342 | |
---|
| 343 | if ( owner == NULL ) { |
---|
| 344 | #if defined(RTEMS_SMP) |
---|
| 345 | if ( |
---|
| 346 | _Thread_Scheduler_get_home( executing ) |
---|
| 347 | != _POSIX_Mutex_Get_scheduler( the_mutex ) |
---|
| 348 | ) { |
---|
| 349 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 350 | return STATUS_NOT_DEFINED; |
---|
| 351 | } |
---|
| 352 | #endif |
---|
| 353 | |
---|
| 354 | _Thread_queue_Context_clear_priority_updates( queue_context ); |
---|
| 355 | return _POSIX_Mutex_Ceiling_set_owner( |
---|
| 356 | the_mutex, |
---|
| 357 | executing, |
---|
| 358 | queue_context |
---|
| 359 | ); |
---|
| 360 | } |
---|
| 361 | |
---|
| 362 | if ( owner == executing ) { |
---|
| 363 | Status_Control status; |
---|
| 364 | |
---|
| 365 | status = _POSIX_Mutex_Lock_nested( the_mutex, flags ); |
---|
| 366 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 367 | return status; |
---|
| 368 | } |
---|
| 369 | |
---|
| 370 | return _POSIX_Mutex_Seize_slow( |
---|
| 371 | the_mutex, |
---|
| 372 | POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS, |
---|
| 373 | executing, |
---|
[c3105894] | 374 | abstime, |
---|
[de59c065] | 375 | queue_context |
---|
| 376 | ); |
---|
[4600bd7c] | 377 | } |
---|
[f9d533a5] | 378 | |
---|
[de59c065] | 379 | RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_surrender( |
---|
| 380 | POSIX_Mutex_Control *the_mutex, |
---|
| 381 | Thread_Control *executing, |
---|
| 382 | Thread_queue_Context *queue_context |
---|
| 383 | ) |
---|
| 384 | { |
---|
| 385 | unsigned int nest_level; |
---|
| 386 | ISR_lock_Context lock_context; |
---|
| 387 | Per_CPU_Control *cpu_self; |
---|
| 388 | Thread_queue_Heads *heads; |
---|
| 389 | |
---|
| 390 | if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) { |
---|
| 391 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 392 | return STATUS_NOT_OWNER; |
---|
| 393 | } |
---|
| 394 | |
---|
| 395 | nest_level = the_mutex->Recursive.nest_level; |
---|
| 396 | |
---|
| 397 | if ( nest_level > 0 ) { |
---|
| 398 | the_mutex->Recursive.nest_level = nest_level - 1; |
---|
| 399 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 400 | return STATUS_SUCCESSFUL; |
---|
| 401 | } |
---|
| 402 | |
---|
| 403 | _Thread_Resource_count_decrement( executing ); |
---|
| 404 | |
---|
| 405 | _Thread_queue_Context_clear_priority_updates( queue_context ); |
---|
| 406 | _Thread_Wait_acquire_default_critical( executing, &lock_context ); |
---|
| 407 | _Thread_Priority_remove( |
---|
| 408 | executing, |
---|
| 409 | &the_mutex->Priority_ceiling, |
---|
| 410 | queue_context |
---|
| 411 | ); |
---|
| 412 | _Thread_Wait_release_default_critical( executing, &lock_context ); |
---|
| 413 | |
---|
[db3a3de] | 414 | cpu_self = _Thread_queue_Dispatch_disable( queue_context ); |
---|
[de59c065] | 415 | |
---|
| 416 | heads = the_mutex->Recursive.Mutex.Queue.Queue.heads; |
---|
| 417 | |
---|
| 418 | if ( heads != NULL ) { |
---|
| 419 | const Thread_queue_Operations *operations; |
---|
| 420 | Thread_Control *new_owner; |
---|
| 421 | |
---|
| 422 | operations = POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS; |
---|
| 423 | new_owner = ( *operations->first )( heads ); |
---|
| 424 | _POSIX_Mutex_Set_owner( the_mutex, new_owner ); |
---|
| 425 | _Thread_Resource_count_increment( new_owner ); |
---|
| 426 | _Thread_Priority_add( |
---|
| 427 | new_owner, |
---|
| 428 | &the_mutex->Priority_ceiling, |
---|
| 429 | queue_context |
---|
| 430 | ); |
---|
| 431 | _Thread_queue_Extract_critical( |
---|
| 432 | &the_mutex->Recursive.Mutex.Queue.Queue, |
---|
| 433 | operations, |
---|
| 434 | new_owner, |
---|
| 435 | queue_context |
---|
| 436 | ); |
---|
| 437 | } else { |
---|
| 438 | _POSIX_Mutex_Set_owner( the_mutex, NULL ); |
---|
| 439 | _POSIX_Mutex_Release( the_mutex, queue_context ); |
---|
| 440 | } |
---|
| 441 | |
---|
| 442 | _Thread_Priority_update( queue_context ); |
---|
| 443 | _Thread_Dispatch_enable( cpu_self ); |
---|
| 444 | return STATUS_SUCCESSFUL; |
---|
| 445 | } |
---|
[f9d533a5] | 446 | |
---|
[c3105894] | 447 | #define POSIX_MUTEX_ABSTIME_TRY_LOCK ((uintptr_t) 1) |
---|
| 448 | |
---|
[f9d533a5] | 449 | int _POSIX_Mutex_Lock_support( |
---|
[c3105894] | 450 | pthread_mutex_t *mutex, |
---|
| 451 | const struct timespec *abstime, |
---|
| 452 | Thread_queue_Enqueue_callout enqueue_callout |
---|
[f9d533a5] | 453 | ); |
---|
| 454 | |
---|
[de59c065] | 455 | static inline POSIX_Mutex_Control *_POSIX_Mutex_Get( |
---|
| 456 | pthread_mutex_t *mutex |
---|
[7f4ee2b] | 457 | ) |
---|
| 458 | { |
---|
[de59c065] | 459 | return (POSIX_Mutex_Control *) mutex; |
---|
[7f4ee2b] | 460 | } |
---|
| 461 | |
---|
[de59c065] | 462 | bool _POSIX_Mutex_Auto_initialization( POSIX_Mutex_Control *the_mutex ); |
---|
| 463 | |
---|
| 464 | #define POSIX_MUTEX_VALIDATE_OBJECT( the_mutex, flags ) \ |
---|
| 465 | do { \ |
---|
| 466 | if ( ( the_mutex ) == NULL ) { \ |
---|
| 467 | return EINVAL; \ |
---|
| 468 | } \ |
---|
| 469 | flags = ( the_mutex )->flags; \ |
---|
| 470 | if ( \ |
---|
| 471 | ( ( (uintptr_t) ( the_mutex ) ^ POSIX_MUTEX_MAGIC ) \ |
---|
| 472 | & ~POSIX_MUTEX_FLAGS_MASK ) \ |
---|
| 473 | != ( flags & ~POSIX_MUTEX_FLAGS_MASK ) \ |
---|
| 474 | ) { \ |
---|
| 475 | if ( !_POSIX_Mutex_Auto_initialization( the_mutex ) ) { \ |
---|
| 476 | return EINVAL; \ |
---|
| 477 | } \ |
---|
| 478 | } \ |
---|
| 479 | } while ( 0 ) |
---|
| 480 | |
---|
[f9d533a5] | 481 | #ifdef __cplusplus |
---|
| 482 | } |
---|
| 483 | #endif |
---|
| 484 | |
---|
| 485 | #endif |
---|
| 486 | /* end of include file */ |
---|