summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/semaphorecreatesupp.c
blob: aa04d9599957dc8dadbf4482917df96192d9177c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 *  $Id$
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdarg.h>

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <limits.h>

#include <rtems/system.h>
#include <rtems/score/object.h>
#include <rtems/posix/semaphore.h>
#include <rtems/posix/time.h>
#include <rtems/seterr.h>

/*PAGE
 *
 *  _POSIX_Semaphore_Create_support
 *
 *  This routine does the actual creation and initialization of
 *  a poxix semaphore.  It is a support routine for sem_init and
 *  sem_open.
 */

int _POSIX_Semaphore_Create_support(
  const char                *name,
  int                        pshared,
  unsigned int               value,
  POSIX_Semaphore_Control  **the_sem
)
{
  POSIX_Semaphore_Control   *the_semaphore;
  CORE_semaphore_Attributes *the_sem_attr;

  _Thread_Disable_dispatch();
 
  /* Sharing semaphores among processes is not currently supported */
  if (pshared != 0) {
    _Thread_Enable_dispatch();
    set_errno_and_return_minus_one( ENOSYS );
  }

  if ( name ) {
    if( strlen(name) > PATH_MAX ) { 
      _Thread_Enable_dispatch();
      set_errno_and_return_minus_one( ENAMETOOLONG );
    }
  }

  the_semaphore = _POSIX_Semaphore_Allocate();
 
  if ( !the_semaphore ) {
    _Thread_Enable_dispatch();
    set_errno_and_return_minus_one( ENOSPC );
  }
 
#if defined(RTEMS_MULTIPROCESSING)
  if ( pshared == PTHREAD_PROCESS_SHARED &&
       !( _Objects_MP_Allocate_and_open( &_POSIX_Semaphore_Information, 0,
                            the_semaphore->Object.id, FALSE ) ) ) {
    _POSIX_Semaphore_Free( the_semaphore );
    _Thread_Enable_dispatch();
    set_errno_and_return_minus_one( EAGAIN );
  }
#endif
 
  the_semaphore->process_shared  = pshared;

  if ( name ) {
    the_semaphore->named = TRUE;
    the_semaphore->open_count = 1;
    the_semaphore->linked = TRUE;
  }
  else 
    the_semaphore->named = FALSE;

  the_sem_attr = &the_semaphore->Semaphore.Attributes;
 
  /*
   *  POSIX does not appear to specify what the discipline for 
   *  blocking tasks on this semaphore should be.  It could somehow 
   *  be derived from the current scheduling policy.  One
   *  thing is certain, no matter what we decide, it won't be 
   *  the same as  all other POSIX implementations. :)
   */

  the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;

  /*
   *  This effectively disables limit checking.
   */

  the_sem_attr->maximum_count = 0xFFFFFFFF;

  _CORE_semaphore_Initialize(
    &the_semaphore->Semaphore,
    OBJECTS_POSIX_SEMAPHORES,
    the_sem_attr,
    value,
    NULL                 /* multiprocessing is not supported */
  );

  /*
   *  Make the semaphore available for use.
   */
 
  _Objects_Open(
    &_POSIX_Semaphore_Information,
    &the_semaphore->Object,
    (char *) name
  );
 
  *the_sem = the_semaphore;
 
#if defined(RTEMS_MULTIPROCESSING)
  if ( pshared == PTHREAD_PROCESS_SHARED )
    _POSIX_Semaphore_MP_Send_process_packet(
      POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE,
      the_semaphore->Object.id,
      (char *) name,
      0                           /* proxy id - Not used */
    );
#endif
 
  _Thread_Enable_dispatch();
  return 0;
}