Rebase against 3d8353fe182f3e7742cd7dab3420635e45ace129.

This commit is contained in:
Sebastian Lackner 2015-07-02 17:45:32 +02:00
parent 16aad8a55f
commit dfd86e0f91
16 changed files with 448 additions and 1000 deletions

View File

@ -1,81 +0,0 @@
From aec44ffb06857ee5c954136e82500e1dcb71f97b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 06:57:53 +0100
Subject: ntdll: Add support for threadpool group cancel callback.
---
dlls/ntdll/threadpool.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index da41ba0..93d9b28 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -171,6 +171,7 @@ struct threadpool_object
struct threadpool *pool;
struct threadpool_group *group;
PVOID userdata;
+ PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback;
/* information about the group, locked via .group->cs */
struct list group_entry;
BOOL is_group_member;
@@ -1370,6 +1371,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->pool = pool;
object->group = NULL;
object->userdata = userdata;
+ object->group_cancel_callback = NULL;
memset( &object->group_entry, 0, sizeof(object->group_entry) );
object->is_group_member = FALSE;
@@ -1385,6 +1387,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
FIXME( "unsupported environment version %u\n", environment->Version );
object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup );
+ object->group_cancel_callback = environment->CleanupGroupCancelCallback;
WARN( "environment not fully implemented yet\n" );
}
@@ -1467,7 +1470,7 @@ static void tp_object_submit( struct threadpool_object *object )
*
* Cancels all currently pending callbacks for a specific object.
*/
-static void tp_object_cancel( struct threadpool_object *object )
+static void tp_object_cancel( struct threadpool_object *object, BOOL group_cancel, PVOID userdata )
{
struct threadpool *pool = object->pool;
LONG pending_callbacks = 0;
@@ -1481,6 +1484,14 @@ static void tp_object_cancel( struct threadpool_object *object )
}
RtlLeaveCriticalSection( &pool->cs );
+ /* Execute group cancellation callback if defined, and if this was actually a group cancel. */
+ if (pending_callbacks && group_cancel && object->group_cancel_callback)
+ {
+ TRACE( "executing group cancel callback %p(%p, %p)\n", object->group_cancel_callback, object, userdata );
+ object->group_cancel_callback( object, userdata );
+ TRACE( "callback %p returned\n", object->group_cancel_callback );
+ }
+
while (pending_callbacks--)
tp_object_release( object );
}
@@ -1766,7 +1777,7 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p
{
LIST_FOR_EACH_ENTRY( object, &members, struct threadpool_object, group_entry )
{
- tp_object_cancel( object );
+ tp_object_cancel( object, TRUE, userdata );
}
}
@@ -1894,6 +1905,6 @@ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending )
TRACE( "%p %u\n", work, cancel_pending );
if (cancel_pending)
- tp_object_cancel( this );
+ tp_object_cancel( this, FALSE, NULL );
tp_object_wait( this );
}
--
2.4.4

View File

@ -0,0 +1,175 @@
From 1651eab61e449fef2119ff35703d6c9acc43f2b3 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 2 Jul 2015 17:15:41 +0200
Subject: ntdll: Implement TpDisassociateCallback and add separate group
finished event.
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/threadpool.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 134a3f7..ee90705 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -979,6 +979,7 @@
@ stdcall TpCallbackReleaseSemaphoreOnCompletion(ptr long long)
@ stdcall TpCallbackSetEventOnCompletion(ptr long)
@ stdcall TpCallbackUnloadDllOnCompletion(ptr ptr)
+@ stdcall TpDisassociateCallback(ptr)
@ stdcall TpPostWork(ptr)
@ stdcall TpReleaseCleanupGroup(ptr)
@ stdcall TpReleaseCleanupGroupMembers(ptr long ptr)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index eeb275f..0e09d0f 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -181,8 +181,10 @@ struct threadpool_object
/* information about the pool, locked via .pool->cs */
struct list pool_entry;
RTL_CONDITION_VARIABLE finished_event;
+ RTL_CONDITION_VARIABLE group_finished_event;
LONG num_pending_callbacks;
LONG num_running_callbacks;
+ LONG num_associated_callbacks;
/* arguments for callback */
union
{
@@ -202,6 +204,7 @@ struct threadpool_instance
{
struct threadpool_object *object;
DWORD threadid;
+ BOOL associated;
BOOL may_run_long;
struct
{
@@ -1406,8 +1409,10 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
memset( &object->pool_entry, 0, sizeof(object->pool_entry) );
RtlInitializeConditionVariable( &object->finished_event );
+ RtlInitializeConditionVariable( &object->group_finished_event );
object->num_pending_callbacks = 0;
object->num_running_callbacks = 0;
+ object->num_associated_callbacks = 0;
if (environment)
{
@@ -1540,13 +1545,21 @@ static void tp_object_cancel( struct threadpool_object *object, BOOL group_cance
* Waits until all pending and running callbacks of a specific object
* have been processed.
*/
-static void tp_object_wait( struct threadpool_object *object )
+static void tp_object_wait( struct threadpool_object *object, BOOL group_wait )
{
struct threadpool *pool = object->pool;
RtlEnterCriticalSection( &pool->cs );
- while (object->num_pending_callbacks || object->num_running_callbacks)
- RtlSleepConditionVariableCS( &object->finished_event, &pool->cs, NULL );
+ if (group_wait)
+ {
+ while (object->num_pending_callbacks || object->num_running_callbacks)
+ RtlSleepConditionVariableCS( &object->group_finished_event, &pool->cs, NULL );
+ }
+ else
+ {
+ while (object->num_pending_callbacks || object->num_associated_callbacks)
+ RtlSleepConditionVariableCS( &object->finished_event, &pool->cs, NULL );
+ }
RtlLeaveCriticalSection( &pool->cs );
}
@@ -1631,6 +1644,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
list_add_tail( &pool->pool, &object->pool_entry );
/* Leave critical section and do the actual callback. */
+ object->num_associated_callbacks++;
object->num_running_callbacks++;
pool->num_busy_workers++;
RtlLeaveCriticalSection( &pool->cs );
@@ -1639,6 +1653,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
callback_instance = (TP_CALLBACK_INSTANCE *)&instance;
instance.object = object;
instance.threadid = GetCurrentThreadId();
+ instance.associated = TRUE;
instance.may_run_long = object->may_run_long;
instance.cleanup.critical_section = NULL;
instance.cleanup.mutex = NULL;
@@ -1709,9 +1724,18 @@ static void CALLBACK threadpool_worker_proc( void *param )
skip_cleanup:
RtlEnterCriticalSection( &pool->cs );
pool->num_busy_workers--;
+
object->num_running_callbacks--;
if (!object->num_pending_callbacks && !object->num_running_callbacks)
- RtlWakeAllConditionVariable( &object->finished_event );
+ RtlWakeAllConditionVariable( &object->group_finished_event );
+
+ if (instance.associated)
+ {
+ object->num_associated_callbacks--;
+ if (!object->num_pending_callbacks && !object->num_associated_callbacks)
+ RtlWakeAllConditionVariable( &object->finished_event );
+ }
+
tp_object_release( object );
}
@@ -1913,6 +1937,37 @@ VOID WINAPI TpCallbackUnloadDllOnCompletion( TP_CALLBACK_INSTANCE *instance, HMO
}
/***********************************************************************
+ * TpDisassociateCallback (NTDLL.@)
+ */
+VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+ struct threadpool_object *object = this->object;
+ struct threadpool *pool;
+
+ TRACE( "%p\n", instance );
+
+ if (this->threadid != GetCurrentThreadId())
+ {
+ ERR("called from wrong thread, ignoring\n");
+ return;
+ }
+
+ if (!this->associated)
+ return;
+
+ pool = object->pool;
+ RtlEnterCriticalSection( &pool->cs );
+
+ object->num_associated_callbacks--;
+ if (!object->num_pending_callbacks && !object->num_associated_callbacks)
+ RtlWakeAllConditionVariable( &object->finished_event );
+
+ RtlLeaveCriticalSection( &pool->cs );
+ this->associated = FALSE;
+}
+
+/***********************************************************************
* TpPostWork (NTDLL.@)
*/
VOID WINAPI TpPostWork( TP_WORK *work )
@@ -1993,7 +2048,7 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p
/* Wait for remaining callbacks to finish */
LIST_FOR_EACH_ENTRY_SAFE( object, next, &members, struct threadpool_object, group_entry )
{
- tp_object_wait( object );
+ tp_object_wait( object, TRUE );
tp_object_release( object );
}
}
@@ -2115,5 +2170,5 @@ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending )
if (cancel_pending)
tp_object_cancel( this, FALSE, NULL );
- tp_object_wait( this );
+ tp_object_wait( this, FALSE );
}
--
2.4.4

