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

4.104.114.84.95
Last change on this file since eb5a7e07 was eb5a7e07, checked in by Joel Sherrill <joel.sherrill@…>, on 10/06/95 at 20:48:38

fixed missing CVS IDs

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