File indexing completed on 2025-05-11 08:24:21
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 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/posix/muteximpl.h>
0042 #include <rtems/posix/posixapi.h>
0043 #include <rtems/posix/priorityimpl.h>
0044 #include <rtems/score/schedulerimpl.h>
0045
0046 #include <limits.h>
0047
0048 RTEMS_STATIC_ASSERT(
0049 offsetof( POSIX_Mutex_Control, flags )
0050 == offsetof( pthread_mutex_t, _flags ),
0051 POSIX_MUTEX_CONTROL_FLAGS
0052 );
0053
0054 RTEMS_STATIC_ASSERT(
0055 offsetof( POSIX_Mutex_Control, Recursive )
0056 == offsetof( pthread_mutex_t, _Recursive ),
0057 POSIX_MUTEX_CONTROL_RECURSIVE
0058 );
0059
0060 RTEMS_STATIC_ASSERT(
0061 offsetof( POSIX_Mutex_Control, Priority_ceiling )
0062 == offsetof( pthread_mutex_t, _Priority_ceiling ),
0063 POSIX_MUTEX_CONTROL_PRIORITY_CEILING
0064 );
0065
0066 RTEMS_STATIC_ASSERT(
0067 offsetof( POSIX_Mutex_Control, scheduler )
0068 == offsetof( pthread_mutex_t, _scheduler ),
0069 POSIX_MUTEX_CONTROL_SCHEDULER
0070 );
0071
0072 RTEMS_STATIC_ASSERT(
0073 sizeof( POSIX_Mutex_Control ) == sizeof( pthread_mutex_t ),
0074 POSIX_MUTEX_CONTROL_SIZE
0075 );
0076
0077 const pthread_mutexattr_t _POSIX_Mutex_Default_attributes = {
0078 #if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES)
0079 .type = PTHREAD_MUTEX_DEFAULT,
0080 #endif
0081 .is_initialized = true,
0082 .process_shared = PTHREAD_PROCESS_PRIVATE,
0083 .prio_ceiling = INT_MAX,
0084 .protocol = PTHREAD_PRIO_NONE,
0085 .recursive = false
0086 };
0087
0088
0089
0090
0091
0092
0093
0094
0095 int pthread_mutex_init(
0096 pthread_mutex_t *mutex,
0097 const pthread_mutexattr_t *attr
0098 )
0099 {
0100 POSIX_Mutex_Control *the_mutex;
0101 const pthread_mutexattr_t *the_attr;
0102 POSIX_Mutex_Protocol protocol;
0103 unsigned long flags;
0104 Priority_Control priority;
0105 const Scheduler_Control *scheduler;
0106
0107 if ( attr ) the_attr = attr;
0108 else the_attr = &_POSIX_Mutex_Default_attributes;
0109
0110
0111 if ( !mutex )
0112 return EINVAL;
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 if ( !the_attr->is_initialized )
0128 return EINVAL;
0129
0130 if ( !_POSIX_Is_valid_pshared( the_attr->process_shared ) ) {
0131 return EINVAL;
0132 }
0133
0134
0135
0136
0137 switch ( the_attr->protocol ) {
0138 case PTHREAD_PRIO_NONE:
0139 protocol = POSIX_MUTEX_NO_PROTOCOL;
0140 break;
0141 case PTHREAD_PRIO_INHERIT:
0142 protocol = POSIX_MUTEX_PRIORITY_INHERIT;
0143 break;
0144 case PTHREAD_PRIO_PROTECT:
0145 protocol = POSIX_MUTEX_PRIORITY_CEILING;
0146 break;
0147 default:
0148 return EINVAL;
0149 }
0150
0151 #if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES)
0152
0153
0154
0155
0156 switch ( the_attr->type ) {
0157 case PTHREAD_MUTEX_NORMAL:
0158 case PTHREAD_MUTEX_RECURSIVE:
0159 case PTHREAD_MUTEX_ERRORCHECK:
0160 case PTHREAD_MUTEX_DEFAULT:
0161 break;
0162
0163 default:
0164 return EINVAL;
0165 }
0166 #endif
0167
0168 the_mutex = _POSIX_Mutex_Get( mutex );
0169
0170 flags = (uintptr_t) the_mutex ^ POSIX_MUTEX_MAGIC;
0171 flags &= ~POSIX_MUTEX_FLAGS_MASK;
0172 flags |= protocol;
0173
0174 if ( the_attr->type == PTHREAD_MUTEX_RECURSIVE ) {
0175 flags |= POSIX_MUTEX_RECURSIVE;
0176 }
0177
0178 the_mutex->flags = flags;
0179
0180 if ( protocol == POSIX_MUTEX_PRIORITY_CEILING ) {
0181 int prio_ceiling;
0182 bool valid;
0183
0184 scheduler = _Thread_Scheduler_get_home( _Thread_Get_executing() );
0185 prio_ceiling = the_attr->prio_ceiling;
0186
0187 if ( prio_ceiling == INT_MAX ) {
0188 prio_ceiling = _POSIX_Priority_Get_maximum( scheduler );
0189 }
0190
0191 priority = _POSIX_Priority_To_core( scheduler, prio_ceiling, &valid );
0192 if ( !valid ) {
0193 return EINVAL;
0194 }
0195 } else {
0196 priority = 0;
0197 scheduler = NULL;
0198 }
0199
0200 _Thread_queue_Queue_initialize(
0201 &the_mutex->Recursive.Mutex.Queue.Queue,
0202 NULL
0203 );
0204 the_mutex->Recursive.nest_level = 0;
0205 _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority );
0206 the_mutex->scheduler = scheduler;
0207 return 0;
0208 }