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