[PATCH 3/7] ntdll: Move Rtl(Un)RegisterWait code below threadpool structs.
Rémi Bernon
rbernon at codeweavers.com
Wed Dec 2 04:01:12 CST 2020
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/ntdll/threadpool.c | 432 ++++++++++++++++++++--------------------
1 file changed, 216 insertions(+), 216 deletions(-)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 1d64bd82bf4..db645118059 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -553,222 +553,6 @@ static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout
return pTime;
}
-static void delete_wait_work_item(struct wait_work_item *wait_work_item)
-{
- NtClose( wait_work_item->CancelEvent );
- RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
-}
-
-static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
-{
- struct wait_work_item *wait_work_item = Arg;
- NTSTATUS status;
- BOOLEAN alertable = (wait_work_item->Flags & WT_EXECUTEINIOTHREAD) != 0;
- HANDLE handles[2] = { wait_work_item->Object, wait_work_item->CancelEvent };
- LARGE_INTEGER timeout;
- HANDLE completion_event;
-
- TRACE("\n");
-
- while (TRUE)
- {
- status = NtWaitForMultipleObjects( 2, handles, TRUE, alertable,
- get_nt_timeout( &timeout, wait_work_item->Milliseconds ) );
- if (status == STATUS_WAIT_0 || status == STATUS_TIMEOUT)
- {
- BOOLEAN TimerOrWaitFired;
-
- if (status == STATUS_WAIT_0)
- {
- TRACE( "object %p signaled, calling callback %p with context %p\n",
- wait_work_item->Object, wait_work_item->Callback,
- wait_work_item->Context );
- TimerOrWaitFired = FALSE;
- }
- else
- {
- TRACE( "wait for object %p timed out, calling callback %p with context %p\n",
- wait_work_item->Object, wait_work_item->Callback,
- wait_work_item->Context );
- TimerOrWaitFired = TRUE;
- }
- InterlockedExchange( &wait_work_item->CallbackInProgress, TRUE );
- if (wait_work_item->CompletionEvent)
- {
- TRACE( "Work has been canceled.\n" );
- break;
- }
- wait_work_item->Callback( wait_work_item->Context, TimerOrWaitFired );
- InterlockedExchange( &wait_work_item->CallbackInProgress, FALSE );
-
- if (wait_work_item->Flags & WT_EXECUTEONLYONCE)
- break;
- }
- else if (status != STATUS_USER_APC)
- break;
- }
-
-
- if (InterlockedIncrement( &wait_work_item->DeleteCount ) == 2 )
- {
- completion_event = wait_work_item->CompletionEvent;
- delete_wait_work_item( wait_work_item );
- if (completion_event && completion_event != INVALID_HANDLE_VALUE)
- NtSetEvent( completion_event, NULL );
- }
-
- return 0;
-}
-
-/***********************************************************************
- * RtlRegisterWait (NTDLL.@)
- *
- * Registers a wait for a handle to become signaled.
- *
- * PARAMS
- * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it.
- * Object [I] Object to wait to become signaled.
- * Callback [I] Callback function to execute when the wait times out or the handle is signaled.
- * Context [I] Context to pass to the callback function when it is executed.
- * Milliseconds [I] Number of milliseconds to wait before timing out.
- * Flags [I] Flags. See notes.
- *
- * RETURNS
- * Success: STATUS_SUCCESS.
- * Failure: Any NTSTATUS code.
- *
- * NOTES
- * Flags can be one or more of the following:
- *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread.
- *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread.
- *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent.
- *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time.
- *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token.
- */
-NTSTATUS WINAPI RtlRegisterWait(PHANDLE NewWaitObject, HANDLE Object,
- RTL_WAITORTIMERCALLBACKFUNC Callback,
- PVOID Context, ULONG Milliseconds, ULONG Flags)
-{
- struct wait_work_item *wait_work_item;
- NTSTATUS status;
-
- TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags );
-
- wait_work_item = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wait_work_item) );
- if (!wait_work_item)
- return STATUS_NO_MEMORY;
-
- wait_work_item->Object = Object;
- wait_work_item->Callback = Callback;
- wait_work_item->Context = Context;
- wait_work_item->Milliseconds = Milliseconds;
- wait_work_item->Flags = Flags;
- wait_work_item->CallbackInProgress = FALSE;
- wait_work_item->DeleteCount = 0;
- wait_work_item->CompletionEvent = NULL;
-
- status = NtCreateEvent( &wait_work_item->CancelEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
- if (status != STATUS_SUCCESS)
- {
- RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
- return status;
- }
-
- Flags = Flags & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD |
- WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION);
- status = RtlQueueWorkItem( wait_thread_proc, wait_work_item, Flags );
- if (status != STATUS_SUCCESS)
- {
- delete_wait_work_item( wait_work_item );
- return status;
- }
-
- *NewWaitObject = wait_work_item;
- return status;
-}
-
-/***********************************************************************
- * RtlDeregisterWaitEx (NTDLL.@)
- *
- * Cancels a wait operation and frees the resources associated with calling
- * RtlRegisterWait().
- *
- * PARAMS
- * WaitObject [I] Handle to the wait object to free.
- *
- * RETURNS
- * Success: STATUS_SUCCESS.
- * Failure: Any NTSTATUS code.
- */
-NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
-{
- struct wait_work_item *wait_work_item = WaitHandle;
- NTSTATUS status;
- HANDLE LocalEvent = NULL;
- int CallbackInProgress;
-
- TRACE( "(%p %p)\n", WaitHandle, CompletionEvent );
-
- if (WaitHandle == NULL)
- return STATUS_INVALID_HANDLE;
-
- InterlockedExchangePointer( &wait_work_item->CompletionEvent, INVALID_HANDLE_VALUE );
- CallbackInProgress = wait_work_item->CallbackInProgress;
- TRACE( "callback in progress %u\n", CallbackInProgress );
- if (CompletionEvent == INVALID_HANDLE_VALUE || !CallbackInProgress)
- {
- status = NtCreateEvent( &LocalEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
- if (status != STATUS_SUCCESS)
- return status;
- InterlockedExchangePointer( &wait_work_item->CompletionEvent, LocalEvent );
- }
- else if (CompletionEvent != NULL)
- {
- InterlockedExchangePointer( &wait_work_item->CompletionEvent, CompletionEvent );
- }
-
- NtSetEvent( wait_work_item->CancelEvent, NULL );
-
- if (InterlockedIncrement( &wait_work_item->DeleteCount ) == 2 )
- {
- status = STATUS_SUCCESS;
- delete_wait_work_item( wait_work_item );
- }
- else if (LocalEvent)
- {
- TRACE( "Waiting for completion event\n" );
- NtWaitForSingleObject( LocalEvent, FALSE, NULL );
- status = STATUS_SUCCESS;
- }
- else
- {
- status = STATUS_PENDING;
- }
-
- if (LocalEvent)
- NtClose( LocalEvent );
-
- return status;
-}
-
-/***********************************************************************
- * RtlDeregisterWait (NTDLL.@)
- *
- * Cancels a wait operation and frees the resources associated with calling
- * RtlRegisterWait().
- *
- * PARAMS
- * WaitObject [I] Handle to the wait object to free.
- *
- * RETURNS
- * Success: STATUS_SUCCESS.
- * Failure: Any NTSTATUS code.
- */
-NTSTATUS WINAPI RtlDeregisterWait(HANDLE WaitHandle)
-{
- return RtlDeregisterWaitEx(WaitHandle, NULL);
-}
-
/************************** Timer Queue Impl **************************/
@@ -3350,3 +3134,219 @@ NTSTATUS WINAPI TpQueryPoolStackInformation( TP_POOL *pool, TP_POOL_STACK_INFORM
return STATUS_SUCCESS;
}
+
+static void delete_wait_work_item(struct wait_work_item *wait_work_item)
+{
+ NtClose( wait_work_item->CancelEvent );
+ RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
+}
+
+static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
+{
+ struct wait_work_item *wait_work_item = Arg;
+ NTSTATUS status;
+ BOOLEAN alertable = (wait_work_item->Flags & WT_EXECUTEINIOTHREAD) != 0;
+ HANDLE handles[2] = { wait_work_item->Object, wait_work_item->CancelEvent };
+ LARGE_INTEGER timeout;
+ HANDLE completion_event;
+
+ TRACE("\n");
+
+ while (TRUE)
+ {
+ status = NtWaitForMultipleObjects( 2, handles, TRUE, alertable,
+ get_nt_timeout( &timeout, wait_work_item->Milliseconds ) );
+ if (status == STATUS_WAIT_0 || status == STATUS_TIMEOUT)
+ {
+ BOOLEAN TimerOrWaitFired;
+
+ if (status == STATUS_WAIT_0)
+ {
+ TRACE( "object %p signaled, calling callback %p with context %p\n",
+ wait_work_item->Object, wait_work_item->Callback,
+ wait_work_item->Context );
+ TimerOrWaitFired = FALSE;
+ }
+ else
+ {
+ TRACE( "wait for object %p timed out, calling callback %p with context %p\n",
+ wait_work_item->Object, wait_work_item->Callback,
+ wait_work_item->Context );
+ TimerOrWaitFired = TRUE;
+ }
+ InterlockedExchange( &wait_work_item->CallbackInProgress, TRUE );
+ if (wait_work_item->CompletionEvent)
+ {
+ TRACE( "Work has been canceled.\n" );
+ break;
+ }
+ wait_work_item->Callback( wait_work_item->Context, TimerOrWaitFired );
+ InterlockedExchange( &wait_work_item->CallbackInProgress, FALSE );
+
+ if (wait_work_item->Flags & WT_EXECUTEONLYONCE)
+ break;
+ }
+ else if (status != STATUS_USER_APC)
+ break;
+ }
+
+
+ if (InterlockedIncrement( &wait_work_item->DeleteCount ) == 2 )
+ {
+ completion_event = wait_work_item->CompletionEvent;
+ delete_wait_work_item( wait_work_item );
+ if (completion_event && completion_event != INVALID_HANDLE_VALUE)
+ NtSetEvent( completion_event, NULL );
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ * RtlRegisterWait (NTDLL.@)
+ *
+ * Registers a wait for a handle to become signaled.
+ *
+ * PARAMS
+ * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it.
+ * Object [I] Object to wait to become signaled.
+ * Callback [I] Callback function to execute when the wait times out or the handle is signaled.
+ * Context [I] Context to pass to the callback function when it is executed.
+ * Milliseconds [I] Number of milliseconds to wait before timing out.
+ * Flags [I] Flags. See notes.
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS.
+ * Failure: Any NTSTATUS code.
+ *
+ * NOTES
+ * Flags can be one or more of the following:
+ *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread.
+ *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread.
+ *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent.
+ *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time.
+ *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token.
+ */
+NTSTATUS WINAPI RtlRegisterWait(PHANDLE NewWaitObject, HANDLE Object,
+ RTL_WAITORTIMERCALLBACKFUNC Callback,
+ PVOID Context, ULONG Milliseconds, ULONG Flags)
+{
+ struct wait_work_item *wait_work_item;
+ NTSTATUS status;
+
+ TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags );
+
+ wait_work_item = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wait_work_item) );
+ if (!wait_work_item)
+ return STATUS_NO_MEMORY;
+
+ wait_work_item->Object = Object;
+ wait_work_item->Callback = Callback;
+ wait_work_item->Context = Context;
+ wait_work_item->Milliseconds = Milliseconds;
+ wait_work_item->Flags = Flags;
+ wait_work_item->CallbackInProgress = FALSE;
+ wait_work_item->DeleteCount = 0;
+ wait_work_item->CompletionEvent = NULL;
+
+ status = NtCreateEvent( &wait_work_item->CancelEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
+ if (status != STATUS_SUCCESS)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
+ return status;
+ }
+
+ Flags = Flags & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD |
+ WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION);
+ status = RtlQueueWorkItem( wait_thread_proc, wait_work_item, Flags );
+ if (status != STATUS_SUCCESS)
+ {
+ delete_wait_work_item( wait_work_item );
+ return status;
+ }
+
+ *NewWaitObject = wait_work_item;
+ return status;
+}
+
+/***********************************************************************
+ * RtlDeregisterWaitEx (NTDLL.@)
+ *
+ * Cancels a wait operation and frees the resources associated with calling
+ * RtlRegisterWait().
+ *
+ * PARAMS
+ * WaitObject [I] Handle to the wait object to free.
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS.
+ * Failure: Any NTSTATUS code.
+ */
+NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
+{
+ struct wait_work_item *wait_work_item = WaitHandle;
+ NTSTATUS status;
+ HANDLE LocalEvent = NULL;
+ int CallbackInProgress;
+
+ TRACE( "(%p %p)\n", WaitHandle, CompletionEvent );
+
+ if (WaitHandle == NULL)
+ return STATUS_INVALID_HANDLE;
+
+ InterlockedExchangePointer( &wait_work_item->CompletionEvent, INVALID_HANDLE_VALUE );
+ CallbackInProgress = wait_work_item->CallbackInProgress;
+ TRACE( "callback in progress %u\n", CallbackInProgress );
+ if (CompletionEvent == INVALID_HANDLE_VALUE || !CallbackInProgress)
+ {
+ status = NtCreateEvent( &LocalEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
+ if (status != STATUS_SUCCESS)
+ return status;
+ InterlockedExchangePointer( &wait_work_item->CompletionEvent, LocalEvent );
+ }
+ else if (CompletionEvent != NULL)
+ {
+ InterlockedExchangePointer( &wait_work_item->CompletionEvent, CompletionEvent );
+ }
+
+ NtSetEvent( wait_work_item->CancelEvent, NULL );
+
+ if (InterlockedIncrement( &wait_work_item->DeleteCount ) == 2 )
+ {
+ status = STATUS_SUCCESS;
+ delete_wait_work_item( wait_work_item );
+ }
+ else if (LocalEvent)
+ {
+ TRACE( "Waiting for completion event\n" );
+ NtWaitForSingleObject( LocalEvent, FALSE, NULL );
+ status = STATUS_SUCCESS;
+ }
+ else
+ {
+ status = STATUS_PENDING;
+ }
+
+ if (LocalEvent)
+ NtClose( LocalEvent );
+
+ return status;
+}
+
+/***********************************************************************
+ * RtlDeregisterWait (NTDLL.@)
+ *
+ * Cancels a wait operation and frees the resources associated with calling
+ * RtlRegisterWait().
+ *
+ * PARAMS
+ * WaitObject [I] Handle to the wait object to free.
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS.
+ * Failure: Any NTSTATUS code.
+ */
+NTSTATUS WINAPI RtlDeregisterWait(HANDLE WaitHandle)
+{
+ return RtlDeregisterWaitEx(WaitHandle, NULL);
+}
--
2.29.2
More information about the wine-devel
mailing list