Added new functions (from Win98)
[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 "k32obj.h"
12 #include "heap.h"
13 #include "process.h"
14 #include "thread.h"
15 #include "winerror.h"
16 #include "syslevel.h"
17 #include "server.h"
18 #include "debug.h"
19
20 /***********************************************************************
21  *           SYNC_BuildWaitStruct
22  */
23 static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
24                                     BOOL32 wait_all, WAIT_STRUCT *wait )
25 {
26     DWORD i;
27     K32OBJ **ptr;
28
29     SYSTEM_LOCK();
30     wait->count    = count;
31     wait->wait_all = wait_all;
32     for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
33     {
34         TRACE(win32,"handle %i is %08x\n",i,handles[i]);
35         if (!(*ptr = HANDLE_GetObjPtr( PROCESS_Current(), handles[i],
36                                        K32OBJ_UNKNOWN, SYNCHRONIZE,
37                                        &wait->server[i] )))
38         { 
39             ERR(win32, "Bad handle %08x\n", handles[i]); 
40             break; 
41         }
42         if (wait->server[i] == -1)
43             WARN(win32,"No server handle for %08x (type %d)\n",
44                  handles[i], (*ptr)->type );
45     }
46
47     if (i != count)
48     {
49         /* There was an error */
50         while (i--) K32OBJ_DecCount( wait->objs[i] );
51     }
52     SYSTEM_UNLOCK();
53     return (i == count);
54 }
55
56
57 /***********************************************************************
58  *           SYNC_FreeWaitStruct
59  */
60 static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
61 {
62     DWORD i;
63     K32OBJ **ptr;
64     SYSTEM_LOCK();
65     for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
66         K32OBJ_DecCount( *ptr );
67     SYSTEM_UNLOCK();
68 }
69
70 /***********************************************************************
71  *              Sleep  (KERNEL32.679)
72  */
73 VOID WINAPI Sleep( DWORD timeout )
74 {
75     WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
76 }
77
78 /******************************************************************************
79  *              SleepEx   (KERNEL32.680)
80  */
81 DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
82 {
83     DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
84     if (ret != WAIT_IO_COMPLETION) ret = 0;
85     return ret;
86 }
87
88
89 /***********************************************************************
90  *           WaitForSingleObject   (KERNEL32.723)
91  */
92 DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
93 {
94     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
95 }
96
97
98 /***********************************************************************
99  *           WaitForSingleObjectEx   (KERNEL32.724)
100  */
101 DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
102                                     BOOL32 alertable )
103 {
104     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
105 }
106
107
108 /***********************************************************************
109  *           WaitForMultipleObjects   (KERNEL32.721)
110  */
111 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
112                                      BOOL32 wait_all, DWORD timeout )
113 {
114     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
115 }
116
117
118 /***********************************************************************
119  *           WaitForMultipleObjectsEx   (KERNEL32.722)
120  */
121 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE32 *handles,
122                                        BOOL32 wait_all, DWORD timeout,
123                                        BOOL32 alertable )
124 {
125     WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
126     struct select_request req;
127     struct select_reply reply;
128     void *apc[32];
129     int len;
130
131     if (count > MAXIMUM_WAIT_OBJECTS)
132     {
133         SetLastError( ERROR_INVALID_PARAMETER );
134         return WAIT_FAILED;
135     }
136
137     if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
138         return WAIT_FAILED;
139
140     req.count   = count;
141     req.flags   = 0;
142     req.timeout = timeout;
143
144     if (wait_all) req.flags |= SELECT_ALL;
145     if (alertable) req.flags |= SELECT_ALERTABLE;
146     if (timeout != INFINITE32) req.flags |= SELECT_TIMEOUT;
147
148     CLIENT_SendRequest( REQ_SELECT, -1, 2,
149                         &req, sizeof(req),
150                         wait->server, count * sizeof(int) );
151     CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply),
152                       apc, sizeof(apc) );
153     if ((reply.signaled == STATUS_USER_APC) && (len > sizeof(reply)))
154     {
155         int i;
156         len -= sizeof(reply);
157         for (i = 0; i < len / sizeof(void*); i += 2)
158         {
159             PAPCFUNC func = (PAPCFUNC)apc[i];
160             func( (ULONG_PTR)apc[i+1] );
161         }
162     }
163     SYNC_FreeWaitStruct( wait );
164     return reply.signaled;
165 }
166
167
168 /***********************************************************************
169  *           WIN16_WaitForSingleObject   (KERNEL.460)
170  */
171 DWORD WINAPI WIN16_WaitForSingleObject( HANDLE32 handle, DWORD timeout )
172 {
173     DWORD retval;
174
175     SYSLEVEL_ReleaseWin16Lock();
176     retval = WaitForSingleObject( handle, timeout );
177     SYSLEVEL_RestoreWin16Lock();
178
179     return retval;
180 }
181
182 /***********************************************************************
183  *           WIN16_WaitForMultipleObjects   (KERNEL.461)
184  */
185 DWORD WINAPI WIN16_WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
186                                            BOOL32 wait_all, DWORD timeout )
187 {
188     DWORD retval;
189
190     SYSLEVEL_ReleaseWin16Lock();
191     retval = WaitForMultipleObjects( count, handles, wait_all, timeout );
192     SYSLEVEL_RestoreWin16Lock();
193
194     return retval;
195 }
196
197 /***********************************************************************
198  *           WIN16_WaitForMultipleObjectsEx   (KERNEL.495)
199  */
200 DWORD WINAPI WIN16_WaitForMultipleObjectsEx( DWORD count, 
201                                              const HANDLE32 *handles,
202                                              BOOL32 wait_all, DWORD timeout,
203                                              BOOL32 alertable )
204 {
205     DWORD retval;
206
207     SYSLEVEL_ReleaseWin16Lock();
208     retval = WaitForMultipleObjectsEx( count, handles, 
209                                        wait_all, timeout, alertable );
210     SYSLEVEL_RestoreWin16Lock();
211
212     return retval;
213 }
214