2 * WinPR: Windows Portable Runtime
3 * Synchronization Functions
5 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
34 #include "../thread/thread.h"
35 #include <winpr/thread.h>
39 * WaitForSingleObjectEx
40 * WaitForMultipleObjectsEx
46 #include "../handle/handle.h"
48 static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
50 ts->tv_sec += dwMilliseconds / 1000L;
51 ts->tv_nsec += (dwMilliseconds % 1000L) * 1000000L;
53 while(ts->tv_nsec >= 1000000000L)
56 ts->tv_nsec -= 1000000000L;
60 DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
65 if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
68 if (Type == HANDLE_TYPE_THREAD)
72 void* thread_status = NULL;
74 thread = (WINPR_THREAD*) Object;
78 if (dwMilliseconds != INFINITE)
80 #if HAVE_PTHREAD_GNU_EXT
81 struct timespec timeout;
83 clock_gettime(CLOCK_REALTIME, &timeout);
84 ts_add_ms(&timeout, dwMilliseconds);
86 status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);
88 fprintf(stderr, "[ERROR] %s: Thread timeouts not implemented.\n", __func__);
93 status = pthread_join(thread->thread, &thread_status);
96 fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n",
97 status, strerror(status));
100 thread->dwExitCode = ((DWORD) (size_t) thread_status);
103 else if (Type == HANDLE_TYPE_MUTEX)
107 mutex = (WINPR_MUTEX*) Object;
109 #if HAVE_PTHREAD_GNU_EXT
110 if (dwMilliseconds != INFINITE)
112 struct timespec timeout;
114 clock_gettime(CLOCK_REALTIME, &timeout);
115 ts_add_ms(&timeout, dwMilliseconds);
117 pthread_mutex_timedlock(&mutex->mutex, &timeout);
122 pthread_mutex_lock(&mutex->mutex);
125 else if (Type == HANDLE_TYPE_EVENT)
130 struct timeval timeout;
132 event = (WINPR_EVENT*) Object;
135 FD_SET(event->pipe_fd[0], &rfds);
136 ZeroMemory(&timeout, sizeof(timeout));
138 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
140 timeout.tv_usec = dwMilliseconds * 1000;
143 status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
144 (dwMilliseconds == INFINITE) ? NULL : &timeout);
152 else if (Type == HANDLE_TYPE_SEMAPHORE)
154 WINPR_SEMAPHORE* semaphore;
156 semaphore = (WINPR_SEMAPHORE*) Object;
158 #ifdef WINPR_PIPE_SEMAPHORE
159 if (semaphore->pipe_fd[0] != -1)
164 struct timeval timeout;
167 FD_SET(semaphore->pipe_fd[0], &rfds);
168 ZeroMemory(&timeout, sizeof(timeout));
170 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
172 timeout.tv_usec = dwMilliseconds * 1000;
175 status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
176 (dwMilliseconds == INFINITE) ? NULL : &timeout);
184 length = read(semaphore->pipe_fd[0], &length, 1);
191 #if defined __APPLE__
192 semaphore_wait(*((winpr_sem_t*) semaphore->sem));
194 sem_wait((winpr_sem_t*) semaphore->sem);
199 else if (Type == HANDLE_TYPE_TIMER)
203 timer = (WINPR_TIMER*) Object;
205 #ifdef HAVE_EVENTFD_H
211 struct timeval timeout;
214 FD_SET(timer->fd, &rfds);
215 ZeroMemory(&timeout, sizeof(timeout));
217 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
219 timeout.tv_usec = dwMilliseconds * 1000;
222 status = select(timer->fd + 1, &rfds, 0, 0,
223 (dwMilliseconds == INFINITE) ? NULL : &timeout);
231 status = read(timer->fd, (void*) &expirations, sizeof(UINT64));
246 fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type);
249 return WAIT_OBJECT_0;
252 DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
254 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);
256 return WAIT_OBJECT_0;
259 DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
268 struct timeval timeout;
275 ZeroMemory(&timeout, sizeof(timeout));
279 fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n");
283 for (index = 0; index < nCount; index++)
285 if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object))
288 if (Type == HANDLE_TYPE_EVENT)
290 fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
292 else if (Type == HANDLE_TYPE_SEMAPHORE)
294 #ifdef WINPR_PIPE_SEMAPHORE
295 fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
300 else if (Type == HANDLE_TYPE_TIMER)
302 WINPR_TIMER* timer = (WINPR_TIMER*) Object;
319 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
321 timeout.tv_usec = dwMilliseconds * 1000;
324 status = select(maxfd + 1, &fds, 0, 0,
325 (dwMilliseconds == INFINITE) ? NULL : &timeout);
333 for (index = 0; index < nCount; index++)
335 winpr_Handle_GetInfo(lpHandles[index], &Type, &Object);
337 if (Type == HANDLE_TYPE_EVENT)
339 fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
341 else if (Type == HANDLE_TYPE_SEMAPHORE)
343 fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
345 else if (Type == HANDLE_TYPE_TIMER)
347 WINPR_TIMER* timer = (WINPR_TIMER*) Object;
351 if (FD_ISSET(fd, &fds))
353 if (Type == HANDLE_TYPE_SEMAPHORE)
357 length = read(fd, &length, 1);
362 else if (Type == HANDLE_TYPE_TIMER)
367 length = read(fd, (void*) &expirations, sizeof(UINT64));
373 return (WAIT_OBJECT_0 + index);
380 DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
382 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);
387 DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
389 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);