View File

@ -1,56 +0,0 @@
From 9a973853b87ff70fac8fbc42308300a861dc39de Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 07:03:15 +0100
Subject: ntdll: Add support for threadpool finalization callback.
---
dlls/ntdll/threadpool.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 93d9b28..0133e66 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -172,6 +172,7 @@ struct threadpool_object
struct threadpool_group *group;
PVOID userdata;
PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback;
+ PTP_SIMPLE_CALLBACK finalization_callback;
/* information about the group, locked via .group->cs */
struct list group_entry;
BOOL is_group_member;
@@ -1372,6 +1373,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->group = NULL;
object->userdata = userdata;
object->group_cancel_callback = NULL;
+ object->finalization_callback = NULL;
memset( &object->group_entry, 0, sizeof(object->group_entry) );
object->is_group_member = FALSE;
@@ -1388,6 +1390,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup );
object->group_cancel_callback = environment->CleanupGroupCancelCallback;
+ object->finalization_callback = environment->FinalizationCallback;
WARN( "environment not fully implemented yet\n" );
}
@@ -1616,6 +1619,15 @@ static void CALLBACK threadpool_worker_proc( void *param )
break;
}
+ /* Execute finalization callback. */
+ if (object->finalization_callback)
+ {
+ TRACE( "executing finalization callback %p(NULL, %p)\n",
+ object->finalization_callback, object->userdata );
+ object->finalization_callback( NULL, object->userdata );
+ TRACE( "callback %p returned\n", object->finalization_callback );
+ }
+
RtlEnterCriticalSection( &pool->cs );
pool->num_busy_workers--;
object->num_running_callbacks--;
--
2.4.4

View File

