source: rtems/c/src/exec/posix/src/semaphore.c @ fd882ee

4.104.114.84.9
Last change on this file since fd882ee was fd882ee, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 2, 1999 at 3:29:47 PM

Now much closer to working.

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