1 krisbash 1.1 #include "sem.h"
2 #include <stdio.h>
3 #include <pal/palcommon.h>
4 #include <pal/strings.h>
5
6 #ifndef __MSC_VER
7 # ifndef SEM_FAILED
8 # define SEM_FAILED (sem_t*)-1
9 # endif
10 #endif
11
12 /*
13 **==============================================================================
14 **
15 ** Sem
16 **
17 **==============================================================================
18 */
19
20 _Success_(return == 0) int Sem_Init_Injected(
21 _Out_ Sem* self,
22 krisbash 1.1 SemUserAccess userAccess,
23 unsigned int count,
24 NitsCallSite cs)
25 {
26 #if defined(USE_ALLOCATOR)
27 if (cs.file && NitsShouldFault(cs, NitsAutomatic))
28 return -1;
29 #else
30 if (NitsShouldFault(cs, NitsAutomatic))
31 return -1;
32 #endif
33
34 #if defined(_MSC_VER)
35
36 self->handle = CreateSemaphoreEx(
37 (userAccess == SEM_USER_ACCESS_ALLOW_ALL) ? &g_SecurityAttributes : NULL,
38 count,
39 0xFFFF,
40 NULL,
41 0,
42 SEMAPHORE_ALL_ACCESS);
43 krisbash 1.1
44 if (!self->handle)
45 return -1;
46
47 return 0;
48
49 #else
50
51 # if defined(USE_ALLOCATOR)
52 if (!(self->sem = (sem_t*)__PAL_Calloc(
53 cs.file, cs.line, cs.function, 1, sizeof(sem_t))))
54 {
55 return -1;
56 }
57 # else
58 if (!(self->sem = (sem_t*)PAL_Calloc(1, sizeof(sem_t))))
59 return -1;
60 # endif
61
62 return sem_init(self->sem, 0, count) == 0 ? 0 : -1;
63
64 krisbash 1.1 #endif
65 }
66
67 int Sem_Post(
68 _Inout_ Sem* self,
69 unsigned int count)
70 {
71 #if defined(_MSC_VER)
72 ReleaseSemaphore(self->handle, count, NULL);
73 return 0;
74 #else
75 while (count--)
76 {
77 if (sem_post(self->sem) != 0)
78 return -1;
79 }
80
81 return 0;
82 #endif
83 }
84
85 krisbash 1.1 /*
86 **==============================================================================
87 **
88 ** NamedSem
89 **
90 ** (1) On Linux, sem_open("/erp", ...) creates "/dev/shm/sem.erp"
91 **
92 **==============================================================================
93 */
94
95 _Return_type_success_(return == 0) int NamedSem_Open_Injected(
96 _Out_ NamedSem* self,
97 SemUserAccess userAccess,
98 unsigned int count,
99 _In_z_ const PAL_Char *name,
100 unsigned long flags,
101 NitsCallSite cs)
102 {
103 PAL_UNUSED(flags);
104
105 if (NitsShouldFault(cs, NitsAutomatic))
106 krisbash 1.1 return -1;
107
108 #if defined(_MSC_VER)
109 PAL_UNUSED(flags);
110
111 if (flags & NAMEDSEM_FLAG_CREATE)
112 {
113 self->handle = CreateSemaphoreEx(
114 (userAccess == SEM_USER_ACCESS_ALLOW_ALL) ? &g_SecurityAttributes : NULL,
115 count,
116 0xFFFF,
117 name,
118 0,
119 SEMAPHORE_ALL_ACCESS);
120 }
121 else
122 {
123 self->handle = OpenSemaphoreW(
124 SEMAPHORE_ALL_ACCESS,
125 FALSE,
126 name);
127 krisbash 1.1 }
128
129 if (!self->handle)
130 return -1;
131
132 return 0;
133
134 #else
135
136 int tflags = 0;
137
138 /*
139 * This is done since the sem_open is only defined for char * and does not take wchar_t
140 */
141 if (!name)
142 return -1;
143
144 #if defined(CONFIG_ENABLE_WCHAR)
145 StrWcslcpy(self->semname, name, PAL_MAX_PATH_SIZE);
146 #else
147 Strlcpy(self->semname, name, PAL_MAX_PATH_SIZE);
148 krisbash 1.1 #endif
149
150 if (flags & NAMEDSEM_FLAG_CREATE)
151 tflags |= O_CREAT;
152
153 if (flags & NAMEDSEM_FLAG_EXCLUSIVE)
154 tflags |= O_EXCL;
155
156 self->sem = sem_open(self->semname, tflags, 0600, count);
157
158 if (self->sem == SEM_FAILED)
159 return -1;
160
161 return 0;
162
163 #endif
164 }
165
166 void NamedSem_Close(
167 _Inout_ NamedSem* self)
168 {
169 krisbash 1.1 #if defined(_MSC_VER)
170 CloseHandle(self->handle);
171 #else
172 sem_close(self->sem);
173 #endif
174 }
175
176 int NamedSem_Post(
177 _Inout_ NamedSem* self,
178 unsigned int count)
179 {
180 #if defined(_MSC_VER)
181 return ReleaseSemaphore(self->handle, count, NULL) ? 0 : -1;
182 #else
183
184 while (count--)
185 {
186 if (sem_post(self->sem) != 0)
187 return -1;
188 }
189
190 krisbash 1.1 return 0;
191
192 #endif
193 }
194
195 #if !defined(CONFIG_HAVE_SEM_TIMEDWAIT)
196 int __TimedWaitHelper(sem_t* sem, int milliseconds)
197 {
198 PAL_Uint64 currentTimeUsec = 0;
199 if (PAL_TRUE != PAL_Time(¤tTimeUsec))
200 return -1;
201
202 PAL_Uint64 finalTimeUsec = currentTimeUsec + (milliseconds * 1000);
203
204 while(currentTimeUsec < finalTimeUsec)
205 {
206 if(sem_trywait(sem) == 0)
207 {
208 return 0;
209 }
210 else if(EAGAIN == errno)
211 krisbash 1.1 {
212 Sleep_Milliseconds(1);
213 }
214 else
215 return -1;
216
217 if (PAL_TRUE != PAL_Time(¤tTimeUsec))
218 return -1;
219 }
220
221 errno = ETIMEDOUT;
222
223 return -1;
224 }
225 #endif
226
|