source: rtems/c/src/exec/posix/src/mutex.c @ b521ae2

4.104.114.84.95
Last change on this file since b521ae2 was 69c9543, checked in by Joel Sherrill <joel.sherrill@…>, on 07/04/96 at 18:09:23

basic test cases passed

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