ReactOS  0.4.14-dev-358-gbef841c
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 
19 typedef 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 
41 static VOID
42 NTAPI
44 {
45  PRTLP_WAIT Wait = (PRTLP_WAIT) Arg;
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  */
130 NTSTATUS
131 NTAPI
132 RtlRegisterWait(PHANDLE NewWaitObject,
133  HANDLE Object,
135  PVOID Context,
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  */
200 NTSTATUS
201 NTAPI
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  */
268 NTSTATUS
269 NTAPI
271 {
272  return RtlDeregisterWaitEx(WaitHandle, NULL);
273 }
274 
275 /* EOF */
#define TRUE
Definition: types.h:120
ULONG Flags
Definition: wait.c:26
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 png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
WAITORTIMERCALLBACKFUNC Callback
Definition: wait.c:27
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSYSAPI NTSTATUS NTAPI RtlQueueWorkItem(_In_ WORKERCALLBACKFUNC Function, _In_opt_ PVOID Context, _In_ ULONG Flags)
#define WT_EXECUTEINIOTHREAD
Definition: winnt_old.h:1072
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:100
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
VOID(NTAPI * WAITORTIMERCALLBACKFUNC)(PVOID pvContext, BOOLEAN fTimerOrWaitFired)
Definition: rtltypes.h:492
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
Definition: dhcpd.h:245
#define WT_TRANSFER_IMPERSONATION
Definition: winnt_old.h:1080
ULONG Milliseconds
Definition: wait.c:29
PVOID Context
Definition: wait.c:28
GLbitfield GLuint64 timeout
Definition: glext.h:7164
#define WT_EXECUTEINPERSISTENTTHREAD
Definition: winnt_old.h:1079
struct _RTLP_WAIT * PRTLP_WAIT
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_WAIT_1
Definition: ntstatus.h:71
static PLARGE_INTEGER get_nt_timeout(PLARGE_INTEGER pTime, ULONG timeout)
Definition: wait.c:34
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME pTime
Definition: wincrypt.h:4840
HANDLE Object
Definition: wait.c:21
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
Definition: wait.c:202
BOOLEAN CallbackInProgress
Definition: wait.c:22
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#define WT_EXECUTELONGFUNCTION
Definition: winnt_old.h:1076
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
static object_header_t ** handles
Definition: handle.c:46
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:458
#define STATUS_PENDING
Definition: ntstatus.h:82
#define WT_EXECUTEONLYONCE
Definition: winnt_old.h:1075
NTSTATUS NTAPI RtlDeregisterWait(HANDLE WaitHandle)
Definition: wait.c:270
uint64_t ULONGLONG
Definition: typedefs.h:65
struct _RTLP_WAIT RTLP_WAIT
static IUnknown Object
Definition: main.c:512
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
Status
Definition: gdiplustypes.h:24
#define STATUS_USER_APC
Definition: ntstatus.h:78
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
LONG DeleteCount
Definition: wait.c:24
HANDLE CancelEvent
Definition: wait.c:23
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
HANDLE CompletionEvent
Definition: wait.c:25
#define INFINITE
Definition: serial.h:102
return STATUS_SUCCESS
Definition: btrfs.c:2938
LPFNPSPCALLBACK Callback
Definition: desk.c:111
IN BOOLEAN Wait
Definition: fatprocs.h:1529
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)