@ -0,0 +1,191 @@
From 8041e8ccf5ed9021525a95b7c6bcedfa7d945cb4 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 2 Jul 2015 17:18:00 +0200
Subject: ntdll/tests: Add tests for TpDisassociateCallback.
---
dlls/ntdll/tests/threadpool.c | 149 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index 62bd064..a75b622 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -26,6 +26,7 @@ static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID);
static NTSTATUS (WINAPI *pTpAllocWork)(TP_WORK **,PTP_WORK_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *);
static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE,DWORD);
+static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *);
static VOID (WINAPI *pTpPostWork)(TP_WORK *);
static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *);
static VOID (WINAPI *pTpReleaseCleanupGroupMembers)(TP_CLEANUP_GROUP *,BOOL,PVOID);
@@ -57,6 +58,7 @@ static BOOL init_threadpool(void)
NTDLL_GET_PROC(TpAllocWork);
NTDLL_GET_PROC(TpCallbackMayRunLong);
NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
+ NTDLL_GET_PROC(TpDisassociateCallback);
NTDLL_GET_PROC(TpPostWork);
NTDLL_GET_PROC(TpReleaseCleanupGroup);
NTDLL_GET_PROC(TpReleaseCleanupGroupMembers);
@@ -498,6 +500,152 @@ static void test_tp_instance(void)
CloseHandle(semaphores[1]);
}
+static void CALLBACK disassociate_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK *work)
+{
+ HANDLE *semaphores = userdata;
+ DWORD result;
+
+ trace("Running disassociate callback\n");
+
+ pTpDisassociateCallback(instance);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+}
+
+static void CALLBACK disassociate2_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK *work)
+{
+ HANDLE *semaphores = userdata;
+ DWORD result;
+
+ trace("Running disassociate2 callback\n");
+
+ pTpDisassociateCallback(instance);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+}
+
+static void CALLBACK disassociate3_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ HANDLE *semaphores = userdata;
+ DWORD result;
+
+ trace("Running disassociate3 callback\n");
+
+ pTpDisassociateCallback(instance);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+}
+
+static void test_tp_disassociate(void)
+{
+ TP_CALLBACK_ENVIRON environment;
+ TP_CLEANUP_GROUP *group;
+ HANDLE semaphores[2];
+ NTSTATUS status;
+ TP_POOL *pool;
+ TP_WORK *work;
+ DWORD result;
+
+ semaphores[0] = CreateSemaphoreW(NULL, 0, 1, NULL);
+ ok(semaphores[0] != NULL, "failed to create semaphore\n");
+ semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
+ ok(semaphores[1] != NULL, "failed to create semaphore\n");
+
+ /* allocate new threadpool and cleanup group */
+ pool = NULL;
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(pool != NULL, "expected pool != NULL\n");
+
+ group = NULL;
+ status = pTpAllocCleanupGroup(&group);
+ ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(group != NULL, "expected pool != NULL\n");
+
+ /* test TpDisassociateCallback on work objects without group */
+ work = NULL;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ status = pTpAllocWork(&work, disassociate_cb, semaphores, &environment);
+ ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(work != NULL, "expected work != NULL\n");
+
+ pTpPostWork(work);
+ pTpWaitForWork(work, FALSE);
+
+ result = WaitForSingleObject(semaphores[1], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[0], 1, NULL);
+ result = WaitForSingleObject(semaphores[1], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ pTpReleaseWork(work);
+
+ /* test TpDisassociateCallback on work objects with group (1) */
+ work = NULL;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ status = pTpAllocWork(&work, disassociate_cb, semaphores, &environment);
+ ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(work != NULL, "expected work != NULL\n");
+
+ pTpPostWork(work);
+ pTpWaitForWork(work, FALSE);
+
+ result = WaitForSingleObject(semaphores[1], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[0], 1, NULL);
+ result = WaitForSingleObject(semaphores[1], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
+
+ /* test TpDisassociateCallback on work objects with group (2) */
+ work = NULL;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ status = pTpAllocWork(&work, disassociate2_cb, semaphores, &environment);
+ ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(work != NULL, "expected work != NULL\n");
+
+ pTpPostWork(work);
+ pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
+
+ ReleaseSemaphore(semaphores[0], 1, NULL);
+ result = WaitForSingleObject(semaphores[1], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ /* test TpDisassociateCallback on simple callbacks */
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ status = pTpSimpleTryPost(disassociate3_cb, semaphores, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
+
+ ReleaseSemaphore(semaphores[0], 1, NULL);
+ result = WaitForSingleObject(semaphores[1], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ /* cleanup */
+ pTpReleaseCleanupGroup(group);
+ pTpReleasePool(pool);
+ CloseHandle(semaphores[0]);
+ CloseHandle(semaphores[1]);
+}
+
START_TEST(threadpool)
{
if (!init_threadpool())
@@ -508,4 +656,5 @@ START_TEST(threadpool)
test_tp_work_scheduler();
test_tp_group_cancel();
test_tp_instance();
+ test_tp_disassociate();
}
--
2.4.4

View File

@ -1,4 +1,4 @@
From 75e6178d889b0883a03119d372858751d130b751 Mon Sep 17 00:00:00 2001
From aef4ab9059bc29f2449c7ec19cb6562896ac1708 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 08:01:00 +0100
Subject: ntdll: Add remaining threadpool functions to specfile.

View File

@ -1,57 +0,0 @@
From 6bc11921f0b13e7029d5f42f3fd9d2c88891cd41 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 07:07:07 +0100
Subject: ntdll: Implement threadpool RaceDll environment variable.
---
dlls/ntdll/threadpool.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 0133e66..4ae81b0 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -173,6 +173,7 @@ struct threadpool_object
PVOID userdata;
PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback;
PTP_SIMPLE_CALLBACK finalization_callback;
+ HMODULE race_dll;
/* information about the group, locked via .group->cs */
struct list group_entry;
BOOL is_group_member;
@@ -1374,6 +1375,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->userdata = userdata;
object->group_cancel_callback = NULL;
object->finalization_callback = NULL;
+ object->race_dll = NULL;
memset( &object->group_entry, 0, sizeof(object->group_entry) );
object->is_group_member = FALSE;
@@ -1391,10 +1393,14 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup );
object->group_cancel_callback = environment->CleanupGroupCancelCallback;
object->finalization_callback = environment->FinalizationCallback;
+ object->race_dll = environment->RaceDll;
WARN( "environment not fully implemented yet\n" );
}
+ if (object->race_dll)
+ LdrAddRefDll( 0, object->race_dll );
+
TRACE( "allocated object %p of type %u\n", object, object->type );
/* For simple callbacks we have to run tp_object_submit before adding this object
@@ -1560,6 +1566,9 @@ static BOOL tp_object_release( struct threadpool_object *object )
tp_threadpool_unlock( object->pool );
+ if (object->race_dll)
+ LdrUnloadDll( object->race_dll );
+
RtlFreeHeap( GetProcessHeap(), 0, object );
return TRUE;
}
--
2.4.4

View File

@ -1,195 +0,0 @@
From 592d1e479946fc84440b05cc03041ccd5ba07a2b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 07:25:35 +0100
Subject: ntdll: Implement TpCallbackMayRunLong and instance structure.
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/threadpool.c | 91 +++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 82 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 4b5ece5..5a698c4 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 TpCallbackMayRunLong(ptr)
@ stdcall TpPostWork(ptr)
@ stdcall TpReleaseCleanupGroup(ptr)
@ stdcall TpReleaseCleanupGroupMembers(ptr long ptr)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 4ae81b0..8634f44 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -173,6 +173,7 @@ struct threadpool_object
PVOID userdata;
PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback;
PTP_SIMPLE_CALLBACK finalization_callback;
+ BOOL may_run_long;
HMODULE race_dll;
/* information about the group, locked via .group->cs */
struct list group_entry;
@@ -196,6 +197,14 @@ struct threadpool_object
} u;
};
+/* internal threadpool instance representation */
+struct threadpool_instance
+{
+ struct threadpool_object *object;
+ DWORD threadid;
+ BOOL may_run_long;
+};
+
/* internal threadpool group representation */
struct threadpool_group
{
@@ -223,6 +232,11 @@ static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GR
return (struct threadpool_group *)group;
}
+static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CALLBACK_INSTANCE *instance )
+{
+ return (struct threadpool_instance *)instance;
+}
+
static void CALLBACK threadpool_worker_proc( void *param );
static void tp_object_submit( struct threadpool_object *object );
static void tp_object_shutdown( struct threadpool_object *object );
@@ -1375,6 +1389,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->userdata = userdata;
object->group_cancel_callback = NULL;
object->finalization_callback = NULL;
+ object->may_run_long = 0;
object->race_dll = NULL;
memset( &object->group_entry, 0, sizeof(object->group_entry) );
@@ -1393,9 +1408,14 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup );
object->group_cancel_callback = environment->CleanupGroupCancelCallback;
object->finalization_callback = environment->FinalizationCallback;
+ object->may_run_long = environment->u.s.LongFunction != 0;
object->race_dll = environment->RaceDll;
- WARN( "environment not fully implemented yet\n" );
+ if (environment->ActivationContext)
+ FIXME("activation context not supported yet\n");
+
+ if (environment->u.s.Persistent)
+ FIXME("persistent threads not supported yet\n");
}
if (object->race_dll)
@@ -1578,6 +1598,8 @@ static BOOL tp_object_release( struct threadpool_object *object )
*/
static void CALLBACK threadpool_worker_proc( void *param )
{
+ struct threadpool_instance instance;
+ TP_CALLBACK_INSTANCE *cb_instance = (TP_CALLBACK_INSTANCE *)&instance;
struct threadpool *pool = param;
LARGE_INTEGER timeout;
struct list *ptr;
@@ -1603,22 +1625,27 @@ static void CALLBACK threadpool_worker_proc( void *param )
pool->num_busy_workers++;
RtlLeaveCriticalSection( &pool->cs );
+ /* Initialize threadpool instance struct. */
+ instance.object = object;
+ instance.threadid = GetCurrentThreadId();
+ instance.may_run_long = object->may_run_long;
+
switch (object->type)
{
case TP_OBJECT_TYPE_SIMPLE:
{
- TRACE( "executing simple callback %p(NULL, %p)\n",
- object->u.simple.callback, object->userdata );
- object->u.simple.callback( NULL, object->userdata );
+ TRACE( "executing simple callback %p(%p, %p)\n",
+ object->u.simple.callback, cb_instance, object->userdata );
+ object->u.simple.callback( cb_instance, object->userdata );
TRACE( "callback %p returned\n", object->u.simple.callback );
break;
}
case TP_OBJECT_TYPE_WORK:
{
- TRACE( "executing work callback %p(NULL, %p, %p)\n",
- object->u.work.callback, object->userdata, object );
- object->u.work.callback( NULL, object->userdata, (TP_WORK *)object );
+ TRACE( "executing work callback %p(%p, %p, %p)\n",
+ object->u.work.callback, cb_instance, object->userdata, object );
+ object->u.work.callback( cb_instance, object->userdata, (TP_WORK *)object );
TRACE( "callback %p returned\n", object->u.work.callback );
break;
}
@@ -1631,9 +1658,9 @@ static void CALLBACK threadpool_worker_proc( void *param )
/* Execute finalization callback. */
if (object->finalization_callback)
{
- TRACE( "executing finalization callback %p(NULL, %p)\n",
- object->finalization_callback, object->userdata );
- object->finalization_callback( NULL, object->userdata );
+ TRACE( "executing finalization callback %p(%p, %p)\n",
+ object->finalization_callback, cb_instance, object->userdata );
+ object->finalization_callback( cb_instance, object->userdata );
TRACE( "callback %p returned\n", object->finalization_callback );
}
@@ -1725,6 +1752,50 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us
}
/***********************************************************************
+ * TpCallbackMayRunLong (NTDLL.@)
+ */
+NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+ struct threadpool_object *object = this->object;
+ struct threadpool *pool;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TRACE( "%p\n", instance );
+
+ if (this->threadid != GetCurrentThreadId())
+ {
+ ERR("called from wrong thread, ignoring\n");
+ return STATUS_UNSUCCESSFUL; /* FIXME */
+ }
+
+ if (this->may_run_long)
+ return STATUS_SUCCESS;
+
+ pool = object->pool;
+ RtlEnterCriticalSection( &pool->cs );
+
+ /* Start new worker threads if required. */
+ if (pool->num_busy_workers >= pool->num_workers &&
+ pool->num_workers < pool->max_workers)
+ {
+ HANDLE thread;
+ status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0,
+ threadpool_worker_proc, pool, &thread, NULL );
+ if (status == STATUS_SUCCESS)
+ {
+ interlocked_inc( &pool->refcount );
+ pool->num_workers++;
+ NtClose( thread );
+ }
+ }
+
+ RtlLeaveCriticalSection( &pool->cs );
+ this->may_run_long = TRUE;
+ return status;
+}
+
+/***********************************************************************
* TpPostWork (NTDLL.@)
*/
VOID WINAPI TpPostWork( TP_WORK *work )
--
2.4.4

View File

