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)
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\n", status);
99 thread->dwExitCode = ((DWORD) (size_t) thread_status);
102 else if (Type == HANDLE_TYPE_MUTEX)
106 mutex = (WINPR_MUTEX*) Object;
109 if (dwMilliseconds != INFINITE)
111 struct timespec timeout;
113 clock_gettime(CLOCK_REALTIME, &timeout);
114 ts_add_ms(&timeout, dwMilliseconds);
116 pthread_mutex_timedlock(&mutex->mutex, &timeout);
121 pthread_mutex_lock(&mutex->mutex);
124 else if (Type == HANDLE_TYPE_EVENT)
129 struct timeval timeout;
131 event = (WINPR_EVENT*) Object;
134 FD_SET(event->pipe_fd[0], &rfds);
135 ZeroMemory(&timeout, sizeof(timeout));
137 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
139 timeout.tv_usec = dwMilliseconds * 1000;
142 status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
143 (dwMilliseconds == INFINITE) ? NULL : &timeout);
151 else if (Type == HANDLE_TYPE_SEMAPHORE)
153 WINPR_SEMAPHORE* semaphore;
155 semaphore = (WINPR_SEMAPHORE*) Object;
157 #ifdef WINPR_PIPE_SEMAPHORE
158 if (semaphore->pipe_fd[0] != -1)
163 struct timeval timeout;
166 FD_SET(semaphore->pipe_fd[0], &rfds);
167 ZeroMemory(&timeout, sizeof(timeout));
169 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
171 timeout.tv_usec = dwMilliseconds * 1000;
174 status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
175 (dwMilliseconds == INFINITE) ? NULL : &timeout);
183 length = read(semaphore->pipe_fd[0], &length, 1);
190 #if defined __APPLE__
191 semaphore_wait(*((winpr_sem_t*) semaphore->sem));
193 sem_wait((winpr_sem_t*) semaphore->sem);
198 else if (Type == HANDLE_TYPE_TIMER)
202 timer = (WINPR_TIMER*) Object;
204 #ifdef HAVE_EVENTFD_H
210 struct timeval timeout;
213 FD_SET(timer->fd, &rfds);
214 ZeroMemory(&timeout, sizeof(timeout));
216 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
218 timeout.tv_usec = dwMilliseconds * 1000;
221 status = select(timer->fd + 1, &rfds, 0, 0,
222 (dwMilliseconds == INFINITE) ? NULL : &timeout);
230 status = read(timer->fd, (void*) &expirations, sizeof(UINT64));
245 fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type);
248 return WAIT_OBJECT_0;
251 DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
253 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);
255 return WAIT_OBJECT_0;
258 DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
267 struct timeval timeout;
274 ZeroMemory(&timeout, sizeof(timeout));
278 fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n");
282 for (index = 0; index < nCount; index++)
284 if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object))
287 if (Type == HANDLE_TYPE_EVENT)
289 fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
291 else if (Type == HANDLE_TYPE_SEMAPHORE)
293 #ifdef WINPR_PIPE_SEMAPHORE
294 fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
299 else if (Type == HANDLE_TYPE_TIMER)
301 WINPR_TIMER* timer = (WINPR_TIMER*) Object;
318 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
320 timeout.tv_usec = dwMilliseconds * 1000;
323 status = select(maxfd + 1, &fds, 0, 0,
324 (dwMilliseconds == INFINITE) ? NULL : &timeout);
332 for (index = 0; index < nCount; index++)
334 winpr_Handle_GetInfo(lpHandles[index], &Type, &Object);
336 if (Type == HANDLE_TYPE_EVENT)
338 fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
340 else if (Type == HANDLE_TYPE_SEMAPHORE)
342 fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
344 else if (Type == HANDLE_TYPE_TIMER)
346 WINPR_TIMER* timer = (WINPR_TIMER*) Object;
350 if (FD_ISSET(fd, &fds))
352 if (Type == HANDLE_TYPE_SEMAPHORE)
356 length = read(fd, &length, 1);
361 else if (Type == HANDLE_TYPE_TIMER)
366 length = read(fd, (void*) &expirations, sizeof(UINT64));
372 return (WAIT_OBJECT_0 + index);
379 DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
381 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);
386 DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
388 fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__);