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
);