@ -1,4 +1,4 @@
From 04e6df6c221a7f6fc57cfb431d889e62fe64fc47 Mon Sep 17 00:00:00 2001
From e138d4b3eedeb471f70f2e48cdbb8c4c55207554 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 08:19:47 +0100
Subject: ntdll: Implement threadpool timer functions. (rev 2)
@ -58,7 +58,7 @@ index d75efdc..0f4374e 100644
@ stdcall TpWaitForWork(ptr long)
@ stdcall -ret64 VerSetConditionMask(int64 long long)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 9874315..f4c9cba 100644
index 0e09d0f..c44988c 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -158,7 +158,8 @@ struct threadpool
@ -71,7 +71,7 @@ index 9874315..f4c9cba 100644
};
/* internal threadpool object representation */
@@ -194,6 +195,18 @@ struct threadpool_object
@@ -196,6 +197,18 @@ struct threadpool_object
{
PTP_WORK_CALLBACK callback;
} work;
@ -90,7 +90,7 @@ index 9874315..f4c9cba 100644
} u;
};
@@ -225,6 +238,33 @@ struct threadpool_group
@@ -227,6 +240,33 @@ struct threadpool_group
struct list members;
};
@ -124,7 +124,7 @@ index 9874315..f4c9cba 100644
static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool )
{
return (struct threadpool *)pool;
@@ -237,6 +277,13 @@ static inline struct threadpool_object *impl_from_TP_WORK( TP_WORK *work )
@@ -239,6 +279,13 @@ static inline struct threadpool_object *impl_from_TP_WORK( TP_WORK *work )
return object;
}
@ -138,7 +138,7 @@ index 9874315..f4c9cba 100644
static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group )
{
return (struct threadpool_group *)group;
@@ -248,6 +295,7 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL
@@ -250,6 +297,7 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL
}
static void CALLBACK threadpool_worker_proc( void *param );
@ -146,7 +146,7 @@ index 9874315..f4c9cba 100644
static void tp_object_submit( struct threadpool_object *object );
static void tp_object_shutdown( struct threadpool_object *object );
static BOOL tp_object_release( struct threadpool_object *object );
@@ -1171,6 +1219,230 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer,
@@ -1173,6 +1221,230 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer,
return status;
}
@ -377,7 +377,7 @@ index 9874315..f4c9cba 100644
/***********************************************************************
* tp_threadpool_alloc (internal)
*
@@ -1559,6 +1831,9 @@ static void tp_object_wait( struct threadpool_object *object )
@@ -1571,6 +1843,9 @@ static void tp_object_wait( struct threadpool_object *object, BOOL group_wait )
*/
static void tp_object_shutdown( struct threadpool_object *object )
{
@ -387,15 +387,15 @@ index 9874315..f4c9cba 100644
object->shutdown = TRUE;
}
@@ -1668,6 +1943,15 @@ static void CALLBACK threadpool_worker_proc( void *param )
@@ -1682,6 +1957,15 @@ static void CALLBACK threadpool_worker_proc( void *param )
break;
}
+ case TP_OBJECT_TYPE_TIMER:
+ {
+ TRACE( "executing timer callback %p(%p, %p, %p)\n",
+ object->u.timer.callback, cb_instance, object->userdata, object );
+ object->u.timer.callback( cb_instance, object->userdata, (TP_TIMER *)object );
+ object->u.timer.callback, callback_instance, object->userdata, object );
+ object->u.timer.callback( callback_instance, object->userdata, (TP_TIMER *)object );
+ TRACE( "callback %p returned\n", object->u.timer.callback );
+ break;
+ }
@ -403,7 +403,7 @@ index 9874315..f4c9cba 100644
default:
assert(0);
break;
@@ -1768,6 +2052,46 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved )
@@ -1788,6 +2072,46 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved )
}
/***********************************************************************
@ -450,7 +450,7 @@ index 9874315..f4c9cba 100644
* TpAllocWork (NTDLL.@)
*/
NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata,
@@ -1942,6 +2266,17 @@ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance )
@@ -1968,6 +2292,17 @@ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance )
}
/***********************************************************************
@ -468,7 +468,7 @@ index 9874315..f4c9cba 100644
* TpPostWork (NTDLL.@)
*/
VOID WINAPI TpPostWork( TP_WORK *work )
@@ -2041,6 +2376,19 @@ VOID WINAPI TpReleasePool( TP_POOL *pool )
@@ -2067,6 +2402,19 @@ VOID WINAPI TpReleasePool( TP_POOL *pool )
}
/***********************************************************************
@ -488,7 +488,7 @@ index 9874315..f4c9cba 100644
* TpReleaseWork (NTDLL.@)
*/
VOID WINAPI TpReleaseWork( TP_WORK *work )
@@ -2104,6 +2452,18 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum )
@@ -2130,6 +2478,18 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum )
}
/***********************************************************************
@ -507,7 +507,7 @@ index 9874315..f4c9cba 100644
* TpSimpleTryPost (NTDLL.@)
*/
NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata,
@@ -2134,6 +2494,20 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata,
@@ -2160,6 +2520,20 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata,
}
/***********************************************************************
@ -521,7 +521,7 @@ index 9874315..f4c9cba 100644
+
+ if (cancel_pending)
+ tp_object_cancel( this, FALSE, NULL );
+ tp_object_wait( this );
+ tp_object_wait( this, FALSE );
+}
+
+/***********************************************************************

View File

@ -1,99 +0,0 @@
From e6ab4f5a5525d2d65cafef3b45ccd156105ebe46 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 07:31:27 +0100
Subject: ntdll: Implement TpDisassociateCallback.
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/threadpool.c | 42 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 5a698c4..f61728f 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -974,6 +974,7 @@
@ stdcall TpAllocPool(ptr ptr)
@ stdcall TpAllocWork(ptr ptr ptr ptr)
@ stdcall TpCallbackMayRunLong(ptr)
+@ stdcall TpDisassociateCallback(ptr)
@ stdcall TpPostWork(ptr)
@ stdcall TpReleaseCleanupGroup(ptr)
@ stdcall TpReleaseCleanupGroupMembers(ptr long ptr)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 8634f44..6bd3206 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -202,6 +202,7 @@ struct threadpool_instance
{
struct threadpool_object *object;
DWORD threadid;
+ BOOL disassociated;
BOOL may_run_long;
};
@@ -1628,6 +1629,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
/* Initialize threadpool instance struct. */
instance.object = object;
instance.threadid = GetCurrentThreadId();
+ instance.disassociated = FALSE;
instance.may_run_long = object->may_run_long;
switch (object->type)
@@ -1666,9 +1668,12 @@ static void CALLBACK threadpool_worker_proc( void *param )
RtlEnterCriticalSection( &pool->cs );
pool->num_busy_workers--;
- object->num_running_callbacks--;
- if (!object->num_pending_callbacks && !object->num_running_callbacks)
- RtlWakeAllConditionVariable( &object->finished_event );
+ if (!instance.disassociated)
+ {
+ object->num_running_callbacks--;
+ if (!object->num_pending_callbacks && !object->num_running_callbacks)
+ RtlWakeAllConditionVariable( &object->finished_event );
+ }
tp_object_release( object );
}
@@ -1796,6 +1801,37 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance )
}
/***********************************************************************
+ * TpDisassociateCallback (NTDLL.@)
+ */
+VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+ struct threadpool_object *object = this->object;
+ struct threadpool *pool;
+
+ TRACE( "%p\n", instance );
+
+ if (this->threadid != GetCurrentThreadId())
+ {
+ ERR("called from wrong thread, ignoring\n");
+ return;
+ }
+
+ if (this->disassociated)
+ return;
+
+ pool = object->pool;
+ RtlEnterCriticalSection( &pool->cs );
+
+ object->num_running_callbacks--;
+ if (!object->num_pending_callbacks && !object->num_running_callbacks)
+ RtlWakeAllConditionVariable( &object->finished_event );
+
+ RtlLeaveCriticalSection( &pool->cs );
+ this->disassociated = TRUE;
+}
+
+/***********************************************************************
* TpPostWork (NTDLL.@)
*/
VOID WINAPI TpPostWork( TP_WORK *work )
--
2.4.4

