source: rtems/c/src/exec/posix/src/mutex.c @ 1ceface

4.104.114.84.95
Last change on this file since 1ceface was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

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