source: rtems/cpukit/posix/src/semaphore.c @ 5b748a1

4.104.114.84.95
Last change on this file since 5b748a1 was 5b748a1, checked in by Joel Sherrill <joel.sherrill@…>, on 06/03/96 at 17:32:19

renamed _POSIX_Time_Spec_to_interval to _POSIX_Timespec_to_interval

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