source: rtems/cpukit/posix/src/semaphore.c @ 93994fdb

4.104.114.84.95
Last change on this file since 93994fdb was 93994fdb, checked in by Joel Sherrill <joel.sherrill@…>, on 04/15/99 at 18:57:31

Now compiles and is included in normal build even though it is untested.

Added multiprocessing conditional.

  • Property mode set to 100644
File size: 12.7 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#include <rtems/posix/seterr.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    set_errno_and_return_minus_one( ENOMEM );
69  }
70 
71#if defined(RTEMS_MULTIPROCESSING)
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    set_errno_and_return_minus_one( EAGAIN );
78  }
79#endif
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 defined(RTEMS_MULTIPROCESSING)
118  if ( pshared == PTHREAD_PROCESS_SHARED )
119    _POSIX_Semaphore_MP_Send_process_packet(
120      POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE,
121      the_semaphore->Object.id,
122      (char *) name,
123      0                /* proxy id - Not used */
124    );
125#endif
126 
127  _Thread_Enable_dispatch();
128  return 0;
129}
130
131
132/*PAGE
133 *
134 *  11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219
135 */
136
137int sem_init(
138  sem_t         *sem,
139  int            pshared,
140  unsigned int   value
141)
142{
143  int                        status;
144  POSIX_Semaphore_Control   *the_semaphore;
145
146  status = _POSIX_Semaphore_Create_support(
147    NULL,
148    pshared,
149    value,
150    &the_semaphore
151  );
152   
153  if ( status != -1 )
154    *sem = the_semaphore->Object.id;
155
156  return status;
157}
158
159/*PAGE
160 *
161 *  11.2.2 Destroy an Unnamed Semaphore, P1003.1b-1993, p.220
162 */
163
164int sem_destroy(
165  sem_t *sem
166)
167{
168  register POSIX_Semaphore_Control *the_semaphore;
169  Objects_Locations                 location;
170 
171  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
172  switch ( location ) {
173    case OBJECTS_ERROR:
174      set_errno_and_return_minus_one( EINVAL );
175    case OBJECTS_REMOTE:
176      _Thread_Dispatch();
177      return POSIX_MP_NOT_IMPLEMENTED();
178      set_errno_and_return_minus_one( EINVAL );
179    case OBJECTS_LOCAL:
180      /*
181       *  Undefined operation on a named semaphore.
182       */
183
184      if ( the_semaphore->named == TRUE ) {
185        set_errno_and_return_minus_one( EINVAL );
186      }
187 
188      _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object );
189 
190      _CORE_semaphore_Flush(
191        &the_semaphore->Semaphore,
192#if defined(RTEMS_MULTIPROCESSING)
193        _POSIX_Semaphore_MP_Send_object_was_deleted,
194#else
195        NULL,
196#endif
197        -1  /* XXX should also seterrno -> EINVAL */
198      );
199 
200      _POSIX_Semaphore_Free( the_semaphore );
201 
202#if defined(RTEMS_MULTIPROCESSING)
203      if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
204 
205        _Objects_MP_Close(
206          &_POSIX_Semaphore_Information,
207          the_semaphore->Object.id
208        );
209 
210        _POSIX_Semaphore_MP_Send_process_packet(
211          POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
212          the_semaphore->Object.id,
213          0,                         /* Not used */
214          0                          /* Not used */
215        );
216      }
217#endif
218      _Thread_Enable_dispatch();
219      return 0;
220  }
221  return POSIX_BOTTOM_REACHED();
222}
223
224/*PAGE
225 *
226 *  11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221
227 *
228 *  NOTE: When oflag is O_CREAT, then optional third and fourth
229 *        parameters must be present.
230 */
231
232sem_t *sem_open(
233  const char *name,
234  int         oflag,
235  ...
236  /* mode_t mode, */
237  /* unsigned int value */
238)
239{
240  va_list                    arg;
241  mode_t                     mode;
242  unsigned int               value;
243  int                        status;
244  Objects_Id                 the_semaphore_id;
245  POSIX_Semaphore_Control   *the_semaphore;
246 
247
248  if ( oflag & O_CREAT ) {
249    va_start(arg, oflag);
250    mode = (mode_t) va_arg( arg, mode_t * );
251    value = (unsigned int) va_arg( arg, unsigned int * );
252    va_end(arg);
253  }
254
255  status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
256   
257  /*
258   *  If the name to id translation worked, then the semaphore exists
259   *  and we can just return a pointer to the id.  Otherwise we may
260   *  need to check to see if this is a "semaphore does not exist"
261   *  or some other miscellaneous error on the name.
262   */
263
264  if ( status ) {
265
266    if ( status == EINVAL ) {      /* name -> ID translation failed */
267      if ( !(oflag & O_CREAT) ) {  /* willing to create it? */
268        set_errno_and_return_minus_one_cast( ENOENT, sem_t * );
269      }
270      /* we are willing to create it */
271    }
272    /* some type of error */
273    set_errno_and_return_minus_one_cast( status, sem_t * );
274
275  } else {                /* name -> ID translation succeeded */
276
277    if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
278      set_errno_and_return_minus_one_cast( EEXIST, sem_t * );
279    }
280
281    /*
282     * XXX In this case we need to do an ID->pointer conversion to
283     *     check the mode.   This is probably a good place for a subroutine.
284     */
285
286    the_semaphore->open_count += 1;
287
288    return (sem_t *)&the_semaphore->Object.id;
289
290  }
291 
292  /* XXX verify this comment...
293   *
294   *  At this point, the semaphore does not exist and everything has been
295   *  checked. We should go ahead and create a semaphore.
296   */
297
298  status = _POSIX_Semaphore_Create_support(
299    name,
300    TRUE,         /* shared across processes */
301    value,
302    &the_semaphore
303  );
304 
305  if ( status == -1 )
306    return (sem_t *) -1;
307
308  return (sem_t *) &the_semaphore->Object.id;
309 
310}
311
312/*PAGE
313 *
314 *  _POSIX_Semaphore_Delete
315 */
316
317void _POSIX_Semaphore_Delete(
318  POSIX_Semaphore_Control *the_semaphore
319)
320{
321  if ( !the_semaphore->linked && !the_semaphore->open_count ) {
322    _POSIX_Semaphore_Free( the_semaphore );
323
324#if defined(RTEMS_MULTIPROCESSING)
325    if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
326
327      _Objects_MP_Close(
328        &_POSIX_Semaphore_Information,
329        the_semaphore->Object.id
330      );
331
332      _POSIX_Semaphore_MP_Send_process_packet(
333        POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
334        the_semaphore->Object.id,
335        0,                         /* Not used */
336        0                          /* Not used */
337      );
338    }
339#endif
340
341  }
342}
343
344/*PAGE
345 *
346 *  11.2.4 Close a Named Semaphore, P1003.1b-1993, p.224
347 */
348
349int sem_close(
350  sem_t *sem
351)
352{
353  register POSIX_Semaphore_Control *the_semaphore;
354  Objects_Locations                 location;
355 
356  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
357  switch ( location ) {
358    case OBJECTS_ERROR:
359      set_errno_and_return_minus_one( EINVAL );
360    case OBJECTS_REMOTE:
361      _Thread_Dispatch();
362      return POSIX_MP_NOT_IMPLEMENTED();
363      set_errno_and_return_minus_one( EINVAL );
364    case OBJECTS_LOCAL:
365      the_semaphore->open_count -= 1;
366      _POSIX_Semaphore_Delete( the_semaphore );
367      _Thread_Enable_dispatch();
368      return 0;
369  }
370  return POSIX_BOTTOM_REACHED();
371}
372
373/*PAGE
374 *
375 *  11.2.5 Remove a Named Semaphore, P1003.1b-1993, p.225
376 */
377
378int sem_unlink(
379  const char *name
380)
381{
382  int  status;
383  register POSIX_Semaphore_Control *the_semaphore;
384  Objects_Id                        the_semaphore_id;
385  Objects_Locations                 location;
386 
387  status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
388   
389  if ( !status )
390    set_errno_and_return_minus_one( status );
391
392  the_semaphore = _POSIX_Semaphore_Get( &the_semaphore_id, &location );
393  switch ( location ) {
394    case OBJECTS_ERROR:
395      set_errno_and_return_minus_one( EINVAL );
396    case OBJECTS_REMOTE:
397      _Thread_Dispatch();
398      return POSIX_MP_NOT_IMPLEMENTED();
399      set_errno_and_return_minus_one( EINVAL );
400    case OBJECTS_LOCAL:
401
402#if defined(RTEMS_MULTIPROCESSING)
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#endif
410
411      the_semaphore->linked = FALSE;
412
413      _POSIX_Semaphore_Delete( the_semaphore );
414
415      _Thread_Enable_dispatch();
416      return 0;
417  }
418  return POSIX_BOTTOM_REACHED();
419}
420
421/*PAGE
422 *
423 *  _POSIX_Semaphore_Wait_support
424 */
425
426int _POSIX_Semaphore_Wait_support(
427  sem_t              *sem,
428  boolean             blocking,
429  Watchdog_Interval   timeout
430)
431{
432  register POSIX_Semaphore_Control *the_semaphore;
433  Objects_Locations                 location;
434 
435  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
436  switch ( location ) {
437    case OBJECTS_ERROR:
438      set_errno_and_return_minus_one( EINVAL );
439    case OBJECTS_REMOTE:
440      _Thread_Dispatch();
441      return POSIX_MP_NOT_IMPLEMENTED();
442      set_errno_and_return_minus_one( EINVAL );
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      set_errno_and_return_minus_one( EINVAL );
528    case OBJECTS_REMOTE:
529      _Thread_Dispatch();
530      return POSIX_MP_NOT_IMPLEMENTED();
531      set_errno_and_return_minus_one( EINVAL );
532    case OBJECTS_LOCAL:
533      _CORE_semaphore_Surrender(
534        &the_semaphore->Semaphore,
535        the_semaphore->Object.id,
536#if defined(RTEMS_MULTIPROCESSING)
537        POSIX_Semaphore_MP_support
538#else
539        NULL
540#endif
541      );
542      _Thread_Enable_dispatch();
543      return 0;
544  }
545  return POSIX_BOTTOM_REACHED();
546}
547
548/*PAGE
549 *
550 *  11.2.8 Get the Value of a Semaphore, P1003.1b-1993, p.229
551 */
552
553int sem_getvalue(
554  sem_t  *sem,
555  int    *sval
556)
557{
558  register POSIX_Semaphore_Control *the_semaphore;
559  Objects_Locations                 location;
560 
561  the_semaphore = _POSIX_Semaphore_Get( sem, &location );
562  switch ( location ) {
563    case OBJECTS_ERROR:
564      set_errno_and_return_minus_one( EINVAL );
565    case OBJECTS_REMOTE:
566      _Thread_Dispatch();
567      return POSIX_MP_NOT_IMPLEMENTED();
568      set_errno_and_return_minus_one( EINVAL );
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.