20#include <winpr/config.h>
21#include <winpr/debug.h>
22#include <winpr/synch.h>
26#ifdef WINPR_HAVE_UNISTD_H
33#include "../handle/handle.h"
35#define TAG WINPR_TAG("synch.semaphore")
37static BOOL SemaphoreCloseHandle(HANDLE handle);
39static BOOL SemaphoreIsHandled(HANDLE handle)
41 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_SEMAPHORE, FALSE);
44static int SemaphoreGetFd(HANDLE handle)
46 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
48 if (!SemaphoreIsHandled(handle))
51 return sem->pipe_fd[0];
54static DWORD SemaphoreCleanupHandle(HANDLE handle)
56 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
58 if (!SemaphoreIsHandled(handle))
62 const SSIZE_T length = read(sem->pipe_fd[0], &val,
sizeof(val));
66 char ebuffer[256] = { 0 };
67 WLog_ERR(TAG,
"semaphore read() failure [%d] %s", errno,
68 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
75BOOL SemaphoreCloseHandle(HANDLE handle)
77 WINPR_SEMAPHORE* semaphore = (WINPR_SEMAPHORE*)handle;
79 if (!SemaphoreIsHandled(handle))
82#ifdef WINPR_PIPE_SEMAPHORE
84 if (semaphore->pipe_fd[0] != -1)
86 close(semaphore->pipe_fd[0]);
87 semaphore->pipe_fd[0] = -1;
89 if (semaphore->pipe_fd[1] != -1)
91 close(semaphore->pipe_fd[1]);
92 semaphore->pipe_fd[1] = -1;
98 semaphore_destroy(mach_task_self(), *((winpr_sem_t*)semaphore->sem));
100 sem_destroy((winpr_sem_t*)semaphore->sem);
108 SemaphoreCloseHandle,
110 SemaphoreCleanupHandle,
129HANDLE CreateSemaphoreW(WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
130 LONG lInitialCount, WINPR_ATTR_UNUSED LONG lMaximumCount,
131 WINPR_ATTR_UNUSED LPCWSTR lpName)
133 HANDLE handle = NULL;
134 WINPR_SEMAPHORE* semaphore = NULL;
135 semaphore = (WINPR_SEMAPHORE*)calloc(1,
sizeof(WINPR_SEMAPHORE));
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
146 if (pipe(semaphore->pipe_fd) < 0)
148 WLog_ERR(TAG,
"failed to create semaphore");
153 while (lInitialCount > 0)
155 if (write(semaphore->pipe_fd[1],
"-", 1) != 1)
157 close(semaphore->pipe_fd[0]);
158 close(semaphore->pipe_fd[1]);
167 semaphore->sem = (winpr_sem_t*)malloc(
sizeof(winpr_sem_t));
171 WLog_ERR(TAG,
"failed to allocate semaphore memory");
178 if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) !=
181 if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
184 WLog_ERR(TAG,
"failed to create semaphore");
185 free(semaphore->sem);
191 WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
192 handle = (HANDLE)semaphore;
196HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
197 LONG lMaximumCount, WINPR_ATTR_UNUSED LPCSTR lpName)
199 return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, NULL);
202HANDLE OpenSemaphoreW(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
203 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCWSTR lpName)
205 WLog_ERR(TAG,
"not implemented");
209HANDLE OpenSemaphoreA(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
210 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCSTR lpName)
212 WLog_ERR(TAG,
"not implemented");
216BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,
217 WINPR_ATTR_UNUSED LPLONG lpPreviousCount)
221 WINPR_SEMAPHORE* semaphore = NULL;
223 if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
226 if (Type == HANDLE_TYPE_SEMAPHORE)
228 semaphore = (WINPR_SEMAPHORE*)Object;
229#ifdef WINPR_PIPE_SEMAPHORE
231 if (semaphore->pipe_fd[0] != -1)
233 while (lReleaseCount > 0)
235 if (write(semaphore->pipe_fd[1],
"-", 1) != 1)
244 while (lReleaseCount > 0)
247 semaphore_signal(*((winpr_sem_t*)semaphore->sem));
249 sem_post((winpr_sem_t*)semaphore->sem);
257 WLog_ERR(TAG,
"called on a handle that is not a semaphore");