ReactOS 0.4.15-dev-7958-gcd0bb1a
wait.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Rtl user wait functions
5 * FILE: lib/rtl/wait.c
6 * PROGRAMERS:
7 * Alex Ionescu (alex@relsoft.net)
8 * Eric Kohl
9 * KJK::Hyperion
10 */
11
12/* INCLUDES *****************************************************************/
13
14#include <rtl.h>
15
16#define NDEBUG
17#include <debug.h>
18
19typedef struct _RTLP_WAIT
20{
31
32/* PRIVATE FUNCTIONS *******************************************************/
33
35{
36 if (timeout == INFINITE) return NULL;
37 pTime->QuadPart = (ULONGLONG)timeout * -10000;
38 return pTime;
39}
40
41static VOID
44{
47 BOOLEAN alertable = (Wait->Flags & WT_EXECUTEINIOTHREAD) != 0;
48 HANDLE handles[2] = { Wait->CancelEvent, Wait->Object };
50 HANDLE completion_event;
51
52// TRACE("\n");
53
54 while (TRUE)
55 {
57 handles,
58 WaitAny,
59 alertable,
60 get_nt_timeout( &timeout, Wait->Milliseconds ) );
61
63 {
64 BOOLEAN TimerOrWaitFired;
65
66 if (Status == STATUS_WAIT_1)
67 {
68 // TRACE( "object %p signaled, calling callback %p with context %p\n",
69 // Wait->Object, Wait->Callback,
70 // Wait->Context );
71 TimerOrWaitFired = FALSE;
72 }
73 else
74 {
75 // TRACE( "wait for object %p timed out, calling callback %p with context %p\n",
76 // Wait->Object, Wait->Callback,
77 // Wait->Context );
78 TimerOrWaitFired = TRUE;
79 }
80 Wait->CallbackInProgress = TRUE;
81 Wait->Callback( Wait->Context, TimerOrWaitFired );
82 Wait->CallbackInProgress = FALSE;
83
84 if (Wait->Flags & WT_EXECUTEONLYONCE)
85 break;
86 }
87 else if (Status != STATUS_USER_APC)
88 break;
89 }
90
91 completion_event = Wait->CompletionEvent;
92 if (completion_event) NtSetEvent( completion_event, NULL );
93
94 if (InterlockedIncrement( &Wait->DeleteCount ) == 2 )
95 {
96 NtClose( Wait->CancelEvent );
97 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait );
98 }
99}
100
101
102/* FUNCTIONS ***************************************************************/
103
104
105/***********************************************************************
106 * RtlRegisterWait
107 *
108 * Registers a wait for a handle to become signaled.
109 *
110 * PARAMS
111 * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it.
112 * Object [I] Object to wait to become signaled.
113 * Callback [I] Callback function to execute when the wait times out or the handle is signaled.
114 * Context [I] Context to pass to the callback function when it is executed.
115 * Milliseconds [I] Number of milliseconds to wait before timing out.
116 * Flags [I] Flags. See notes.
117 *
118 * RETURNS
119 * Success: STATUS_SUCCESS.
120 * Failure: Any NTSTATUS code.
121 *
122 * NOTES
123 * Flags can be one or more of the following:
124 *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread.
125 *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread.
126 *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent.
127 *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time.
128 *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token.
129 */
131NTAPI
136 ULONG Milliseconds,
137 ULONG Flags)
138{
141
142 //TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags );
143
144 Wait = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(RTLP_WAIT) );
145 if (!Wait)
146 return STATUS_NO_MEMORY;
147
148 Wait->Object = Object;
149 Wait->Callback = Callback;
150 Wait->Context = Context;
151 Wait->Milliseconds = Milliseconds;
152 Wait->Flags = Flags;
153 Wait->CallbackInProgress = FALSE;
154 Wait->DeleteCount = 0;
155 Wait->CompletionEvent = NULL;
156
157 Status = NtCreateEvent( &Wait->CancelEvent,
159 NULL,
161 FALSE );
162
163 if (Status != STATUS_SUCCESS)
164 {
165 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait );
166 return Status;
167 }
168
171
173 Wait,
174 Flags );
175
176 if (Status != STATUS_SUCCESS)
177 {
178 NtClose( Wait->CancelEvent );
179 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait );
180 return Status;
181 }
182
183 *NewWaitObject = Wait;
184 return Status;
185}
186
187/***********************************************************************
188 * RtlDeregisterWaitEx
189 *
190 * Cancels a wait operation and frees the resources associated with calling
191 * RtlRegisterWait().
192 *
193 * PARAMS
194 * WaitObject [I] Handle to the wait object to free.
195 *
196 * RETURNS
197 * Success: STATUS_SUCCESS.
198 * Failure: Any NTSTATUS code.
199 */
201NTAPI
203 HANDLE CompletionEvent)
204{
205 PRTLP_WAIT Wait = (PRTLP_WAIT) WaitHandle;
207
208 //TRACE( "(%p)\n", WaitHandle );
209
210 NtSetEvent( Wait->CancelEvent, NULL );
211 if (Wait->CallbackInProgress)
212 {
213 if (CompletionEvent != NULL)
214 {
215 if (CompletionEvent == INVALID_HANDLE_VALUE)
216 {
217 Status = NtCreateEvent( &CompletionEvent,
219 NULL,
221 FALSE );
222
223 if (Status != STATUS_SUCCESS)
224 return Status;
225
226 (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent );
227
228 if (Wait->CallbackInProgress)
229 NtWaitForSingleObject( CompletionEvent, FALSE, NULL );
230
231 NtClose( CompletionEvent );
232 }
233 else
234 {
235 (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent );
236
237 if (Wait->CallbackInProgress)
239 }
240 }
241 else
243 }
244
245 if (InterlockedIncrement( &Wait->DeleteCount ) == 2 )
246 {
248 NtClose( Wait->CancelEvent );
249 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait );
250 }
251
252 return Status;
253}
254
255/***********************************************************************
256 * RtlDeregisterWait
257 *
258 * Cancels a wait operation and frees the resources associated with calling
259 * RtlRegisterWait().
260 *
261 * PARAMS
262 * WaitObject [I] Handle to the wait object to free.
263 *
264 * RETURNS
265 * Success: STATUS_SUCCESS.
266 * Failure: Any NTSTATUS code.
267 */
269NTAPI
271{
272 return RtlDeregisterWaitEx(WaitHandle, NULL);
273}
274
275/* EOF */
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define INFINITE
Definition: serial.h:102
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
Status
Definition: gdiplustypes.h:25
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
NTSYSAPI NTSTATUS NTAPI RtlQueueWorkItem(_In_ WORKERCALLBACKFUNC Function, _In_opt_ PVOID Context, _In_ ULONG Flags)
VOID(NTAPI * WAITORTIMERCALLBACKFUNC)(PVOID pvContext, BOOLEAN fTimerOrWaitFired)
Definition: rtltypes.h:496
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
@ NotificationEvent
@ WaitAny
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:455
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define STATUS_USER_APC
Definition: ntstatus.h:78
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSTATUS NTAPI NtWaitForMultipleObjects(IN ULONG ObjectCount, IN PHANDLE HandleArray, IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL)
Definition: obwait.c:46
long LONG
Definition: pedump.c:60
static PLARGE_INTEGER get_nt_timeout(PLARGE_INTEGER pTime, ULONG timeout)
Definition: wait.c:34
NTSTATUS NTAPI RtlDeregisterWait(HANDLE WaitHandle)
Definition: wait.c:270
static VOID NTAPI Wait_thread_proc(LPVOID Arg)
Definition: wait.c:43
NTSTATUS NTAPI RtlRegisterWait(PHANDLE NewWaitObject, HANDLE Object, WAITORTIMERCALLBACKFUNC Callback, PVOID Context, ULONG Milliseconds, ULONG Flags)
Definition: wait.c:132
struct _RTLP_WAIT * PRTLP_WAIT
struct _RTLP_WAIT RTLP_WAIT
NTSTATUS NTAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
Definition: wait.c:202
#define STATUS_SUCCESS
Definition: shellext.h:65
PVOID Context
Definition: wait.c:28
LONG DeleteCount
Definition: wait.c:24
ULONG Flags
Definition: wait.c:26
ULONG Milliseconds
Definition: wait.c:29
HANDLE Object
Definition: wait.c:21
HANDLE CancelEvent
Definition: wait.c:23
WAITORTIMERCALLBACKFUNC Callback
Definition: wait.c:27
BOOLEAN CallbackInProgress
Definition: wait.c:22
HANDLE CompletionEvent
Definition: wait.c:25
Definition: dhcpd.h:245
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
static EFI_HANDLE * handles
Definition: uefidisk.c:62
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME pTime
Definition: wincrypt.h:4837
#define WT_TRANSFER_IMPERSONATION
Definition: winnt_old.h:1047
#define WT_EXECUTEINPERSISTENTTHREAD
Definition: winnt_old.h:1046
#define WT_EXECUTEONLYONCE
Definition: winnt_old.h:1042
#define WT_EXECUTEINIOTHREAD
Definition: winnt_old.h:1039
#define WT_EXECUTELONGFUNCTION
Definition: winnt_old.h:1043
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170