You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-09-12 18:50:20 -07:00
Rebase against 8b566b1da71a412fe58c3cc1988d610c2aba5f2d.
This commit is contained in:
@@ -1,175 +0,0 @@
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,191 +0,0 @@
|
||||
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,18 +1,66 @@
|
||||
From 0aa4ad9970796cbbbe4fc5f81209e6d5d505a385 Mon Sep 17 00:00:00 2001
|
||||
From c8a3a30a9d4f4a3609d59298d486b691f682390e 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.
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/threadpool.c | 287 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 287 insertions(+)
|
||||
dlls/ntdll/tests/threadpool.c | 295 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 295 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
|
||||
index 4be3a8b..fd587ba 100644
|
||||
index 0671202..9904d46 100644
|
||||
--- a/dlls/ntdll/tests/threadpool.c
|
||||
+++ b/dlls/ntdll/tests/threadpool.c
|
||||
@@ -869,6 +869,291 @@ static void test_tp_window_length(void)
|
||||
pTpReleasePool(pool);
|
||||
@@ -24,11 +24,13 @@ static HMODULE hntdll = 0;
|
||||
static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **);
|
||||
static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID);
|
||||
static NTSTATUS (WINAPI *pTpAllocTimer)(TP_TIMER **,PTP_TIMER_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+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 NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *);
|
||||
static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE,DWORD);
|
||||
static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *);
|
||||
static BOOL (WINAPI *pTpIsTimerSet)(TP_TIMER *);
|
||||
+static VOID (WINAPI *pTpReleaseWait)(TP_WAIT *);
|
||||
static VOID (WINAPI *pTpPostWork)(TP_WORK *);
|
||||
static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *);
|
||||
static VOID (WINAPI *pTpReleaseCleanupGroupMembers)(TP_CLEANUP_GROUP *,BOOL,PVOID);
|
||||
@@ -37,8 +39,10 @@ static VOID (WINAPI *pTpReleaseTimer)(TP_TIMER *);
|
||||
static VOID (WINAPI *pTpReleaseWork)(TP_WORK *);
|
||||
static VOID (WINAPI *pTpSetPoolMaxThreads)(TP_POOL *,DWORD);
|
||||
static VOID (WINAPI *pTpSetTimer)(TP_TIMER *,LARGE_INTEGER *,LONG,LONG);
|
||||
+static VOID (WINAPI *pTpSetWait)(TP_WAIT *,HANDLE,LARGE_INTEGER *);
|
||||
static NTSTATUS (WINAPI *pTpSimpleTryPost)(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
static VOID (WINAPI *pTpWaitForTimer)(TP_TIMER *,BOOL);
|
||||
+static VOID (WINAPI *pTpWaitForWait)(TP_WAIT *,BOOL);
|
||||
static VOID (WINAPI *pTpWaitForWork)(TP_WORK *,BOOL);
|
||||
|
||||
#define NTDLL_GET_PROC(func) \
|
||||
@@ -61,6 +65,7 @@ static BOOL init_threadpool(void)
|
||||
NTDLL_GET_PROC(TpAllocCleanupGroup);
|
||||
NTDLL_GET_PROC(TpAllocPool);
|
||||
NTDLL_GET_PROC(TpAllocTimer);
|
||||
+ NTDLL_GET_PROC(TpAllocWait);
|
||||
NTDLL_GET_PROC(TpAllocWork);
|
||||
NTDLL_GET_PROC(TpCallbackMayRunLong);
|
||||
NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
|
||||
@@ -71,11 +76,14 @@ static BOOL init_threadpool(void)
|
||||
NTDLL_GET_PROC(TpReleaseCleanupGroupMembers);
|
||||
NTDLL_GET_PROC(TpReleasePool);
|
||||
NTDLL_GET_PROC(TpReleaseTimer);
|
||||
+ NTDLL_GET_PROC(TpReleaseWait);
|
||||
NTDLL_GET_PROC(TpReleaseWork);
|
||||
NTDLL_GET_PROC(TpSetPoolMaxThreads);
|
||||
NTDLL_GET_PROC(TpSetTimer);
|
||||
+ NTDLL_GET_PROC(TpSetWait);
|
||||
NTDLL_GET_PROC(TpSimpleTryPost);
|
||||
NTDLL_GET_PROC(TpWaitForTimer);
|
||||
+ NTDLL_GET_PROC(TpWaitForWait);
|
||||
NTDLL_GET_PROC(TpWaitForWork);
|
||||
|
||||
if (!pTpAllocPool)
|
||||
@@ -906,6 +914,291 @@ static void test_tp_window_length(void)
|
||||
CloseHandle(semaphore);
|
||||
}
|
||||
|
||||
+static void CALLBACK wait_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WAIT *wait, TP_WAIT_RESULT result)
|
||||
@@ -303,15 +351,13 @@ index 4be3a8b..fd587ba 100644
|
||||
START_TEST(threadpool)
|
||||
{
|
||||
if (!init_threadpool())
|
||||
@@ -882,6 +1167,8 @@ START_TEST(threadpool)
|
||||
@@ -919,4 +1212,6 @@ START_TEST(threadpool)
|
||||
test_tp_disassociate();
|
||||
test_tp_timer();
|
||||
test_tp_window_length();
|
||||
+ test_tp_wait();
|
||||
+ test_tp_multi_wait();
|
||||
|
||||
/* FIXME: Make sure worker threads have terminated before. */
|
||||
Sleep(100);
|
||||
}
|
||||
--
|
||||
2.4.4
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From b32a93ef14e23672df3a11ef1e9718857c933ff9 Mon Sep 17 00:00:00 2001
|
||||
From 898045c05b21aa7cbdfb168f4b4ce8ffb06b1ae0 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.
|
||||
@@ -10,7 +10,7 @@ Subject: kernel32: Forward threadpool wait functions to ntdll.
|
||||
3 files changed, 51 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
|
||||
index 337b339..146db0f 100644
|
||||
index a14d03b..77e55e1 100644
|
||||
--- a/dlls/kernel32/kernel32.spec
|
||||
+++ b/dlls/kernel32/kernel32.spec
|
||||
@@ -233,7 +233,7 @@
|
||||
@@ -50,10 +50,10 @@ index 337b339..146db0f 100644
|
||||
@ stdcall WaitNamedPipeA (str long)
|
||||
@ stdcall WaitNamedPipeW (wstr long)
|
||||
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
|
||||
index 945fe0b..89b0b60 100644
|
||||
index 21ec276..d592692 100644
|
||||
--- a/dlls/kernel32/thread.c
|
||||
+++ b/dlls/kernel32/thread.c
|
||||
@@ -923,6 +923,27 @@ PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userd
|
||||
@@ -942,6 +942,27 @@ PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userd
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -81,9 +81,9 @@ index 945fe0b..89b0b60 100644
|
||||
* CreateThreadpoolWork (KERNEL32.@)
|
||||
*/
|
||||
PTP_WORK WINAPI CreateThreadpoolWork( PTP_WORK_CALLBACK callback, PVOID userdata,
|
||||
@@ -961,3 +982,25 @@ VOID WINAPI SetThreadpoolTimer( TP_TIMER *timer, FILETIME *due_time,
|
||||
@@ -1000,3 +1021,25 @@ BOOL WINAPI TrySubmitThreadpoolCallback( PTP_SIMPLE_CALLBACK callback, PVOID use
|
||||
|
||||
TpSetTimer( timer, due_time ? &timeout : NULL, period, window_length );
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+/***********************************************************************
|
||||
@@ -1,84 +0,0 @@
|
||||
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.
|
||||
|
||||
---
|
||||
dlls/ntdll/ntdll.spec | 43 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 43 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
|
||||
index ee90705..d75efdc 100644
|
||||
--- a/dlls/ntdll/ntdll.spec
|
||||
+++ b/dlls/ntdll/ntdll.spec
|
||||
@@ -970,24 +970,67 @@
|
||||
@ stdcall RtlxOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize
|
||||
@ stdcall RtlxUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize
|
||||
@ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize
|
||||
+# @ stub TpAllocAlpcCompletion
|
||||
+# @ stub TpAllocAlpcCompletionEx
|
||||
@ stdcall TpAllocCleanupGroup(ptr)
|
||||
+# @ stub TpAllocIoCompletion
|
||||
+# @ stub TpAllocJobNotification
|
||||
@ stdcall TpAllocPool(ptr ptr)
|
||||
+# @ stub TpAllocTimer
|
||||
+# @ stub TpAllocWait
|
||||
@ stdcall TpAllocWork(ptr ptr ptr ptr)
|
||||
+# @ stub TpAlpcRegisterCompletionList
|
||||
+# @ stub TpAlpcUnregisterCompletionList
|
||||
+# @ stub TpCallbackDetectedUnrecoverableError
|
||||
+# @ stub TpCallbackIndependent
|
||||
@ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr)
|
||||
@ stdcall TpCallbackMayRunLong(ptr)
|
||||
@ stdcall TpCallbackReleaseMutexOnCompletion(ptr long)
|
||||
@ stdcall TpCallbackReleaseSemaphoreOnCompletion(ptr long long)
|
||||
+# @ stub TpCallbackSendAlpcMessageOnCompletion
|
||||
+# @ stub TpCallbackSendPendingAlpcMessage
|
||||
@ stdcall TpCallbackSetEventOnCompletion(ptr long)
|
||||
@ stdcall TpCallbackUnloadDllOnCompletion(ptr ptr)
|
||||
+# @ stub TpCancelAsyncIoOperation
|
||||
+# @ stub TpCaptureCaller
|
||||
+# @ stub TpCheckTerminateWorker
|
||||
+# @ stub TpDbgDumpHeapUsage
|
||||
+# @ stub TpDbgSetLogRoutine
|
||||
+# @ stub TpDisablePoolCallbackChecks
|
||||
@ stdcall TpDisassociateCallback(ptr)
|
||||
+# @ stub TpIsTimerSet
|
||||
@ stdcall TpPostWork(ptr)
|
||||
+# @ stub TpQueryPoolStackInformation
|
||||
+# @ stub TpReleaseAlpcCompletion
|
||||
@ stdcall TpReleaseCleanupGroup(ptr)
|
||||
@ stdcall TpReleaseCleanupGroupMembers(ptr long ptr)
|
||||
+# @ stub TpReleaseIoCompletion
|
||||
+# @ stub TpReleaseJobNotification
|
||||
@ stdcall TpReleasePool(ptr)
|
||||
+# @ stub TpReleaseTimer
|
||||
+# @ stub TpReleaseWait
|
||||
@ stdcall TpReleaseWork(ptr)
|
||||
+# @ stub TpSetDefaultPoolMaxThreads
|
||||
+# @ stub TpSetDefaultPoolStackInformation
|
||||
@ stdcall TpSetPoolMaxThreads(ptr long)
|
||||
+# @ stub TpSetPoolMaxThreadsSoftLimit
|
||||
@ stdcall TpSetPoolMinThreads(ptr long)
|
||||
+# @ stub TpSetPoolStackInformation
|
||||
+# @ stub TpSetPoolThreadBasePriority
|
||||
+# @ stub TpSetPoolWorkerThreadIdleTimeout
|
||||
+# @ stub TpSetTimer
|
||||
+# @ stub TpSetTimerEx
|
||||
+# @ stub TpSetWait
|
||||
+# @ stub TpSetWaitEx
|
||||
@ stdcall TpSimpleTryPost(ptr ptr ptr)
|
||||
+# @ stub TpStartAsyncIoOperation
|
||||
+# @ stub TpTimerOutstandingCallbackCount
|
||||
+# @ stub TpTrimPools
|
||||
+# @ stub TpWaitForAlpcCompletion
|
||||
+# @ stub TpWaitForIoCompletion
|
||||
+# @ stub TpWaitForJobNotification
|
||||
+# @ stub TpWaitForTimer
|
||||
+# @ stub TpWaitForWait
|
||||
@ stdcall TpWaitForWork(ptr long)
|
||||
@ stdcall -ret64 VerSetConditionMask(int64 long long)
|
||||
@ stdcall WinSqmIsOptedIn()
|
||||
--
|
||||
2.4.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,294 +0,0 @@
|
||||
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 | 228 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 228 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
|
||||
index a75b622..4be3a8b 100644
|
||||
--- a/dlls/ntdll/tests/threadpool.c
|
||||
+++ b/dlls/ntdll/tests/threadpool.c
|
||||
@@ -22,18 +22,37 @@
|
||||
|
||||
static HMODULE hntdll = 0;
|
||||
static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **);
|
||||
+static NTSTATUS (WINAPI *pTpAllocIoCompletion)(TP_IO **,HANDLE,PTP_WIN32_IO_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID);
|
||||
+static NTSTATUS (WINAPI *pTpAllocTimer)(TP_TIMER **,PTP_TIMER_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+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 VOID (WINAPI *pTpCallbackReleaseMutexOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE);
|
||||
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 BOOL (WINAPI *pTpIsTimerSet)(TP_TIMER *);
|
||||
static VOID (WINAPI *pTpPostWork)(TP_WORK *);
|
||||
static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *);
|
||||
static VOID (WINAPI *pTpReleaseCleanupGroupMembers)(TP_CLEANUP_GROUP *,BOOL,PVOID);
|
||||
+static VOID (WINAPI *pTpReleaseIoCompletion)(TP_IO *);
|
||||
static VOID (WINAPI *pTpReleasePool)(TP_POOL *);
|
||||
+static VOID (WINAPI *pTpReleaseTimer)(TP_TIMER *);
|
||||
+static VOID (WINAPI *pTpReleaseWait)(TP_WAIT *);
|
||||
static VOID (WINAPI *pTpReleaseWork)(TP_WORK *);
|
||||
static VOID (WINAPI *pTpSetPoolMaxThreads)(TP_POOL *,DWORD);
|
||||
+static BOOL (WINAPI *pTpSetPoolMinThreads)(TP_POOL *,DWORD);
|
||||
+static VOID (WINAPI *pTpSetTimer)(TP_TIMER *,LARGE_INTEGER *,LONG,LONG);
|
||||
+static VOID (WINAPI *pTpSetWait)(TP_WAIT *,HANDLE,LARGE_INTEGER *);
|
||||
static NTSTATUS (WINAPI *pTpSimpleTryPost)(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+static VOID (WINAPI *pTpStartAsyncIoOperation)(TP_IO *);
|
||||
+static VOID (WINAPI *pTpWaitForIoCompletion)(TP_IO *,BOOL);
|
||||
+static VOID (WINAPI *pTpWaitForTimer)(TP_TIMER *,BOOL);
|
||||
+static VOID (WINAPI *pTpWaitForWait)(TP_WAIT *,BOOL);
|
||||
static VOID (WINAPI *pTpWaitForWork)(TP_WORK *,BOOL);
|
||||
|
||||
#define NTDLL_GET_PROC(func) \
|
||||
@@ -54,18 +73,37 @@ static BOOL init_threadpool(void)
|
||||
}
|
||||
|
||||
NTDLL_GET_PROC(TpAllocCleanupGroup);
|
||||
+ NTDLL_GET_PROC(TpAllocIoCompletion);
|
||||
NTDLL_GET_PROC(TpAllocPool);
|
||||
+ NTDLL_GET_PROC(TpAllocTimer);
|
||||
+ NTDLL_GET_PROC(TpAllocWait);
|
||||
NTDLL_GET_PROC(TpAllocWork);
|
||||
+ NTDLL_GET_PROC(TpCallbackLeaveCriticalSectionOnCompletion);
|
||||
NTDLL_GET_PROC(TpCallbackMayRunLong);
|
||||
+ NTDLL_GET_PROC(TpCallbackReleaseMutexOnCompletion);
|
||||
NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
|
||||
+ NTDLL_GET_PROC(TpCallbackSetEventOnCompletion);
|
||||
+ NTDLL_GET_PROC(TpCallbackUnloadDllOnCompletion);
|
||||
+ NTDLL_GET_PROC(TpCancelAsyncIoOperation);
|
||||
NTDLL_GET_PROC(TpDisassociateCallback);
|
||||
+ NTDLL_GET_PROC(TpIsTimerSet);
|
||||
NTDLL_GET_PROC(TpPostWork);
|
||||
NTDLL_GET_PROC(TpReleaseCleanupGroup);
|
||||
NTDLL_GET_PROC(TpReleaseCleanupGroupMembers);
|
||||
+ NTDLL_GET_PROC(TpReleaseIoCompletion);
|
||||
NTDLL_GET_PROC(TpReleasePool);
|
||||
+ NTDLL_GET_PROC(TpReleaseTimer);
|
||||
+ NTDLL_GET_PROC(TpReleaseWait);
|
||||
NTDLL_GET_PROC(TpReleaseWork);
|
||||
NTDLL_GET_PROC(TpSetPoolMaxThreads);
|
||||
+ NTDLL_GET_PROC(TpSetPoolMinThreads);
|
||||
+ NTDLL_GET_PROC(TpSetTimer);
|
||||
+ NTDLL_GET_PROC(TpSetWait);
|
||||
NTDLL_GET_PROC(TpSimpleTryPost);
|
||||
+ NTDLL_GET_PROC(TpStartAsyncIoOperation);
|
||||
+ NTDLL_GET_PROC(TpWaitForIoCompletion);
|
||||
+ NTDLL_GET_PROC(TpWaitForTimer);
|
||||
+ NTDLL_GET_PROC(TpWaitForWait);
|
||||
NTDLL_GET_PROC(TpWaitForWork);
|
||||
|
||||
if (!pTpAllocPool)
|
||||
@@ -646,6 +684,191 @@ static void test_tp_disassociate(void)
|
||||
CloseHandle(semaphores[1]);
|
||||
}
|
||||
|
||||
+static void CALLBACK timer_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER *timer)
|
||||
+{
|
||||
+ trace("Running timer callback\n");
|
||||
+ InterlockedIncrement( (LONG *)userdata );
|
||||
+}
|
||||
+
|
||||
+static void test_tp_timer(void)
|
||||
+{
|
||||
+ TP_CALLBACK_ENVIRON environment;
|
||||
+ TP_TIMER *timer;
|
||||
+ TP_POOL *pool;
|
||||
+ NTSTATUS status;
|
||||
+ LONG userdata;
|
||||
+ BOOL success;
|
||||
+ LARGE_INTEGER when;
|
||||
+ DWORD ticks;
|
||||
+
|
||||
+ /* 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");
|
||||
+
|
||||
+ /* Allocate new timer item */
|
||||
+ timer = NULL;
|
||||
+ memset(&environment, 0, sizeof(environment));
|
||||
+ environment.Version = 1;
|
||||
+ environment.Pool = pool;
|
||||
+ status = pTpAllocTimer(&timer, timer_cb, &userdata, &environment);
|
||||
+ ok(!status, "TpAllocTimer failed with status %x\n", status);
|
||||
+ ok(timer != NULL, "expected timer != NULL\n");
|
||||
+
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(!success, "expected TpIsTimerSet(...) = FALSE\n");
|
||||
+
|
||||
+ /* Set a relative timeout */
|
||||
+ userdata = 0;
|
||||
+ when.QuadPart = (ULONGLONG)500 * -10000;
|
||||
+ pTpSetTimer(timer, &when, 0, 0);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Wait until timer has triggered */
|
||||
+ pTpWaitForTimer(timer, FALSE);
|
||||
+ Sleep(250);
|
||||
+ ok(userdata == 0, "expected userdata = 0, got %u\n", userdata);
|
||||
+ while (userdata == 0) Sleep(10);
|
||||
+ ok(userdata == 1, "expected userdata = 1, got %u\n", userdata);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Set an absolute timeout */
|
||||
+ userdata = 0;
|
||||
+ NtQuerySystemTime( &when );
|
||||
+ when.QuadPart += (ULONGLONG)500 * 10000;
|
||||
+ pTpSetTimer(timer, &when, 0, 0);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Wait until timer has triggered */
|
||||
+ pTpWaitForTimer(timer, FALSE);
|
||||
+ Sleep(250);
|
||||
+ ok(userdata == 0, "expected userdata = 0, got %u\n", userdata);
|
||||
+ while (userdata == 0) Sleep(10);
|
||||
+ ok(userdata == 1, "expected userdata = 1, got %u\n", userdata);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Test a relative timeout repeated periodically */
|
||||
+ userdata = 0;
|
||||
+ when.QuadPart = (ULONGLONG)50 * -10000;
|
||||
+ pTpSetTimer(timer, &when, 50, 0);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Wait until the timer was triggered a couple of times */
|
||||
+ ticks = GetTickCount();
|
||||
+ while (userdata < 100) Sleep(10);
|
||||
+ ticks = GetTickCount() - ticks;
|
||||
+ pTpSetTimer(timer, NULL, 0, 0);
|
||||
+ pTpWaitForTimer(timer, TRUE);
|
||||
+ ok(ticks >= 4500 && ticks <= 5500, "expected approximately 5000 ticks, got %u\n", ticks);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(!success, "expected TpIsTimerSet(...) = FALSE\n");
|
||||
+
|
||||
+ /* Test with zero timeout, we expect a call immediately */
|
||||
+ userdata = 0;
|
||||
+ when.QuadPart = 0;
|
||||
+ pTpSetTimer(timer, &when, 0, 0);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Wait until timer has triggered */
|
||||
+ pTpWaitForTimer(timer, FALSE);
|
||||
+ ok(userdata == 1 || broken(userdata == 0) /* Win 8 */,
|
||||
+ "expected userdata = 1, got %u\n", userdata);
|
||||
+ while (userdata == 0) Sleep(10);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(success, "expected TpIsTimerSet(...) = TRUE\n");
|
||||
+
|
||||
+ /* Unset the timer again */
|
||||
+ pTpSetTimer(timer, NULL, 0, 0);
|
||||
+ success = pTpIsTimerSet(timer);
|
||||
+ ok(!success, "expected TpIsTimerSet(...) = FALSE\n");
|
||||
+
|
||||
+ /* Cleanup */
|
||||
+ pTpReleaseTimer(timer);
|
||||
+ pTpReleasePool(pool);
|
||||
+}
|
||||
+
|
||||
+static void CALLBACK window_length_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER *timer)
|
||||
+{
|
||||
+ trace("Running window length callback\n");
|
||||
+ (*(DWORD *)userdata) = GetTickCount();
|
||||
+}
|
||||
+
|
||||
+static void test_tp_window_length(void)
|
||||
+{
|
||||
+ TP_CALLBACK_ENVIRON environment;
|
||||
+ TP_TIMER *timer, *timer2;
|
||||
+ DWORD ticks, ticks2;
|
||||
+ TP_POOL *pool;
|
||||
+ NTSTATUS status;
|
||||
+ LARGE_INTEGER when;
|
||||
+
|
||||
+ /* 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");
|
||||
+
|
||||
+ /* Allocate two identical timers */
|
||||
+ timer = NULL;
|
||||
+ memset(&environment, 0, sizeof(environment));
|
||||
+ environment.Version = 1;
|
||||
+ environment.Pool = pool;
|
||||
+ status = pTpAllocTimer(&timer, window_length_cb, &ticks, &environment);
|
||||
+ ok(!status, "TpAllocTimer failed with status %x\n", status);
|
||||
+ ok(timer != NULL, "expected timer != NULL\n");
|
||||
+
|
||||
+ timer2 = NULL;
|
||||
+ status = pTpAllocTimer(&timer2, window_length_cb, &ticks2, &environment);
|
||||
+ ok(!status, "TpAllocTimer failed with status %x\n", status);
|
||||
+ ok(timer2 != NULL, "expected timer2 != NULL\n");
|
||||
+
|
||||
+ /* Choose parameters so that timers are not merged */
|
||||
+ ticks = ticks2 = 0;
|
||||
+ NtQuerySystemTime( &when );
|
||||
+ when.QuadPart += (ULONGLONG)500 * 10000;
|
||||
+ pTpSetTimer(timer2, &when, 0, 0);
|
||||
+ Sleep(50);
|
||||
+ when.QuadPart -= (ULONGLONG)400 * 10000;
|
||||
+ pTpSetTimer(timer, &when, 0, 200);
|
||||
+ while (!ticks || !ticks2) Sleep(10);
|
||||
+ ok(ticks2 >= ticks + 150, "expected that timers are not merged\n");
|
||||
+
|
||||
+ /* On Windows the timers also get merged in this case */
|
||||
+ ticks = ticks2 = 0;
|
||||
+ NtQuerySystemTime( &when );
|
||||
+ when.QuadPart += (ULONGLONG)100 * 10000;
|
||||
+ pTpSetTimer(timer, &when, 0, 450);
|
||||
+ Sleep(50);
|
||||
+ when.QuadPart += (ULONGLONG)400 * 10000;
|
||||
+ pTpSetTimer(timer2, &when, 0, 0);
|
||||
+ while (!ticks || !ticks2) Sleep(10);
|
||||
+ todo_wine
|
||||
+ ok(ticks2 >= ticks - 50 && ticks2 <= ticks + 50, "expected that timers are merged\n");
|
||||
+
|
||||
+ /* Timers will be merged */
|
||||
+ ticks = ticks2 = 0;
|
||||
+ NtQuerySystemTime( &when );
|
||||
+ when.QuadPart += (ULONGLONG)500 * 10000;
|
||||
+ pTpSetTimer(timer2, &when, 0, 0);
|
||||
+ Sleep(50);
|
||||
+ when.QuadPart -= (ULONGLONG)400 * 10000;
|
||||
+ pTpSetTimer(timer, &when, 0, 450);
|
||||
+ while (!ticks || !ticks2) Sleep(10);
|
||||
+ ok(ticks2 >= ticks - 50 && ticks2 <= ticks + 50, "expected that timers are merged\n");
|
||||
+
|
||||
+ /* Cleanup */
|
||||
+ pTpReleaseTimer(timer);
|
||||
+ pTpReleaseTimer(timer2);
|
||||
+ pTpReleasePool(pool);
|
||||
+}
|
||||
+
|
||||
START_TEST(threadpool)
|
||||
{
|
||||
if (!init_threadpool())
|
||||
@@ -657,4 +880,9 @@ START_TEST(threadpool)
|
||||
test_tp_group_cancel();
|
||||
test_tp_instance();
|
||||
test_tp_disassociate();
|
||||
+ test_tp_timer();
|
||||
+ test_tp_window_length();
|
||||
+
|
||||
+ /* FIXME: Make sure worker threads have terminated before. */
|
||||
+ Sleep(100);
|
||||
}
|
||||
--
|
||||
2.4.4
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
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.
|
||||
|
||||
---
|
||||
dlls/kernel32/kernel32.spec | 48 ++++++++++----------
|
||||
dlls/kernel32/tests/thread.c | 6 +--
|
||||
dlls/kernel32/thread.c | 101 +++++++++++++++++++++++++++++++++++++++++++
|
||||
include/winternl.h | 27 ++++++++++++
|
||||
4 files changed, 155 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
|
||||
index 3c40975..337b339 100644
|
||||
--- a/dlls/kernel32/kernel32.spec
|
||||
+++ b/dlls/kernel32/kernel32.spec
|
||||
@@ -204,7 +204,7 @@
|
||||
@ stdcall BuildCommDCBAndTimeoutsA(str ptr ptr)
|
||||
@ stdcall BuildCommDCBAndTimeoutsW(wstr ptr ptr)
|
||||
@ stdcall BuildCommDCBW(wstr ptr)
|
||||
-# @ stub CallbackMayRunLong
|
||||
+@ stdcall CallbackMayRunLong(ptr) ntdll.TpCallbackMayRunLong
|
||||
@ stdcall CallNamedPipeA(str ptr long ptr long ptr long)
|
||||
@ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long)
|
||||
@ stub CancelDeviceWakeupRequest
|
||||
@@ -228,13 +228,13 @@
|
||||
# @ stub ClosePrivateNamespace
|
||||
@ stdcall CloseProfileUserMapping()
|
||||
@ stub CloseSystemHandle
|
||||
-# @ stub CloseThreadpool
|
||||
-# @ stub CloseThreadpoolCleanupGroup
|
||||
-# @ stub CloseThreadpoolCleanupGroupMembers
|
||||
+@ stdcall CloseThreadpool(ptr) ntdll.TpReleasePool
|
||||
+@ stdcall CloseThreadpoolCleanupGroup(ptr) ntdll.TpReleaseCleanupGroup
|
||||
+@ stdcall CloseThreadpoolCleanupGroupMembers(ptr long ptr) ntdll.TpReleaseCleanupGroupMembers
|
||||
# @ stub CloseThreadpoolIo
|
||||
-# @ stub CloseThreadpoolTimer
|
||||
+@ stdcall CloseThreadpoolTimer(ptr) ntdll.TpReleaseTimer
|
||||
# @ stub CloseThreadpoolWait
|
||||
-# @ stub CloseThreadpoolWork
|
||||
+@ stdcall CloseThreadpoolWork(ptr) ntdll.TpReleaseWork
|
||||
@ stdcall CmdBatNotification(long)
|
||||
@ stdcall CommConfigDialogA(str long ptr)
|
||||
@ stdcall CommConfigDialogW(wstr long ptr)
|
||||
@@ -331,12 +331,12 @@
|
||||
@ stdcall CreateSymbolicLinkW(wstr wstr long)
|
||||
@ stdcall CreateTapePartition(long long long long)
|
||||
@ stdcall CreateThread(ptr long ptr long long ptr)
|
||||
-# @ stub CreateThreadpool
|
||||
-# @ stub CreateThreadpoolCleanupGroup
|
||||
+@ stdcall CreateThreadpool(ptr)
|
||||
+@ stdcall CreateThreadpoolCleanupGroup()
|
||||
# @ stub CreateThreadpoolIo
|
||||
-# @ stub CreateThreadpoolTimer
|
||||
+@ stdcall CreateThreadpoolTimer(ptr ptr ptr)
|
||||
# @ stub CreateThreadpoolWait
|
||||
-# @ stub CreateThreadpoolWork
|
||||
+@ stdcall CreateThreadpoolWork(ptr ptr ptr)
|
||||
@ stdcall CreateTimerQueue ()
|
||||
@ stdcall CreateTimerQueueTimer(ptr long ptr ptr long long long)
|
||||
@ stdcall CreateToolhelp32Snapshot(long long)
|
||||
@@ -369,7 +369,7 @@
|
||||
@ stdcall DeleteFileW(wstr)
|
||||
# @ stub DeleteProcThreadAttributeList
|
||||
# @ stub DisableThreadProfiling
|
||||
-# @ stub DisassociateCurrentThreadFromCallback
|
||||
+@ stdcall DisassociateCurrentThreadFromCallback(ptr) ntdll.TpDisassociateCallback
|
||||
@ stdcall DeleteTimerQueue(long)
|
||||
@ stdcall DeleteTimerQueueEx (long long)
|
||||
@ stdcall DeleteTimerQueueTimer(long long long)
|
||||
@@ -495,7 +495,6 @@
|
||||
@ stdcall FindFirstVolumeMountPointA(str ptr long)
|
||||
@ stdcall FindFirstVolumeMountPointW(wstr ptr long)
|
||||
@ stdcall FindFirstVolumeW(ptr long)
|
||||
-# @ stub FreeLibraryWhenCallbackReturns
|
||||
@ stdcall FindNextChangeNotification(long)
|
||||
@ stdcall FindNextFileA(long ptr)
|
||||
# @ stub FindNextFileNameW
|
||||
@@ -533,6 +532,7 @@
|
||||
@ stub -i386 FreeLSCallback
|
||||
@ stdcall FreeLibrary(long)
|
||||
@ stdcall FreeLibraryAndExitThread(long long)
|
||||
+@ stdcall FreeLibraryWhenCallbackReturns(ptr ptr) ntdll.TpCallbackUnloadDllOnCompletion
|
||||
@ stdcall FreeResource(long)
|
||||
@ stdcall -i386 -private FreeSLCallback(long) krnl386.exe16.FreeSLCallback
|
||||
@ stub FreeUserPhysicalPages
|
||||
@@ -981,7 +981,7 @@
|
||||
@ stub -i386 IsSLCallback
|
||||
@ stdcall IsSystemResumeAutomatic()
|
||||
@ stdcall IsThreadAFiber()
|
||||
-# @ stub IsThreadpoolTimerSet
|
||||
+@ stdcall IsThreadpoolTimerSet(ptr) ntdll.TpIsTimerSet
|
||||
# @ stub IsTimeZoneRedirectionEnabled
|
||||
# @ stub IsValidCalDateTime
|
||||
@ stdcall IsValidCodePage(long)
|
||||
@@ -1035,7 +1035,7 @@
|
||||
@ stdcall LZSeek(long long long)
|
||||
@ stdcall LZStart()
|
||||
@ stdcall LeaveCriticalSection(ptr) ntdll.RtlLeaveCriticalSection
|
||||
-# @ stub LeaveCriticalSectionWhenCallbackReturns
|
||||
+@ stdcall LeaveCriticalSectionWhenCallbackReturns(ptr ptr) ntdll.TpCallbackLeaveCriticalSectionOnCompletion
|
||||
# @ stub LoadAppInitDlls
|
||||
@ stdcall LoadLibraryA(str)
|
||||
@ stdcall LoadLibraryExA( str long long)
|
||||
@@ -1252,9 +1252,9 @@
|
||||
@ stdcall ReinitializeCriticalSection(ptr)
|
||||
@ stdcall ReleaseActCtx(ptr)
|
||||
@ stdcall ReleaseMutex(long)
|
||||
-# @ stub ReleaseMutexWhenCallbackReturns
|
||||
+@ stdcall ReleaseMutexWhenCallbackReturns(ptr long) ntdll.TpCallbackReleaseMutexOnCompletion
|
||||
@ stdcall ReleaseSemaphore(long long ptr)
|
||||
-# @ stub ReleaseSemaphoreWhenCallbackReturns
|
||||
+@ stdcall ReleaseSemaphoreWhenCallbackReturns(ptr long long) ntdll.TpCallbackReleaseSemaphoreOnCompletion
|
||||
@ stdcall ReleaseSRWLockExclusive(ptr) ntdll.RtlReleaseSRWLockExclusive
|
||||
@ stdcall ReleaseSRWLockShared(ptr) ntdll.RtlReleaseSRWLockShared
|
||||
@ stdcall RemoveDirectoryA(str)
|
||||
@@ -1385,7 +1385,7 @@
|
||||
@ stdcall SetEnvironmentVariableW(wstr wstr)
|
||||
@ stdcall SetErrorMode(long)
|
||||
@ stdcall SetEvent(long)
|
||||
-# @ stub SetEventWhenCallbackReturns
|
||||
+@ stdcall SetEventWhenCallbackReturns(ptr long) ntdll.TpCallbackSetEventOnCompletion
|
||||
@ stdcall SetFileApisToANSI()
|
||||
@ stdcall SetFileApisToOEM()
|
||||
@ stdcall SetFileAttributesA(str long)
|
||||
@@ -1454,9 +1454,9 @@
|
||||
# @ stub SetThreadToken
|
||||
@ stdcall SetThreadUILanguage(long)
|
||||
# @ stub SetThreadpoolStackInformation
|
||||
-# @ stub SetThreadpoolThreadMaximum
|
||||
-# @ stub SetThreadpoolThreadMinimum
|
||||
-# @ stub SetThreadpoolTimer
|
||||
+@ stdcall SetThreadpoolThreadMaximum(ptr long) ntdll.TpSetPoolMaxThreads
|
||||
+@ stdcall SetThreadpoolThreadMinimum(ptr long) ntdll.TpSetPoolMinThreads
|
||||
+@ stdcall SetThreadpoolTimer(ptr ptr long long)
|
||||
# @ stub SetThreadpoolWait
|
||||
@ stdcall SetTimeZoneInformation(ptr)
|
||||
@ stub SetTimerQueueTimer
|
||||
@@ -1482,7 +1482,7 @@
|
||||
# @ stub SortCloseHandle
|
||||
# @ stub SortGetHandle
|
||||
# @ stub StartThreadpoolIo
|
||||
-# @ stub SubmitThreadpoolWork
|
||||
+@ stdcall SubmitThreadpoolWork(ptr) ntdll.TpPostWork
|
||||
@ stdcall SuspendThread(long)
|
||||
@ stdcall SwitchToFiber(ptr)
|
||||
@ stdcall SwitchToThread()
|
||||
@@ -1509,7 +1509,7 @@
|
||||
@ stdcall TryAcquireSRWLockExclusive(ptr) ntdll.RtlTryAcquireSRWLockExclusive
|
||||
@ stdcall TryAcquireSRWLockShared(ptr) ntdll.RtlTryAcquireSRWLockShared
|
||||
@ stdcall TryEnterCriticalSection(ptr) ntdll.RtlTryEnterCriticalSection
|
||||
-# @ stub TrySubmitThreadpoolCallback
|
||||
+@ stdcall TrySubmitThreadpoolCallback(ptr ptr ptr) ntdll.TpSimpleTryPost
|
||||
@ stdcall TzSpecificLocalTimeToSystemTime(ptr ptr ptr)
|
||||
# @ stub TzSpecificLocalTimeToSystemTimeEx
|
||||
# @ stub -arch=x86_64 uaw_lstrcmpW
|
||||
@@ -1571,9 +1571,9 @@
|
||||
@ stdcall WaitForSingleObject(long long)
|
||||
@ stdcall WaitForSingleObjectEx(long long long)
|
||||
# @ stub WaitForThreadpoolIoCallbacks
|
||||
-# @ stub WaitForThreadpoolTimerCallbacks
|
||||
+@ stdcall WaitForThreadpoolTimerCallbacks(ptr long) ntdll.TpWaitForTimer
|
||||
# @ stub WaitForThreadpoolWaitCallbacks
|
||||
-# @ stub WaitForThreadpoolWorkCallbacks
|
||||
+@ stdcall WaitForThreadpoolWorkCallbacks(ptr long) ntdll.TpWaitForWork
|
||||
@ stdcall WaitNamedPipeA (str long)
|
||||
@ stdcall WaitNamedPipeW (wstr long)
|
||||
@ stdcall WakeAllConditionVariable(ptr) ntdll.RtlWakeAllConditionVariable
|
||||
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
|
||||
index d3ecd2a..25801b2 100644
|
||||
--- a/dlls/kernel32/tests/thread.c
|
||||
+++ b/dlls/kernel32/tests/thread.c
|
||||
@@ -1627,8 +1627,8 @@ static void test_threadpool(void)
|
||||
int workcalled = 0;
|
||||
|
||||
if (!pCreateThreadpool) {
|
||||
- todo_wine win_skip("thread pool apis not supported.\n");
|
||||
- return;
|
||||
+ win_skip("thread pool apis not supported.\n");
|
||||
+ return;
|
||||
}
|
||||
|
||||
work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
|
||||
@@ -1640,7 +1640,7 @@ static void test_threadpool(void)
|
||||
ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
|
||||
|
||||
pool = pCreateThreadpool(NULL);
|
||||
- todo_wine ok (pool != NULL, "CreateThreadpool failed\n");
|
||||
+ ok (pool != NULL, "CreateThreadpool failed\n");
|
||||
}
|
||||
|
||||
static void test_reserved_tls(void)
|
||||
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
|
||||
index 3dabf94..945fe0b 100644
|
||||
--- a/dlls/kernel32/thread.c
|
||||
+++ b/dlls/kernel32/thread.c
|
||||
@@ -860,3 +860,104 @@ BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, PULONG count, PCZZWSTR b
|
||||
*buffersize = 0;
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * CreateThreadpool (KERNEL32.@)
|
||||
+ */
|
||||
+PTP_POOL WINAPI CreateThreadpool( PVOID reserved )
|
||||
+{
|
||||
+ TP_POOL *pool;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ TRACE( "%p\n", reserved );
|
||||
+
|
||||
+ status = TpAllocPool( &pool, reserved );
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return pool;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * CreateThreadpoolCleanupGroup (KERNEL32.@)
|
||||
+ */
|
||||
+PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup( void )
|
||||
+{
|
||||
+ TP_CLEANUP_GROUP *group;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ TRACE( "\n" );
|
||||
+
|
||||
+ status = TpAllocCleanupGroup( &group );
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return group;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * CreateThreadpoolTimer (KERNEL32.@)
|
||||
+ */
|
||||
+PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userdata,
|
||||
+ TP_CALLBACK_ENVIRON *environment )
|
||||
+{
|
||||
+ TP_TIMER *timer;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ TRACE( "%p, %p, %p\n", callback, userdata, environment );
|
||||
+
|
||||
+ status = TpAllocTimer( &timer, callback, userdata, environment );
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return timer;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * CreateThreadpoolWork (KERNEL32.@)
|
||||
+ */
|
||||
+PTP_WORK WINAPI CreateThreadpoolWork( PTP_WORK_CALLBACK callback, PVOID userdata,
|
||||
+ TP_CALLBACK_ENVIRON *environment )
|
||||
+{
|
||||
+ TP_WORK *work;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ TRACE( "%p, %p, %p\n", callback, userdata, environment );
|
||||
+
|
||||
+ status = TpAllocWork( &work, callback, userdata, environment );
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return work;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * SetThreadpoolTimer (KERNEL32.@)
|
||||
+ */
|
||||
+VOID WINAPI SetThreadpoolTimer( TP_TIMER *timer, FILETIME *due_time,
|
||||
+ DWORD period, DWORD window_length )
|
||||
+{
|
||||
+ LARGE_INTEGER timeout;
|
||||
+
|
||||
+ TRACE( "%p, %p, %u, %u\n", timer, due_time, period, window_length );
|
||||
+
|
||||
+ if (due_time)
|
||||
+ {
|
||||
+ timeout.u.LowPart = due_time->dwLowDateTime;
|
||||
+ timeout.u.HighPart = due_time->dwHighDateTime;
|
||||
+ }
|
||||
+
|
||||
+ TpSetTimer( timer, due_time ? &timeout : NULL, period, window_length );
|
||||
+}
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index a84c6d4..e1707fd 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -2616,6 +2616,33 @@ NTSYSAPI LONGLONG WINAPI RtlLargeIntegerSubtract(LONGLONG,LONGLONG);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlLargeIntegerToChar(const ULONGLONG *,ULONG,ULONG,PCHAR);
|
||||
#endif
|
||||
|
||||
+/* Threadpool functions */
|
||||
+
|
||||
+NTSYSAPI NTSTATUS WINAPI TpAllocCleanupGroup(TP_CLEANUP_GROUP **);
|
||||
+NTSYSAPI NTSTATUS WINAPI TpAllocPool(TP_POOL **,PVOID);
|
||||
+NTSYSAPI NTSTATUS WINAPI TpAllocTimer(TP_TIMER **,PTP_TIMER_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+NTSYSAPI NTSTATUS WINAPI TpAllocWork(TP_WORK **,PTP_WORK_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+NTSYSAPI void WINAPI TpCallbackLeaveCriticalSectionOnCompletion(TP_CALLBACK_INSTANCE *,RTL_CRITICAL_SECTION *);
|
||||
+NTSYSAPI NTSTATUS WINAPI TpCallbackMayRunLong(TP_CALLBACK_INSTANCE *);
|
||||
+NTSYSAPI void WINAPI TpCallbackReleaseMutexOnCompletion(TP_CALLBACK_INSTANCE *,HANDLE);
|
||||
+NTSYSAPI void WINAPI TpCallbackReleaseSemaphoreOnCompletion(TP_CALLBACK_INSTANCE *,HANDLE,DWORD);
|
||||
+NTSYSAPI void WINAPI TpCallbackSetEventOnCompletion(TP_CALLBACK_INSTANCE *,HANDLE);
|
||||
+NTSYSAPI void WINAPI TpCallbackUnloadDllOnCompletion(TP_CALLBACK_INSTANCE *,HMODULE);
|
||||
+NTSYSAPI void WINAPI TpDisassociateCallback(TP_CALLBACK_INSTANCE *);
|
||||
+NTSYSAPI BOOL WINAPI TpIsTimerSet(TP_TIMER *);
|
||||
+NTSYSAPI void WINAPI TpPostWork(TP_WORK *);
|
||||
+NTSYSAPI void WINAPI TpReleaseCleanupGroup(TP_CLEANUP_GROUP *);
|
||||
+NTSYSAPI void WINAPI TpReleaseCleanupGroupMembers(TP_CLEANUP_GROUP *,BOOL,PVOID);
|
||||
+NTSYSAPI void WINAPI TpReleasePool(TP_POOL *);
|
||||
+NTSYSAPI void WINAPI TpReleaseTimer(TP_TIMER *);
|
||||
+NTSYSAPI void WINAPI TpReleaseWork(TP_WORK *);
|
||||
+NTSYSAPI void WINAPI TpSetPoolMaxThreads(TP_POOL *,DWORD);
|
||||
+NTSYSAPI BOOL WINAPI TpSetPoolMinThreads(TP_POOL *,DWORD);
|
||||
+NTSYSAPI void WINAPI TpSetTimer(TP_TIMER *, LARGE_INTEGER *,LONG,LONG);
|
||||
+NTSYSAPI NTSTATUS WINAPI TpSimpleTryPost(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
|
||||
+NTSYSAPI void WINAPI TpWaitForTimer(TP_TIMER *,BOOL);
|
||||
+NTSYSAPI void WINAPI TpWaitForWork(TP_WORK *,BOOL);
|
||||
+
|
||||
/* Wine internal functions */
|
||||
|
||||
NTSYSAPI NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret,
|
||||
--
|
||||
2.4.4
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Fixes: [35192] Add implementation for CreateThreadpool
|
||||
Fixes: [32531] Implement threadpool work items
|
||||
Fixes: [37306] Implement threadpool timers
|
||||
# Fixes: [35192] Add implementation for CreateThreadpool
|
||||
# Fixes: [32531] Implement threadpool work items
|
||||
# Fixes: [37306] Implement threadpool timers
|
||||
Fixes: Implement threadpool wait objects
|
||||
|
||||
Reference in New Issue
Block a user