The test on line 244 can fail if scheduling happens to preempt the main thread at just the right time, especially if a page fault is hit and I/O is needed or the semaphore implementation is faster than it was when this test was originally written. --- dlls/ntdll/tests/threadpool.c | 62 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c index 7be3f0d..5397419 100644 --- a/dlls/ntdll/tests/threadpool.c +++ b/dlls/ntdll/tests/threadpool.c @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdio.h> +#include <sys/time.h> + #include "ntdll_test.h"
static HMODULE hntdll = 0; @@ -238,7 +241,7 @@ static void test_tp_simple(void) ok(!status, "TpSimpleTryPost failed with status %x\n", status); } pTpReleaseCleanupGroupMembers(group, TRUE, NULL); - ok(userdata < 100, "expected userdata < 100, got %u\n", userdata); + ok(userdata <= 100, "expected userdata <= 100, got %u\n", userdata);
/* cleanup */ pTpReleaseCleanupGroup(group); @@ -1235,11 +1238,15 @@ static void CALLBACK multi_wait_cb(TP_CALLBACK_INSTANCE *instance, void *userdat ReleaseSemaphore(multi_wait_info.semaphore, 1, NULL); }
+#define TP_TEST_SIZE 512 static void test_tp_multi_wait(void) { TP_CALLBACK_ENVIRON environment; - HANDLE semaphores[512]; - TP_WAIT *waits[512]; + HANDLE semaphores[TP_TEST_SIZE]; + TP_WAIT *waits[TP_TEST_SIZE]; + int rand_order[TP_TEST_SIZE]; + struct timeval now; + unsigned int seed; LARGE_INTEGER when; HANDLE semaphore; NTSTATUS status; @@ -1247,7 +1254,7 @@ static void test_tp_multi_wait(void) DWORD result; int i;
- semaphore = CreateSemaphoreW(NULL, 0, 512, NULL); + semaphore = CreateSemaphoreW(NULL, 0, TP_TEST_SIZE, NULL); ok(semaphore != NULL, "failed to create semaphore\n"); multi_wait_info.semaphore = semaphore;
@@ -1261,8 +1268,27 @@ static void test_tp_multi_wait(void) environment.Version = 1; environment.Pool = pool;
+ /* init a randomized index */ + if (gettimeofday (&now, NULL)) + perror("gettimeofday"); + seed = now.tv_sec ^ now.tv_usec; + + memset(&rand_order, 0, TP_TEST_SIZE * sizeof(rand_order[0])); + for (i = 1; i < TP_TEST_SIZE; i++) + { + int j; + for (j = rand_r(&seed) % TP_TEST_SIZE; ; j = (j + 1) % TP_TEST_SIZE) + { + if (!rand_order[j]) + { + rand_order[j] = i; + break; + } + } + } + /* create semaphores and corresponding wait objects */ - for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { semaphores[i] = CreateSemaphoreW(NULL, 0, 1, NULL); ok(semaphores[i] != NULL, "failed to create semaphore %i\n", i); @@ -1276,7 +1302,7 @@ static void test_tp_multi_wait(void) }
/* release all semaphores and wait for callback */ - for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { multi_wait_info.result = 0; ReleaseSemaphore(semaphores[i], 1, NULL); @@ -1289,7 +1315,7 @@ static void test_tp_multi_wait(void) }
/* repeat the same test in reverse order */ - for (i = sizeof(semaphores)/sizeof(semaphores[0]) - 1; i >= 0; i--) + for (i = TP_TEST_SIZE - 1; i >= 0; i--) { multi_wait_info.result = 0; ReleaseSemaphore(semaphores[i], 1, NULL); @@ -1301,15 +1327,29 @@ static void test_tp_multi_wait(void) pTpSetWait(waits[i], semaphores[i], NULL); }
+ /* repeat again in random order */ + for (i = 0; i < TP_TEST_SIZE; i++) + { + int j = rand_order[i]; + multi_wait_info.result = 0; + ReleaseSemaphore(semaphores[j], 1, NULL); + + result = WaitForSingleObject(semaphore, 100); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + ok(multi_wait_info.result == j, "expected result %d, got %u\n", j, multi_wait_info.result); + + pTpSetWait(waits[j], semaphores[j], NULL); + } + /* test timeout of wait objects */ multi_wait_info.result = 0; - for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { when.QuadPart = (ULONGLONG)50 * -10000; pTpSetWait(waits[i], semaphores[i], &when); }
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { result = WaitForSingleObject(semaphore, 150); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); @@ -1318,14 +1358,14 @@ static void test_tp_multi_wait(void) ok(multi_wait_info.result >> 16, "expected multi_wait_info.result >> 16 != 0\n");
/* destroy the wait objects and semaphores while waiting */ - for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { pTpSetWait(waits[i], semaphores[i], NULL); }
Sleep(50);
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) + for (i = 0; i < TP_TEST_SIZE; i++) { pTpReleaseWait(waits[i]); NtClose(semaphores[i]);