source: rtems/cpukit/posix/src/mutexinit.c @ 40398c4

4.11
Last change on this file since 40398c4 was 40398c4, checked in by Chris Johns <chrisj@…>, on Aug 13, 2013 at 11:29:56 PM

posix: Handle recursive attributes correctly.

The recursive field in the pthread_mutexattr_t is now not used. The
code in pthread_mutexattr_settype only sets the type field and not
the recursive field.

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