source: rtems/cpukit/posix/src/mutex.c @ 1402ee25

4.104.114.84.95
Last change on this file since 1402ee25 was 1402ee25, checked in by Joel Sherrill <joel.sherrill@…>, on 08/12/96 at 18:56:04

fixed spacing ; moved a dummy MP support routine to clean up printout.

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