Module: wine Branch: master Commit: a9dd37be6827e7df90838c604404db1d112ebf42 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a9dd37be6827e7df90838c6044...
Author: Sebastian Lackner sebastian@fds-team.de Date: Wed Jul 1 22:55:52 2015 +0200
ntdll: Implement TpCallbackLeaveCriticalSectionOnCompletion.
An instance can only have one completion of each type, trying to add a second one leads to an exception on Windows.
---
dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/threadpool.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5a698c4..5cfcfd7 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -973,6 +973,7 @@ @ stdcall TpAllocCleanupGroup(ptr) @ stdcall TpAllocPool(ptr ptr) @ stdcall TpAllocWork(ptr ptr ptr ptr) +@ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) @ stdcall TpCallbackMayRunLong(ptr) @ stdcall TpPostWork(ptr) @ stdcall TpReleaseCleanupGroup(ptr) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index a0090c0..21e5b7d 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -203,6 +203,10 @@ struct threadpool_instance struct threadpool_object *object; DWORD threadid; BOOL may_run_long; + struct + { + CRITICAL_SECTION *critical_section; + } cleanup; };
/* internal threadpool group representation */ @@ -1630,6 +1634,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) instance.object = object; instance.threadid = GetCurrentThreadId(); instance.may_run_long = object->may_run_long; + instance.cleanup.critical_section = NULL;
switch (object->type) { @@ -1665,6 +1670,12 @@ static void CALLBACK threadpool_worker_proc( void *param ) TRACE( "callback %p returned\n", object->finalization_callback ); }
+ /* Execute cleanup tasks. */ + if (instance.cleanup.critical_section) + { + RtlLeaveCriticalSection( instance.cleanup.critical_section ); + } + RtlEnterCriticalSection( &pool->cs ); pool->num_busy_workers--; object->num_running_callbacks--; @@ -1753,6 +1764,19 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us }
/*********************************************************************** + * TpCallbackLeaveCriticalSectionOnCompletion (NTDLL.@) + */ +VOID WINAPI TpCallbackLeaveCriticalSectionOnCompletion( TP_CALLBACK_INSTANCE *instance, CRITICAL_SECTION *crit ) +{ + struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance ); + + TRACE( "%p %p\n", instance, crit ); + + if (!this->cleanup.critical_section) + this->cleanup.critical_section = crit; +} + +/*********************************************************************** * TpCallbackMayRunLong (NTDLL.@) */ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance )