mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Rebase against 3d8353fe182f3e7742cd7dab3420635e45ace129.
This commit is contained in:
parent
16aad8a55f
commit
dfd86e0f91
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
@ -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
|
||||
|
@ -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();
|
||||
+
|
@ -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.
|
@ -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
|
||||
|
@ -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 );
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
@ -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();
|
@ -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.
|
@ -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 },';
|
||||
|
Loading…
x
Reference in New Issue
Block a user