2 * Win32 process and thread synchronisation
4 * Copyright 1997 Alexandre Julliard
20 /***********************************************************************
21 * SYNC_BuildWaitStruct
23 static BOOL32
SYNC_BuildWaitStruct( DWORD count
, const HANDLE32
*handles
,
24 BOOL32 wait_all
, BOOL32 wait_msg
,
32 wait
->signaled
= WAIT_FAILED
;
33 wait
->wait_all
= wait_all
;
34 wait
->wait_msg
= wait_msg
;
35 for (i
= 0, ptr
= wait
->objs
; i
< count
; i
++, ptr
++)
37 if (!(*ptr
= HANDLE_GetObjPtr( PROCESS_Current(), handles
[i
],
38 K32OBJ_UNKNOWN
, SYNCHRONIZE
,
41 ERR(win32
, "Bad handle %08x\n", handles
[i
]);
44 if (!K32OBJ_OPS( *ptr
)->signaled
)
46 /* This object type cannot be waited upon */
47 ERR(win32
, "Cannot wait on handle %08x\n", handles
[i
]);
48 K32OBJ_DecCount( *ptr
);
55 /* There was an error */
56 wait
->wait_msg
= FALSE
;
57 while (i
--) K32OBJ_DecCount( wait
->objs
[i
] );
64 /***********************************************************************
67 static void SYNC_FreeWaitStruct( WAIT_STRUCT
*wait
)
72 wait
->wait_msg
= FALSE
;
73 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
74 K32OBJ_DecCount( *ptr
);
79 /***********************************************************************
82 static BOOL32
SYNC_CheckCondition( WAIT_STRUCT
*wait
, DWORD thread_id
)
90 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
92 if (!K32OBJ_OPS( *ptr
)->signaled( *ptr
, thread_id
))
98 /* Wait satisfied: tell it to all objects */
99 wait
->signaled
= WAIT_OBJECT_0
;
100 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
101 if (K32OBJ_OPS( *ptr
)->satisfied( *ptr
, thread_id
))
102 wait
->signaled
= WAIT_ABANDONED_0
;
108 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
110 if (K32OBJ_OPS( *ptr
)->signaled( *ptr
, thread_id
))
112 /* Wait satisfied: tell it to the object */
113 wait
->signaled
= WAIT_OBJECT_0
+ i
;
114 if (K32OBJ_OPS( *ptr
)->satisfied( *ptr
, thread_id
))
115 wait
->signaled
= WAIT_ABANDONED_0
+ i
;
126 /***********************************************************************
127 * SYNC_WaitForCondition
129 void SYNC_WaitForCondition( WAIT_STRUCT
*wait
, DWORD timeout
)
131 DWORD i
, thread_id
= GetCurrentThreadId();
137 if (SYNC_CheckCondition( wait
, thread_id
))
138 goto done
; /* Condition already satisfied */
141 /* No need to wait */
142 wait
->signaled
= WAIT_TIMEOUT
;
146 /* Add ourselves to the waiting list of all objects */
148 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
149 K32OBJ_OPS( *ptr
)->add_wait( *ptr
, thread_id
);
151 /* Release the system lock completely */
153 count
= SYSTEM_LOCK_COUNT();
154 for (i
= count
; i
> 0; i
--) SYSTEM_UNLOCK();
156 /* Now wait for it */
158 TRACE(win32
, "starting wait (%p %04x)\n",
159 THREAD_Current(), THREAD_Current()->teb_sel
);
161 sigprocmask( SIG_SETMASK
, NULL
, &set
);
162 sigdelset( &set
, SIGUSR1
);
163 sigdelset( &set
, SIGALRM
);
164 if (timeout
!= INFINITE32
)
166 while (wait
->signaled
== WAIT_FAILED
)
168 struct itimerval timer
;
169 DWORD start_ticks
, elapsed
;
170 timer
.it_interval
.tv_sec
= timer
.it_interval
.tv_usec
= 0;
171 timer
.it_value
.tv_sec
= timeout
/ 1000;
172 timer
.it_value
.tv_usec
= (timeout
% 1000) * 1000;
173 start_ticks
= GetTickCount();
174 setitimer( ITIMER_REAL
, &timer
, NULL
);
176 if (wait
->signaled
!= WAIT_FAILED
) break;
177 /* Recompute the timer value */
178 elapsed
= GetTickCount() - start_ticks
;
179 if (elapsed
>= timeout
) wait
->signaled
= WAIT_TIMEOUT
;
180 else timeout
-= elapsed
;
185 while (wait
->signaled
== WAIT_FAILED
)
191 /* Grab the system lock again */
193 while (count
--) SYSTEM_LOCK();
194 TRACE(win32
, "wait finished (%p %04x)\n",
195 THREAD_Current(), THREAD_Current()->teb_sel
);
197 /* Remove ourselves from the lists */
199 for (i
= 0, ptr
= wait
->objs
; i
< wait
->count
; i
++, ptr
++)
200 K32OBJ_OPS( *ptr
)->remove_wait( *ptr
, thread_id
);
207 /***********************************************************************
208 * SYNC_DummySigHandler
210 * Dummy signal handler
212 static void SYNC_DummySigHandler(void)
217 /***********************************************************************
220 * Setup signal handlers for a new thread.
221 * FIXME: should merge with SIGNAL_Init.
223 void SYNC_SetupSignals(void)
226 SIGNAL_SetHandler( SIGUSR1
, SYNC_DummySigHandler
, 0 );
227 /* FIXME: conflicts with system timers */
228 SIGNAL_SetHandler( SIGALRM
, SYNC_DummySigHandler
, 0 );
230 /* Make sure these are blocked by default */
231 sigaddset( &set
, SIGUSR1
);
232 sigaddset( &set
, SIGALRM
);
233 sigprocmask( SIG_BLOCK
, &set
, NULL
);
237 /***********************************************************************
240 void SYNC_WakeUp( THREAD_QUEUE
*wait_queue
, DWORD max
)
244 if (!max
) max
= INFINITE32
;
251 entry
= (*wait_queue
)->next
;
254 THDB
*thdb
= entry
->thread
;
255 if (SYNC_CheckCondition( &thdb
->wait_struct
, THDB_TO_THREAD_ID(thdb
) ))
257 TRACE(win32
, "waking up %04x (pid %d)\n", thdb
->teb_sel
, thdb
->unix_pid
);
259 kill( thdb
->unix_pid
, SIGUSR1
);
261 FIXME(win32
,"have got unix_pid 0\n");
264 if (entry
== *wait_queue
) break;
270 /***********************************************************************
273 void SYNC_MsgWakeUp( THDB
*thdb
)
283 if (thdb
->wait_struct
.wait_msg
)
285 thdb
->wait_struct
.signaled
= thdb
->wait_struct
.count
;
287 TRACE(win32
, "waking up %04x for message\n", thdb
->teb_sel
);
289 kill( thdb
->unix_pid
, SIGUSR1
);
291 FIXME(win32
,"have got unix_pid 0\n");
297 /***********************************************************************
300 DWORD
SYNC_DoWait( DWORD count
, const HANDLE32
*handles
,
301 BOOL32 wait_all
, DWORD timeout
,
302 BOOL32 alertable
, BOOL32 wait_msg
)
304 WAIT_STRUCT
*wait
= &THREAD_Current()->wait_struct
;
306 if (count
> MAXIMUM_WAIT_OBJECTS
)
308 SetLastError( ERROR_INVALID_PARAMETER
);
313 FIXME(win32
, "alertable not implemented\n" );
316 if (!SYNC_BuildWaitStruct( count
, handles
, wait_all
, wait_msg
, wait
))
317 wait
->signaled
= WAIT_FAILED
;
321 /* Check if we can use a server wait */
322 for (i
= 0; i
< count
; i
++)
323 if (wait
->server
[i
] == -1) break;
328 if (wait_all
) flags
|= SELECT_ALL
;
329 if (alertable
) flags
|= SELECT_ALERTABLE
;
330 if (wait_msg
) flags
|= SELECT_MSG
;
331 if (timeout
!= INFINITE32
) flags
|= SELECT_TIMEOUT
;
332 return CLIENT_Select( count
, wait
->server
, flags
, timeout
);
336 /* Now wait for it */
337 SYNC_WaitForCondition( wait
, timeout
);
338 SYNC_FreeWaitStruct( wait
);
342 return wait
->signaled
;
345 /***********************************************************************
346 * Sleep (KERNEL32.679)
348 VOID WINAPI
Sleep( DWORD timeout
)
350 SYNC_DoWait( 0, NULL
, FALSE
, timeout
, FALSE
, FALSE
);
353 /******************************************************************************
354 * SleepEx (KERNEL32.680)
356 DWORD WINAPI
SleepEx( DWORD timeout
, BOOL32 alertable
)
358 DWORD ret
= SYNC_DoWait( 0, NULL
, FALSE
, timeout
, alertable
, FALSE
);
359 if (ret
!= WAIT_IO_COMPLETION
) ret
= 0;
364 /***********************************************************************
365 * WaitForSingleObject (KERNEL32.723)
367 DWORD WINAPI
WaitForSingleObject( HANDLE32 handle
, DWORD timeout
)
369 return SYNC_DoWait( 1, &handle
, FALSE
, timeout
, FALSE
, FALSE
);
373 /***********************************************************************
374 * WaitForSingleObjectEx (KERNEL32.724)
376 DWORD WINAPI
WaitForSingleObjectEx( HANDLE32 handle
, DWORD timeout
,
379 return SYNC_DoWait( 1, &handle
, FALSE
, timeout
, alertable
, FALSE
);
383 /***********************************************************************
384 * WaitForMultipleObjects (KERNEL32.721)
386 DWORD WINAPI
WaitForMultipleObjects( DWORD count
, const HANDLE32
*handles
,
387 BOOL32 wait_all
, DWORD timeout
)
389 return SYNC_DoWait( count
, handles
, wait_all
, timeout
, FALSE
, FALSE
);
393 /***********************************************************************
394 * WaitForMultipleObjectsEx (KERNEL32.722)
396 DWORD WINAPI
WaitForMultipleObjectsEx( DWORD count
, const HANDLE32
*handles
,
397 BOOL32 wait_all
, DWORD timeout
,
400 return SYNC_DoWait( count
, handles
, wait_all
, timeout
, alertable
, FALSE
);
404 /***********************************************************************
405 * WIN16_WaitForSingleObject (KERNEL.460)
407 DWORD WINAPI
WIN16_WaitForSingleObject( HANDLE32 handle
, DWORD timeout
)
411 SYSLEVEL_ReleaseWin16Lock();
412 retval
= WaitForSingleObject( handle
, timeout
);
413 SYSLEVEL_RestoreWin16Lock();
418 /***********************************************************************
419 * WIN16_WaitForMultipleObjects (KERNEL.461)
421 DWORD WINAPI
WIN16_WaitForMultipleObjects( DWORD count
, const HANDLE32
*handles
,
422 BOOL32 wait_all
, DWORD timeout
)
426 SYSLEVEL_ReleaseWin16Lock();
427 retval
= WaitForMultipleObjects( count
, handles
, wait_all
, timeout
);
428 SYSLEVEL_RestoreWin16Lock();