Moved stack switch handling (large stack) to sysdeps.c
[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 "process.h"
13 #include "thread.h"
14 #include "winerror.h"
15 #include "syslevel.h"
16 #include "message.h"
17 #include "server.h"
18
19 /***********************************************************************
20  *              call_apcs
21  *
22  * Call outstanding APCs.
23  */
24 static void call_apcs(void)
25 {
26 #define MAX_APCS 16
27     int i;
28     void *buffer[MAX_APCS * 2];
29     struct get_apcs_request *req = get_req_buffer();
30
31     if (server_call( REQ_GET_APCS ) || !req->count) return;
32     assert( req->count <= MAX_APCS );
33     memcpy( buffer, req->apcs, req->count * 2 * sizeof(req->apcs[0]) );
34     for (i = 0; i < req->count * 2; i += 2)
35     {
36         PAPCFUNC func = (PAPCFUNC)req->apcs[i];
37         if (func) func( (ULONG_PTR)req->apcs[i+1] );
38     }
39 }
40
41 /***********************************************************************
42  *              Sleep  (KERNEL32.679)
43  */
44 VOID WINAPI Sleep( DWORD timeout )
45 {
46     WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
47 }
48
49 /******************************************************************************
50  *              SleepEx   (KERNEL32.680)
51  */
52 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
53 {
54     DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
55     if (ret != WAIT_IO_COMPLETION) ret = 0;
56     return ret;
57 }
58
59
60 /***********************************************************************
61  *           WaitForSingleObject   (KERNEL32.723)
62  */
63 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
64 {
65     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
66 }
67
68
69 /***********************************************************************
70  *           WaitForSingleObjectEx   (KERNEL32.724)
71  */
72 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
73                                     BOOL alertable )
74 {
75     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
76 }
77
78
79 /***********************************************************************
80  *           WaitForMultipleObjects   (KERNEL32.721)
81  */
82 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
83                                      BOOL wait_all, DWORD timeout )
84 {
85     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
86 }
87
88
89 /***********************************************************************
90  *           WaitForMultipleObjectsEx   (KERNEL32.722)
91  */
92 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
93                                        BOOL wait_all, DWORD timeout,
94                                        BOOL alertable )
95 {
96     struct select_request *req = get_req_buffer();
97     int i, ret;
98
99     if (count > MAXIMUM_WAIT_OBJECTS)
100     {
101         SetLastError( ERROR_INVALID_PARAMETER );
102         return WAIT_FAILED;
103     }
104
105     req->count   = count;
106     req->flags   = 0;
107     req->timeout = timeout;
108     for (i = 0; i < count; i++) req->handles[i] = handles[i];
109
110     if (wait_all) req->flags |= SELECT_ALL;
111     if (alertable) req->flags |= SELECT_ALERTABLE;
112     if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
113
114     server_call( REQ_SELECT );
115     if ((ret = req->signaled) == STATUS_USER_APC) call_apcs();
116     return ret;
117 }
118
119
120 /***********************************************************************
121  *           WIN16_WaitForSingleObject   (KERNEL.460)
122  */
123 DWORD WINAPI WIN16_WaitForSingleObject( HANDLE handle, DWORD timeout )
124 {
125     DWORD retval;
126
127     SYSLEVEL_ReleaseWin16Lock();
128     retval = WaitForSingleObject( handle, timeout );
129     SYSLEVEL_RestoreWin16Lock();
130
131     return retval;
132 }
133
134 /***********************************************************************
135  *           WIN16_WaitForMultipleObjects   (KERNEL.461)
136  */
137 DWORD WINAPI WIN16_WaitForMultipleObjects( DWORD count, const HANDLE *handles,
138                                            BOOL wait_all, DWORD timeout )
139 {
140     DWORD retval;
141
142     SYSLEVEL_ReleaseWin16Lock();
143     retval = WaitForMultipleObjects( count, handles, wait_all, timeout );
144     SYSLEVEL_RestoreWin16Lock();
145
146     return retval;
147 }
148
149 /***********************************************************************
150  *           WIN16_WaitForMultipleObjectsEx   (KERNEL.495)
151  */
152 DWORD WINAPI WIN16_WaitForMultipleObjectsEx( DWORD count, 
153                                              const HANDLE *handles,
154                                              BOOL wait_all, DWORD timeout,
155                                              BOOL alertable )
156 {
157     DWORD retval;
158
159     SYSLEVEL_ReleaseWin16Lock();
160     retval = WaitForMultipleObjectsEx( count, handles, 
161                                        wait_all, timeout, alertable );
162     SYSLEVEL_RestoreWin16Lock();
163
164     return retval;
165 }
166