Merge branch 'master' of https://github.com/C-o-r-E/FreeRDP
[platform/upstream/freerdp.git] / winpr / libwinpr / synch / wait.c
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
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include <winpr/crt.h>
29 #include <winpr/synch.h>
30
31 #include "synch.h"
32 #include "../thread/thread.h"
33 #include <winpr/thread.h>
34
35 /**
36  * WaitForSingleObject
37  * WaitForSingleObjectEx
38  * WaitForMultipleObjectsEx
39  * SignalObjectAndWait
40  */
41
42 #ifndef _WIN32
43
44 #include "../handle/handle.h"
45
46 DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
47 {
48         ULONG Type;
49         PVOID Object;
50
51         if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
52                 return WAIT_FAILED;
53
54         if (Type == HANDLE_TYPE_THREAD)
55         {
56                 int status;
57                 WINPR_THREAD* thread;
58                 void* thread_status = NULL;
59
60                 if (dwMilliseconds != INFINITE)
61                         fprintf(stderr, "WaitForSingleObject: timeout not implemented for thread wait\n");
62
63                 thread = (WINPR_THREAD*) Object;
64
65                 status = pthread_join(thread->thread, &thread_status);
66
67                 if (status != 0)
68                         fprintf(stderr, "WaitForSingleObject: pthread_join failure: %d\n", status);
69
70                 if (thread_status)
71                         thread->dwExitCode = ((DWORD) (size_t) thread_status);
72         }
73         else if (Type == HANDLE_TYPE_MUTEX)
74         {
75                 WINPR_MUTEX* mutex;
76
77                 mutex = (WINPR_MUTEX*) Object;
78
79                 if (dwMilliseconds != INFINITE)
80                         fprintf(stderr, "WaitForSingleObject: timeout not implemented for mutex wait\n");
81
82                 pthread_mutex_lock(&mutex->mutex);
83         }
84         else if (Type == HANDLE_TYPE_EVENT)
85         {
86                 int status;
87                 fd_set rfds;
88                 WINPR_EVENT* event;
89                 struct timeval timeout;
90
91                 event = (WINPR_EVENT*) Object;
92
93                 FD_ZERO(&rfds);
94                 FD_SET(event->pipe_fd[0], &rfds);
95                 ZeroMemory(&timeout, sizeof(timeout));
96
97                 if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
98                 {
99                         timeout.tv_usec = dwMilliseconds * 1000;
100                 }
101
102                 status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
103                                 (dwMilliseconds == INFINITE) ? NULL : &timeout);
104
105                 if (status < 0)
106                         return WAIT_FAILED;
107
108                 if (status != 1)
109                         return WAIT_TIMEOUT;
110         }
111         else if (Type == HANDLE_TYPE_SEMAPHORE)
112         {
113                 WINPR_SEMAPHORE* semaphore;
114
115                 semaphore = (WINPR_SEMAPHORE*) Object;
116
117 #ifdef WINPR_PIPE_SEMAPHORE
118                 if (semaphore->pipe_fd[0] != -1)
119                 {
120                         int status;
121                         int length;
122                         fd_set rfds;
123                         struct timeval timeout;
124
125                         FD_ZERO(&rfds);
126                         FD_SET(semaphore->pipe_fd[0], &rfds);
127                         ZeroMemory(&timeout, sizeof(timeout));
128
129                         if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
130                         {
131                                 timeout.tv_usec = dwMilliseconds * 1000;
132                         }
133
134                         status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
135                                         (dwMilliseconds == INFINITE) ? NULL : &timeout);
136
137                         if (status < 0)
138                                 return WAIT_FAILED;
139
140                         if (status != 1)
141                                 return WAIT_TIMEOUT;
142
143                         length = read(semaphore->pipe_fd[0], &length, 1);
144
145                         if (length != 1)
146                                 return FALSE;
147                 }
148 #else
149
150 #if defined __APPLE__
151                 semaphore_wait(*((winpr_sem_t*) semaphore->sem));
152 #else
153                 sem_wait((winpr_sem_t*) semaphore->sem);
154 #endif
155
156 #endif
157         }
158         else
159         {
160                 fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type);
161         }
162
163         return WAIT_OBJECT_0;
164 }
165
166 DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
167 {
168         return WAIT_OBJECT_0;
169 }
170
171 DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
172 {
173         int fd = -1;
174         int maxfd;
175         int index;
176         int status;
177         fd_set fds;
178         ULONG Type;
179         PVOID Object;
180         struct timeval timeout;
181
182         if (!nCount)
183                 return WAIT_FAILED;
184         maxfd = 0;
185         FD_ZERO(&fds);
186         ZeroMemory(&timeout, sizeof(timeout));
187
188         if (bWaitAll)
189                 fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n");
190
191         for (index = 0; index < nCount; index++)
192         {
193                 if (!winpr_Handle_GetInfo(lpHandles[index], &Type, &Object))
194                         return WAIT_FAILED;
195
196                 if (Type == HANDLE_TYPE_EVENT)
197                 {
198                         fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
199                 }
200                 else if (Type == HANDLE_TYPE_SEMAPHORE)
201                 {
202 #ifdef WINPR_PIPE_SEMAPHORE
203                         fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
204 #else
205                         return WAIT_FAILED;
206 #endif
207                 }
208                 else
209                 {
210                         return WAIT_FAILED;
211                 }
212
213                 FD_SET(fd, &fds);
214
215                 if (fd > maxfd)
216                         maxfd = fd;
217         }
218
219         if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
220         {
221                 timeout.tv_usec = dwMilliseconds * 1000;
222         }
223
224         status = select(maxfd + 1, &fds, 0, 0,
225                         (dwMilliseconds == INFINITE) ? NULL : &timeout);
226
227         if (status < 0)
228                 return WAIT_FAILED;
229
230         if (status == 0)
231                 return WAIT_TIMEOUT;
232
233         for (index = 0; index < nCount; index++)
234         {
235                 winpr_Handle_GetInfo(lpHandles[index], &Type, &Object);
236
237                 if (Type == HANDLE_TYPE_EVENT)
238                         fd = ((WINPR_EVENT*) Object)->pipe_fd[0];
239                 else if (Type == HANDLE_TYPE_SEMAPHORE)
240                         fd = ((WINPR_SEMAPHORE*) Object)->pipe_fd[0];
241
242                 if (FD_ISSET(fd, &fds))
243                 {
244                         if (Type == HANDLE_TYPE_SEMAPHORE)
245                         {
246                                 int length = read(fd, &length, 1);
247
248                                 if (length != 1)
249                                         return WAIT_FAILED;
250                         }
251
252                         return (WAIT_OBJECT_0 + index);
253                 }
254         }
255
256         return WAIT_FAILED;
257 }
258
259 DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
260 {
261         return 0;
262 }
263
264 DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
265 {
266         return 0;
267 }
268
269 #endif