source: rtems/c/src/exec/posix/src/semaphore.c @ 05ce4e09

4.104.114.84.95
Last change on this file since 05ce4e09 was 05ce4e09, checked in by Joel Sherrill <joel.sherrill@…>, on 06/07/96 at 15:21:27

changed code which set errno and then returned -1 to use the macro
set_errno_and_return_minus_one.

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