source: rtems/cpukit/posix/src/mutex.c @ 0553a3a

4.104.114.84.95
Last change on this file since 0553a3a was f4719d5a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/22/96 at 22:32:39

These files have been modified in the initial pass at getting the portion
of the POSIX API necessary to support the GNAT runtime to initially compile.
We now have verified that the specifications for the necessary routines
are correct per the POSIX standards we have.

  • Property mode set to 100644
File size: 12.5 KB
Line 
1/*  mutex.c
2 *
3 *  $Id$
4 */
5
6#include <errno.h>
7#include <pthread.h>
8
9#include <rtems/system.h>
10#include <rtems/score/coremutex.h>
11#include <rtems/score/watchdog.h>
12#include <rtems/score/mpci.h>
13#include <rtems/posix/mutex.h>
14#include <rtems/posix/priority.h>
15#include <rtems/posix/time.h>
16
17/*PAGE
18 * 
19 *  The default mutex attributes structure.
20 */
21
22const pthread_mutexattr_t _POSIX_Mutex_Default_attributes = {
23  TRUE,                                    /* is_initialized */
24  PTHREAD_PROCESS_PRIVATE,                 /* process_shared */
25  POSIX_SCHEDULER_MINIMUM_PRIORITY,        /* prio_ceiling   */
26  PTHREAD_PRIO_NONE,                       /* protocol       */
27  FALSE                                    /* recursive      */
28};
29
30/*PAGE
31 *
32 *  _POSIX_Mutex_Manager_initialization
33 *
34 *  This routine initializes all mutex manager related data structures.
35 *
36 *  Input parameters:
37 *    maximum_mutexes - maximum configured mutexes
38 *
39 *  Output parameters:  NONE
40 */
41 
42void _POSIX_Mutex_Manager_initialization(
43  unsigned32 maximum_mutexes
44)
45{
46  _Objects_Initialize_information(
47    &_POSIX_Mutex_Information,
48    OBJECTS_POSIX_MUTEXES,
49    TRUE,
50    maximum_mutexes,
51    sizeof( POSIX_Mutex_Control ),
52    FALSE,
53    0,
54    FALSE
55  );
56}
57
58/*PAGE
59 *
60 *  11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
61 */
62
63int pthread_mutexattr_init(
64  pthread_mutexattr_t *attr
65)
66{
67  if ( !attr )
68    return EINVAL;
69
70  *attr = _POSIX_Mutex_Default_attributes;
71  return 0;
72}
73
74/*PAGE
75 *
76 *  11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
77 */
78
79int pthread_mutexattr_destroy(
80  pthread_mutexattr_t *attr
81)
82{
83  if ( !attr || attr->is_initialized == FALSE )
84    return EINVAL;
85
86  attr->is_initialized = FALSE;
87  return 0;
88}
89
90/*PAGE
91 *
92 *  11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
93 */
94
95int pthread_mutexattr_getpshared(
96  const pthread_mutexattr_t *attr,
97  int                       *pshared
98)
99{
100  if ( !attr )
101    return EINVAL;
102
103  *pshared = attr->process_shared;
104  return 0;
105}
106
107/*PAGE
108 *
109 *  11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
110 */
111
112int pthread_mutexattr_setpshared(
113  pthread_mutexattr_t *attr,
114  int                  pshared
115)
116{
117  if ( !attr )
118    return EINVAL;
119
120  attr->process_shared = pshared;
121  return 0;
122}
123
124/*PAGE
125 *
126 *  11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
127 *
128 *  NOTE:  XXX Could be optimized so all the attribute error checking
129 *             is not performed when attr is NULL.
130 */
131
132int pthread_mutex_init(
133  pthread_mutex_t           *mutex,
134  const pthread_mutexattr_t *attr
135)
136{
137  POSIX_Mutex_Control        *the_mutex;
138  CORE_mutex_Attributes      *the_mutex_attr;
139  const pthread_mutexattr_t  *the_attr;
140  CORE_mutex_Disciplines      the_discipline;
141
142  if ( attr ) the_attr = attr;
143  else        the_attr = &_POSIX_Mutex_Default_attributes;
144
145  /*
146   *  XXX: Be careful about attributes when global!!!
147   */
148
149  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
150    return POSIX_MP_NOT_IMPLEMENTED();
151 
152  if ( !the_attr->is_initialized )
153    return EINVAL;
154
155  /*
156   *  Determine the discipline of the mutex
157   */
158 
159  switch ( the_attr->protocol ) {
160    case PTHREAD_PRIO_NONE:
161      the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
162      break;
163    case PTHREAD_PRIO_INHERIT:
164      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
165      break;
166    case PTHREAD_PRIO_PROTECT:
167      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
168      break;
169    default:
170      return EINVAL;
171  }
172
173  if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) )
174    return EINVAL;
175
176  _Thread_Disable_dispatch();
177
178  the_mutex = _POSIX_Mutex_Allocate();
179 
180  if ( !the_mutex ) {
181    _Thread_Enable_dispatch();
182    return ENOMEM;
183  }
184
185  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED &&
186       !( _Objects_MP_Allocate_and_open( &_POSIX_Mutex_Information, 0,
187                            the_mutex->Object.id, FALSE ) ) ) {
188    _POSIX_Mutex_Free( the_mutex );
189    _Thread_Enable_dispatch();
190    return EAGAIN;
191  }
192
193  the_mutex->process_shared = the_attr->process_shared;
194
195  the_mutex_attr = &the_mutex->Mutex.Attributes;
196
197  the_mutex_attr->allow_nesting = the_attr->recursive;
198  the_mutex_attr->priority_ceiling =
199    _POSIX_Priority_To_core( the_attr->prio_ceiling );
200  the_mutex_attr->discipline = the_discipline;
201
202  /*
203   *  Must be initialized to unlocked.
204   */
205
206  _CORE_mutex_Initialize(
207    &the_mutex->Mutex,
208    OBJECTS_POSIX_MUTEXES,
209    the_mutex_attr,
210    CORE_MUTEX_UNLOCKED,
211    0                  /* XXX proxy_extract_callout */
212  );
213
214  _Objects_Open( &_POSIX_Mutex_Information, &the_mutex->Object, 0 );
215
216  *mutex = the_mutex->Object.id;
217
218  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
219    _POSIX_Mutex_MP_Send_process_packet(
220      POSIX_MUTEX_MP_ANNOUNCE_CREATE,
221      the_mutex->Object.id,
222      0,                         /* Name not used */
223      0                          /* Not used */
224    );
225
226  _Thread_Enable_dispatch();
227  return 0;
228}
229
230/*PAGE
231 *
232 *  11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
233 */
234
235int pthread_mutex_destroy(
236  pthread_mutex_t           *mutex
237)
238{
239  register POSIX_Mutex_Control *the_mutex;
240  Objects_Locations             location;
241 
242  the_mutex = _POSIX_Mutex_Get( mutex, &location );
243  switch ( location ) {
244    case OBJECTS_ERROR:
245      return EINVAL;
246    case OBJECTS_REMOTE:
247      _Thread_Dispatch();
248      return POSIX_MP_NOT_IMPLEMENTED();
249      return EINVAL;
250    case OBJECTS_LOCAL:
251       /*
252        * XXX: There is an error for the mutex being locked
253        *  or being in use by a condition variable.
254        */
255
256      if ( _CORE_mutex_Is_locked( &the_mutex->Mutex ) ) {
257        _Thread_Enable_dispatch();
258        return EBUSY;
259      }
260 
261      _Objects_Close( &_POSIX_Mutex_Information, &the_mutex->Object );
262 
263      _CORE_mutex_Flush(
264        &the_mutex->Mutex,
265        _POSIX_Mutex_MP_Send_object_was_deleted,
266        EINVAL
267      );
268 
269      _POSIX_Mutex_Free( the_mutex );
270 
271      if ( the_mutex->process_shared == PTHREAD_PROCESS_SHARED ) {
272 
273        _Objects_MP_Close( &_POSIX_Mutex_Information, the_mutex->Object.id );
274 
275        _POSIX_Mutex_MP_Send_process_packet(
276          POSIX_MUTEX_MP_ANNOUNCE_DELETE,
277          the_mutex->Object.id,
278          0,                         /* Not used */
279          0                          /* Not used */
280        );
281      }
282      _Thread_Enable_dispatch();
283      return 0;
284  }
285  return POSIX_BOTTOM_REACHED();
286}
287
288/*
289 *  _POSIX_Mutex_Lock_support
290 *
291 *  A support routine which implements guts of the blocking, non-blocking, and
292 *  timed wait version of mutex lock.
293 */
294
295int _POSIX_Mutex_Lock_support(
296  pthread_mutex_t           *mutex,
297  boolean                    blocking,
298  Watchdog_Interval          timeout
299)
300{
301  register POSIX_Mutex_Control *the_mutex;
302  Objects_Locations             location;
303 
304  the_mutex = _POSIX_Mutex_Get( mutex, &location );
305  switch ( location ) {
306    case OBJECTS_ERROR:
307      return EINVAL;
308    case OBJECTS_REMOTE:
309      return _POSIX_Mutex_MP_Send_request_packet(
310          POSIX_MUTEX_MP_OBTAIN_REQUEST,
311          *mutex,
312          0,   /* must define the option set */
313          WATCHDOG_NO_TIMEOUT
314      );
315    case OBJECTS_LOCAL:
316      _CORE_mutex_Seize(
317        &the_mutex->Mutex,
318        the_mutex->Object.id,
319        blocking,
320        timeout
321      );
322      _Thread_Enable_dispatch();
323      return _Thread_Executing->Wait.return_code;
324      break;
325  }
326  return POSIX_BOTTOM_REACHED();
327}
328
329/*PAGE
330 *
331 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
332 *       
333 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
334 */
335
336int pthread_mutex_lock(
337  pthread_mutex_t           *mutex
338)
339{
340  return _POSIX_Mutex_Lock_support( mutex, TRUE, THREAD_QUEUE_WAIT_FOREVER );
341}
342
343/*PAGE
344 *
345 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
346 *       
347 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
348 */
349
350int pthread_mutex_trylock(
351  pthread_mutex_t           *mutex
352)
353{
354  return _POSIX_Mutex_Lock_support( mutex, FALSE, THREAD_QUEUE_WAIT_FOREVER );
355}
356
357/*PAGE
358 *
359 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
360 *       
361 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
362 */
363
364void POSIX_Threads_mutex_MP_support(
365  Thread_Control *the_thread,
366  Objects_Id      id
367)
368{
369  (void) POSIX_MP_NOT_IMPLEMENTED();   /* XXX: should never get here */
370}
371
372int pthread_mutex_unlock(
373  pthread_mutex_t           *mutex
374)
375{
376  register POSIX_Mutex_Control *the_mutex;
377  Objects_Locations             location;
378 
379  the_mutex = _POSIX_Mutex_Get( mutex, &location );
380  switch ( location ) {
381    case OBJECTS_ERROR:
382      return EINVAL;
383    case OBJECTS_REMOTE:
384      return _POSIX_Mutex_MP_Send_request_packet(
385          POSIX_MUTEX_MP_RELEASE_REQUEST,
386          *mutex,
387          0,                    /* Not used */
388          MPCI_DEFAULT_TIMEOUT
389      );
390    case OBJECTS_LOCAL:
391      _CORE_mutex_Surrender(
392        &the_mutex->Mutex,
393        the_mutex->Object.id,
394        POSIX_Threads_mutex_MP_support
395      );
396      _Thread_Enable_dispatch();
397      return _Thread_Executing->Wait.return_code; /* XXX return status */
398      break;
399  }
400  return POSIX_BOTTOM_REACHED();
401}
402
403/*PAGE
404 *
405 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
406 *       
407 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
408 */
409
410int pthread_mutex_timedlock(
411  pthread_mutex_t       *mutex,
412  const struct timespec *timeout
413)
414{
415  return _POSIX_Mutex_Lock_support(
416    mutex,
417    TRUE,
418    _POSIX_Time_Spec_to_interval( timeout )
419  );
420}
421
422/*PAGE
423 *
424 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
425 */
426 
427int pthread_mutexattr_setprotocol(
428  pthread_mutexattr_t   *attr,
429  int                    protocol
430)
431{
432  if ( !attr )
433    return EINVAL;
434
435  attr->protocol = protocol;
436  return 0;
437}
438
439/*PAGE
440 *
441 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
442 */
443 
444int pthread_mutexattr_getprotocol(
445  const pthread_mutexattr_t   *attr,
446  int                         *protocol
447)
448{
449  if ( !attr )
450    return EINVAL;
451
452  *protocol = attr->protocol;
453  return 0;
454}
455
456/*PAGE
457 *
458 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
459 */
460 
461int pthread_mutexattr_setprioceiling(
462  pthread_mutexattr_t   *attr,
463  int                    prioceiling
464)
465{
466  if ( !attr )
467    return EINVAL;
468
469  if ( !_POSIX_Priority_Is_valid( attr->prio_ceiling ) )
470    return EINVAL;
471
472  attr->prio_ceiling = prioceiling;
473  return 0;
474}
475
476/*PAGE
477 *
478 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
479 */
480 
481int pthread_mutexattr_getprioceiling(
482  const pthread_mutexattr_t   *attr,
483  int                         *prioceiling
484)
485{
486  if ( !attr )
487    return EINVAL;
488
489  *prioceiling = attr->prio_ceiling;
490  return 0;
491}
492
493/*PAGE
494 *
495 *  13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
496 */
497
498int pthread_mutex_setprioceiling(
499  pthread_mutex_t   *mutex,
500  int                prioceiling,
501  int               *old_ceiling
502)
503{
504  register POSIX_Mutex_Control *the_mutex;
505  Objects_Locations             location;
506  Priority_Control              the_priority;
507  int                           status;
508
509  if ( !_POSIX_Priority_Is_valid( prioceiling ) )
510    return EINVAL;
511
512  the_priority = _POSIX_Priority_To_core( prioceiling );
513
514  /*
515   *  Must acquire the mutex before we can change it's ceiling
516   */
517
518  status = pthread_mutex_lock( mutex );
519  if ( status )
520    return status;
521
522  the_mutex = _POSIX_Mutex_Get( mutex, &location );
523  switch ( location ) {
524    case OBJECTS_ERROR:
525      return EINVAL;
526    case OBJECTS_REMOTE:
527      return POSIX_MP_NOT_IMPLEMENTED();   /* XXX feels questionable */
528      return EINVAL;
529    case OBJECTS_LOCAL:
530      the_mutex->Mutex.Attributes.priority_ceiling = the_priority;
531      _CORE_mutex_Surrender(
532        &the_mutex->Mutex,
533        the_mutex->Object.id,
534        POSIX_Threads_mutex_MP_support
535      );
536      _Thread_Enable_dispatch();
537      return 0;
538  }
539  return POSIX_BOTTOM_REACHED();
540}
541 
542/*PAGE
543 *
544 *  13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
545 */
546
547int pthread_mutex_getprioceiling(
548  pthread_mutex_t   *mutex,
549  int               *prioceiling
550)
551{
552  register POSIX_Mutex_Control *the_mutex;
553  Objects_Locations             location;
554
555  the_mutex = _POSIX_Mutex_Get( mutex, &location );
556  switch ( location ) {
557    case OBJECTS_ERROR:
558      return EINVAL;
559    case OBJECTS_REMOTE:
560      return POSIX_MP_NOT_IMPLEMENTED();   /* XXX feels questionable */
561    case OBJECTS_LOCAL:
562      *prioceiling = _POSIX_Priority_From_core(
563        the_mutex->Mutex.Attributes.priority_ceiling
564      );
565      _Thread_Enable_dispatch();
566      return 0;
567  }
568  return POSIX_BOTTOM_REACHED();
569}
Note: See TracBrowser for help on using the repository browser.