source: rtems/c/src/exec/posix/src/mutex.c @ 97e2729d

4.104.114.84.95
Last change on this file since 97e2729d was 97e2729d, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 23, 1998 at 5:38:09 PM

Added --disable-multiprocessing flag and modified a lot of files to make
it work.

  • Property mode set to 100644
File size: 15.9 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  register POSIX_Mutex_Control *mutex_in_use;
227  Objects_Locations             location;
228
229  if ( attr ) the_attr = attr;
230  else        the_attr = &_POSIX_Mutex_Default_attributes;
231
232  /* Check for NULL mutex */
233
234  if ( !mutex )
235    return EINVAL;
236
237  /* avoid infinite recursion on call to this routine in _POSIX_Mutex_Get */
238
239  if ( *mutex != PTHREAD_MUTEX_INITIALIZER ) {
240
241    /* EBUSY if *mutex is a valid id */
242
243    mutex_in_use = _POSIX_Mutex_Get( mutex, &location );
244    switch ( location ) {
245      case OBJECTS_REMOTE:
246      case OBJECTS_ERROR:
247        break;
248      case OBJECTS_LOCAL:
249        _Thread_Enable_dispatch();
250        return EBUSY;
251    }
252  }
253 
254  if ( !the_attr->is_initialized ) 
255    return EINVAL;
256
257  /*
258   *  XXX: Be careful about attributes when global!!!
259   */
260
261  assert( the_attr->process_shared == PTHREAD_PROCESS_PRIVATE );
262
263#if defined(RTEMS_MULTIPROCESSING)
264  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
265    return POSIX_MP_NOT_IMPLEMENTED();
266#endif
267 
268  /*
269   *  Determine the discipline of the mutex
270   */
271 
272  switch ( the_attr->protocol ) {
273    case PTHREAD_PRIO_NONE:
274      the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
275      break;
276    case PTHREAD_PRIO_INHERIT:
277      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
278      break;
279    case PTHREAD_PRIO_PROTECT:
280      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
281      break;
282    default:
283      return EINVAL;
284  }
285
286  if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) )
287    return EINVAL;
288
289  _Thread_Disable_dispatch();
290
291  the_mutex = _POSIX_Mutex_Allocate();
292 
293  if ( !the_mutex ) {
294    _Thread_Enable_dispatch();
295    return EAGAIN;
296  }
297
298#if defined(RTEMS_MULTIPROCESSING)
299  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED && 
300       !( _Objects_MP_Allocate_and_open( &_POSIX_Mutex_Information, 0,
301                            the_mutex->Object.id, FALSE ) ) ) {
302    _POSIX_Mutex_Free( the_mutex );
303    _Thread_Enable_dispatch();
304    return EAGAIN;
305  }
306#endif
307
308  the_mutex->process_shared = the_attr->process_shared;
309
310  the_mutex_attr = &the_mutex->Mutex.Attributes;
311
312  the_mutex_attr->allow_nesting = the_attr->recursive;
313  the_mutex_attr->priority_ceiling =
314    _POSIX_Priority_To_core( the_attr->prio_ceiling );
315  the_mutex_attr->discipline = the_discipline;
316
317  /*
318   *  Must be initialized to unlocked.
319   */
320
321  _CORE_mutex_Initialize(
322    &the_mutex->Mutex,
323    OBJECTS_POSIX_MUTEXES,
324    the_mutex_attr,
325    CORE_MUTEX_UNLOCKED,
326    NULL                      /* proxy_extract_callout */
327  );
328
329  _Objects_Open( &_POSIX_Mutex_Information, &the_mutex->Object, 0 );
330
331  *mutex = the_mutex->Object.id;
332
333#if defined(RTEMS_MULTIPROCESSING)
334  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
335    _POSIX_Mutex_MP_Send_process_packet(
336      POSIX_MUTEX_MP_ANNOUNCE_CREATE,
337      the_mutex->Object.id,
338      0,                         /* Name not used */
339      0                          /* Not used */
340    );
341#endif
342
343  _Thread_Enable_dispatch();
344  return 0;
345}
346
347/*PAGE
348 *
349 *  11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
350 */
351
352int pthread_mutex_destroy(
353  pthread_mutex_t           *mutex
354)
355{
356  register POSIX_Mutex_Control *the_mutex;
357  Objects_Locations             location;
358 
359  the_mutex = _POSIX_Mutex_Get( mutex, &location );
360  switch ( location ) {
361    case OBJECTS_REMOTE:
362#if defined(RTEMS_MULTIPROCESSING)
363      _Thread_Dispatch();
364      return POSIX_MP_NOT_IMPLEMENTED();
365      return EINVAL;
366#endif
367    case OBJECTS_ERROR:
368      return EINVAL;
369    case OBJECTS_LOCAL:
370       /*
371        * XXX: There is an error for the mutex being locked
372        *  or being in use by a condition variable.
373        */
374
375      if ( _CORE_mutex_Is_locked( &the_mutex->Mutex ) ) {
376        _Thread_Enable_dispatch();
377        return EBUSY;
378      }
379 
380      _Objects_Close( &_POSIX_Mutex_Information, &the_mutex->Object );
381 
382      _CORE_mutex_Flush(
383        &the_mutex->Mutex,
384#if defined(RTEMS_MULTIPROCESSING)
385        _POSIX_Mutex_MP_Send_object_was_deleted,
386#else
387        NULL,
388#endif
389        EINVAL
390      );
391 
392      _POSIX_Mutex_Free( the_mutex );
393 
394#if defined(RTEMS_MULTIPROCESSING)
395      if ( the_mutex->process_shared == PTHREAD_PROCESS_SHARED ) {
396 
397        _Objects_MP_Close( &_POSIX_Mutex_Information, the_mutex->Object.id );
398 
399        _POSIX_Mutex_MP_Send_process_packet(
400          POSIX_MUTEX_MP_ANNOUNCE_DELETE,
401          the_mutex->Object.id,
402          0,                         /* Not used */
403          0                          /* Not used */
404        );
405      }
406#endif
407      _Thread_Enable_dispatch();
408      return 0;
409  }
410  return POSIX_BOTTOM_REACHED();
411}
412
413/*PAGE
414 *
415 *  _POSIX_Mutex_Lock_support
416 *
417 *  A support routine which implements guts of the blocking, non-blocking, and
418 *  timed wait version of mutex lock.
419 */
420
421int _POSIX_Mutex_Lock_support(
422  pthread_mutex_t           *mutex,
423  boolean                    blocking,
424  Watchdog_Interval          timeout
425)
426{
427  register POSIX_Mutex_Control *the_mutex;
428  Objects_Locations             location;
429 
430  the_mutex = _POSIX_Mutex_Get( mutex, &location );
431  switch ( location ) {
432    case OBJECTS_REMOTE:
433#if defined(RTEMS_MULTIPROCESSING)
434      return _POSIX_Mutex_MP_Send_request_packet(
435          POSIX_MUTEX_MP_OBTAIN_REQUEST,
436          *mutex,
437          0,   /* must define the option set */
438          WATCHDOG_NO_TIMEOUT
439      );
440#endif
441    case OBJECTS_ERROR:
442      return EINVAL;
443    case OBJECTS_LOCAL:
444      _CORE_mutex_Seize(
445        &the_mutex->Mutex,
446        the_mutex->Object.id,
447        blocking,
448        timeout
449      );
450      _Thread_Enable_dispatch();
451      return _POSIX_Mutex_From_core_mutex_status(
452        (CORE_mutex_Status) _Thread_Executing->Wait.return_code
453      );
454  }
455  return POSIX_BOTTOM_REACHED();
456}
457
458/*PAGE
459 *
460 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
461 *       
462 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
463 */
464
465int pthread_mutex_lock(
466  pthread_mutex_t           *mutex
467)
468{
469  return _POSIX_Mutex_Lock_support( mutex, TRUE, THREAD_QUEUE_WAIT_FOREVER );
470}
471
472/*PAGE
473 *
474 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
475 *       
476 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
477 */
478
479int pthread_mutex_trylock(
480  pthread_mutex_t           *mutex
481)
482{
483  return _POSIX_Mutex_Lock_support( mutex, FALSE, THREAD_QUEUE_WAIT_FOREVER );
484}
485
486/*PAGE
487 *
488 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
489 *       
490 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
491 */
492
493int pthread_mutex_unlock(
494  pthread_mutex_t           *mutex
495)
496{
497  register POSIX_Mutex_Control *the_mutex;
498  Objects_Locations             location;
499  CORE_mutex_Status             status;
500 
501  the_mutex = _POSIX_Mutex_Get( mutex, &location );
502  switch ( location ) {
503    case OBJECTS_REMOTE:
504#if defined(RTEMS_MULTIPROCESSING)
505      return _POSIX_Mutex_MP_Send_request_packet(
506          POSIX_MUTEX_MP_RELEASE_REQUEST,
507          *mutex,
508          0,                    /* Not used */
509          MPCI_DEFAULT_TIMEOUT
510      );
511#endif
512    case OBJECTS_ERROR:
513      return EINVAL;
514    case OBJECTS_LOCAL:
515      status = _CORE_mutex_Surrender(
516        &the_mutex->Mutex,
517        the_mutex->Object.id, 
518#if defined(RTEMS_MULTIPROCESSING)
519        POSIX_Threads_mutex_MP_support
520#else
521        NULL
522#endif
523      );
524      _Thread_Enable_dispatch();
525      return _POSIX_Mutex_From_core_mutex_status( status );
526      break;
527  }
528  return POSIX_BOTTOM_REACHED();
529}
530
531/*PAGE
532 *
533 *  11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
534 *       
535 *  NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
536 */
537
538int pthread_mutex_timedlock(
539  pthread_mutex_t       *mutex,
540  const struct timespec *timeout
541)
542{
543  return _POSIX_Mutex_Lock_support( 
544    mutex,
545    TRUE,
546    _POSIX_Timespec_to_interval( timeout )
547  );
548}
549
550/*PAGE
551 *
552 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
553 */
554 
555int pthread_mutexattr_setprotocol(
556  pthread_mutexattr_t   *attr,
557  int                    protocol
558)
559{
560  if ( !attr || !attr->is_initialized )
561    return EINVAL;
562
563  switch ( protocol ) {
564    case PTHREAD_PRIO_NONE:
565    case PTHREAD_PRIO_INHERIT:
566    case PTHREAD_PRIO_PROTECT:
567      attr->protocol = protocol;
568      return 0;
569 
570    default:
571      return EINVAL;
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_getprotocol(
581  const pthread_mutexattr_t   *attr,
582  int                         *protocol
583)
584{
585  if ( !attr || !attr->is_initialized || !protocol )
586    return EINVAL;
587
588  *protocol = attr->protocol;
589  return 0;
590}
591
592/*PAGE
593 *
594 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
595 */
596 
597int pthread_mutexattr_setprioceiling(
598  pthread_mutexattr_t   *attr,
599  int                    prioceiling
600)
601{
602  if ( !attr || !attr->is_initialized )
603    return EINVAL;
604
605  if ( !_POSIX_Priority_Is_valid( prioceiling ) )
606    return EINVAL;
607
608  attr->prio_ceiling = prioceiling;
609  return 0;
610}
611
612/*PAGE
613 *
614 *  13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
615 */
616 
617int pthread_mutexattr_getprioceiling(
618  const pthread_mutexattr_t   *attr,
619  int                         *prioceiling
620)
621{
622  if ( !attr || !attr->is_initialized || !prioceiling )
623    return EINVAL;
624
625  *prioceiling = attr->prio_ceiling;
626  return 0;
627}
628
629/*PAGE
630 *
631 *  13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
632 */
633
634int pthread_mutex_setprioceiling(
635  pthread_mutex_t   *mutex,
636  int                prioceiling,
637  int               *old_ceiling
638)
639{
640  register POSIX_Mutex_Control *the_mutex;
641  Objects_Locations             location;
642  Priority_Control              the_priority;
643  int                           status;
644
645  if ( !old_ceiling )
646    return EINVAL;
647
648  if ( !_POSIX_Priority_Is_valid( prioceiling ) )
649    return EINVAL;
650
651  the_priority = _POSIX_Priority_To_core( prioceiling );
652
653  /*
654   *  Must acquire the mutex before we can change it's ceiling
655   */
656
657  status = pthread_mutex_lock( mutex );
658  if ( status )
659    return status;
660
661  the_mutex = _POSIX_Mutex_Get( mutex, &location );
662  switch ( location ) {
663    case OBJECTS_REMOTE:
664#if defined(RTEMS_MULTIPROCESSING)
665      /*  XXX It feels questionable to set the ceiling on a remote mutex. */
666      return EINVAL;
667#endif
668    case OBJECTS_ERROR:
669      return EINVAL;        /* impossible to get here */
670    case OBJECTS_LOCAL:
671      *old_ceiling = _POSIX_Priority_From_core(
672        the_mutex->Mutex.Attributes.priority_ceiling
673      );
674      the_mutex->Mutex.Attributes.priority_ceiling = the_priority;
675      _CORE_mutex_Surrender(
676        &the_mutex->Mutex,
677        the_mutex->Object.id, 
678#if defined(RTEMS_MULTIPROCESSING)
679        POSIX_Threads_mutex_MP_support
680#else
681        NULL
682#endif
683      );
684      _Thread_Enable_dispatch();
685      return 0;
686  }
687  return POSIX_BOTTOM_REACHED();
688}
689 
690/*PAGE
691 *
692 *  13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
693 */
694
695int pthread_mutex_getprioceiling(
696  pthread_mutex_t   *mutex,
697  int               *prioceiling
698)
699{
700  register POSIX_Mutex_Control *the_mutex;
701  Objects_Locations             location;
702
703  if ( !prioceiling )
704    return EINVAL;
705
706  the_mutex = _POSIX_Mutex_Get( mutex, &location );
707  switch ( location ) {
708    case OBJECTS_REMOTE:
709#if defined(RTEMS_MULTIPROCESSING)
710      return POSIX_MP_NOT_IMPLEMENTED();   /* XXX feels questionable */
711#endif
712    case OBJECTS_ERROR:
713      return EINVAL;
714    case OBJECTS_LOCAL:
715      *prioceiling = _POSIX_Priority_From_core(
716        the_mutex->Mutex.Attributes.priority_ceiling
717      );
718      _Thread_Enable_dispatch();
719      return 0;
720  }
721  return POSIX_BOTTOM_REACHED();
722}
Note: See TracBrowser for help on using the repository browser.