source: rtems/cpukit/posix/src/mutex.c @ 9ac3e76

4.104.114.84.95
Last change on this file since 9ac3e76 was 9ac3e76, checked in by Mark Johannes <Mark.Johannes@…>, on 08/15/96 at 19:38:46

changed ENOMEM error message

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