source: rtems/cpukit/posix/src/mutex.c @ 684c3c4

4.104.114.84.95
Last change on this file since 684c3c4 was 684c3c4, checked in by Joel Sherrill <joel.sherrill@…>, on 08/12/96 at 16:29:14

pthread_mutexattr_getprotocol: added check for attribute structure being
initialized

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