Sebastian Lackner : ntdll: Reimplement RtlQueueWorkItem on top of new threadpool API.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Jul 28 13:30:06 CDT 2015
Module: wine
Branch: master
Commit: 9562e818101e67304c613dec922b86a793c26e59
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9562e818101e67304c613dec922b86a793c26e59
Author: Sebastian Lackner <sebastian at fds-team.de>
Date: Sun Jul 26 23:24:06 2015 +0200
ntdll: Reimplement RtlQueueWorkItem on top of new threadpool API.
---
dlls/ntdll/threadpool.c | 143 +++++++++---------------------------------------
1 file changed, 27 insertions(+), 116 deletions(-)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 23091f3..ad4951f 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -42,44 +42,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(threadpool);
* Old thread pooling API
*/
-#define OLD_WORKER_TIMEOUT 30000 /* 30 seconds */
+struct rtl_work_item
+{
+ PRTL_WORK_ITEM_ROUTINE function;
+ PVOID context;
+};
+
#define EXPIRE_NEVER (~(ULONGLONG)0)
#define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */
-static RTL_CRITICAL_SECTION_DEBUG critsect_debug;
static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug;
static struct
{
- /* threadpool_cs must be held while modifying the following four elements */
- struct list work_item_list;
- LONG num_workers;
- LONG num_busy_workers;
- LONG num_items_processed;
- RTL_CONDITION_VARIABLE threadpool_cond;
- RTL_CRITICAL_SECTION threadpool_cs;
HANDLE compl_port;
RTL_CRITICAL_SECTION threadpool_compl_cs;
}
old_threadpool =
{
- LIST_INIT(old_threadpool.work_item_list), /* work_item_list */
- 0, /* num_workers */
- 0, /* num_busy_workers */
- 0, /* num_items_processed */
- RTL_CONDITION_VARIABLE_INIT, /* threadpool_cond */
- { &critsect_debug, -1, 0, 0, 0, 0 }, /* threadpool_cs */
NULL, /* compl_port */
{ &critsect_compl_debug, -1, 0, 0, 0, 0 }, /* threadpool_compl_cs */
};
-static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
-{
- 0, 0, &old_threadpool.threadpool_cs,
- { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": threadpool_cs") }
-};
-
static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug =
{
0, 0, &old_threadpool.threadpool_compl_cs,
@@ -87,13 +71,6 @@ static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug =
0, 0, { (DWORD_PTR)(__FILE__ ": threadpool_compl_cs") }
};
-struct work_item
-{
- struct list entry;
- PRTL_WORK_ITEM_ROUTINE function;
- PVOID context;
-};
-
struct wait_work_item
{
HANDLE Object;
@@ -364,47 +341,14 @@ static inline LONG interlocked_dec( PLONG dest )
return interlocked_xchg_add( dest, -1 ) - 1;
}
-static void WINAPI worker_thread_proc(void * param)
+static void CALLBACK process_rtl_work_item( TP_CALLBACK_INSTANCE *instance, void *userdata )
{
- struct list *item;
- struct work_item *work_item_ptr, work_item;
- LARGE_INTEGER timeout;
- timeout.QuadPart = -(OLD_WORKER_TIMEOUT * (ULONGLONG)10000);
-
- RtlEnterCriticalSection( &old_threadpool.threadpool_cs );
- old_threadpool.num_workers++;
-
- for (;;)
- {
- if ((item = list_head( &old_threadpool.work_item_list )))
- {
- work_item_ptr = LIST_ENTRY( item, struct work_item, entry );
- list_remove( &work_item_ptr->entry );
- old_threadpool.num_busy_workers++;
- old_threadpool.num_items_processed++;
- RtlLeaveCriticalSection( &old_threadpool.threadpool_cs );
-
- /* copy item to stack and do the work */
- work_item = *work_item_ptr;
- RtlFreeHeap( GetProcessHeap(), 0, work_item_ptr );
- TRACE("executing %p(%p)\n", work_item.function, work_item.context);
- work_item.function( work_item.context );
-
- RtlEnterCriticalSection( &old_threadpool.threadpool_cs );
- old_threadpool.num_busy_workers--;
- }
- else if (RtlSleepConditionVariableCS( &old_threadpool.threadpool_cond,
- &old_threadpool.threadpool_cs, &timeout ) != STATUS_SUCCESS)
- {
- break;
- }
- }
+ struct rtl_work_item *item = userdata;
- old_threadpool.num_workers--;
- RtlLeaveCriticalSection( &old_threadpool.threadpool_cs );
- RtlExitUserThread( 0 );
+ TRACE("executing %p(%p)\n", item->function, item->context);
+ item->function( item->context );
- /* never reached */
+ RtlFreeHeap( GetProcessHeap(), 0, item );
}
/***********************************************************************
@@ -413,9 +357,9 @@ static void WINAPI worker_thread_proc(void * param)
* Queues a work item into a thread in the thread pool.
*
* PARAMS
- * Function [I] Work function to execute.
- * Context [I] Context to pass to the work function when it is executed.
- * Flags [I] Flags. See notes.
+ * function [I] Work function to execute.
+ * context [I] Context to pass to the work function when it is executed.
+ * flags [I] Flags. See notes.
*
* RETURNS
* Success: STATUS_SUCCESS.
@@ -429,59 +373,26 @@ static void WINAPI worker_thread_proc(void * param)
*|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time.
*|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token.
*/
-NTSTATUS WINAPI RtlQueueWorkItem(PRTL_WORK_ITEM_ROUTINE Function, PVOID Context, ULONG Flags)
+NTSTATUS WINAPI RtlQueueWorkItem( PRTL_WORK_ITEM_ROUTINE function, PVOID context, ULONG flags )
{
- HANDLE thread;
+ TP_CALLBACK_ENVIRON environment;
+ struct rtl_work_item *item;
NTSTATUS status;
- LONG items_processed;
- struct work_item *work_item = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(struct work_item));
- if (!work_item)
+ item = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*item) );
+ if (!item)
return STATUS_NO_MEMORY;
- work_item->function = Function;
- work_item->context = Context;
-
- if (Flags & ~WT_EXECUTELONGFUNCTION)
- FIXME("Flags 0x%x not supported\n", Flags);
-
- RtlEnterCriticalSection( &old_threadpool.threadpool_cs );
- list_add_tail( &old_threadpool.work_item_list, &work_item->entry );
- status = (old_threadpool.num_workers > old_threadpool.num_busy_workers) ?
- STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
- items_processed = old_threadpool.num_items_processed;
- RtlLeaveCriticalSection( &old_threadpool.threadpool_cs );
-
- /* FIXME: tune this algorithm to not be as aggressive with creating threads
- * if WT_EXECUTELONGFUNCTION isn't specified */
- if (status == STATUS_SUCCESS)
- RtlWakeConditionVariable( &old_threadpool.threadpool_cond );
- else
- {
- status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0,
- worker_thread_proc, NULL, &thread, NULL );
+ memset( &environment, 0, sizeof(environment) );
+ environment.Version = 1;
+ environment.u.s.LongFunction = (flags & WT_EXECUTELONGFUNCTION) != 0;
+ environment.u.s.Persistent = (flags & WT_EXECUTEINPERSISTENTTHREAD) != 0;
- /* NOTE: we don't care if we couldn't create the thread if there is at
- * least one other available to process the request */
- if (status == STATUS_SUCCESS)
- NtClose( thread );
- else
- {
- RtlEnterCriticalSection( &old_threadpool.threadpool_cs );
- if (old_threadpool.num_workers > 0 ||
- old_threadpool.num_items_processed != items_processed)
- {
- status = STATUS_SUCCESS;
- }
- else
- list_remove( &work_item->entry );
- RtlLeaveCriticalSection( &old_threadpool.threadpool_cs );
-
- if (status != STATUS_SUCCESS)
- RtlFreeHeap( GetProcessHeap(), 0, work_item );
- }
- }
+ item->function = function;
+ item->context = context;
+ status = TpSimpleTryPost( process_rtl_work_item, item, &environment );
+ if (status) RtlFreeHeap( GetProcessHeap(), 0, item );
return status;
}
More information about the wine-cvs
mailing list