View File

@ -1,17 +1,17 @@
From 8d1fba2b1f7b014130cfb64447cba2c2d257864a Mon Sep 17 00:00:00 2001
From 8e03c37240d2a0fafbe6347bc8d509ce5555757a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 13:17:04 +0100
Subject: ntdll/tests: Add tests for Tp* threadpool functions.
---
dlls/ntdll/tests/threadpool.c | 470 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 470 insertions(+)
dlls/ntdll/tests/threadpool.c | 228 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 228 insertions(+)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index b261cd1..76db2d0 100644
index a75b622..4be3a8b 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -22,15 +22,37 @@
@@ -22,18 +22,37 @@
static HMODULE hntdll = 0;
static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **);
@ -21,13 +21,13 @@ index b261cd1..76db2d0 100644
+static NTSTATUS (WINAPI *pTpAllocWait)(TP_WAIT **,PTP_WAIT_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpAllocWork)(TP_WORK **,PTP_WORK_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
+static VOID (WINAPI *pTpCallbackLeaveCriticalSectionOnCompletion)(TP_CALLBACK_INSTANCE *,CRITICAL_SECTION *);
+static NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *);
static NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *);
+static VOID (WINAPI *pTpCallbackReleaseMutexOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE);
+static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE,DWORD);
static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE,DWORD);
+static VOID (WINAPI *pTpCallbackSetEventOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE);
+static VOID (WINAPI *pTpCallbackUnloadDllOnCompletion)(TP_CALLBACK_INSTANCE *,HMODULE);
+static VOID (WINAPI *pTpCancelAsyncIoOperation)(TP_IO *);
+static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *);
static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *);
+static BOOL (WINAPI *pTpIsTimerSet)(TP_TIMER *);
static VOID (WINAPI *pTpPostWork)(TP_WORK *);
static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *);
@ -49,7 +49,7 @@ index b261cd1..76db2d0 100644
static VOID (WINAPI *pTpWaitForWork)(TP_WORK *,BOOL);
#define NTDLL_GET_PROC(func) \
@@ -51,15 +73,37 @@ static BOOL init_threadpool(void)
@@ -54,18 +73,37 @@ static BOOL init_threadpool(void)
}
NTDLL_GET_PROC(TpAllocCleanupGroup);
@ -59,13 +59,13 @@ index b261cd1..76db2d0 100644
+ NTDLL_GET_PROC(TpAllocWait);
NTDLL_GET_PROC(TpAllocWork);
+ NTDLL_GET_PROC(TpCallbackLeaveCriticalSectionOnCompletion);
+ NTDLL_GET_PROC(TpCallbackMayRunLong);
NTDLL_GET_PROC(TpCallbackMayRunLong);
+ NTDLL_GET_PROC(TpCallbackReleaseMutexOnCompletion);
+ NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
+ NTDLL_GET_PROC(TpCallbackSetEventOnCompletion);
+ NTDLL_GET_PROC(TpCallbackUnloadDllOnCompletion);
+ NTDLL_GET_PROC(TpCancelAsyncIoOperation);
+ NTDLL_GET_PROC(TpDisassociateCallback);
NTDLL_GET_PROC(TpDisassociateCallback);
+ NTDLL_GET_PROC(TpIsTimerSet);
NTDLL_GET_PROC(TpPostWork);
NTDLL_GET_PROC(TpReleaseCleanupGroup);
@ -87,244 +87,10 @@ index b261cd1..76db2d0 100644
NTDLL_GET_PROC(TpWaitForWork);
if (!pTpAllocPool)
@@ -307,6 +351,425 @@ static void test_tp_work_scheduler(void)
pTpReleasePool(pool);
@@ -646,6 +684,191 @@ static void test_tp_disassociate(void)
CloseHandle(semaphores[1]);
}
+static void CALLBACK instance_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running instance callback\n");
+ pTpCallbackMayRunLong(instance);
+ Sleep(100);
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+static void CALLBACK instance2_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running instance2 callback\n");
+ ok(*(LONG *)userdata == 1, "expected *userdata = 1, got %u\n", *(LONG *)userdata);
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+static void CALLBACK instance3_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running instance3 callback\n");
+ pTpDisassociateCallback(instance);
+ Sleep(100);
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+static void CALLBACK instance4_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running instance4 callback\n");
+ pTpCallbackReleaseSemaphoreOnCompletion(instance, userdata, 1);
+}
+
+static HANDLE instance_finalization_semaphore;
+
+static void CALLBACK instance_finalization_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ DWORD ret;
+ trace("Running instance finalization callback\n");
+ ok(*(LONG *)userdata == 1, "expected *userdata = 1, got %u\n", *(LONG *)userdata);
+
+ /* Make sure that this callback is called before the regular instance cleanup tasks */
+ ret = WaitForSingleObject(instance_finalization_semaphore, 100);
+ ok(ret == WAIT_TIMEOUT, "expected ret = WAIT_TIMEOUT, got %u\n", ret);
+
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+static void CALLBACK instance5_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running instance5 callback\n");
+ pTpCallbackReleaseSemaphoreOnCompletion(instance, instance_finalization_semaphore, 1);
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+
+static void test_tp_instance(void)
+{
+ TP_CALLBACK_ENVIRON environment;
+ TP_CLEANUP_GROUP *group;
+ TP_POOL *pool;
+ NTSTATUS status;
+ LONG userdata;
+ HANDLE semaphore;
+ DWORD ret;
+
+ /* Allocate new threadpool */
+ pool = NULL;
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(pool != NULL, "expected pool != NULL\n");
+
+ /* We limit the pool to a single thread */
+ pTpSetPoolMaxThreads(pool, 1);
+
+ /* Test behaviour of TpCallbackMayRunLong when the max number of threads is reached */
+ userdata = 0;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ status = pTpSimpleTryPost(instance_cb, &userdata, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ status = pTpSimpleTryPost(instance2_cb, &userdata, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ while (userdata != 2) Sleep(10);
+
+ /* Test behaviour of TpDisassociateCallback on wait functions */
+ group = NULL;
+ status = pTpAllocCleanupGroup(&group);
+ ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(group != NULL, "expected pool != NULL\n");
+
+ userdata = 0;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ status = pTpSimpleTryPost(instance3_cb, &userdata, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
+ todo_wine /* behaviour contradicts the MSDN description? */
+ ok(userdata == 1, "expected userdata = 1, got %u\n", userdata);
+ while (userdata == 0) Sleep(10);
+
+ pTpReleaseCleanupGroup(group);
+
+ /* Test for TpCallbackReleaseSemaphoreOnCompletion */
+ semaphore = CreateSemaphoreW(NULL, 0, 1, NULL);
+ ok(semaphore != NULL, "failed to create semaphore\n");
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ status = pTpSimpleTryPost(instance4_cb, semaphore, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ret = WaitForSingleObject(semaphore, 1000);
+ ok(ret == WAIT_OBJECT_0, "expected ret = WAIT_OBJECT_0, got %u\n", ret);
+
+ /* Test for finalization callback */
+ userdata = 0;
+ instance_finalization_semaphore = semaphore;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.FinalizationCallback = instance_finalization_cb;
+ status = pTpSimpleTryPost(instance5_cb, &userdata, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ret = WaitForSingleObject(semaphore, 1000);
+ ok(ret == WAIT_OBJECT_0, "expected ret = WAIT_OBJECT_0, got %u\n", ret);
+ while (userdata != 2) Sleep(10);
+
+ CloseHandle(semaphore);
+
+ /* Cleanup */
+ pTpReleasePool(pool);
+}
+
+static DWORD group_cancel_tid;
+
+static void CALLBACK group_cancel_cleanup_cb(void *object, void *userdata)
+{
+ trace("Running group cancel cleanup callback\n");
+ InterlockedIncrement( (LONG *)userdata );
+ group_cancel_tid = GetCurrentThreadId();
+}
+
+static void CALLBACK group_cancel_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ trace("Running group cancel callback\n");
+ pTpCallbackMayRunLong(instance);
+ Sleep(100);
+ ok(*(LONG *)userdata == 1, "expected *userdata = 1, got %u\n", *(LONG *)userdata);
+ InterlockedIncrement( (LONG *)userdata );
+}
+
+static void CALLBACK dummy_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ ok(0, "Unexpected call to dummy_cb function\n");
+}
+
+static void test_tp_group_cancel(void)
+{
+ TP_CALLBACK_ENVIRON environment;
+ TP_CLEANUP_GROUP *group;
+ TP_WORK *work;
+ TP_POOL *pool;
+ NTSTATUS status;
+ LONG userdata, userdata2;
+ int i;
+
+ /* Allocate new threadpool */
+ pool = NULL;
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(pool != NULL, "expected pool != NULL\n");
+
+ /* We limit the pool to a single thread */
+ pTpSetPoolMaxThreads(pool, 1);
+
+ /* Allocate a cleanup group */
+ group = NULL;
+ status = pTpAllocCleanupGroup(&group);
+ ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(group != NULL, "expected pool != NULL\n");
+
+ /* Test execution of cancellation callback */
+ userdata = 0;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ status = pTpSimpleTryPost(group_cancel_cb, &userdata, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ environment.CleanupGroupCancelCallback = group_cancel_cleanup_cb;
+ status = pTpSimpleTryPost(dummy_cb, NULL, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ group_cancel_tid = 0;
+ pTpReleaseCleanupGroupMembers(group, TRUE, &userdata);
+ ok(userdata == 1, "expected userdata = 1, got %u\n", userdata);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ GetCurrentThreadId(), group_cancel_tid);
+ while (userdata != 2) Sleep(10);
+
+ /* Test cancellation callback for elements with multiple instances */
+ /* Allocate new work item */
+ work = NULL;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ environment.CleanupGroupCancelCallback = group_cancel_cleanup_cb;
+ status = pTpAllocWork(&work, work_cb, &userdata, &environment);
+ ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(work != NULL, "expected work != NULL\n");
+
+ /* Post 10 identical work items at once */
+ userdata = userdata2 = 0;
+ for (i = 0; i < 10; i++)
+ pTpPostWork(work);
+
+ /* Check if we get multiple cancellation callbacks */
+ group_cancel_tid = 0;
+ pTpReleaseCleanupGroupMembers(group, TRUE, &userdata2);
+ ok(userdata < 10, "expected userdata < 10, got %u\n", userdata);
+ ok(userdata2 == 1, "expected only one cancellation callback, got %u\n", userdata2);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ GetCurrentThreadId(), group_cancel_tid);
+
+ /* Cleanup */
+ pTpReleaseCleanupGroup(group);
+ pTpReleasePool(pool);
+}
+
+static void CALLBACK timer_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER *timer)
+{
+ trace("Running timer callback\n");
@ -513,12 +279,10 @@ index b261cd1..76db2d0 100644
START_TEST(threadpool)
{
if (!init_threadpool())
@@ -315,4 +778,11 @@ START_TEST(threadpool)
test_tp_simple();
test_tp_work();
test_tp_work_scheduler();
+ test_tp_instance();
+ test_tp_group_cancel();
@@ -657,4 +880,9 @@ START_TEST(threadpool)
test_tp_group_cancel();
test_tp_instance();
test_tp_disassociate();
+ test_tp_timer();
+ test_tp_window_length();
+

View File

@ -1,4 +1,4 @@
From e6dda25c2975565acf141011fba0694b27c8c8a0 Mon Sep 17 00:00:00 2001
From 37906069933d6bd73b8c6a691292288c57b09e22 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 1 Feb 2015 19:41:13 +0100
Subject: kernel32: Forward various threadpool functions to ntdll.

View File

@ -1,186 +0,0 @@
From c38bf17c8f87444feca7e4ce3508e55c581671e9 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 07:40:02 +0100
Subject: ntdll: Implement various TpCallback*OnCompletion functions.
---
dlls/ntdll/ntdll.spec | 5 +++
dlls/ntdll/threadpool.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index f61728f..ee90705 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -973,7 +973,12 @@
@ stdcall TpAllocCleanupGroup(ptr)
@ stdcall TpAllocPool(ptr ptr)
@ stdcall TpAllocWork(ptr ptr ptr ptr)
+@ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr)
@ stdcall TpCallbackMayRunLong(ptr)
+@ stdcall TpCallbackReleaseMutexOnCompletion(ptr long)
+@ stdcall TpCallbackReleaseSemaphoreOnCompletion(ptr long long)
+@ stdcall TpCallbackSetEventOnCompletion(ptr long)
+@ stdcall TpCallbackUnloadDllOnCompletion(ptr ptr)
@ stdcall TpDisassociateCallback(ptr)
@ stdcall TpPostWork(ptr)
@ stdcall TpReleaseCleanupGroup(ptr)
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 6bd3206..9874315 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -204,6 +204,15 @@ struct threadpool_instance
DWORD threadid;
BOOL disassociated;
BOOL may_run_long;
+ struct
+ {
+ CRITICAL_SECTION *critical_section;
+ HANDLE mutex;
+ HANDLE semaphore;
+ LONG semaphore_count;
+ HANDLE event;
+ HMODULE library;
+ } cleanup;
};
/* internal threadpool group representation */
@@ -1604,6 +1613,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
struct threadpool *pool = param;
LARGE_INTEGER timeout;
struct list *ptr;
+ NTSTATUS status;
TRACE( "starting worker thread for pool %p\n", pool );
@@ -1631,6 +1641,12 @@ static void CALLBACK threadpool_worker_proc( void *param )
instance.threadid = GetCurrentThreadId();
instance.disassociated = FALSE;
instance.may_run_long = object->may_run_long;
+ instance.cleanup.critical_section = NULL;
+ instance.cleanup.mutex = NULL;
+ instance.cleanup.semaphore = NULL;
+ instance.cleanup.semaphore_count = 0;
+ instance.cleanup.event = NULL;
+ instance.cleanup.library = NULL;
switch (object->type)
{
@@ -1666,6 +1682,32 @@ 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 );
+ }
+ if (instance.cleanup.mutex)
+ {
+ status = NtReleaseMutant( instance.cleanup.mutex, NULL );
+ if (status != STATUS_SUCCESS) goto skip_cleanup;
+ }
+ if (instance.cleanup.semaphore)
+ {
+ status = NtReleaseSemaphore( instance.cleanup.semaphore, instance.cleanup.semaphore_count, NULL );
+ if (status != STATUS_SUCCESS) goto skip_cleanup;
+ }
+ if (instance.cleanup.event)
+ {
+ status = NtSetEvent( instance.cleanup.event, NULL );
+ if (status != STATUS_SUCCESS) goto skip_cleanup;
+ }
+ if (instance.cleanup.library)
+ {
+ LdrUnloadDll( instance.cleanup.library );
+ }
+
+ skip_cleanup:
RtlEnterCriticalSection( &pool->cs );
pool->num_busy_workers--;
if (!instance.disassociated)
@@ -1757,6 +1799,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 )
@@ -1801,6 +1856,61 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance )
}
/***********************************************************************
+ * TpCallbackReleaseMutexOnCompletion (NTDLL.@)
+ */
+VOID WINAPI TpCallbackReleaseMutexOnCompletion( TP_CALLBACK_INSTANCE *instance, HANDLE mutex )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+
+ TRACE( "%p %p\n", instance, mutex );
+
+ if (!this->cleanup.mutex)
+ this->cleanup.mutex = mutex;
+}
+
+/***********************************************************************
+ * TpCallbackReleaseSemaphoreOnCompletion (NTDLL.@)
+ */
+VOID WINAPI TpCallbackReleaseSemaphoreOnCompletion( TP_CALLBACK_INSTANCE *instance, HANDLE semaphore, DWORD count )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+
+ TRACE( "%p %p %u\n", instance, semaphore, count );
+
+ if (!this->cleanup.semaphore)
+ {
+ this->cleanup.semaphore = semaphore;
+ this->cleanup.semaphore_count = count;
+ }
+}
+
+/***********************************************************************
+ * TpCallbackSetEventOnCompletion (NTDLL.@)
+ */
+VOID WINAPI TpCallbackSetEventOnCompletion( TP_CALLBACK_INSTANCE *instance, HANDLE event )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+
+ TRACE( "%p %p\n", instance, event );
+
+ if (!this->cleanup.event)
+ this->cleanup.event = event;
+}
+
+/***********************************************************************
+ * TpCallbackUnloadDllOnCompletion (NTDLL.@)
+ */
+VOID WINAPI TpCallbackUnloadDllOnCompletion( TP_CALLBACK_INSTANCE *instance, HMODULE module )
+{
+ struct threadpool_instance *this = impl_from_TP_CALLBACK_INSTANCE( instance );
+
+ TRACE( "%p %p\n", instance, module );
+
+ if (!this->cleanup.library)
+ this->cleanup.library = module;
+}
+
+/***********************************************************************
* TpDisassociateCallback (NTDLL.@)
*/
VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance )
--
2.4.4

