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