semaphore.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * Synchronization Functions
  4. *
  5. * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include <winpr/synch.h>
  23. #include "synch.h"
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifndef _WIN32
  28. #include <errno.h>
  29. #include "../handle/handle.h"
  30. #include "../log.h"
  31. #define TAG WINPR_TAG("synch.semaphore")
  32. static BOOL SemaphoreCloseHandle(HANDLE handle);
  33. static BOOL SemaphoreIsHandled(HANDLE handle)
  34. {
  35. WINPR_TIMER* pSemaphore = (WINPR_TIMER*)handle;
  36. if (!pSemaphore || (pSemaphore->Type != HANDLE_TYPE_SEMAPHORE))
  37. {
  38. SetLastError(ERROR_INVALID_HANDLE);
  39. return FALSE;
  40. }
  41. return TRUE;
  42. }
  43. static int SemaphoreGetFd(HANDLE handle)
  44. {
  45. WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
  46. if (!SemaphoreIsHandled(handle))
  47. return -1;
  48. return sem->pipe_fd[0];
  49. }
  50. static DWORD SemaphoreCleanupHandle(HANDLE handle)
  51. {
  52. int length;
  53. WINPR_SEMAPHORE* sem = (WINPR_SEMAPHORE*)handle;
  54. if (!SemaphoreIsHandled(handle))
  55. return WAIT_FAILED;
  56. do
  57. {
  58. length = read(sem->pipe_fd[0], &length, 1);
  59. } while (length < 0 && errno == EINTR);
  60. if (length != 1)
  61. {
  62. WLog_ERR(TAG, "semaphore read() failure [%d] %s", errno, strerror(errno));
  63. return WAIT_FAILED;
  64. }
  65. return WAIT_OBJECT_0;
  66. }
  67. BOOL SemaphoreCloseHandle(HANDLE handle)
  68. {
  69. WINPR_SEMAPHORE* semaphore = (WINPR_SEMAPHORE*)handle;
  70. if (!SemaphoreIsHandled(handle))
  71. return FALSE;
  72. #ifdef WINPR_PIPE_SEMAPHORE
  73. if (semaphore->pipe_fd[0] != -1)
  74. {
  75. close(semaphore->pipe_fd[0]);
  76. semaphore->pipe_fd[0] = -1;
  77. if (semaphore->pipe_fd[1] != -1)
  78. {
  79. close(semaphore->pipe_fd[1]);
  80. semaphore->pipe_fd[1] = -1;
  81. }
  82. }
  83. #else
  84. #if defined __APPLE__
  85. semaphore_destroy(mach_task_self(), *((winpr_sem_t*)semaphore->sem));
  86. #else
  87. sem_destroy((winpr_sem_t*)semaphore->sem);
  88. #endif
  89. #endif
  90. free(semaphore);
  91. return TRUE;
  92. }
  93. static HANDLE_OPS ops = { SemaphoreIsHandled,
  94. SemaphoreCloseHandle,
  95. SemaphoreGetFd,
  96. SemaphoreCleanupHandle,
  97. NULL,
  98. NULL,
  99. NULL,
  100. NULL,
  101. NULL,
  102. NULL,
  103. NULL,
  104. NULL,
  105. NULL,
  106. NULL,
  107. NULL,
  108. NULL,
  109. NULL,
  110. NULL,
  111. NULL,
  112. NULL };
  113. HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
  114. LONG lMaximumCount, LPCWSTR lpName)
  115. {
  116. HANDLE handle;
  117. WINPR_SEMAPHORE* semaphore;
  118. semaphore = (WINPR_SEMAPHORE*)calloc(1, sizeof(WINPR_SEMAPHORE));
  119. if (!semaphore)
  120. return NULL;
  121. semaphore->pipe_fd[0] = -1;
  122. semaphore->pipe_fd[1] = -1;
  123. semaphore->sem = (winpr_sem_t*)NULL;
  124. semaphore->ops = &ops;
  125. #ifdef WINPR_PIPE_SEMAPHORE
  126. if (pipe(semaphore->pipe_fd) < 0)
  127. {
  128. WLog_ERR(TAG, "failed to create semaphore");
  129. free(semaphore);
  130. return NULL;
  131. }
  132. while (lInitialCount > 0)
  133. {
  134. if (write(semaphore->pipe_fd[1], "-", 1) != 1)
  135. {
  136. close(semaphore->pipe_fd[0]);
  137. close(semaphore->pipe_fd[1]);
  138. free(semaphore);
  139. return NULL;
  140. }
  141. lInitialCount--;
  142. }
  143. #else
  144. semaphore->sem = (winpr_sem_t*)malloc(sizeof(winpr_sem_t));
  145. if (!semaphore->sem)
  146. {
  147. WLog_ERR(TAG, "failed to allocate semaphore memory");
  148. free(semaphore);
  149. return NULL;
  150. }
  151. #if defined __APPLE__
  152. if (semaphore_create(mach_task_self(), semaphore->sem, SYNC_POLICY_FIFO, lMaximumCount) !=
  153. KERN_SUCCESS)
  154. #else
  155. if (sem_init(semaphore->sem, 0, lMaximumCount) == -1)
  156. #endif
  157. {
  158. WLog_ERR(TAG, "failed to create semaphore");
  159. free(semaphore->sem);
  160. free(semaphore);
  161. return NULL;
  162. }
  163. #endif
  164. WINPR_HANDLE_SET_TYPE_AND_MODE(semaphore, HANDLE_TYPE_SEMAPHORE, WINPR_FD_READ);
  165. handle = (HANDLE)semaphore;
  166. return handle;
  167. }
  168. HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
  169. LONG lMaximumCount, LPCSTR lpName)
  170. {
  171. return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, NULL);
  172. }
  173. HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
  174. {
  175. WLog_ERR(TAG, "not implemented");
  176. return NULL;
  177. }
  178. HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
  179. {
  180. WLog_ERR(TAG, "not implemented");
  181. return NULL;
  182. }
  183. BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount)
  184. {
  185. ULONG Type;
  186. WINPR_HANDLE* Object;
  187. WINPR_SEMAPHORE* semaphore;
  188. if (!winpr_Handle_GetInfo(hSemaphore, &Type, &Object))
  189. return FALSE;
  190. if (Type == HANDLE_TYPE_SEMAPHORE)
  191. {
  192. semaphore = (WINPR_SEMAPHORE*)Object;
  193. #ifdef WINPR_PIPE_SEMAPHORE
  194. if (semaphore->pipe_fd[0] != -1)
  195. {
  196. while (lReleaseCount > 0)
  197. {
  198. if (write(semaphore->pipe_fd[1], "-", 1) != 1)
  199. return FALSE;
  200. lReleaseCount--;
  201. }
  202. }
  203. #else
  204. while (lReleaseCount > 0)
  205. {
  206. #if defined __APPLE__
  207. semaphore_signal(*((winpr_sem_t*)semaphore->sem));
  208. #else
  209. sem_post((winpr_sem_t*)semaphore->sem);
  210. #endif
  211. }
  212. #endif
  213. return TRUE;
  214. }
  215. WLog_ERR(TAG, "calling %s on a handle that is not a semaphore", __FUNCTION__);
  216. return FALSE;
  217. }
  218. #endif