Added a first-cut version of MapVirtualKeyExW() that has the same
[wine] / scheduler / synchro.c
1 /*
2  * Win32 process and thread synchronisation
3  *
4  * Copyright 1997 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <signal.h>
9 #include <sys/time.h>
10 #include <unistd.h>
11 #include "heap.h"
12 #include "file.h"  /* for DOSFS_UnixTimeToFileTime */
13 #include "thread.h"
14 #include "winerror.h"
15 #include "server.h"
16
17
18 /***********************************************************************
19  *              call_apcs
20  *
21  * Call outstanding APCs.
22  */
23 static void call_apcs(void)
24 {
25     FARPROC proc = NULL;
26     FILETIME ft;
27     void *args[4];
28
29     for (;;)
30     {
31         int type = APC_NONE;
32         SERVER_START_REQ
33         {
34             struct get_apc_request *req = server_alloc_req( sizeof(*req), sizeof(args) );
35             if (!server_call( REQ_GET_APC ))
36             {
37                 type = req->type;
38                 proc = req->func;
39                 memcpy( args, server_data_ptr(req), server_data_size(req) );
40             }
41         }
42         SERVER_END_REQ;
43
44         switch(type)
45         {
46         case APC_NONE:
47             return;  /* no more APCs */
48         case APC_ASYNC:
49             proc( &args[0] );
50             break;
51         case APC_USER:
52             proc( args[0] );
53             break;
54         case APC_TIMER:
55             /* convert sec/usec to NT time */
56             DOSFS_UnixTimeToFileTime( (time_t)args[0], &ft, (DWORD)args[1] * 10 );
57             proc( args[2], ft.dwLowDateTime, ft.dwHighDateTime );
58             break;
59         default:
60             server_protocol_error( "get_apc_request: bad type %d\n", type );
61             break;
62         }
63     }
64 }
65
66 /***********************************************************************
67  *              Sleep  (KERNEL32.679)
68  */
69 VOID WINAPI Sleep( DWORD timeout )
70 {
71     WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
72 }
73
74 /******************************************************************************
75  *              SleepEx   (KERNEL32.680)
76  */
77 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
78 {
79     DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
80     if (ret != WAIT_IO_COMPLETION) ret = 0;
81     return ret;
82 }
83
84
85 /***********************************************************************
86  *           WaitForSingleObject   (KERNEL32.723)
87  */
88 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
89 {
90     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
91 }
92
93
94 /***********************************************************************
95  *           WaitForSingleObjectEx   (KERNEL32.724)
96  */
97 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
98                                     BOOL alertable )
99 {
100     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
101 }
102
103
104 /***********************************************************************
105  *           WaitForMultipleObjects   (KERNEL32.721)
106  */
107 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
108                                      BOOL wait_all, DWORD timeout )
109 {
110     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
111 }
112
113
114 /***********************************************************************
115  *           WaitForMultipleObjectsEx   (KERNEL32.722)
116  */
117 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
118                                        BOOL wait_all, DWORD timeout,
119                                        BOOL alertable )
120 {
121     int i, ret;
122
123     if (count > MAXIMUM_WAIT_OBJECTS)
124     {
125         SetLastError( ERROR_INVALID_PARAMETER );
126         return WAIT_FAILED;
127     }
128
129     SERVER_START_REQ
130     {
131         struct select_request *req = server_alloc_req( sizeof(*req), count * sizeof(int) );
132         int *data = server_data_ptr( req );
133
134         req->flags   = 0;
135         req->timeout = timeout;
136         for (i = 0; i < count; i++) data[i] = handles[i];
137
138         if (wait_all) req->flags |= SELECT_ALL;
139         if (alertable) req->flags |= SELECT_ALERTABLE;
140         if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
141
142         server_call( REQ_SELECT );
143         ret = req->signaled;
144     }
145     SERVER_END_REQ;
146     if (ret == STATUS_USER_APC) call_apcs();
147     return ret;
148 }
149
150
151 /***********************************************************************
152  *           WIN16_WaitForSingleObject   (KERNEL.460)
153  */
154 DWORD WINAPI WIN16_WaitForSingleObject( HANDLE handle, DWORD timeout )
155 {
156     DWORD retval, mutex_count;
157
158     ReleaseThunkLock( &mutex_count );
159     retval = WaitForSingleObject( handle, timeout );
160     RestoreThunkLock( mutex_count );
161     return retval;
162 }
163
164 /***********************************************************************
165  *           WIN16_WaitForMultipleObjects   (KERNEL.461)
166  */
167 DWORD WINAPI WIN16_WaitForMultipleObjects( DWORD count, const HANDLE *handles,
168                                            BOOL wait_all, DWORD timeout )
169 {
170     DWORD retval, mutex_count;
171
172     ReleaseThunkLock( &mutex_count );
173     retval = WaitForMultipleObjects( count, handles, wait_all, timeout );
174     RestoreThunkLock( mutex_count );
175     return retval;
176 }
177
178 /***********************************************************************
179  *           WIN16_WaitForMultipleObjectsEx   (KERNEL.495)
180  */
181 DWORD WINAPI WIN16_WaitForMultipleObjectsEx( DWORD count, 
182                                              const HANDLE *handles,
183                                              BOOL wait_all, DWORD timeout,
184                                              BOOL alertable )
185 {
186     DWORD retval, mutex_count;
187
188     ReleaseThunkLock( &mutex_count );
189     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
190     RestoreThunkLock( mutex_count );
191     return retval;
192 }
193