source: rtems/cpukit/posix/src/mutex.c @ 2b95c07

4.104.114.84.95
Last change on this file since 2b95c07 was 2b95c07, checked in by Joel Sherrill <joel.sherrill@…>, on 11/02/99 at 15:28:02

Commented out lines causing warning.

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