FreeRDP
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 
37 static BOOL SemaphoreCloseHandle(HANDLE handle);
38 
39 static BOOL SemaphoreIsHandled(HANDLE handle)
40 {
41  return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_SEMAPHORE, FALSE);
42 }
43 
44 static 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 
54 static DWORD SemaphoreCleanupHandle(HANDLE handle)
55 {
56  SSIZE_T length = 0;
57  WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
58 
59  if (!SemaphoreIsHandled(handle))
60  return WAIT_FAILED;
61 
62  length = read(sem->pipe_fd[0], &length, 1);
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 
75 BOOL 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 
107 static 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 
129 HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
130  LONG lMaximumCount, LPCWSTR lpName)
131 {
132  HANDLE handle = NULL;
133  WINPR_SEMAPHORE* semaphore = NULL;
134  semaphore = (WINPR_SEMAPHORE*)calloc(1, sizeof(WINPR_SEMAPHORE));
135 
136  if (!semaphore)
137  return NULL;
138 
139  semaphore->pipe_fd[0] = -1;
140  semaphore->pipe_fd[1] = -1;
141  semaphore->sem = (winpr_sem_t*)NULL;
142  semaphore->common.ops = &ops;
143 #ifdef WINPR_PIPE_SEMAPHORE
144 
145  if (pipe(semaphore->pipe_fd) < 0)
146  {
147  WLog_ERR(TAG, "failed to create semaphore");
148  free(semaphore);
149  return NULL;
150  }
151 
152  while (lInitialCount > 0)
153  {
154  if (write(semaphore->pipe_fd[1], "-", 1) != 1)
155  {
156  close(semaphore->pipe_fd[0]);
157  close(semaphore->pipe_fd[1]);
158  free(semaphore);
159  return NULL;
160  }
161 
162  lInitialCount--;
163  }
164 
165 #else
166  semaphore->sem = (winpr_sem_t*)malloc(sizeof(winpr_sem_t));
167 
168  if (!semaphore->sem)
169  {
170  WLog_ERR(TAG, "failed to allocate semaphore memory");
171  free(semaphore);
172  return NULL;
173  }
174 
175 #if defined __APPLE__
176 
177  if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) !=
178  KERN_SUCCESS)
179 #else
180  if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
181 #endif
182  {
183  WLog_ERR(TAG, "failed to create semaphore");
184  free(semaphore->sem);
185  free(semaphore);
186  return NULL;
187  }
188 
189 #endif
190  WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
191  handle = (HANDLE)semaphore;
192  return handle;
193 }
194 
195 HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
196  LONG lMaximumCount, LPCSTR lpName)
197 {
198  return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, NULL);
199 }
200 
201 HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
202 {
203  WLog_ERR(TAG, "not implemented");
204  return NULL;
205 }
206 
207 HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
208 {
209  WLog_ERR(TAG, "not implemented");
210  return NULL;
211 }
212 
213 BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount)
214 {
215  ULONG Type = 0;
216  WINPR_HANDLE* Object = NULL;
217  WINPR_SEMAPHORE* semaphore = NULL;
218 
219  if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
220  return FALSE;
221 
222  if (Type == HANDLE_TYPE_SEMAPHORE)
223  {
224  semaphore = (WINPR_SEMAPHORE*)Object;
225 #ifdef WINPR_PIPE_SEMAPHORE
226 
227  if (semaphore->pipe_fd[0] != -1)
228  {
229  while (lReleaseCount > 0)
230  {
231  if (write(semaphore->pipe_fd[1], "-", 1) != 1)
232  return FALSE;
233 
234  lReleaseCount--;
235  }
236  }
237 
238 #else
239 
240  while (lReleaseCount > 0)
241  {
242 #if defined __APPLE__
243  semaphore_signal(*((winpr_sem_t*)semaphore->sem));
244 #else
245  sem_post((winpr_sem_t*)semaphore->sem);
246 #endif
247  }
248 
249 #endif
250  return TRUE;
251  }
252 
253  WLog_ERR(TAG, "called on a handle that is not a semaphore");
254  return FALSE;
255 }
256 
257 #endif