source: rtems/cpukit/posix/src/semaphore.c @ 8d0b7d96

4.104.114.84.95
Last change on this file since 8d0b7d96 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.3 KB
Line 
1/*  semaphore.c
2 *
3 *  $Id$
4 */
5
6#include <stdarg.h>
7
8#include <errno.h>
9#include <fcntl.h>
10#include <pthread.h>
11#include <semaphore.h>
12#include <limits.h>
13
14#include <rtems/system.h>
15#include <rtems/score/object.h>
16#include <rtems/posix/semaphore.h>
17#include <rtems/posix/time.h>
18
19/*PAGE
20 *
21 *  _POSIX_Semaphore_Manager_initialization
22 *
23 *  This routine initializes all semaphore manager related data structures.
24 *
25 *  Input parameters:
26 *    maximum_semaphores - maximum configured semaphores
27 *
28 *  Output parameters:  NONE
29 */
30 
31void _POSIX_Semaphore_Manager_initialization(
32  unsigned32 maximum_semaphores
33)
34{
35  _Objects_Initialize_information(
36    &_POSIX_Semaphore_Information,
37    OBJECTS_POSIX_SEMAPHORES,
38    TRUE,
39    maximum_semaphores,
40    sizeof( POSIX_Semaphore_Control ),
41    TRUE,
42    _POSIX_PATH_MAX,
43    FALSE
44  );
45}
46
47/*PAGE
48 *
49 *  _POSIX_Semaphore_Create_support
50 */
51
52int _POSIX_Semaphore_Create_support(
53  const char                *name,
54  int                        pshared,
55  unsigned int               value,
56  POSIX_Semaphore_Control  **the_sem
57)
58{
59  POSIX_Semaphore_Control   *the_semaphore;
60  CORE_semaphore_Attributes *the_sem_attr;
61
62  _Thread_Disable_dispatch();
63 
64  the_semaphore = _POSIX_Semaphore_Allocate();
65 
66  if ( !the_semaphore ) {
67    _Thread_Enable_dispatch();
68    seterrno( ENOMEM );
69    return -1;
70  }
71 
72  if ( pshared == PTHREAD_PROCESS_SHARED &&
73       !( _Objects_MP_Allocate_and_open( &_POSIX_Semaphore_Information, 0,
74                            the_semaphore->Object.id, FALSE ) ) ) {
75    _POSIX_Semaphore_Free( the_semaphore );
76    _Thread_Enable_dispatch();
77    seterrno( EAGAIN );
78    return -1;
79  }
80 
81  the_semaphore->process_shared  = pshared;
82
83  if ( name ) {
84    the_semaphore->named = TRUE;
85    the_semaphore->open_count = 1;
86    the_semaphore->linked = TRUE;
87  }
88  else
89    the_semaphore->named = FALSE;
90
91  the_sem_attr = &the_semaphore->Semaphore.Attributes;
92 
93  /* XXX
94   *
95   *  Note should this be based on the current scheduling policy?
96   */
97
98  the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
99 
100  _CORE_semaphore_Initialize(
101    &the_semaphore->Semaphore,
102    OBJECTS_POSIX_SEMAPHORES,
103    the_sem_attr,
104    value,
105    0      /* XXX - proxy_extract_callout is unused */
106  );
107 
108  /* XXX - need Names to be a string!!! */
109  _Objects_Open(
110    &_POSIX_Semaphore_Information,
111    &the_semaphore->Object,
112    (char *) name
113  );
114 
115  *the_sem = the_semaphore;
116 
117  if ( pshared == PTHREAD_PROCESS_SHARED )
118    _POSIX_Semaphore_MP_Send_process_packet(
119      POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE,
120      the_semaphore->Object.id,
121      (char *) name,
122      0                /* proxy id - Not used */
123    );
124 
125  _Thread_Enable_dispatch();
126  return 0;
127}
128
129
130/*PAGE
131 *
132 *  11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219
133 */
134
135int sem_init(
136  sem_t         *sem,
137  int            pshared,
138  unsigned int   value
139)
140{
141  int                        status;
142  POSIX_Semaphore_Control   *the_semaphore;
143
144  status = _POSIX_Semaphore_Create_support(
145    NULL,
146    pshared,
147    value,
148    &the_semaphore
149  );
150   
151  if ( status != -1 )
152    *sem = the_semaphore->Object.id;
153
154  return status;
155}
156
157/*PAGE
158 *
159 *  11.2.2 Destroy an Unnamed Semaphore, P1003.1b-1993, p.220
160 */
161
162int sem_destroy(
163  sem_t *sem
164)
165{
166  register POSIX_Semaphore_Control *the_semaphore;
167  Objects_Locations                 location;
168 
169  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
170  switch ( location ) {
171    case OBJECTS_ERROR:
172      seterrno( EINVAL );
173      return( -1 );
174    case OBJECTS_REMOTE:
175      _Thread_Dispatch();
176      return POSIX_MP_NOT_IMPLEMENTED();
177      seterrno( EINVAL );
178      return( -1 );
179    case OBJECTS_LOCAL:
180      /*
181       *  Undefined operation on a named semaphore.
182       */
183
184      if ( the_semaphore->named == TRUE ) {
185        seterrno( EINVAL );
186        return( -1 );
187      }
188 
189      _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object );
190 
191      _CORE_semaphore_Flush(
192        &the_semaphore->Semaphore,
193        _POSIX_Semaphore_MP_Send_object_was_deleted,
194        -1  /* XXX should also seterrno -> EINVAL */
195      );
196 
197      _POSIX_Semaphore_Free( the_semaphore );
198 
199      if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
200 
201        _Objects_MP_Close(
202          &_POSIX_Semaphore_Information,
203          the_semaphore->Object.id
204        );
205 
206        _POSIX_Semaphore_MP_Send_process_packet(
207          POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
208          the_semaphore->Object.id,
209          0,                         /* Not used */
210          0                          /* Not used */
211        );
212      }
213      _Thread_Enable_dispatch();
214      return 0;
215  }
216  return POSIX_BOTTOM_REACHED();
217}
218
219/*PAGE
220 *
221 *  11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221
222 *
223 *  NOTE: When oflag is O_CREAT, then optional third and fourth
224 *        parameters must be present.
225 */
226
227sem_t *sem_open(
228  const char *name,
229  int         oflag,
230  ...
231  /* mode_t mode, */
232  /* unsigned int value */
233)
234{
235  va_list                    arg;
236  mode_t                     mode;
237  unsigned int               value;
238  int                        status;
239  Objects_Id                 the_semaphore_id;
240  POSIX_Semaphore_Control   *the_semaphore;
241 
242
243  if ( oflag & O_CREAT ) {
244    va_start(arg, oflag);
245    mode = (mode_t) va_arg( arg, mode_t * );
246    value = (unsigned int) va_arg( arg, unsigned int * );
247    va_end(arg);
248  }
249
250  status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
251   
252  /*
253   *  If the name to id translation worked, then the semaphore exists
254   *  and we can just return a pointer to the id.  Otherwise we may
255   *  need to check to see if this is a "semaphore does not exist"
256   *  or some other miscellaneous error on the name.
257   */
258
259  if ( status ) {
260
261    if ( status == EINVAL ) {      /* name -> ID translation failed */
262      if ( !(oflag & O_CREAT) ) {  /* willing to create it? */
263        seterrno( ENOENT );
264        return (sem_t *) -1;
265      }
266      /* we are willing to create it */
267    }
268    seterrno( status );               /* some type of error */
269    return (sem_t *) -1;
270
271  } else {                /* name -> ID translation succeeded */
272
273    if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
274      seterrno( EEXIST );
275      return (sem_t *) -1;
276    }
277
278    /*
279     * XXX In this case we need to do an ID->pointer conversion to
280     *     check the mode.   This is probably a good place for a subroutine.
281     */
282
283    the_semaphore->open_count += 1;
284
285    return (sem_t *)&the_semaphore->Object.id;
286
287  }
288 
289  /* XXX verify this comment...
290   *
291   *  At this point, the semaphore does not exist and everything has been
292   *  checked. We should go ahead and create a semaphore.
293   */
294
295  status = _POSIX_Semaphore_Create_support(
296    name,
297    TRUE,         /* shared across processes */
298    value,
299    &the_semaphore
300  );
301 
302  if ( status == -1 )
303    return (sem_t *) -1;
304
305  return (sem_t *) &the_semaphore->Object.id;
306 
307}
308
309/*PAGE
310 *
311 *  _POSIX_Semaphore_Delete
312 */
313
314void _POSIX_Semaphore_Delete(
315  POSIX_Semaphore_Control *the_semaphore
316)
317{
318  if ( !the_semaphore->linked && !the_semaphore->open_count ) {
319    _POSIX_Semaphore_Free( the_semaphore );
320
321    if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
322
323      _Objects_MP_Close(
324        &_POSIX_Semaphore_Information,
325        the_semaphore->Object.id
326      );
327
328      _POSIX_Semaphore_MP_Send_process_packet(
329        POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
330        the_semaphore->Object.id,
331        0,                         /* Not used */
332        0                          /* Not used */
333      );
334    }
335
336  }
337}
338
339/*PAGE
340 *
341 *  11.2.4 Close a Named Semaphore, P1003.1b-1993, p.224
342 */
343
344int sem_close(
345  sem_t *sem
346)
347{
348  register POSIX_Semaphore_Control *the_semaphore;
349  Objects_Locations                 location;
350 
351  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
352  switch ( location ) {
353    case OBJECTS_ERROR:
354      seterrno( EINVAL );
355      return( -1 );
356    case OBJECTS_REMOTE:
357      _Thread_Dispatch();
358      return POSIX_MP_NOT_IMPLEMENTED();
359      seterrno( EINVAL );
360      return( -1 );
361    case OBJECTS_LOCAL:
362      the_semaphore->open_count -= 1;
363      _POSIX_Semaphore_Delete( the_semaphore );
364      _Thread_Enable_dispatch();
365      return 0;
366  }
367  return POSIX_BOTTOM_REACHED();
368}
369
370/*PAGE
371 *
372 *  11.2.5 Remove a Named Semaphore, P1003.1b-1993, p.225
373 */
374
375int sem_unlink(
376  const char *name
377)
378{
379  int  status;
380  register POSIX_Semaphore_Control *the_semaphore;
381  Objects_Id                        the_semaphore_id;
382  Objects_Locations                 location;
383 
384  status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
385   
386  if ( !status ) {
387    seterrno( status );
388    return -1;
389  }
390
391  the_semaphore = _POSIX_Semaphore_Get( &the_semaphore_id, &location );
392  switch ( location ) {
393    case OBJECTS_ERROR:
394      seterrno( EINVAL );
395      return( -1 );
396    case OBJECTS_REMOTE:
397      _Thread_Dispatch();
398      return POSIX_MP_NOT_IMPLEMENTED();
399      seterrno( EINVAL );
400      return( -1 );
401    case OBJECTS_LOCAL:
402
403      if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
404        _Objects_MP_Close(
405          &_POSIX_Semaphore_Information,
406          the_semaphore->Object.id
407        );
408      }
409
410      the_semaphore->linked = FALSE;
411
412      _POSIX_Semaphore_Delete( the_semaphore );
413
414      _Thread_Enable_dispatch();
415      return 0;
416  }
417  return POSIX_BOTTOM_REACHED();
418}
419
420/*PAGE
421 *
422 *  _POSIX_Semaphore_Wait_support
423 */
424
425int _POSIX_Semaphore_Wait_support(
426  sem_t              *sem,
427  boolean             blocking,
428  Watchdog_Interval   timeout
429)
430{
431  register POSIX_Semaphore_Control *the_semaphore;
432  Objects_Locations                 location;
433 
434  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
435  switch ( location ) {
436    case OBJECTS_ERROR:
437      seterrno( EINVAL );
438      return( -1 );
439    case OBJECTS_REMOTE:
440      _Thread_Dispatch();
441      return POSIX_MP_NOT_IMPLEMENTED();
442      seterrno( EINVAL );
443      return( -1 );
444    case OBJECTS_LOCAL:
445      _CORE_semaphore_Seize(
446        &the_semaphore->Semaphore,
447        the_semaphore->Object.id,
448        blocking,
449        timeout
450      );
451      _Thread_Enable_dispatch();
452      return _Thread_Executing->Wait.return_code;
453  }
454  return POSIX_BOTTOM_REACHED();
455}
456
457/*PAGE
458 *
459 *  11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
460 *
461 *  NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
462 */
463
464int sem_wait(
465  sem_t *sem
466)
467{
468  return _POSIX_Semaphore_Wait_support( sem, TRUE, THREAD_QUEUE_WAIT_FOREVER );
469}
470
471/*PAGE
472 *
473 *  11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
474 *
475 *  NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
476 */
477
478int sem_trywait(
479  sem_t *sem
480)
481{
482  return _POSIX_Semaphore_Wait_support( sem, FALSE, THREAD_QUEUE_WAIT_FOREVER );
483}
484
485/*PAGE
486 *
487 *  11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
488 *
489 *  NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
490 */
491
492int sem_timedwait(
493  sem_t                 *sem,
494  const struct timespec *timeout
495)
496{
497  return _POSIX_Semaphore_Wait_support(
498    sem,
499    TRUE,
500    _POSIX_Time_Spec_to_interval( timeout )
501  );
502}
503
504/*PAGE
505 *
506 *  11.2.7 Unlock a Semaphore, P1003.1b-1993, p.227
507 */
508
509void POSIX_Semaphore_MP_support(
510  Thread_Control *the_thread,
511  Objects_Id      id
512)
513{
514  (void) POSIX_MP_NOT_IMPLEMENTED();
515}
516 
517
518int sem_post(
519  sem_t  *sem
520)
521{
522  register POSIX_Semaphore_Control *the_semaphore;
523  Objects_Locations                 location;
524 
525  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
526  switch ( location ) {
527    case OBJECTS_ERROR:
528      seterrno( EINVAL );
529      return( -1 );
530    case OBJECTS_REMOTE:
531      _Thread_Dispatch();
532      return POSIX_MP_NOT_IMPLEMENTED();
533      seterrno( EINVAL );
534      return( -1 );
535    case OBJECTS_LOCAL:
536      _CORE_semaphore_Surrender(
537        &the_semaphore->Semaphore,
538        the_semaphore->Object.id,
539        POSIX_Semaphore_MP_support
540      );
541      _Thread_Enable_dispatch();
542      return 0;
543  }
544  return POSIX_BOTTOM_REACHED();
545}
546
547/*PAGE
548 *
549 *  11.2.8 Get the Value of a Semaphore, P1003.1b-1993, p.229
550 */
551
552int sem_getvalue(
553  sem_t  *sem,
554  int    *sval
555)
556{
557  register POSIX_Semaphore_Control *the_semaphore;
558  Objects_Locations                 location;
559 
560  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
561  switch ( location ) {
562    case OBJECTS_ERROR:
563      seterrno( EINVAL );
564      return( -1 );
565    case OBJECTS_REMOTE:
566      _Thread_Dispatch();
567      return POSIX_MP_NOT_IMPLEMENTED();
568      seterrno( EINVAL );
569      return( -1 );
570    case OBJECTS_LOCAL:
571      *sval = _CORE_semaphore_Get_count( &the_semaphore->Semaphore );
572      _Thread_Enable_dispatch();
573      return 0;
574  }
575  return POSIX_BOTTOM_REACHED();
576}
Note: See TracBrowser for help on using the repository browser.