20#include <winpr/config.h>
21#include <winpr/debug.h>
22#include <winpr/synch.h>
26#ifdef WINPR_HAVE_UNISTD_H
34#include "../handle/handle.h"
36#define TAG WINPR_TAG("synch.semaphore")
38static BOOL SemaphoreCloseHandle(HANDLE handle);
40static BOOL SemaphoreIsHandled(HANDLE handle)
42 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_SEMAPHORE, FALSE);
45static int SemaphoreGetFd(HANDLE handle)
47 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
49 if (!SemaphoreIsHandled(handle))
52 return sem->pipe_fd[0];
55static DWORD SemaphoreCleanupHandle(HANDLE handle)
57 WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
59 if (!SemaphoreIsHandled(handle))
63 const SSIZE_T length = read(sem->pipe_fd[0], &val,
sizeof(val));
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)));
76BOOL SemaphoreCloseHandle(HANDLE handle)
78 WINPR_SEMAPHORE* semaphore = (WINPR_SEMAPHORE*)handle;
80 if (!SemaphoreIsHandled(handle))
83#ifdef WINPR_PIPE_SEMAPHORE
85 if (semaphore->pipe_fd[0] != -1)
87 close(semaphore->pipe_fd[0]);
88 semaphore->pipe_fd[0] = -1;
90 if (semaphore->pipe_fd[1] != -1)
92 close(semaphore->pipe_fd[1]);
93 semaphore->pipe_fd[1] = -1;
99 semaphore_destroy(mach_task_self(), *((winpr_sem_t*)semaphore->sem));
101 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 =
nullptr;
134 WINPR_SEMAPHORE* semaphore =
nullptr;
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*)
nullptr;
143 semaphore->common.ops = &ops;
144#ifdef WINPR_PIPE_SEMAPHORE
146#ifdef WINPR_HAVE_PIPE2
147 if (pipe2(semaphore->pipe_fd, O_CLOEXEC) < 0)
149 if (pipe(semaphore->pipe_fd) < 0)
152 WLog_ERR(TAG,
"failed to create semaphore");
157#ifndef WINPR_HAVE_PIPE2
158 if (!winpr_set_cloexec(semaphore->pipe_fd[0], TRUE) ||
159 !winpr_set_cloexec(semaphore->pipe_fd[1], TRUE))
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]);
169 while (lInitialCount > 0)
171 if (write(semaphore->pipe_fd[1],
"-", 1) != 1)
173 close(semaphore->pipe_fd[0]);
174 close(semaphore->pipe_fd[1]);
183 semaphore->sem = (winpr_sem_t*)malloc(
sizeof(winpr_sem_t));
187 WLog_ERR(TAG,
"failed to allocate semaphore memory");
194 if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) !=
197 if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
200 WLog_ERR(TAG,
"failed to create semaphore");
201 free(semaphore->sem);
207 WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
208 handle = (HANDLE)semaphore;
212HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
213 LONG lMaximumCount, WINPR_ATTR_UNUSED LPCSTR lpName)
215 return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount,
nullptr);
218HANDLE OpenSemaphoreW(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
219 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCWSTR lpName)
221 WLog_ERR(TAG,
"not implemented");
225HANDLE OpenSemaphoreA(WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
226 WINPR_ATTR_UNUSED BOOL bInheritHandle, WINPR_ATTR_UNUSED LPCSTR lpName)
228 WLog_ERR(TAG,
"not implemented");
232BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,
233 WINPR_ATTR_UNUSED LPLONG lpPreviousCount)
237 WINPR_SEMAPHORE* semaphore =
nullptr;
239 if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
242 if (Type == HANDLE_TYPE_SEMAPHORE)
244 semaphore = (WINPR_SEMAPHORE*)Object;
245#ifdef WINPR_PIPE_SEMAPHORE
247 if (semaphore->pipe_fd[0] != -1)
249 while (lReleaseCount > 0)
251 if (write(semaphore->pipe_fd[1],
"-", 1) != 1)
260 while (lReleaseCount > 0)
263 semaphore_signal(*((winpr_sem_t*)semaphore->sem));
265 sem_post((winpr_sem_t*)semaphore->sem);
273 WLog_ERR(TAG,
"called on a handle that is not a semaphore");