[d86308b] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @brief Initialize a Mutex |
---|
[5cb175bb] | 5 | * @ingroup POSIXAPI |
---|
[d86308b] | 6 | */ |
---|
| 7 | |
---|
[96c041c] | 8 | /* |
---|
[81551a2] | 9 | * COPYRIGHT (c) 1989-2009. |
---|
[fbfb5926] | 10 | * On-Line Applications Research Corporation (OAR). |
---|
| 11 | * |
---|
| 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 14 | * http://www.rtems.org/license/LICENSE. |
---|
[96c041c] | 15 | */ |
---|
| 16 | |
---|
[f42b726] | 17 | #if HAVE_CONFIG_H |
---|
| 18 | #include "config.h" |
---|
| 19 | #endif |
---|
| 20 | |
---|
[f9d533a5] | 21 | #include <rtems/posix/muteximpl.h> |
---|
[97552c98] | 22 | #include <rtems/posix/priorityimpl.h> |
---|
[96c041c] | 23 | |
---|
[d86308b] | 24 | /** |
---|
| 25 | * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 |
---|
[96c041c] | 26 | * |
---|
[d86308b] | 27 | * NOTE: XXX Could be optimized so all the attribute error checking |
---|
| 28 | * is not performed when attr is NULL. |
---|
[96c041c] | 29 | */ |
---|
| 30 | |
---|
| 31 | int pthread_mutex_init( |
---|
| 32 | pthread_mutex_t *mutex, |
---|
| 33 | const pthread_mutexattr_t *attr |
---|
| 34 | ) |
---|
| 35 | { |
---|
| 36 | POSIX_Mutex_Control *the_mutex; |
---|
| 37 | CORE_mutex_Attributes *the_mutex_attr; |
---|
| 38 | const pthread_mutexattr_t *the_attr; |
---|
| 39 | CORE_mutex_Disciplines the_discipline; |
---|
| 40 | |
---|
| 41 | if ( attr ) the_attr = attr; |
---|
| 42 | else the_attr = &_POSIX_Mutex_Default_attributes; |
---|
| 43 | |
---|
| 44 | /* Check for NULL mutex */ |
---|
| 45 | if ( !mutex ) |
---|
| 46 | return EINVAL; |
---|
| 47 | |
---|
| 48 | /* |
---|
[874297f3] | 49 | * This code should eventually be removed. |
---|
[96c041c] | 50 | * |
---|
| 51 | * Although the POSIX specification says: |
---|
| 52 | * |
---|
| 53 | * "Attempting to initialize an already initialized mutex results |
---|
| 54 | * in undefined behavior." |
---|
| 55 | * |
---|
| 56 | * Trying to keep the caller from doing the create when *mutex |
---|
| 57 | * is actually a valid ID causes grief. All it takes is the wrong |
---|
| 58 | * value in an uninitialized variable to make this fail. As best |
---|
| 59 | * I can tell, RTEMS was the only pthread implementation to choose |
---|
| 60 | * this option for "undefined behavior" and doing so has created |
---|
| 61 | * portability problems. In particular, Rosimildo DaSilva |
---|
| 62 | * <rdasilva@connecttel.com> saw seemingly random failures in the |
---|
| 63 | * RTEMS port of omniORB2 when this code was enabled. |
---|
| 64 | * |
---|
| 65 | * Joel Sherrill <joel@OARcorp.com> 14 May 1999 |
---|
[8cdf733] | 66 | * NOTE: Be careful to avoid infinite recursion on call to this |
---|
| 67 | * routine in _POSIX_Mutex_Get. |
---|
[96c041c] | 68 | */ |
---|
[8cdf733] | 69 | #if 0 |
---|
| 70 | { |
---|
| 71 | POSIX_Mutex_Control *mutex_in_use; |
---|
| 72 | Objects_Locations location; |
---|
| 73 | |
---|
| 74 | if ( *mutex != PTHREAD_MUTEX_INITIALIZER ) { |
---|
| 75 | |
---|
| 76 | /* EBUSY if *mutex is a valid id */ |
---|
| 77 | |
---|
| 78 | mutex_in_use = _POSIX_Mutex_Get( mutex, &location ); |
---|
| 79 | switch ( location ) { |
---|
| 80 | case OBJECTS_LOCAL: |
---|
[2d2352b] | 81 | _Objects_Put( &mutex_in_use->Object ); |
---|
[8cdf733] | 82 | return EBUSY; |
---|
| 83 | #if defined(RTEMS_MULTIPROCESSING) |
---|
| 84 | case OBJECTS_REMOTE: |
---|
| 85 | #endif |
---|
| 86 | case OBJECTS_ERROR: |
---|
| 87 | break; |
---|
| 88 | } |
---|
[96c041c] | 89 | } |
---|
| 90 | } |
---|
[8cdf733] | 91 | #endif |
---|
[874297f3] | 92 | |
---|
| 93 | if ( !the_attr->is_initialized ) |
---|
[96c041c] | 94 | return EINVAL; |
---|
| 95 | |
---|
| 96 | /* |
---|
[290d2b79] | 97 | * We only support process private mutexes. |
---|
[96c041c] | 98 | */ |
---|
| 99 | if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) |
---|
[b8596d8] | 100 | return ENOSYS; |
---|
[874297f3] | 101 | |
---|
[290d2b79] | 102 | if ( the_attr->process_shared != PTHREAD_PROCESS_PRIVATE ) |
---|
| 103 | return EINVAL; |
---|
| 104 | |
---|
[96c041c] | 105 | /* |
---|
| 106 | * Determine the discipline of the mutex |
---|
| 107 | */ |
---|
| 108 | switch ( the_attr->protocol ) { |
---|
| 109 | case PTHREAD_PRIO_NONE: |
---|
| 110 | the_discipline = CORE_MUTEX_DISCIPLINES_FIFO; |
---|
| 111 | break; |
---|
| 112 | case PTHREAD_PRIO_INHERIT: |
---|
| 113 | the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT; |
---|
| 114 | break; |
---|
| 115 | case PTHREAD_PRIO_PROTECT: |
---|
| 116 | the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING; |
---|
| 117 | break; |
---|
| 118 | default: |
---|
| 119 | return EINVAL; |
---|
| 120 | } |
---|
| 121 | |
---|
[8cdf733] | 122 | /* |
---|
| 123 | * Validate the priority ceiling field -- should always be valid. |
---|
| 124 | */ |
---|
[96c041c] | 125 | if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) ) |
---|
| 126 | return EINVAL; |
---|
| 127 | |
---|
[8cdf733] | 128 | #if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) |
---|
| 129 | /* |
---|
| 130 | * Validate the mutex type and set appropriate SuperCore mutex |
---|
| 131 | * attributes. |
---|
| 132 | */ |
---|
| 133 | switch ( the_attr->type ) { |
---|
| 134 | case PTHREAD_MUTEX_NORMAL: |
---|
| 135 | case PTHREAD_MUTEX_RECURSIVE: |
---|
| 136 | case PTHREAD_MUTEX_ERRORCHECK: |
---|
| 137 | case PTHREAD_MUTEX_DEFAULT: |
---|
| 138 | break; |
---|
| 139 | |
---|
| 140 | default: |
---|
| 141 | return EINVAL; |
---|
| 142 | } |
---|
| 143 | #endif |
---|
| 144 | |
---|
[96c041c] | 145 | the_mutex = _POSIX_Mutex_Allocate(); |
---|
[874297f3] | 146 | |
---|
[96c041c] | 147 | if ( !the_mutex ) { |
---|
[23fec9f0] | 148 | _Objects_Allocator_unlock(); |
---|
[96c041c] | 149 | return EAGAIN; |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | the_mutex->process_shared = the_attr->process_shared; |
---|
| 153 | |
---|
| 154 | the_mutex_attr = &the_mutex->Mutex.Attributes; |
---|
| 155 | |
---|
[40398c4] | 156 | if ( the_attr->type == PTHREAD_MUTEX_RECURSIVE ) |
---|
[5870ac55] | 157 | the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES; |
---|
| 158 | else |
---|
| 159 | the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR; |
---|
[b1dbfd7] | 160 | the_mutex_attr->only_owner_release = true; |
---|
[96c041c] | 161 | the_mutex_attr->priority_ceiling = |
---|
| 162 | _POSIX_Priority_To_core( the_attr->prio_ceiling ); |
---|
| 163 | the_mutex_attr->discipline = the_discipline; |
---|
| 164 | |
---|
| 165 | /* |
---|
| 166 | * Must be initialized to unlocked. |
---|
| 167 | */ |
---|
[03e89287] | 168 | _CORE_mutex_Initialize( &the_mutex->Mutex, NULL, the_mutex_attr, false ); |
---|
[96c041c] | 169 | |
---|
[ce19f1fa] | 170 | _Objects_Open_u32( &_POSIX_Mutex_Information, &the_mutex->Object, 0 ); |
---|
[96c041c] | 171 | |
---|
| 172 | *mutex = the_mutex->Object.id; |
---|
| 173 | |
---|
[23fec9f0] | 174 | _Objects_Allocator_unlock(); |
---|
[96c041c] | 175 | return 0; |
---|
| 176 | } |
---|