source: rtems/cpukit/posix/src/mutex.c @ c238a218

4.104.114.84.95
Last change on this file since c238a218 was c238a218, checked in by Joel Sherrill <joel.sherrill@…>, on 05/31/96 at 21:40:48

added checks to validate values passed to set attribute routines

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