From ae94c696acd7a580f09ebe76f69c0cd18802bcd9 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Mon, 3 Jul 2006 20:26:58 +0000 Subject: [PATCH] 4 of 4 commit (sorry my svn clinet is crazy for moment) Commit w3seek patch from bug 1609 : file attachment (id=910) The attached patch implements QueueUserWorkItem()/RtlQueueWorkItem() (lacks optimizations!!!). WINE's latest rpcrt4 relies on it. 1. Implement QueueUserWorkItem()/RtlQueueWorkItem() : 2. A slightly optimized 3. Supports WT_TRANSFER_IMPERSONATION 4. Slightly improved handling of growing/shrinking the pool by assuming work items with WT_EXECUTELONGFUNCTION run longer 5. Fixes a hack that made a worker thread always terminate if there were at least one more thread available svn path=/trunk/; revision=22807 --- reactos/dll/win32/kernel32/misc/stubs.c | 18 ------ reactos/dll/win32/kernel32/thread/thread.c | 75 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/reactos/dll/win32/kernel32/misc/stubs.c b/reactos/dll/win32/kernel32/misc/stubs.c index c611d72c987..3349611c531 100644 --- a/reactos/dll/win32/kernel32/misc/stubs.c +++ b/reactos/dll/win32/kernel32/misc/stubs.c @@ -620,24 +620,6 @@ MapUserPhysicalPagesScatter( return 0; } -/* - * @unimplemented - */ -BOOL -STDCALL -QueueUserWorkItem( - LPTHREAD_START_ROUTINE Function, - PVOID Context, - ULONG Flags - ) -{ - STUB; - return 0; -} - - - - /* * @unimplemented */ diff --git a/reactos/dll/win32/kernel32/thread/thread.c b/reactos/dll/win32/kernel32/thread/thread.c index 3c68a8b263c..916091f3030 100644 --- a/reactos/dll/win32/kernel32/thread/thread.c +++ b/reactos/dll/win32/kernel32/thread/thread.c @@ -873,4 +873,79 @@ SleepEx(DWORD dwMilliseconds, return 0; } + +typedef struct _QUEUE_USER_WORKITEM_CONTEXT +{ + LPTHREAD_START_ROUTINE Function; + PVOID Context; +} QUEUE_USER_WORKITEM_CONTEXT, *PQUEUE_USER_WORKITEM_CONTEXT; + +static VOID +NTAPI +InternalWorkItemTrampoline(PVOID Context) +{ + QUEUE_USER_WORKITEM_CONTEXT Info; + + ASSERT(Context != NULL); + + /* Save the context to the stack */ + Info = *(volatile QUEUE_USER_WORKITEM_CONTEXT *)Context; + + /* Free the context before calling the callback. This avoids + a memory leak in case the thread dies... */ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Context); + + /* Call the real callback */ + Info.Function(Info.Context); +} + + +/* + * @implemented + */ +BOOL +STDCALL +QueueUserWorkItem( + LPTHREAD_START_ROUTINE Function, + PVOID Context, + ULONG Flags + ) +{ + PQUEUE_USER_WORKITEM_CONTEXT WorkItemContext; + NTSTATUS Status; + + /* Save the context for the trampoline function */ + WorkItemContext = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(*WorkItemContext)); + if (WorkItemContext == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + WorkItemContext->Function = Function; + WorkItemContext->Context = Context; + + /* NOTE: Don't use Function directly since the callback signature + differs. This might cause problems on certain platforms... */ + Status = RtlQueueWorkItem(InternalWorkItemTrampoline, + WorkItemContext, + Flags); + if (!NT_SUCCESS(Status)) + { + /* Free the allocated context in case of failure */ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + WorkItemContext); + + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + /* EOF */