View File

@ -1,4 +1,4 @@
From 008bb589716259fa962bdff580d5ec436bbf8ce4 Mon Sep 17 00:00:00 2001
From 5dd5ac0fa0ef0845cc8611ce664e48e8b25f290b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Mar 2015 13:33:25 +0100
Subject: ntdll: Implement threadpool wait objects.
@ -49,7 +49,7 @@ index 0f4374e..ffcf58d 100644
@ stdcall -ret64 VerSetConditionMask(int64 long long)
@ stdcall WinSqmIsOptedIn()
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index f4c9cba..f569506 100644
index c44988c..b8d761b 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -137,6 +137,7 @@ struct timer_queue
@ -70,7 +70,7 @@ index f4c9cba..f569506 100644
};
/* internal threadpool object representation */
@@ -207,6 +209,17 @@ struct threadpool_object
@@ -209,6 +211,17 @@ struct threadpool_object
LONG period;
LONG window_length;
} timer;
@ -88,7 +88,7 @@ index f4c9cba..f569506 100644
} u;
};
@@ -265,6 +278,38 @@ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug =
@@ -267,6 +280,38 @@ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug =
0, 0, { (DWORD_PTR)(__FILE__ ": timerqueue.cs") }
};
@ -127,7 +127,7 @@ index f4c9cba..f569506 100644
static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool )
{
return (struct threadpool *)pool;
@@ -284,6 +329,13 @@ static inline struct threadpool_object *impl_from_TP_TIMER( TP_TIMER *timer )
@@ -286,6 +331,13 @@ static inline struct threadpool_object *impl_from_TP_TIMER( TP_TIMER *timer )
return object;
}
@ -141,7 +141,7 @@ index f4c9cba..f569506 100644
static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group )
{
return (struct threadpool_group *)group;
@@ -296,7 +348,8 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL
@@ -298,7 +350,8 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL
static void CALLBACK threadpool_worker_proc( void *param );
static void CALLBACK timerqueue_thread_proc( void *param );
@ -151,7 +151,7 @@ index f4c9cba..f569506 100644
static void tp_object_shutdown( struct threadpool_object *object );
static BOOL tp_object_release( struct threadpool_object *object );
static struct threadpool *default_threadpool = NULL;
@@ -1350,7 +1403,7 @@ update_timer:
@@ -1352,7 +1405,7 @@ update_timer:
RtlLeaveCriticalSection( &timerqueue.cs );
if (submit_timer)
@ -160,7 +160,7 @@ index f4c9cba..f569506 100644
}
static void CALLBACK timerqueue_thread_proc( void *param )
@@ -1377,7 +1430,7 @@ static void CALLBACK timerqueue_thread_proc( void *param )
@@ -1379,7 +1432,7 @@ static void CALLBACK timerqueue_thread_proc( void *param )
/* Queue a new callback in one of the worker threads */
list_remove( &timer->u.timer.timer_entry );
@ -169,7 +169,7 @@ index f4c9cba..f569506 100644
/* Requeue the timer, except its marked for shutdown */
if (!timer->shutdown && timer->u.timer.period)
@@ -1443,6 +1496,301 @@ static void CALLBACK timerqueue_thread_proc( void *param )
@@ -1445,6 +1498,301 @@ static void CALLBACK timerqueue_thread_proc( void *param )
RtlLeaveCriticalSection( &timerqueue.cs );
}
@ -471,7 +471,7 @@ index f4c9cba..f569506 100644
/***********************************************************************
* tp_threadpool_alloc (internal)
*
@@ -1710,7 +2058,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
@@ -1714,7 +2062,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
* will be set, and tp_object_submit would fail with an assertion. */
if (is_simple_callback)
@ -480,7 +480,7 @@ index f4c9cba..f569506 100644
if (object->group)
{
@@ -1736,7 +2084,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
@@ -1740,7 +2088,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
* Submits a threadpool object to the associcated threadpool. This
* function has to be VOID because TpPostWork can never fail on Windows.
*/
@ -489,7 +489,7 @@ index f4c9cba..f569506 100644
{
struct threadpool *pool = object->pool;
NTSTATUS status = STATUS_UNSUCCESSFUL;
@@ -1766,6 +2114,10 @@ static void tp_object_submit( struct threadpool_object *object )
@@ -1770,6 +2118,10 @@ static void tp_object_submit( struct threadpool_object *object )
if (!object->num_pending_callbacks++)
list_add_tail( &pool->pool, &object->pool_entry );
@ -500,7 +500,7 @@ index f4c9cba..f569506 100644
/* No new thread started - wake up one existing thread. */
if (status != STATUS_SUCCESS)
{
@@ -1793,6 +2145,9 @@ static void tp_object_cancel( struct threadpool_object *object, BOOL group_cance
@@ -1797,6 +2149,9 @@ static void tp_object_cancel( struct threadpool_object *object, BOOL group_cance
object->num_pending_callbacks = 0;
list_remove( &object->pool_entry );
}
@ -510,7 +510,7 @@ index f4c9cba..f569506 100644
RtlLeaveCriticalSection( &pool->cs );
/* Execute group cancellation callback if defined, and if this was actually a group cancel. */
@@ -1833,6 +2188,8 @@ static void tp_object_shutdown( struct threadpool_object *object )
@@ -1845,6 +2200,8 @@ static void tp_object_shutdown( struct threadpool_object *object )
{
if (object->type == TP_OBJECT_TYPE_TIMER)
tp_timerqueue_release( object );
@ -519,15 +519,15 @@ index f4c9cba..f569506 100644
object->shutdown = TRUE;
}
@@ -1886,6 +2243,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
@@ -1898,6 +2255,7 @@ static void CALLBACK threadpool_worker_proc( void *param )
TP_CALLBACK_INSTANCE *callback_instance;
struct threadpool_instance instance;
TP_CALLBACK_INSTANCE *cb_instance = (TP_CALLBACK_INSTANCE *)&instance;
struct threadpool *pool = param;
+ TP_WAIT_RESULT wait_result;
LARGE_INTEGER timeout;
struct list *ptr;
NTSTATUS status;
@@ -1906,6 +2264,18 @@ static void CALLBACK threadpool_worker_proc( void *param )
@@ -1918,6 +2276,18 @@ static void CALLBACK threadpool_worker_proc( void *param )
if (--object->num_pending_callbacks)
list_add_tail( &pool->pool, &object->pool_entry );
@ -544,17 +544,17 @@ index f4c9cba..f569506 100644
+ }
+
/* Leave critical section and do the actual callback. */
object->num_associated_callbacks++;
object->num_running_callbacks++;
pool->num_busy_workers++;
@@ -1952,6 +2322,15 @@ static void CALLBACK threadpool_worker_proc( void *param )
@@ -1966,6 +2336,15 @@ static void CALLBACK threadpool_worker_proc( void *param )
break;
}
+ case TP_OBJECT_TYPE_WAIT:
+ {
+ TRACE( "executing wait callback %p(%p, %p, %p, %u)\n",
+ object->u.wait.callback, cb_instance, object->userdata, object, wait_result );
+ object->u.wait.callback( cb_instance, object->userdata, (TP_WAIT *)object, wait_result );
+ object->u.wait.callback, callback_instance, object->userdata, object, wait_result );
+ object->u.wait.callback( callback_instance, object->userdata, (TP_WAIT *)object, wait_result );
+ TRACE( "callback %p returned\n", object->u.wait.callback );
+ break;
+ }
@ -562,7 +562,7 @@ index f4c9cba..f569506 100644
default:
assert(0);
break;
@@ -2092,6 +2471,46 @@ NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID
@@ -2112,6 +2491,46 @@ NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID
}
/***********************************************************************
@ -609,7 +609,7 @@ index f4c9cba..f569506 100644
* TpAllocWork (NTDLL.@)
*/
NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata,
@@ -2285,7 +2704,7 @@ VOID WINAPI TpPostWork( TP_WORK *work )
@@ -2311,7 +2730,7 @@ VOID WINAPI TpPostWork( TP_WORK *work )
TRACE( "%p\n", work );
@ -618,7 +618,7 @@ index f4c9cba..f569506 100644
}
/***********************************************************************
@@ -2389,6 +2808,19 @@ VOID WINAPI TpReleaseTimer( TP_TIMER *timer )
@@ -2415,6 +2834,19 @@ VOID WINAPI TpReleaseTimer( TP_TIMER *timer )
}
/***********************************************************************
@ -638,7 +638,7 @@ index f4c9cba..f569506 100644
* TpReleaseWork (NTDLL.@)
*/
VOID WINAPI TpReleaseWork( TP_WORK *work )
@@ -2464,6 +2896,18 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO
@@ -2490,6 +2922,18 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO
}
/***********************************************************************
@ -657,7 +657,7 @@ index f4c9cba..f569506 100644
* TpSimpleTryPost (NTDLL.@)
*/
NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata,
@@ -2508,6 +2952,20 @@ VOID WINAPI TpWaitForTimer( TP_TIMER *timer, BOOL cancel_pending )
@@ -2534,6 +2978,20 @@ VOID WINAPI TpWaitForTimer( TP_TIMER *timer, BOOL cancel_pending )
}
/***********************************************************************
@ -671,7 +671,7 @@ index f4c9cba..f569506 100644
+
+ if (cancel_pending)
+ tp_object_cancel( this, FALSE, NULL );
+ tp_object_wait( this );
+ tp_object_wait( this, FALSE );
+}
+
+/***********************************************************************

View File

@ -1,4 +1,4 @@
From 0f5fd3ad8c585b98f2754738fb9a7bb0e9b83708 Mon Sep 17 00:00:00 2001
From 0aa4ad9970796cbbbe4fc5f81209e6d5d505a385 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 6 Feb 2015 20:09:41 +0100
Subject: ntdll/tests: Add tests for threadpool wait objects.
@ -8,10 +8,10 @@ Subject: ntdll/tests: Add tests for threadpool wait objects.
1 file changed, 287 insertions(+)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index 76db2d0..368692b 100644
index 4be3a8b..fd587ba 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -770,6 +770,291 @@ static void test_tp_window_length(void)
@@ -869,6 +869,291 @@ static void test_tp_window_length(void)
pTpReleasePool(pool);
}
@ -303,8 +303,8 @@ index 76db2d0..368692b 100644
START_TEST(threadpool)
{
if (!init_threadpool())
@@ -782,6 +1067,8 @@ START_TEST(threadpool)
test_tp_group_cancel();
@@ -882,6 +1167,8 @@ START_TEST(threadpool)
test_tp_disassociate();
test_tp_timer();
test_tp_window_length();
+ test_tp_wait();

View File

@ -1,4 +1,4 @@
From 2427c8fb3757a84085d22d176f9f6e797ea64498 Mon Sep 17 00:00:00 2001
From b32a93ef14e23672df3a11ef1e9718857c933ff9 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 6 Feb 2015 20:24:27 +0100
Subject: kernel32: Forward threadpool wait functions to ntdll.

View File

@ -55,7 +55,7 @@ version()
echo "Copyright (C) 2014-2015 the Wine Staging project authors."
echo ""
echo "Patchset to be applied on upstream Wine:"
echo " commit 7a3c9889e38ede659230a66a167b82c024f0dc85"
echo " commit 3d8353fe182f3e7742cd7dab3420635e45ace129"
echo ""
}
@ -3701,26 +3701,18 @@ fi
# | dlls/ntdll/tests/threadpool.c, dlls/ntdll/threadpool.c, include/winternl.h
# |
if test "$enable_ntdll_Vista_Threadpool" -eq 1; then
patch_apply ntdll-Vista_Threadpool/0001-ntdll-Add-support-for-threadpool-group-cancel-callba.patch
patch_apply ntdll-Vista_Threadpool/0002-ntdll-Add-support-for-threadpool-finalization-callba.patch
patch_apply ntdll-Vista_Threadpool/0003-ntdll-Implement-threadpool-RaceDll-environment-varia.patch
patch_apply ntdll-Vista_Threadpool/0004-ntdll-Implement-TpCallbackMayRunLong-and-instance-st.patch
patch_apply ntdll-Vista_Threadpool/0005-ntdll-Implement-TpDisassociateCallback.patch
patch_apply ntdll-Vista_Threadpool/0006-ntdll-Implement-various-TpCallback-OnCompletion-func.patch
patch_apply ntdll-Vista_Threadpool/0007-ntdll-Add-remaining-threadpool-functions-to-specfile.patch
patch_apply ntdll-Vista_Threadpool/0008-ntdll-Implement-threadpool-timer-functions.-rev-2.patch
patch_apply ntdll-Vista_Threadpool/0009-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch
patch_apply ntdll-Vista_Threadpool/0010-kernel32-Forward-various-threadpool-functions-to-ntd.patch
patch_apply ntdll-Vista_Threadpool/0011-ntdll-Implement-threadpool-wait-objects.patch
patch_apply ntdll-Vista_Threadpool/0012-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch
patch_apply ntdll-Vista_Threadpool/0013-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch
patch_apply ntdll-Vista_Threadpool/0001-ntdll-Implement-TpDisassociateCallback-and-add-separ.patch
patch_apply ntdll-Vista_Threadpool/0002-ntdll-tests-Add-tests-for-TpDisassociateCallback.patch
patch_apply ntdll-Vista_Threadpool/0003-ntdll-Add-remaining-threadpool-functions-to-specfile.patch
patch_apply ntdll-Vista_Threadpool/0004-ntdll-Implement-threadpool-timer-functions.-rev-2.patch
patch_apply ntdll-Vista_Threadpool/0005-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch
patch_apply ntdll-Vista_Threadpool/0006-kernel32-Forward-various-threadpool-functions-to-ntd.patch
patch_apply ntdll-Vista_Threadpool/0007-ntdll-Implement-threadpool-wait-objects.patch
patch_apply ntdll-Vista_Threadpool/0008-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch
patch_apply ntdll-Vista_Threadpool/0009-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch
(
echo '+ { "Sebastian Lackner", "ntdll: Add support for threadpool group cancel callback.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Add support for threadpool finalization callback.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement threadpool RaceDll environment variable.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement TpCallbackMayRunLong and instance structure.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement TpDisassociateCallback.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement various TpCallback*OnCompletion functions.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement TpDisassociateCallback and add separate group finished event.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for TpDisassociateCallback.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Add remaining threadpool functions to specfile.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement threadpool timer functions.", 2 },';
echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for Tp* threadpool functions.", 1 },';