2 * Win32 process and thread synchronisation
4 * Copyright 1997 Alexandre Julliard
13 #include "file.h" /* for DOSFS_UnixTimeToFileTime */
19 /***********************************************************************
22 inline static void get_timeout( struct timeval *when, int timeout )
24 gettimeofday( when, 0 );
27 long sec = timeout / 1000;
28 if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000)
30 when->tv_usec -= 1000000;
38 /***********************************************************************
41 * Wait for a reply on the waiting pipe of the current thread.
43 static int wait_reply(void)
48 int ret = read( NtCurrentTeb()->wait_fd, &signaled, sizeof(signaled) );
49 if (ret == sizeof(signaled)) return signaled;
51 if (ret > 0) server_protocol_error( "partial wakeup read %d\n", ret );
52 if (errno == EINTR) continue;
53 if (errno == EPIPE) break;
54 server_protocol_perror("read");
56 /* the server closed the connection; time to die... */
57 SYSDEPS_ExitThread(0);
61 /***********************************************************************
64 * Call outstanding APCs.
66 static void call_apcs( BOOL alertable )
75 SERVER_START_VAR_REQ( get_apc, sizeof(args) )
77 req->alertable = alertable;
82 memcpy( args, server_data_ptr(req), server_data_size(req) );
90 return; /* no more APCs */
98 /* convert sec/usec to NT time */
99 DOSFS_UnixTimeToFileTime( (time_t)args[0], &ft, (DWORD)args[1] * 10 );
100 proc( args[2], ft.dwLowDateTime, ft.dwHighDateTime );
103 server_protocol_error( "get_apc_request: bad type %d\n", type );
109 /***********************************************************************
110 * Sleep (KERNEL32.679)
112 VOID WINAPI Sleep( DWORD timeout )
114 WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
117 /******************************************************************************
118 * SleepEx (KERNEL32.680)
120 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
122 DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
123 if (ret != WAIT_IO_COMPLETION) ret = 0;
128 /***********************************************************************
129 * WaitForSingleObject (KERNEL32.723)
131 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
133 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
137 /***********************************************************************
138 * WaitForSingleObjectEx (KERNEL32.724)
140 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
143 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
147 /***********************************************************************
148 * WaitForMultipleObjects (KERNEL32.721)
150 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
151 BOOL wait_all, DWORD timeout )
153 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
157 /***********************************************************************
158 * WaitForMultipleObjectsEx (KERNEL32.722)
160 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
161 BOOL wait_all, DWORD timeout,
167 if (count > MAXIMUM_WAIT_OBJECTS)
169 SetLastError( ERROR_INVALID_PARAMETER );
173 if (timeout == INFINITE) tv.tv_sec = tv.tv_usec = 0;
174 else get_timeout( &tv, timeout );
178 SERVER_START_VAR_REQ( select, count * sizeof(int) )
180 int *data = server_data_ptr( req );
182 req->flags = SELECT_INTERRUPTIBLE;
183 req->sec = tv.tv_sec;
184 req->usec = tv.tv_usec;
185 for (i = 0; i < count; i++) data[i] = handles[i];
187 if (wait_all) req->flags |= SELECT_ALL;
188 if (alertable) req->flags |= SELECT_ALERTABLE;
189 if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
194 if (ret == STATUS_PENDING) ret = wait_reply();
195 if (ret != STATUS_USER_APC) break;
196 call_apcs( alertable );
197 if (alertable) break;
199 if (HIWORD(ret)) /* is it an error code? */
201 SetLastError( RtlNtStatusToDosError(ret) );
208 /***********************************************************************
209 * WaitForSingleObject16 (KERNEL.460)
211 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
213 DWORD retval, mutex_count;
215 ReleaseThunkLock( &mutex_count );
216 retval = WaitForSingleObject( handle, timeout );
217 RestoreThunkLock( mutex_count );
221 /***********************************************************************
222 * WaitForMultipleObjects16 (KERNEL.461)
224 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
225 BOOL wait_all, DWORD timeout )
227 DWORD retval, mutex_count;
229 ReleaseThunkLock( &mutex_count );
230 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
231 RestoreThunkLock( mutex_count );
235 /***********************************************************************
236 * WaitForMultipleObjectsEx16 (KERNEL.495)
238 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
239 BOOL wait_all, DWORD timeout, BOOL alertable )
241 DWORD retval, mutex_count;
243 ReleaseThunkLock( &mutex_count );
244 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
245 RestoreThunkLock( mutex_count );