source: rtems/cpukit/posix/src/mutex.c @ 7d5566e

4.104.114.84.95
Last change on this file since 7d5566e was 9b1f5678, checked in by Joel Sherrill <joel.sherrill@…>, on 08/22/97 at 19:11:02

Fixed infinite recursion bug in PTHREAD_MUTEX_INITIALIZER.

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