FreeRDP
Loading...
Searching...
No Matches
semaphore.c
1
20#include <winpr/config.h>
21#include <winpr/debug.h>
22#include <winpr/synch.h>
23
24#include "synch.h"
25
26#ifdef WINPR_HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29
30#ifndef _WIN32
31
32#include <errno.h>
33#include <fcntl.h>
34#include "../handle/handle.h"
35#include "../log.h"
36#define TAG WINPR_TAG("synch.semaphore")
37
38static BOOL SemaphoreCloseHandle(HANDLE handle);
39
40static BOOL SemaphoreIsHandled(HANDLE handle)
41{
42 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_SEMAPHORE, FALSE);
43}
44
45static int SemaphoreGetFd(HANDLE handle)
46{
47 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
48
49 if (!SemaphoreIsHandled(handle))
50 return -1;
51
52 return sem->pipe_fd[0];
53}
54
55static DWORD SemaphoreCleanupHandle(HANDLE handle)
56{
57 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
58
59 if (!SemaphoreIsHandled(handle))
60 return WAIT_FAILED;
61
62 uint8_t val = 0;
63 const SSIZE_T length = read(sem->pipe_fd[0], &val, sizeof(val));
64
65 if (length != 1)
66 {
67 char ebuffer[256] = WINPR_C_ARRAY_INIT;
68 WLog_ERR(TAG, "semaphore read() failure [%d] %s", errno,
69 winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
70 return WAIT_FAILED;
71 }
72
73 return WAIT_OBJECT_0;
74}
75
76BOOL SemaphoreCloseHandle(HANDLE handle)
77{
78 WINPR_SEMAPHORE* semaphore = (WINPR_SEMAPHORE*)handle;
79
80 if (!SemaphoreIsHandled(handle))
81 return FALSE;
82
83#ifdef WINPR_PIPE_SEMAPHORE
84
85 if (semaphore->pipe_fd[0] != -1)
86 {
87 close(semaphore->pipe_fd[0]);
88 semaphore->pipe_fd[0] = -1;
89
90 if (semaphore->pipe_fd[1] != -1)
91 {
92 close(semaphore->pipe_fd[1]);
93 semaphore->pipe_fd[1] = -1;
94 }
95 }
96
97#else
98#if defined __APPLE__
99 semaphore_destroy(mach_task_self(), *((winpr_sem_t*)semaphore->sem));
100#else
101 sem_destroy((winpr_sem_t*)semaphore->sem);
102#endif
103#endif
104 return TRUE;
105}
106
107static HANDLE_OPS ops = { SemaphoreIsHandled,
108 SemaphoreCloseHandle,
109 SemaphoreGetFd,
110 SemaphoreCleanupHandle,
111 nullptr,
112 nullptr,
113 nullptr,
114 nullptr,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr,
119 nullptr,
120 nullptr,
121 nullptr,
122 nullptr,
123 nullptr,
124 nullptr,
125 nullptr,
126 nullptr,
127 nullptr };
128
129HANDLE CreateSemaphoreW(WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
130 LONG lInitialCount, WINPR_ATTR_UNUSED LONG lMaximumCount,
131 WINPR_ATTR_UNUSED LPCWSTR lpName)
132{
133 HANDLE handle = nullptr;
134 WINPR_SEMAPHORE* semaphore = nullptr;
135 semaphore = (WINPR_SEMAPHORE*)calloc(1, sizeof(WINPR_SEMAPHORE));
136
137 if (!semaphore)
138 return nullptr;
139
140 semaphore->pipe_fd[0] = -1;
141 semaphore->pipe_fd[1] = -1;
142 semaphore->sem = (winpr_sem_t*)nullptr;
143 semaphore->common.ops = &ops;
144#ifdef WINPR_PIPE_SEMAPHORE
145
146#ifdef WINPR_HAVE_PIPE2
147 if (pipe2(semaphore->pipe_fd, O_CLOEXEC) < 0)
148#else
149 if (pipe(semaphore->pipe_fd) < 0)
150#endif
151 {
152 WLog_ERR(TAG, "failed to create semaphore");
153 free(semaphore);
154 return nullptr;
155 }
156
157#ifndef WINPR_HAVE_PIPE2
158 if (!winpr_set_cloexec(semaphore->pipe_fd[0], TRUE) ||
159 !winpr_set_cloexec(semaphore->pipe_fd[1], TRUE))
160 {
161 WLog_ERR(TAG, "failed to set close-on-exec on semaphore pipe");
162 close(semaphore->pipe_fd[0]);
163 close(semaphore->pipe_fd[1]);
164 free(semaphore);
165 return nullptr;
166 }
167#endif
168
169 while (lInitialCount > 0)
170 {
171 if (write(semaphore->pipe_fd[1], "-", 1) != 1)
172 {
173 close(semaphore->pipe_fd[0]);
174 close(semaphore->pipe_fd[1]);
175 free(semaphore);
176 return nullptr;
177 }
178
179 lInitialCount--;
180 }
181
182#else
183 semaphore->sem = (winpr_sem_t*)malloc(sizeof(winpr_sem_t));
184
185 if (!semaphore->sem)
186 {
187 WLog_ERR(TAG, "failed to allocate semaphore memory");
188 free(semaphore);
189 return nullptr;
190 }
191
192#if defined __APPLE__
193
194 if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) !=
195 KERN_SUCCESS)
196#else
197 if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
198#endif
199 {
200 WLog_ERR(TAG, "failed to create semaphore");
201 free(semaphore->sem);
202 free(semaphore);
203 return nullptr;
204 }
205
206#endif
207 WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
208 handle = (HANDLE)semaphore;
209 return handle;
210}
211
212HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
213 LONG lMaximumCount, WINPR_ATTR_UNUSED LPCSTR lpName)
214{
215 return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, nullptr);
216}
217
218HANDLE OpenSemaphoreW(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
219 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCWSTR lpName)
220{
221 WLog_ERR(TAG, "not implemented");
222 return nullptr;
223}
224
225HANDLE OpenSemaphoreA(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
226 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCSTR lpName)
227{
228 WLog_ERR(TAG, "not implemented");
229 return nullptr;
230}
231
232BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,
233 WINPR_ATTR_UNUSED LPLONG lpPreviousCount)
234{
235 ULONG Type = 0;
236 WINPR_HANDLE* Object = nullptr;
237 WINPR_SEMAPHORE* semaphore = nullptr;
238
239 if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
240 return FALSE;
241
242 if (Type == HANDLE_TYPE_SEMAPHORE)
243 {
244 semaphore = (WINPR_SEMAPHORE*)Object;
245#ifdef WINPR_PIPE_SEMAPHORE
246
247 if (semaphore->pipe_fd[0] != -1)
248 {
249 while (lReleaseCount > 0)
250 {
251 if (write(semaphore->pipe_fd[1], "-", 1) != 1)
252 return FALSE;
253
254 lReleaseCount--;
255 }
256 }
257
258#else
259
260 while (lReleaseCount > 0)
261 {
262#if defined __APPLE__
263 semaphore_signal(*((winpr_sem_t*)semaphore->sem));
264#else
265 sem_post((winpr_sem_t*)semaphore->sem);
266#endif
267 }
268
269#endif
270 return TRUE;
271 }
272
273 WLog_ERR(TAG, "called on a handle that is not a semaphore");
274 return FALSE;
275}
276
277#endif