From: Sebastian Lackner Subject: [6/11] ntdll: Implement TpCallbackLeaveCriticalSectionOnCompletion. Message-Id: <559453D8.2000706@fds-team.de> Date: Wed, 1 Jul 2015 22:55:52 +0200 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 ) -- 2.4.4