1 /* 2 * Synchronization tests 3 * 4 * Copyright 2005 Mike McCormack for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #ifndef __REACTOS__ 22 #define _WIN32_WINNT 0x500 23 #endif 24 #include <stdarg.h> 25 #include <stdlib.h> 26 #include <stdio.h> 27 #include <windef.h> 28 #include <winbase.h> 29 #include <winternl.h> 30 31 #include "wine/test.h" 32 33 #ifdef __REACTOS__ 34 #define QueryDepthSList(x) RtlQueryDepthSList(x) 35 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y) 36 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x) 37 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x) 38 #endif 39 40 #undef __fastcall 41 #define __fastcall __stdcall 42 43 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE); 44 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL); 45 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE); 46 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*); 47 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*); 48 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID); 49 50 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE); 51 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD); 52 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG); 53 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE); 54 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE); 55 56 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK); 57 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK); 58 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK); 59 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK); 60 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); 61 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); 62 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); 63 64 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); 65 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); 66 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); 67 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); 68 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, 69 PSLIST_ENTRY last, ULONG count); 70 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first, 71 PSLIST_ENTRY last, ULONG count); 72 73 #ifdef __i386__ 74 75 #include "pshpack1.h" 76 struct fastcall_thunk 77 { 78 BYTE pop_edx; /* popl %edx (ret addr) */ 79 BYTE pop_eax; /* popl %eax (func) */ 80 BYTE pop_ecx; /* popl %ecx (param 1) */ 81 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */ 82 WORD jmp_eax; /* jmp *%eax */ 83 }; 84 #include "poppack.h" 85 86 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d); 87 88 static void init_fastcall_thunk(void) 89 { 90 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 91 thunk->pop_edx = 0x5a; /* popl %edx */ 92 thunk->pop_eax = 0x58; /* popl %eax */ 93 thunk->pop_ecx = 0x59; /* popl %ecx */ 94 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */ 95 thunk->xchg[1] = 0x14; 96 thunk->xchg[2] = 0x24; 97 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */ 98 call_fastcall_func4 = (void *)thunk; 99 } 100 101 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \ 102 (const void *)(b), (const void *)(c), (const void *)(d)) 103 104 #else /* __i386__ */ 105 106 #define init_fastcall_thunk() do { } while(0) 107 #define call_func4(func, a, b, c, d) func(a, b, c, d) 108 109 #endif /* __i386__ */ 110 111 static void test_signalandwait(void) 112 { 113 DWORD r; 114 HANDLE event[2], semaphore[2], file; 115 int i; 116 117 /* invalid parameters */ 118 r = SignalObjectAndWait(NULL, NULL, 0, 0); 119 ok( r == WAIT_FAILED, "should fail\n"); 120 121 event[0] = CreateEventW(NULL, 0, 0, NULL); 122 event[1] = CreateEventW(NULL, 1, 1, NULL); 123 124 ok( event[0] && event[1], "failed to create event flags\n"); 125 126 r = SignalObjectAndWait(event[0], NULL, 0, FALSE); 127 ok( r == WAIT_FAILED, "should fail\n"); 128 129 r = SignalObjectAndWait(NULL, event[0], 0, FALSE); 130 ok( r == WAIT_FAILED, "should fail\n"); 131 132 133 /* valid parameters */ 134 r = SignalObjectAndWait(event[0], event[1], 0, FALSE); 135 ok( r == WAIT_OBJECT_0, "should succeed\n"); 136 137 /* event[0] is now signalled - we repeat this test multiple times 138 * to ensure that the wineserver handles this situation properly. */ 139 for (i = 0; i < 10000; i++) 140 { 141 r = SignalObjectAndWait(event[0], event[0], 0, FALSE); 142 ok(r == WAIT_OBJECT_0, "should succeed\n"); 143 } 144 145 /* event[0] is not signalled */ 146 r = WaitForSingleObject(event[0], 0); 147 ok( r == WAIT_TIMEOUT, "event was signalled\n"); 148 149 r = SignalObjectAndWait(event[0], event[0], 0, FALSE); 150 ok( r == WAIT_OBJECT_0, "should succeed\n"); 151 152 /* clear event[1] and check for a timeout */ 153 ok(ResetEvent(event[1]), "failed to clear event[1]\n"); 154 r = SignalObjectAndWait(event[0], event[1], 0, FALSE); 155 ok( r == WAIT_TIMEOUT, "should timeout\n"); 156 157 CloseHandle(event[0]); 158 CloseHandle(event[1]); 159 160 /* semaphores */ 161 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL ); 162 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL ); 163 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n"); 164 165 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 166 ok( r == WAIT_OBJECT_0, "should succeed\n"); 167 168 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 169 ok( r == WAIT_FAILED, "should fail\n"); 170 171 r = ReleaseSemaphore(semaphore[0],1,NULL); 172 ok( r == FALSE, "should fail\n"); 173 174 r = ReleaseSemaphore(semaphore[1],1,NULL); 175 ok( r == TRUE, "should succeed\n"); 176 177 CloseHandle(semaphore[0]); 178 CloseHandle(semaphore[1]); 179 180 /* try a registry key */ 181 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 182 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); 183 r = SignalObjectAndWait(file, file, 0, FALSE); 184 ok( r == WAIT_FAILED, "should fail\n"); 185 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n"); 186 CloseHandle(file); 187 } 188 189 static void test_mutex(void) 190 { 191 DWORD wait_ret; 192 BOOL ret; 193 HANDLE hCreated; 194 HANDLE hOpened; 195 int i; 196 DWORD failed = 0; 197 198 SetLastError(0xdeadbeef); 199 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 200 ok(hOpened == NULL, "OpenMutex succeeded\n"); 201 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 202 203 SetLastError(0xdeadbeef); 204 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex"); 205 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError()); 206 207 SetLastError(0xdeadbeef); 208 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 209 todo_wine 210 ok(hOpened == NULL, "OpenMutex succeeded\n"); 211 todo_wine 212 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError()); 213 214 SetLastError(0xdeadbeef); 215 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex"); 216 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 217 wait_ret = WaitForSingleObject(hOpened, INFINITE); 218 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError()); 219 CloseHandle(hOpened); 220 221 for(i=0; i < 31; i++) 222 { 223 wait_ret = WaitForSingleObject(hCreated, INFINITE); 224 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret); 225 } 226 227 SetLastError(0xdeadbeef); 228 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); 229 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 230 wait_ret = WaitForSingleObject(hOpened, INFINITE); 231 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); 232 CloseHandle(hOpened); 233 234 for (i = 0; i < 32; i++) 235 { 236 SetLastError(0xdeadbeef); 237 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex"); 238 if(hOpened != NULL) 239 { 240 SetLastError(0xdeadbeef); 241 ret = ReleaseMutex(hOpened); 242 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i); 243 CloseHandle(hOpened); 244 } 245 else 246 { 247 if ((1 << i) == ACCESS_SYSTEM_SECURITY) 248 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i); 249 else 250 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i); 251 ReleaseMutex(hCreated); 252 failed |=0x1 << i; 253 } 254 } 255 256 todo_wine 257 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed); 258 259 SetLastError(0xdeadbeef); 260 ret = ReleaseMutex(hCreated); 261 ok(!ret && (GetLastError() == ERROR_NOT_OWNER), 262 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError()); 263 264 /* test case sensitivity */ 265 266 SetLastError(0xdeadbeef); 267 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX"); 268 ok(!hOpened, "OpenMutex succeeded\n"); 269 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 270 271 SetLastError(0xdeadbeef); 272 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex"); 273 ok(!hOpened, "OpenMutex succeeded\n"); 274 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 275 276 SetLastError(0xdeadbeef); 277 hOpened = OpenMutexA(READ_CONTROL, FALSE, NULL); 278 ok(!hOpened, "OpenMutex succeeded\n"); 279 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 280 281 SetLastError(0xdeadbeef); 282 hOpened = OpenMutexW(READ_CONTROL, FALSE, NULL); 283 ok(!hOpened, "OpenMutex succeeded\n"); 284 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 285 286 SetLastError(0xdeadbeef); 287 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex"); 288 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 289 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 290 CloseHandle(hOpened); 291 292 SetLastError(0xdeadbeef); 293 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX"); 294 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 295 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 296 CloseHandle(hOpened); 297 298 CloseHandle(hCreated); 299 } 300 301 static void test_slist(void) 302 { 303 struct item 304 { 305 SLIST_ENTRY entry; 306 int value; 307 } item1, item2, item3, *item; 308 SLIST_HEADER slist_header; 309 SLIST_ENTRY *entry; 310 USHORT size; 311 int i; 312 313 item1.value = 1; 314 item2.value = 2; 315 item3.value = 3; 316 317 memset(&slist_header, 0xff, sizeof(slist_header)); 318 InitializeSListHead(&slist_header); 319 size = QueryDepthSList(&slist_header); 320 ok(size == 0, "Expected size == 0, got %u\n", size); 321 322 /* test PushEntry, PopEntry and Flush */ 323 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 324 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 325 size = QueryDepthSList(&slist_header); 326 ok(size == 1, "Expected size == 1, got %u\n", size); 327 328 entry = InterlockedPushEntrySList(&slist_header, &item2.entry); 329 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 330 item = CONTAINING_RECORD(entry, struct item, entry); 331 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 332 size = QueryDepthSList(&slist_header); 333 ok(size == 2, "Expected size == 2, got %u\n", size); 334 335 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 336 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 337 item = CONTAINING_RECORD(entry, struct item, entry); 338 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 339 size = QueryDepthSList(&slist_header); 340 ok(size == 3, "Expected size == 3, got %u\n", size); 341 342 entry = InterlockedPopEntrySList(&slist_header); 343 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 344 item = CONTAINING_RECORD(entry, struct item, entry); 345 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 346 size = QueryDepthSList(&slist_header); 347 ok(size == 2, "Expected size == 2, got %u\n", size); 348 349 entry = InterlockedFlushSList(&slist_header); 350 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 351 item = CONTAINING_RECORD(entry, struct item, entry); 352 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 353 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 354 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 355 size = QueryDepthSList(&slist_header); 356 ok(size == 0, "Expected size == 0, got %u\n", size); 357 entry = InterlockedPopEntrySList(&slist_header); 358 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 359 360 /* test RtlInterlockedPushListSList */ 361 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 362 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 363 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42); 364 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 365 item = CONTAINING_RECORD(entry, struct item, entry); 366 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 367 size = QueryDepthSList(&slist_header); 368 ok(size == 43, "Expected size == 43, got %u\n", size); 369 370 entry = InterlockedPopEntrySList(&slist_header); 371 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 372 item = CONTAINING_RECORD(entry, struct item, entry); 373 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 374 size = QueryDepthSList(&slist_header); 375 ok(size == 42, "Expected size == 42, got %u\n", size); 376 377 entry = InterlockedPopEntrySList(&slist_header); 378 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 379 item = CONTAINING_RECORD(entry, struct item, entry); 380 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 381 size = QueryDepthSList(&slist_header); 382 ok(size == 41, "Expected size == 41, got %u\n", size); 383 384 entry = InterlockedPopEntrySList(&slist_header); 385 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 386 item = CONTAINING_RECORD(entry, struct item, entry); 387 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 388 size = QueryDepthSList(&slist_header); 389 ok(size == 40, "Expected size == 40, got %u\n", size); 390 391 entry = InterlockedPopEntrySList(&slist_header); 392 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 393 size = QueryDepthSList(&slist_header); 394 ok(size == 40, "Expected size == 40, got %u\n", size); 395 396 entry = InterlockedFlushSList(&slist_header); 397 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 398 size = QueryDepthSList(&slist_header); 399 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size); 400 401 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 402 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 403 entry = InterlockedFlushSList(&slist_header); 404 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 405 item = CONTAINING_RECORD(entry, struct item, entry); 406 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 407 size = QueryDepthSList(&slist_header); 408 ok(size == 0, "Expected size == 0, got %u\n", size); 409 410 /* test RtlInterlockedPushListSListEx */ 411 if (pRtlInterlockedPushListSListEx) 412 { 413 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 414 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 415 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42); 416 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 417 item = CONTAINING_RECORD(entry, struct item, entry); 418 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 419 size = QueryDepthSList(&slist_header); 420 ok(size == 43, "Expected size == 43, got %u\n", size); 421 422 entry = InterlockedFlushSList(&slist_header); 423 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 424 item = CONTAINING_RECORD(entry, struct item, entry); 425 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 426 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 427 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 428 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 429 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 430 size = QueryDepthSList(&slist_header); 431 ok(size == 0, "Expected size == 0, got %u\n", size); 432 } 433 else 434 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n"); 435 436 /* test with a lot of items */ 437 for (i = 0; i < 65536; i++) 438 { 439 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item)); 440 item->value = i + 1; 441 entry = InterlockedPushEntrySList(&slist_header, &item->entry); 442 if (i) 443 { 444 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 445 item = CONTAINING_RECORD(entry, struct item, entry); 446 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 447 } 448 else 449 { 450 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 451 } 452 size = QueryDepthSList(&slist_header); 453 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size); 454 } 455 456 entry = InterlockedFlushSList(&slist_header); 457 for (i = 65536; i > 0; i--) 458 { 459 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 460 item = CONTAINING_RECORD(entry, struct item, entry); 461 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 462 entry = item->entry.Next; 463 HeapFree(GetProcessHeap(), 0, item); 464 } 465 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 466 size = QueryDepthSList(&slist_header); 467 ok(size == 0, "Expected size == 0, got %u\n", size); 468 entry = InterlockedPopEntrySList(&slist_header); 469 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 470 } 471 472 static void test_event(void) 473 { 474 HANDLE handle, handle2; 475 SECURITY_ATTRIBUTES sa; 476 SECURITY_DESCRIPTOR sd; 477 ACL acl; 478 DWORD ret; 479 BOOL val; 480 481 /* no sd */ 482 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 483 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 484 CloseHandle(handle); 485 486 sa.nLength = sizeof(sa); 487 sa.lpSecurityDescriptor = &sd; 488 sa.bInheritHandle = FALSE; 489 490 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 491 492 /* blank sd */ 493 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 494 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 495 CloseHandle(handle); 496 497 /* sd with NULL dacl */ 498 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); 499 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 500 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 501 CloseHandle(handle); 502 503 /* sd with empty dacl */ 504 InitializeAcl(&acl, sizeof(acl), ACL_REVISION); 505 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE); 506 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 507 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 508 CloseHandle(handle); 509 510 /* test case sensitivity */ 511 512 SetLastError(0xdeadbeef); 513 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 514 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError()); 515 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 516 517 SetLastError(0xdeadbeef); 518 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 519 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 520 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 521 CloseHandle( handle2 ); 522 523 SetLastError(0xdeadbeef); 524 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT"); 525 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 526 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 527 CloseHandle( handle2 ); 528 529 SetLastError(0xdeadbeef); 530 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event"); 531 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError()); 532 CloseHandle( handle2 ); 533 534 SetLastError(0xdeadbeef); 535 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT"); 536 ok( !handle2, "OpenEvent succeeded\n"); 537 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 538 539 SetLastError(0xdeadbeef); 540 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, NULL ); 541 ok( !handle2, "OpenEvent succeeded\n"); 542 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 543 544 SetLastError(0xdeadbeef); 545 handle2 = OpenEventW( EVENT_ALL_ACCESS, FALSE, NULL ); 546 ok( !handle2, "OpenEvent succeeded\n"); 547 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 548 549 CloseHandle( handle ); 550 551 /* resource notifications are events too */ 552 553 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification) 554 { 555 trace( "memory resource notifications not supported\n" ); 556 return; 557 } 558 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 ); 559 ok( !handle, "CreateMemoryResourceNotification succeeded\n" ); 560 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 561 ret = pQueryMemoryResourceNotification( handle, &val ); 562 ok( !ret, "QueryMemoryResourceNotification succeeded\n" ); 563 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 564 565 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification ); 566 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() ); 567 ret = WaitForSingleObject( handle, 10 ); 568 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret ); 569 570 val = ~0; 571 ret = pQueryMemoryResourceNotification( handle, &val ); 572 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 573 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 574 ret = CloseHandle( handle ); 575 ok( ret, "CloseHandle failed err %u\n", GetLastError() ); 576 577 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 578 val = ~0; 579 ret = pQueryMemoryResourceNotification( handle, &val ); 580 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 581 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 582 CloseHandle( handle ); 583 } 584 585 static void test_semaphore(void) 586 { 587 HANDLE handle, handle2; 588 589 /* test case sensitivity */ 590 591 SetLastError(0xdeadbeef); 592 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 593 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError()); 594 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 595 596 SetLastError(0xdeadbeef); 597 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 598 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 599 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 600 CloseHandle( handle2 ); 601 602 SetLastError(0xdeadbeef); 603 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE"); 604 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 605 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 606 CloseHandle( handle2 ); 607 608 SetLastError(0xdeadbeef); 609 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore"); 610 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError()); 611 CloseHandle( handle2 ); 612 613 SetLastError(0xdeadbeef); 614 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE"); 615 ok( !handle2, "OpenSemaphore succeeded\n"); 616 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 617 618 SetLastError(0xdeadbeef); 619 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, NULL ); 620 ok( !handle2, "OpenSemaphore succeeded\n"); 621 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 622 623 SetLastError(0xdeadbeef); 624 handle2 = OpenSemaphoreW( SEMAPHORE_ALL_ACCESS, FALSE, NULL ); 625 ok( !handle2, "OpenSemaphore succeeded\n"); 626 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 627 628 CloseHandle( handle ); 629 } 630 631 static void test_waitable_timer(void) 632 { 633 HANDLE handle, handle2; 634 635 /* test case sensitivity */ 636 637 SetLastError(0xdeadbeef); 638 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 639 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError()); 640 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 641 642 SetLastError(0xdeadbeef); 643 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 644 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 645 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 646 CloseHandle( handle2 ); 647 648 SetLastError(0xdeadbeef); 649 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER"); 650 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 651 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 652 CloseHandle( handle2 ); 653 654 SetLastError(0xdeadbeef); 655 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer"); 656 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError()); 657 CloseHandle( handle2 ); 658 659 SetLastError(0xdeadbeef); 660 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER"); 661 ok( !handle2, "OpenWaitableTimer succeeded\n"); 662 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 663 664 SetLastError(0xdeadbeef); 665 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, NULL ); 666 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError()); 667 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 668 669 SetLastError(0xdeadbeef); 670 handle2 = OpenWaitableTimerW( TIMER_ALL_ACCESS, FALSE, NULL ); 671 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError()); 672 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 673 674 CloseHandle( handle ); 675 } 676 677 static HANDLE sem = 0; 678 679 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped) 680 { 681 ReleaseSemaphore(sem, 1, NULL); 682 } 683 684 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL; 685 686 static void test_iocp_callback(void) 687 { 688 char temp_path[MAX_PATH]; 689 char filename[MAX_PATH]; 690 DWORD ret; 691 BOOL retb; 692 static const char prefix[] = "pfx"; 693 HANDLE hFile; 694 HMODULE hmod = GetModuleHandleA("kernel32.dll"); 695 DWORD bytesWritten; 696 const char *buffer = "12345678123456781234567812345678"; 697 OVERLAPPED overlapped; 698 699 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback"); 700 if(!p_BindIoCompletionCallback) { 701 win_skip("BindIoCompletionCallback not found in this DLL\n"); 702 return; 703 } 704 705 sem = CreateSemaphoreW(NULL, 0, 1, NULL); 706 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n"); 707 708 ret = GetTempPathA(MAX_PATH, temp_path); 709 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 710 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 711 712 ret = GetTempFileNameA(temp_path, prefix, 0, filename); 713 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 714 715 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 716 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 717 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 718 719 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 720 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n"); 721 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 722 723 ret = CloseHandle(hFile); 724 ok( ret, "CloseHandle: error %d\n", GetLastError()); 725 ret = DeleteFileA(filename); 726 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 727 728 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 729 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 730 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 731 732 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 733 ok(retb == TRUE, "BindIoCompletionCallback failed\n"); 734 735 memset(&overlapped, 0, sizeof(overlapped)); 736 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped); 737 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError()); 738 739 ret = WaitForSingleObject(sem, 5000); 740 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n"); 741 CloseHandle(sem); 742 743 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 744 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n"); 745 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 746 retb = p_BindIoCompletionCallback(hFile, NULL, 0); 747 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n"); 748 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 749 750 ret = CloseHandle(hFile); 751 ok( ret, "CloseHandle: error %d\n", GetLastError()); 752 ret = DeleteFileA(filename); 753 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 754 755 /* win2k3 requires the Flags parameter to be zero */ 756 SetLastError(0xdeadbeef); 757 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 758 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 759 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 760 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345); 761 if (!retb) 762 ok(GetLastError() == ERROR_INVALID_PARAMETER, 763 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 764 else 765 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n"); 766 ret = CloseHandle(hFile); 767 ok( ret, "CloseHandle: error %d\n", GetLastError()); 768 ret = DeleteFileA(filename); 769 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 770 771 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0); 772 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n"); 773 ok(GetLastError() == ERROR_INVALID_HANDLE || 774 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */ 775 "Last error is %d\n", GetLastError()); 776 } 777 778 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut) 779 { 780 int *pn = p; 781 disable_success_count 782 ok(timedOut, "Timer callbacks should always time out\n"); 783 ++*pn; 784 } 785 786 struct timer_queue_data1 787 { 788 int num_calls; 789 int max_calls; 790 HANDLE q, t; 791 }; 792 793 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut) 794 { 795 struct timer_queue_data1 *d = p; 796 ok(timedOut, "Timer callbacks should always time out\n"); 797 if (d->t && ++d->num_calls == d->max_calls) 798 { 799 BOOL ret; 800 SetLastError(0xdeadbeef); 801 /* Note, XP SP2 does *not* do any deadlock checking, so passing 802 INVALID_HANDLE_VALUE here will just hang. */ 803 ret = DeleteTimerQueueTimer(d->q, d->t, NULL); 804 ok(!ret, "DeleteTimerQueueTimer\n"); 805 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 806 } 807 } 808 809 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut) 810 { 811 struct timer_queue_data1 *d = p; 812 ok(timedOut, "Timer callbacks should always time out\n"); 813 if (d->t && ++d->num_calls == d->max_calls) 814 { 815 /* Basically kill the timer since it won't have time to run 816 again. */ 817 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0); 818 ok(ret, "ChangeTimerQueueTimer\n"); 819 } 820 } 821 822 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut) 823 { 824 struct timer_queue_data1 *d = p; 825 ok(timedOut, "Timer callbacks should always time out\n"); 826 if (d->t) 827 { 828 /* This tests whether a timer gets flagged for deletion before 829 or after the callback runs. If we start this timer with a 830 period of zero (run once), then ChangeTimerQueueTimer will 831 fail if the timer is already flagged. Hence we really run 832 only once. Otherwise we will run multiple times. */ 833 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50); 834 ok(ret, "ChangeTimerQueueTimer\n"); 835 ++d->num_calls; 836 } 837 } 838 839 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut) 840 { 841 DWORD_PTR delay = (DWORD_PTR) p; 842 ok(timedOut, "Timer callbacks should always time out\n"); 843 if (delay) 844 Sleep(delay); 845 } 846 847 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut) 848 { 849 struct timer_queue_data1 *d = p; 850 ok(timedOut, "Timer callbacks should always time out\n"); 851 /* This tests an original implementation bug where a deleted timer may get 852 to run, but it is tricky to set up. */ 853 if (d->q && d->num_calls++ == 0) 854 { 855 /* First run: delete ourselves, then insert and remove a timer 856 that goes in front of us in the sorted timeout list. Once 857 removed, we will still timeout at the faster timer's due time, 858 but this should be a no-op if we are bug-free. There should 859 not be a second run. We can test the value of num_calls later. */ 860 BOOL ret; 861 HANDLE t; 862 863 /* The delete will pend while we are in this callback. */ 864 SetLastError(0xdeadbeef); 865 ret = DeleteTimerQueueTimer(d->q, d->t, NULL); 866 ok(!ret, "DeleteTimerQueueTimer\n"); 867 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 868 869 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0); 870 ok(ret, "CreateTimerQueueTimer\n"); 871 ok(t != NULL, "CreateTimerQueueTimer\n"); 872 873 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE); 874 ok(ret, "DeleteTimerQueueTimer\n"); 875 876 /* Now we stay alive by hanging around in the callback. */ 877 Sleep(500); 878 } 879 } 880 881 static void test_timer_queue(void) 882 { 883 HANDLE q, t0, t1, t2, t3, t4, t5; 884 int n0, n1, n2, n3, n4, n5; 885 struct timer_queue_data1 d1, d2, d3, d4; 886 HANDLE e, et1, et2; 887 BOOL ret, ret0; 888 889 /* Test asynchronous deletion of the queue. */ 890 q = CreateTimerQueue(); 891 ok(q != NULL, "CreateTimerQueue\n"); 892 893 SetLastError(0xdeadbeef); 894 ret = DeleteTimerQueueEx(q, NULL); 895 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 896 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 897 GetLastError()); 898 899 /* Test synchronous deletion of the queue and running timers. */ 900 q = CreateTimerQueue(); 901 ok(q != NULL, "CreateTimerQueue\n"); 902 903 /* Not called. */ 904 t0 = NULL; 905 n0 = 0; 906 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0); 907 ok(ret, "CreateTimerQueueTimer\n"); 908 ok(t0 != NULL, "CreateTimerQueueTimer\n"); 909 ret0 = DeleteTimerQueueTimer(q, t0, NULL); 910 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) || 911 broken(ret0), /* Win 2000 & XP & 2003 */ 912 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError()); 913 914 /* Called once. */ 915 t1 = NULL; 916 n1 = 0; 917 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0); 918 ok(ret, "CreateTimerQueueTimer\n"); 919 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 920 921 /* A slow one. */ 922 t2 = NULL; 923 n2 = 0; 924 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0); 925 ok(ret, "CreateTimerQueueTimer\n"); 926 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 927 928 /* A fast one. */ 929 t3 = NULL; 930 n3 = 0; 931 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0); 932 ok(ret, "CreateTimerQueueTimer\n"); 933 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 934 935 /* Start really late (it won't start). */ 936 t4 = NULL; 937 n4 = 0; 938 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0); 939 ok(ret, "CreateTimerQueueTimer\n"); 940 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 941 942 /* Start soon, but delay so long it won't run again. */ 943 t5 = NULL; 944 n5 = 0; 945 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0); 946 ok(ret, "CreateTimerQueueTimer\n"); 947 ok(t5 != NULL, "CreateTimerQueueTimer\n"); 948 949 /* Give them a chance to do some work. */ 950 Sleep(500); 951 952 /* Test deleting a once-only timer. */ 953 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE); 954 ok(ret, "DeleteTimerQueueTimer\n"); 955 956 /* A periodic timer. */ 957 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); 958 ok(ret, "DeleteTimerQueueTimer\n"); 959 960 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 961 ok(ret, "DeleteTimerQueueEx\n"); 962 todo_wine 963 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0); 964 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1); 965 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3); 966 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4); 967 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5); 968 969 /* Test synchronous deletion of the timer/queue with event trigger. */ 970 e = CreateEventW(NULL, TRUE, FALSE, NULL); 971 et1 = CreateEventW(NULL, TRUE, FALSE, NULL); 972 et2 = CreateEventW(NULL, TRUE, FALSE, NULL); 973 if (!e || !et1 || !et2) 974 { 975 skip("Failed to create timer queue descruction event\n"); 976 return; 977 } 978 979 q = CreateTimerQueue(); 980 ok(q != NULL, "CreateTimerQueue\n"); 981 982 /* Run once and finish quickly (should be done when we delete it). */ 983 t1 = NULL; 984 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0); 985 ok(ret, "CreateTimerQueueTimer\n"); 986 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 987 988 /* Run once and finish slowly (shouldn't be done when we delete it). */ 989 t2 = NULL; 990 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0); 991 ok(ret, "CreateTimerQueueTimer\n"); 992 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 993 994 /* Run once and finish quickly (should be done when we delete it). */ 995 t3 = NULL; 996 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0); 997 ok(ret, "CreateTimerQueueTimer\n"); 998 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 999 1000 /* Run once and finish slowly (shouldn't be done when we delete it). */ 1001 t4 = NULL; 1002 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0); 1003 ok(ret, "CreateTimerQueueTimer\n"); 1004 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 1005 1006 /* Give them a chance to start. */ 1007 Sleep(400); 1008 1009 /* DeleteTimerQueueTimer always returns PENDING with a NULL event, 1010 even if the timer is finished. */ 1011 SetLastError(0xdeadbeef); 1012 ret = DeleteTimerQueueTimer(q, t1, NULL); 1013 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1014 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1015 GetLastError()); 1016 1017 SetLastError(0xdeadbeef); 1018 ret = DeleteTimerQueueTimer(q, t2, NULL); 1019 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1020 ok(GetLastError() == ERROR_IO_PENDING, 1021 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1022 GetLastError()); 1023 1024 SetLastError(0xdeadbeef); 1025 ret = DeleteTimerQueueTimer(q, t3, et1); 1026 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1027 ok(GetLastError() == 0xdeadbeef, 1028 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n", 1029 GetLastError()); 1030 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0, 1031 "Timer destruction event not triggered\n"); 1032 1033 SetLastError(0xdeadbeef); 1034 ret = DeleteTimerQueueTimer(q, t4, et2); 1035 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1036 ok(GetLastError() == ERROR_IO_PENDING, 1037 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1038 GetLastError()); 1039 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0, 1040 "Timer destruction event not triggered\n"); 1041 1042 SetLastError(0xdeadbeef); 1043 ret = DeleteTimerQueueEx(q, e); 1044 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1045 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1046 GetLastError()); 1047 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0, 1048 "Queue destruction event not triggered\n"); 1049 CloseHandle(e); 1050 1051 /* Test deleting/changing a timer in execution. */ 1052 q = CreateTimerQueue(); 1053 ok(q != NULL, "CreateTimerQueue\n"); 1054 1055 /* Test changing a once-only timer before it fires (this is allowed, 1056 whereas after it fires you cannot). */ 1057 n1 = 0; 1058 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0); 1059 ok(ret, "CreateTimerQueueTimer\n"); 1060 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1061 ret = ChangeTimerQueueTimer(q, t1, 0, 0); 1062 ok(ret, "ChangeTimerQueueTimer\n"); 1063 1064 d2.t = t2 = NULL; 1065 d2.num_calls = 0; 1066 d2.max_calls = 3; 1067 d2.q = q; 1068 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0); 1069 d2.t = t2; 1070 ok(ret, "CreateTimerQueueTimer\n"); 1071 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1072 1073 d3.t = t3 = NULL; 1074 d3.num_calls = 0; 1075 d3.max_calls = 4; 1076 d3.q = q; 1077 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0); 1078 d3.t = t3; 1079 ok(ret, "CreateTimerQueueTimer\n"); 1080 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 1081 1082 d4.t = t4 = NULL; 1083 d4.num_calls = 0; 1084 d4.q = q; 1085 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0); 1086 d4.t = t4; 1087 ok(ret, "CreateTimerQueueTimer\n"); 1088 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 1089 1090 Sleep(500); 1091 1092 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 1093 ok(ret, "DeleteTimerQueueEx\n"); 1094 ok(n1 == 1, "ChangeTimerQueueTimer\n"); 1095 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n"); 1096 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); 1097 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n"); 1098 1099 /* Test an obscure bug that was in the original implementation. */ 1100 q = CreateTimerQueue(); 1101 ok(q != NULL, "CreateTimerQueue\n"); 1102 1103 /* All the work is done in the callback. */ 1104 d1.t = t1 = NULL; 1105 d1.num_calls = 0; 1106 d1.q = q; 1107 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION); 1108 d1.t = t1; 1109 ok(ret, "CreateTimerQueueTimer\n"); 1110 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1111 1112 Sleep(750); 1113 1114 SetLastError(0xdeadbeef); 1115 ret = DeleteTimerQueueEx(q, NULL); 1116 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1117 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1118 GetLastError()); 1119 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n"); 1120 1121 /* Test functions on the default timer queue. */ 1122 t1 = NULL; 1123 n1 = 0; 1124 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0); 1125 ok(ret, "CreateTimerQueueTimer, default queue\n"); 1126 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n"); 1127 1128 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1129 ok(ret, "ChangeTimerQueueTimer, default queue\n"); 1130 1131 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1132 ok(ret, "DeleteTimerQueueTimer, default queue\n"); 1133 1134 /* Try mixing default and non-default queues. Apparently this works. */ 1135 q = CreateTimerQueue(); 1136 ok(q != NULL, "CreateTimerQueue\n"); 1137 1138 t1 = NULL; 1139 n1 = 0; 1140 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0); 1141 ok(ret, "CreateTimerQueueTimer\n"); 1142 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1143 1144 t2 = NULL; 1145 n2 = 0; 1146 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0); 1147 ok(ret, "CreateTimerQueueTimer\n"); 1148 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1149 1150 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1151 ok(ret, "ChangeTimerQueueTimer\n"); 1152 1153 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000); 1154 ok(ret, "ChangeTimerQueueTimer\n"); 1155 1156 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1157 ok(ret, "DeleteTimerQueueTimer\n"); 1158 1159 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); 1160 ok(ret, "DeleteTimerQueueTimer\n"); 1161 1162 /* Try to delete the default queue? In any case: not allowed. */ 1163 SetLastError(0xdeadbeef); 1164 ret = DeleteTimerQueueEx(NULL, NULL); 1165 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n"); 1166 ok(GetLastError() == ERROR_INVALID_HANDLE, 1167 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n", 1168 GetLastError()); 1169 1170 SetLastError(0xdeadbeef); 1171 ret = DeleteTimerQueueEx(q, NULL); 1172 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1173 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1174 GetLastError()); 1175 } 1176 1177 static HANDLE modify_handle(HANDLE handle, DWORD modify) 1178 { 1179 DWORD tmp = HandleToULong(handle); 1180 tmp |= modify; 1181 return ULongToHandle(tmp); 1182 } 1183 1184 static void test_WaitForSingleObject(void) 1185 { 1186 HANDLE signaled, nonsignaled, invalid; 1187 LARGE_INTEGER timeout; 1188 NTSTATUS status; 1189 DWORD ret; 1190 1191 signaled = CreateEventW(NULL, TRUE, TRUE, NULL); 1192 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL); 1193 invalid = (HANDLE) 0xdeadbee0; 1194 1195 /* invalid handle with different values for lower 2 bits */ 1196 SetLastError(0xdeadbeef); 1197 ret = WaitForSingleObject(invalid, 0); 1198 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1199 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1200 1201 SetLastError(0xdeadbeef); 1202 ret = WaitForSingleObject(modify_handle(invalid, 1), 0); 1203 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1204 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1205 1206 SetLastError(0xdeadbeef); 1207 ret = WaitForSingleObject(modify_handle(invalid, 2), 0); 1208 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1209 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1210 1211 SetLastError(0xdeadbeef); 1212 ret = WaitForSingleObject(modify_handle(invalid, 3), 0); 1213 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1214 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1215 1216 /* valid handle with different values for lower 2 bits */ 1217 SetLastError(0xdeadbeef); 1218 ret = WaitForSingleObject(nonsignaled, 0); 1219 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1220 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1221 1222 SetLastError(0xdeadbeef); 1223 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0); 1224 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1225 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1226 1227 SetLastError(0xdeadbeef); 1228 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0); 1229 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1230 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1231 1232 SetLastError(0xdeadbeef); 1233 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0); 1234 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1235 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1236 1237 /* valid handle with different values for lower 2 bits */ 1238 SetLastError(0xdeadbeef); 1239 ret = WaitForSingleObject(signaled, 0); 1240 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1241 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1242 1243 SetLastError(0xdeadbeef); 1244 ret = WaitForSingleObject(modify_handle(signaled, 1), 0); 1245 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1246 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1247 1248 SetLastError(0xdeadbeef); 1249 ret = WaitForSingleObject(modify_handle(signaled, 2), 0); 1250 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1251 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1252 1253 SetLastError(0xdeadbeef); 1254 ret = WaitForSingleObject(modify_handle(signaled, 3), 0); 1255 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1256 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1257 1258 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */ 1259 ret = WaitForSingleObject(GetCurrentProcess(), 100); 1260 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret); 1261 1262 ret = WaitForSingleObject(GetCurrentThread(), 100); 1263 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret); 1264 1265 timeout.QuadPart = -1000000; 1266 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout); 1267 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status); 1268 1269 timeout.QuadPart = -1000000; 1270 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); 1271 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status); 1272 1273 CloseHandle(signaled); 1274 CloseHandle(nonsignaled); 1275 } 1276 1277 static void test_WaitForMultipleObjects(void) 1278 { 1279 LARGE_INTEGER timeout; 1280 NTSTATUS status; 1281 DWORD r; 1282 int i; 1283 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS]; 1284 1285 /* create the maximum number of events and make sure 1286 * we can wait on that many */ 1287 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1288 { 1289 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL); 1290 ok( maxevents[i] != 0, "should create enough events\n"); 1291 } 1292 1293 /* a manual-reset event remains signaled, an auto-reset event is cleared */ 1294 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1295 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r); 1296 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1297 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r); 1298 ok(ResetEvent(maxevents[0]), "ResetEvent\n"); 1299 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) 1300 { 1301 /* the lowest index is checked first and remaining events are untouched */ 1302 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1303 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r); 1304 } 1305 1306 /* run same test with Nt* call */ 1307 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1308 SetEvent(maxevents[i]); 1309 1310 /* a manual-reset event remains signaled, an auto-reset event is cleared */ 1311 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1312 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08x\n", status); 1313 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1314 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08x\n", status); 1315 ok(ResetEvent(maxevents[0]), "ResetEvent\n"); 1316 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) 1317 { 1318 /* the lowest index is checked first and remaining events are untouched */ 1319 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1320 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08x\n", i, status); 1321 } 1322 1323 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1324 if (maxevents[i]) CloseHandle(maxevents[i]); 1325 1326 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in 1327 * WaitForMultipleObjects and NtWaitForMultipleObjects */ 1328 maxevents[0] = GetCurrentProcess(); 1329 SetLastError(0xdeadbeef); 1330 r = WaitForMultipleObjects(1, maxevents, FALSE, 100); 1331 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r); 1332 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, 1333 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 1334 1335 maxevents[0] = GetCurrentThread(); 1336 SetLastError(0xdeadbeef); 1337 r = WaitForMultipleObjects(1, maxevents, FALSE, 100); 1338 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r); 1339 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, 1340 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 1341 1342 timeout.QuadPart = -1000000; 1343 maxevents[0] = GetCurrentProcess(); 1344 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); 1345 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status); 1346 1347 timeout.QuadPart = -1000000; 1348 maxevents[0] = GetCurrentThread(); 1349 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); 1350 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status); 1351 } 1352 1353 static BOOL g_initcallback_ret, g_initcallback_called; 1354 static void *g_initctxt; 1355 1356 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt) 1357 { 1358 g_initcallback_called = TRUE; 1359 /* zero bit set means here that initialization is taking place - initialization locked */ 1360 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt); 1361 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr); 1362 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n"); 1363 return g_initcallback_ret; 1364 } 1365 1366 static void test_initonce(void) 1367 { 1368 INIT_ONCE initonce; 1369 BOOL ret, pending; 1370 1371 if (!pInitOnceInitialize || !pInitOnceExecuteOnce) 1372 { 1373 win_skip("one-time initialization API not supported\n"); 1374 return; 1375 } 1376 1377 /* blocking initialization with callback */ 1378 initonce.Ptr = (void*)0xdeadbeef; 1379 pInitOnceInitialize(&initonce); 1380 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1381 1382 /* initialisation completed successfully */ 1383 g_initcallback_ret = TRUE; 1384 g_initctxt = NULL; 1385 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1386 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1387 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr); 1388 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1389 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1390 1391 /* so it's been called already so won't be called again */ 1392 g_initctxt = NULL; 1393 g_initcallback_called = FALSE; 1394 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1395 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1396 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr); 1397 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1398 ok(!g_initcallback_called, "got %d\n", g_initcallback_called); 1399 1400 pInitOnceInitialize(&initonce); 1401 g_initcallback_called = FALSE; 1402 /* 2 lower order bits should never be used, you'll get a crash in result */ 1403 g_initctxt = (void*)0xFFFFFFF0; 1404 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1405 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1406 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr); 1407 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt); 1408 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1409 1410 /* callback failed */ 1411 g_initcallback_ret = FALSE; 1412 g_initcallback_called = FALSE; 1413 g_initctxt = NULL; 1414 pInitOnceInitialize(&initonce); 1415 SetLastError( 0xdeadbeef ); 1416 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1417 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret, GetLastError()); 1418 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1419 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1420 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1421 1422 /* blocking initialization without a callback */ 1423 pInitOnceInitialize(&initonce); 1424 g_initctxt = NULL; 1425 pending = FALSE; 1426 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1427 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1428 ok(pending, "got %d\n", pending); 1429 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1430 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1431 /* another attempt to begin initialization with block a single thread */ 1432 1433 g_initctxt = NULL; 1434 pending = 0xf; 1435 SetLastError( 0xdeadbeef ); 1436 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1437 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1438 ok(pending == 0xf, "got %d\n", pending); 1439 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1440 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1441 1442 g_initctxt = (void*)0xdeadbee0; 1443 SetLastError( 0xdeadbeef ); 1444 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt); 1445 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1446 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1447 1448 /* once failed already */ 1449 g_initctxt = (void*)0xdeadbee0; 1450 ret = pInitOnceComplete(&initonce, 0, g_initctxt); 1451 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1452 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1453 1454 pInitOnceInitialize(&initonce); 1455 SetLastError( 0xdeadbeef ); 1456 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1457 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1458 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1459 1460 SetLastError( 0xdeadbeef ); 1461 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1462 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1463 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1464 1465 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1466 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1467 ok(pending, "got %d\n", pending); 1468 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1469 1470 SetLastError( 0xdeadbeef ); 1471 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1472 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1473 1474 SetLastError( 0xdeadbeef ); 1475 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1476 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1477 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1478 1479 SetLastError( 0xdeadbeef ); 1480 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef); 1481 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1482 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1483 1484 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1485 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1486 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1487 1488 pInitOnceInitialize(&initonce); 1489 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1490 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1491 ok(pending, "got %d\n", pending); 1492 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1493 1494 SetLastError( 0xdeadbeef ); 1495 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1496 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1497 1498 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1499 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1500 ok(pending, "got %d\n", pending); 1501 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1502 1503 SetLastError( 0xdeadbeef ); 1504 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1505 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1506 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1507 1508 SetLastError( 0xdeadbeef ); 1509 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1510 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1511 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1512 1513 SetLastError( 0xdeadbeef ); 1514 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef); 1515 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1516 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1517 1518 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0); 1519 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1520 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1521 1522 SetLastError( 0xdeadbeef ); 1523 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1524 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1525 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1526 1527 pInitOnceInitialize(&initonce); 1528 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1529 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1530 ok(pending, "got %d\n", pending); 1531 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1532 1533 /* test INIT_ONCE_CHECK_ONLY */ 1534 1535 pInitOnceInitialize(&initonce); 1536 SetLastError( 0xdeadbeef ); 1537 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1538 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1539 SetLastError( 0xdeadbeef ); 1540 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1541 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1542 1543 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1544 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1545 ok(pending, "got %d\n", pending); 1546 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1547 1548 SetLastError( 0xdeadbeef ); 1549 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1550 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1551 SetLastError( 0xdeadbeef ); 1552 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1553 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1554 1555 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0); 1556 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1557 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1558 1559 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1560 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError()); 1561 ok(!pending, "got %d\n", pending); 1562 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1563 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr); 1564 1565 SetLastError( 0xdeadbeef ); 1566 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1567 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1568 1569 pInitOnceInitialize(&initonce); 1570 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1571 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1572 ok(pending, "got %d\n", pending); 1573 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1574 1575 SetLastError( 0xdeadbeef ); 1576 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1577 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1578 SetLastError( 0xdeadbeef ); 1579 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1580 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1581 1582 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0); 1583 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1584 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1585 1586 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1587 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError()); 1588 ok(!pending, "got %d\n", pending); 1589 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1590 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr); 1591 1592 SetLastError( 0xdeadbeef ); 1593 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1594 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1595 } 1596 1597 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT; 1598 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT; 1599 static CRITICAL_SECTION buffercrit; 1600 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE; 1601 static LONG bufferlen,totalproduced,totalconsumed; 1602 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt; 1603 1604 #define BUFFER_SIZE 5 1605 1606 static DWORD WINAPI condvar_producer(LPVOID x) { 1607 DWORD sleepinterval = 5; 1608 1609 while (1) { 1610 Sleep(sleepinterval); 1611 if (sleepinterval > 1) 1612 sleepinterval -= 1; 1613 1614 EnterCriticalSection(&buffercrit); 1615 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) { 1616 condvar_producer_sleepcnt++; 1617 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) { 1618 if (GetLastError() != ERROR_TIMEOUT) 1619 condvar_sleeperr = TRUE; 1620 } 1621 } 1622 if (condvar_stop) { 1623 LeaveCriticalSection(&buffercrit); 1624 break; 1625 } 1626 bufferlen++; 1627 totalproduced++; 1628 LeaveCriticalSection(&buffercrit); 1629 pWakeConditionVariable(&buffernotempty); 1630 } 1631 return 0; 1632 } 1633 1634 static DWORD WINAPI condvar_consumer(LPVOID x) { 1635 DWORD *cnt = (DWORD*)x; 1636 DWORD sleepinterval = 1; 1637 1638 while (1) { 1639 EnterCriticalSection(&buffercrit); 1640 while ((bufferlen == 0) && !condvar_stop) { 1641 condvar_consumer_sleepcnt++; 1642 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) { 1643 if (GetLastError() != ERROR_TIMEOUT) 1644 condvar_sleeperr = TRUE; 1645 } 1646 } 1647 if (condvar_stop && (bufferlen == 0)) { 1648 LeaveCriticalSection(&buffercrit); 1649 break; 1650 } 1651 bufferlen--; 1652 totalconsumed++; 1653 (*cnt)++; 1654 LeaveCriticalSection(&buffercrit); 1655 pWakeConditionVariable(&buffernotfull); 1656 Sleep(sleepinterval); 1657 if (sleepinterval < 5) sleepinterval += 1; 1658 } 1659 return 0; 1660 } 1661 1662 static void test_condvars_consumer_producer(void) 1663 { 1664 HANDLE hp1,hp2,hp3,hc1,hc2,hc3; 1665 DWORD dummy; 1666 DWORD cnt1,cnt2,cnt3; 1667 1668 if (!pInitializeConditionVariable) { 1669 /* function is not yet in XP, only in newer Windows */ 1670 win_skip("no condition variable support.\n"); 1671 return; 1672 } 1673 1674 /* Implement a producer / consumer scheme with non-full / non-empty triggers */ 1675 1676 /* If we have static initialized condition variables, InitializeConditionVariable 1677 * is not strictly necessary. 1678 * pInitializeConditionVariable(&buffernotfull); 1679 */ 1680 pInitializeConditionVariable(&buffernotempty); 1681 InitializeCriticalSection(&buffercrit); 1682 1683 /* Larger Test: consumer/producer example */ 1684 1685 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0; 1686 1687 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1688 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1689 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1690 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy); 1691 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy); 1692 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy); 1693 1694 /* Limit run to 0.5 seconds. */ 1695 Sleep(500); 1696 1697 /* tear down start */ 1698 condvar_stop = TRUE; 1699 1700 /* final wake up call */ 1701 pWakeAllConditionVariable (&buffernotfull); 1702 pWakeAllConditionVariable (&buffernotempty); 1703 1704 /* (mostly an implementation detail) 1705 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr); 1706 */ 1707 1708 WaitForSingleObject(hp1, 1000); 1709 WaitForSingleObject(hp2, 1000); 1710 WaitForSingleObject(hp3, 1000); 1711 WaitForSingleObject(hc1, 1000); 1712 WaitForSingleObject(hc2, 1000); 1713 WaitForSingleObject(hc3, 1000); 1714 1715 ok(totalconsumed == totalproduced, 1716 "consumed %d != produced %d\n", totalconsumed, totalproduced); 1717 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n"); 1718 1719 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where 1720 * one consumer does not get anything to do is possible. */ 1721 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced, cnt1, cnt2, cnt3); 1722 /* The sleeps of the producer or consumer should not go above 100* produced count, 1723 * otherwise the implementation does not sleep correctly. But yet again, this is 1724 * not hard defined. */ 1725 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt); 1726 } 1727 1728 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */ 1729 static DWORD condvar_seq = 0; 1730 static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT; 1731 static CRITICAL_SECTION condvar_crit; 1732 static SRWLOCK condvar_srwlock; 1733 1734 /* Sequence of wake/sleep to check boundary conditions: 1735 * 0: init 1736 * 1: producer emits a WakeConditionVariable without consumer waiting. 1737 * 2: consumer sleeps without a wake expecting timeout 1738 * 3: producer emits a WakeAllConditionVariable without consumer waiting. 1739 * 4: consumer sleeps without a wake expecting timeout 1740 * 5: a wake is handed to a SleepConditionVariableCS 1741 * 6: a wakeall is handed to a SleepConditionVariableCS 1742 * 7: sleep after above should timeout 1743 * 8: wake with crit section locked into the sleep timeout 1744 * 1745 * the following tests will only be executed if InitializeSRWLock is available 1746 * 1747 * 9: producer (exclusive) wakes up consumer (exclusive) 1748 * 10: producer (exclusive) wakes up consumer (shared) 1749 * 11: producer (shared) wakes up consumer (exclusive) 1750 * 12: producer (shared) wakes up consumer (shared) 1751 * 13: end 1752 */ 1753 static DWORD WINAPI condvar_base_producer(LPVOID x) { 1754 while (condvar_seq < 1) Sleep(1); 1755 1756 pWakeConditionVariable (&condvar_base); 1757 condvar_seq = 2; 1758 1759 while (condvar_seq < 3) Sleep(1); 1760 pWakeAllConditionVariable (&condvar_base); 1761 condvar_seq = 4; 1762 1763 while (condvar_seq < 5) Sleep(1); 1764 EnterCriticalSection (&condvar_crit); 1765 pWakeConditionVariable (&condvar_base); 1766 LeaveCriticalSection (&condvar_crit); 1767 while (condvar_seq < 6) Sleep(1); 1768 EnterCriticalSection (&condvar_crit); 1769 pWakeAllConditionVariable (&condvar_base); 1770 LeaveCriticalSection (&condvar_crit); 1771 1772 while (condvar_seq < 8) Sleep(1); 1773 EnterCriticalSection (&condvar_crit); 1774 pWakeConditionVariable (&condvar_base); 1775 Sleep(50); 1776 LeaveCriticalSection (&condvar_crit); 1777 1778 /* skip over remaining tests if InitializeSRWLock is not available */ 1779 if (!pInitializeSRWLock) 1780 return 0; 1781 1782 while (condvar_seq < 9) Sleep(1); 1783 pAcquireSRWLockExclusive(&condvar_srwlock); 1784 pWakeConditionVariable(&condvar_base); 1785 pReleaseSRWLockExclusive(&condvar_srwlock); 1786 1787 while (condvar_seq < 10) Sleep(1); 1788 pAcquireSRWLockExclusive(&condvar_srwlock); 1789 pWakeConditionVariable(&condvar_base); 1790 pReleaseSRWLockExclusive(&condvar_srwlock); 1791 1792 while (condvar_seq < 11) Sleep(1); 1793 pAcquireSRWLockShared(&condvar_srwlock); 1794 pWakeConditionVariable(&condvar_base); 1795 pReleaseSRWLockShared(&condvar_srwlock); 1796 1797 while (condvar_seq < 12) Sleep(1); 1798 Sleep(50); /* ensure that consumer waits for cond variable */ 1799 pAcquireSRWLockShared(&condvar_srwlock); 1800 pWakeConditionVariable(&condvar_base); 1801 pReleaseSRWLockShared(&condvar_srwlock); 1802 1803 return 0; 1804 } 1805 1806 static DWORD WINAPI condvar_base_consumer(LPVOID x) { 1807 BOOL ret; 1808 1809 while (condvar_seq < 2) Sleep(1); 1810 1811 /* wake was emitted, but we were not sleeping */ 1812 EnterCriticalSection (&condvar_crit); 1813 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1814 LeaveCriticalSection (&condvar_crit); 1815 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1816 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1817 1818 condvar_seq = 3; 1819 while (condvar_seq < 4) Sleep(1); 1820 1821 /* wake all was emitted, but we were not sleeping */ 1822 EnterCriticalSection (&condvar_crit); 1823 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1824 LeaveCriticalSection (&condvar_crit); 1825 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1826 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1827 1828 EnterCriticalSection (&condvar_crit); 1829 condvar_seq = 5; 1830 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); 1831 LeaveCriticalSection (&condvar_crit); 1832 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n"); 1833 1834 EnterCriticalSection (&condvar_crit); 1835 condvar_seq = 6; 1836 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); 1837 LeaveCriticalSection (&condvar_crit); 1838 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n"); 1839 condvar_seq = 7; 1840 1841 EnterCriticalSection (&condvar_crit); 1842 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1843 LeaveCriticalSection (&condvar_crit); 1844 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1845 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1846 1847 EnterCriticalSection (&condvar_crit); 1848 condvar_seq = 8; 1849 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20); 1850 LeaveCriticalSection (&condvar_crit); 1851 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n"); 1852 1853 /* skip over remaining tests if InitializeSRWLock is not available */ 1854 if (!pInitializeSRWLock) 1855 { 1856 win_skip("no srw lock support.\n"); 1857 condvar_seq = 13; /* end */ 1858 return 0; 1859 } 1860 1861 pAcquireSRWLockExclusive(&condvar_srwlock); 1862 condvar_seq = 9; 1863 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); 1864 pReleaseSRWLockExclusive(&condvar_srwlock); 1865 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1866 1867 pAcquireSRWLockShared(&condvar_srwlock); 1868 condvar_seq = 10; 1869 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); 1870 pReleaseSRWLockShared(&condvar_srwlock); 1871 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1872 1873 pAcquireSRWLockExclusive(&condvar_srwlock); 1874 condvar_seq = 11; 1875 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); 1876 pReleaseSRWLockExclusive(&condvar_srwlock); 1877 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1878 1879 pAcquireSRWLockShared(&condvar_srwlock); 1880 condvar_seq = 12; 1881 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); 1882 pReleaseSRWLockShared(&condvar_srwlock); 1883 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1884 1885 condvar_seq = 13; 1886 return 0; 1887 } 1888 1889 static void test_condvars_base(void) { 1890 HANDLE hp, hc; 1891 DWORD dummy; 1892 BOOL ret; 1893 1894 1895 if (!pInitializeConditionVariable) { 1896 /* function is not yet in XP, only in newer Windows */ 1897 win_skip("no condition variable support.\n"); 1898 return; 1899 } 1900 1901 InitializeCriticalSection (&condvar_crit); 1902 1903 if (pInitializeSRWLock) 1904 pInitializeSRWLock(&condvar_srwlock); 1905 1906 EnterCriticalSection (&condvar_crit); 1907 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1908 LeaveCriticalSection (&condvar_crit); 1909 1910 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n"); 1911 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1912 1913 if (pInitializeSRWLock) 1914 { 1915 pAcquireSRWLockExclusive(&condvar_srwlock); 1916 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, 0); 1917 pReleaseSRWLockExclusive(&condvar_srwlock); 1918 1919 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); 1920 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1921 1922 pAcquireSRWLockShared(&condvar_srwlock); 1923 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED); 1924 pReleaseSRWLockShared(&condvar_srwlock); 1925 1926 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); 1927 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1928 } 1929 1930 1931 hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy); 1932 hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy); 1933 1934 condvar_seq = 1; /* go */ 1935 1936 while (condvar_seq < 9) 1937 Sleep (5); 1938 WaitForSingleObject(hp, 100); 1939 WaitForSingleObject(hc, 100); 1940 } 1941 1942 static LONG srwlock_seq = 0; 1943 static SRWLOCK srwlock_base; 1944 static struct 1945 { 1946 LONG wrong_execution_order; 1947 LONG samethread_excl_excl; 1948 LONG samethread_excl_shared; 1949 LONG samethread_shared_excl; 1950 LONG multithread_excl_excl; 1951 LONG excl_not_preferred; 1952 LONG trylock_excl; 1953 LONG trylock_shared; 1954 } srwlock_base_errors; 1955 1956 /* Sequence of acquire/release to check boundary conditions: 1957 * 0: init 1958 * 1959 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock 1960 * 2: thread1 expects a deadlock and releases the waiting lock 1961 * thread2 releases the lock again 1962 * 1963 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock 1964 * 4: thread1 expects a deadlock and releases the waiting lock 1965 * thread2 releases the lock again 1966 * 1967 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock 1968 * 6: thread1 expects a deadlock and releases the waiting lock 1969 * thread2 releases the lock again 1970 * 1971 * 7: thread2 acquires and releases two nested shared locks 1972 * 1973 * 8: thread1 acquires an exclusive lock 1974 * 9: thread2 tries to acquire the exclusive lock, too 1975 * thread1 releases the exclusive lock again 1976 * 10: thread2 enters the exclusive lock and leaves it immediately again 1977 * 1978 * 11: thread1 acquires a shared lock 1979 * 12: thread2 acquires and releases a shared lock 1980 * thread1 releases the lock again 1981 * 1982 * 13: thread1 acquires a shared lock 1983 * 14: thread2 tries to acquire an exclusive lock 1984 * 15: thread3 tries to acquire a shared lock 1985 * 16: thread1 releases the shared lock 1986 * 17: thread2 wakes up and releases the exclusive lock 1987 * 18: thread3 wakes up and releases the shared lock 1988 * 1989 * the following tests will only be executed if TryAcquireSRWLock* is available 1990 * 1991 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE 1992 * thread1 checks the result of recursive calls to TryAcquireSRWLock* 1993 * thread1 releases the exclusive lock 1994 * 1995 * thread1 calls TryAcquireSRWLockShared which should return TRUE 1996 * thread1 checks the result of recursive calls to TryAcquireSRWLock* 1997 * thread1 releases the shared lock 1998 * 1999 * thread1 acquires an exclusive lock 2000 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE 2001 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2002 * 21: thread1 releases the exclusive lock 2003 * 2004 * thread1 acquires an shared lock 2005 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE 2006 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2007 * 23: thread1 releases the shared lock 2008 * 2009 * thread1 acquires a shared lock and tries to acquire an exclusive lock 2010 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE 2011 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2012 * 25: thread1 releases the exclusive lock 2013 * 2014 * thread1 acquires two shared locks 2015 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE 2016 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2017 * 27: thread1 releases one shared lock 2018 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE 2019 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2020 * 29: thread1 releases the second shared lock 2021 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE 2022 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE 2023 * 2024 * 31: end 2025 */ 2026 2027 static DWORD WINAPI srwlock_base_thread1(LPVOID x) 2028 { 2029 /* seq 2 */ 2030 while (srwlock_seq < 2) Sleep(1); 2031 Sleep(100); 2032 if (InterlockedIncrement(&srwlock_seq) != 3) 2033 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl); 2034 pReleaseSRWLockExclusive(&srwlock_base); 2035 2036 /* seq 4 */ 2037 while (srwlock_seq < 4) Sleep(1); 2038 Sleep(100); 2039 if (InterlockedIncrement(&srwlock_seq) != 5) 2040 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared); 2041 pReleaseSRWLockExclusive(&srwlock_base); 2042 2043 /* seq 6 */ 2044 while (srwlock_seq < 6) Sleep(1); 2045 Sleep(100); 2046 if (InterlockedIncrement(&srwlock_seq) != 7) 2047 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl); 2048 pReleaseSRWLockShared(&srwlock_base); 2049 2050 /* seq 8 */ 2051 while (srwlock_seq < 8) Sleep(1); 2052 pAcquireSRWLockExclusive(&srwlock_base); 2053 if (InterlockedIncrement(&srwlock_seq) != 9) 2054 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2055 Sleep(100); 2056 if (InterlockedIncrement(&srwlock_seq) != 10) 2057 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl); 2058 pReleaseSRWLockExclusive(&srwlock_base); 2059 2060 /* seq 11 */ 2061 while (srwlock_seq < 11) Sleep(1); 2062 pAcquireSRWLockShared(&srwlock_base); 2063 if (InterlockedIncrement(&srwlock_seq) != 12) 2064 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2065 2066 /* seq 13 */ 2067 while (srwlock_seq < 13) Sleep(1); 2068 pReleaseSRWLockShared(&srwlock_base); 2069 pAcquireSRWLockShared(&srwlock_base); 2070 if (InterlockedIncrement(&srwlock_seq) != 14) 2071 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2072 2073 /* seq 16 */ 2074 while (srwlock_seq < 16) Sleep(1); 2075 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */ 2076 if (InterlockedIncrement(&srwlock_seq) != 17) 2077 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2078 pReleaseSRWLockShared(&srwlock_base); 2079 2080 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2081 if (!pTryAcquireSRWLockExclusive) 2082 return 0; 2083 2084 /* seq 19 */ 2085 while (srwlock_seq < 19) Sleep(1); 2086 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2087 { 2088 if (pTryAcquireSRWLockShared(&srwlock_base)) 2089 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2090 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2091 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2092 pReleaseSRWLockExclusive(&srwlock_base); 2093 } 2094 else 2095 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2096 2097 if (pTryAcquireSRWLockShared(&srwlock_base)) 2098 { 2099 if (pTryAcquireSRWLockShared(&srwlock_base)) 2100 pReleaseSRWLockShared(&srwlock_base); 2101 else 2102 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2103 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2104 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2105 pReleaseSRWLockShared(&srwlock_base); 2106 } 2107 else 2108 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2109 2110 pAcquireSRWLockExclusive(&srwlock_base); 2111 if (InterlockedIncrement(&srwlock_seq) != 20) 2112 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2113 2114 /* seq 21 */ 2115 while (srwlock_seq < 21) Sleep(1); 2116 pReleaseSRWLockExclusive(&srwlock_base); 2117 pAcquireSRWLockShared(&srwlock_base); 2118 if (InterlockedIncrement(&srwlock_seq) != 22) 2119 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2120 2121 /* seq 23 */ 2122 while (srwlock_seq < 23) Sleep(1); 2123 pReleaseSRWLockShared(&srwlock_base); 2124 pAcquireSRWLockShared(&srwlock_base); 2125 if (InterlockedIncrement(&srwlock_seq) != 24) 2126 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2127 2128 /* seq 25 */ 2129 pAcquireSRWLockExclusive(&srwlock_base); 2130 if (srwlock_seq != 25) 2131 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2132 pReleaseSRWLockExclusive(&srwlock_base); 2133 2134 pAcquireSRWLockShared(&srwlock_base); 2135 pAcquireSRWLockShared(&srwlock_base); 2136 if (InterlockedIncrement(&srwlock_seq) != 26) 2137 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2138 2139 /* seq 27 */ 2140 while (srwlock_seq < 27) Sleep(1); 2141 pReleaseSRWLockShared(&srwlock_base); 2142 if (InterlockedIncrement(&srwlock_seq) != 28) 2143 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2144 2145 /* seq 29 */ 2146 while (srwlock_seq < 29) Sleep(1); 2147 pReleaseSRWLockShared(&srwlock_base); 2148 if (InterlockedIncrement(&srwlock_seq) != 30) 2149 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2150 2151 return 0; 2152 } 2153 2154 static DWORD WINAPI srwlock_base_thread2(LPVOID x) 2155 { 2156 /* seq 1 */ 2157 while (srwlock_seq < 1) Sleep(1); 2158 pAcquireSRWLockExclusive(&srwlock_base); 2159 if (InterlockedIncrement(&srwlock_seq) != 2) 2160 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2161 2162 /* seq 3 */ 2163 pAcquireSRWLockExclusive(&srwlock_base); 2164 if (srwlock_seq != 3) 2165 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl); 2166 pReleaseSRWLockExclusive(&srwlock_base); 2167 pAcquireSRWLockExclusive(&srwlock_base); 2168 if (InterlockedIncrement(&srwlock_seq) != 4) 2169 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2170 2171 /* seq 5 */ 2172 pAcquireSRWLockShared(&srwlock_base); 2173 if (srwlock_seq != 5) 2174 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared); 2175 pReleaseSRWLockShared(&srwlock_base); 2176 pAcquireSRWLockShared(&srwlock_base); 2177 if (InterlockedIncrement(&srwlock_seq) != 6) 2178 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2179 2180 /* seq 7 */ 2181 pAcquireSRWLockExclusive(&srwlock_base); 2182 if (srwlock_seq != 7) 2183 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl); 2184 pReleaseSRWLockExclusive(&srwlock_base); 2185 pAcquireSRWLockShared(&srwlock_base); 2186 pAcquireSRWLockShared(&srwlock_base); 2187 pReleaseSRWLockShared(&srwlock_base); 2188 pReleaseSRWLockShared(&srwlock_base); 2189 if (InterlockedIncrement(&srwlock_seq) != 8) 2190 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2191 2192 /* seq 9, 10 */ 2193 while (srwlock_seq < 9) Sleep(1); 2194 pAcquireSRWLockExclusive(&srwlock_base); 2195 if (srwlock_seq != 10) 2196 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl); 2197 pReleaseSRWLockExclusive(&srwlock_base); 2198 if (InterlockedIncrement(&srwlock_seq) != 11) 2199 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2200 2201 /* seq 12 */ 2202 while (srwlock_seq < 12) Sleep(1); 2203 pAcquireSRWLockShared(&srwlock_base); 2204 pReleaseSRWLockShared(&srwlock_base); 2205 if (InterlockedIncrement(&srwlock_seq) != 13) 2206 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2207 2208 /* seq 14 */ 2209 while (srwlock_seq < 14) Sleep(1); 2210 if (InterlockedIncrement(&srwlock_seq) != 15) 2211 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2212 2213 /* seq 17 */ 2214 pAcquireSRWLockExclusive(&srwlock_base); 2215 if (srwlock_seq != 17) 2216 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2217 if (InterlockedIncrement(&srwlock_seq) != 18) 2218 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2219 pReleaseSRWLockExclusive(&srwlock_base); 2220 2221 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2222 if (!pTryAcquireSRWLockExclusive) 2223 return 0; 2224 2225 /* seq 20 */ 2226 while (srwlock_seq < 20) Sleep(1); 2227 if (pTryAcquireSRWLockShared(&srwlock_base)) 2228 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2229 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2230 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2231 if (InterlockedIncrement(&srwlock_seq) != 21) 2232 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2233 2234 /* seq 22 */ 2235 while (srwlock_seq < 22) Sleep(1); 2236 if (pTryAcquireSRWLockShared(&srwlock_base)) 2237 pReleaseSRWLockShared(&srwlock_base); 2238 else 2239 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2240 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2241 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2242 if (InterlockedIncrement(&srwlock_seq) != 23) 2243 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2244 2245 /* seq 24 */ 2246 while (srwlock_seq < 24) Sleep(1); 2247 Sleep(50); /* ensure that exclusive access request is queued */ 2248 if (pTryAcquireSRWLockShared(&srwlock_base)) 2249 { 2250 pReleaseSRWLockShared(&srwlock_base); 2251 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2252 } 2253 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2254 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2255 if (InterlockedIncrement(&srwlock_seq) != 25) 2256 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2257 pReleaseSRWLockShared(&srwlock_base); 2258 2259 /* seq 26 */ 2260 while (srwlock_seq < 26) Sleep(1); 2261 if (pTryAcquireSRWLockShared(&srwlock_base)) 2262 pReleaseSRWLockShared(&srwlock_base); 2263 else 2264 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2265 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2266 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2267 if (InterlockedIncrement(&srwlock_seq) != 27) 2268 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2269 2270 /* seq 28 */ 2271 while (srwlock_seq < 28) Sleep(1); 2272 if (pTryAcquireSRWLockShared(&srwlock_base)) 2273 pReleaseSRWLockShared(&srwlock_base); 2274 else 2275 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2276 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2277 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2278 if (InterlockedIncrement(&srwlock_seq) != 29) 2279 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2280 2281 /* seq 30 */ 2282 while (srwlock_seq < 30) Sleep(1); 2283 if (pTryAcquireSRWLockShared(&srwlock_base)) 2284 pReleaseSRWLockShared(&srwlock_base); 2285 else 2286 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2287 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2288 pReleaseSRWLockExclusive(&srwlock_base); 2289 else 2290 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2291 if (InterlockedIncrement(&srwlock_seq) != 31) 2292 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2293 2294 return 0; 2295 } 2296 2297 static DWORD WINAPI srwlock_base_thread3(LPVOID x) 2298 { 2299 /* seq 15 */ 2300 while (srwlock_seq < 15) Sleep(1); 2301 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */ 2302 if (InterlockedIncrement(&srwlock_seq) != 16) 2303 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2304 2305 /* seq 18 */ 2306 pAcquireSRWLockShared(&srwlock_base); 2307 if (srwlock_seq != 18) 2308 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2309 pReleaseSRWLockShared(&srwlock_base); 2310 if (InterlockedIncrement(&srwlock_seq) != 19) 2311 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2312 2313 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2314 if (!pTryAcquireSRWLockExclusive) 2315 { 2316 /* function is only in Windows 7 and newer */ 2317 win_skip("no srw trylock support.\n"); 2318 srwlock_seq = 31; /* end */ 2319 return 0; 2320 } 2321 2322 return 0; 2323 } 2324 2325 static void test_srwlock_base(void) 2326 { 2327 HANDLE h1, h2, h3; 2328 DWORD dummy; 2329 2330 if (!pInitializeSRWLock) 2331 { 2332 /* function is not yet in XP, only in newer Windows */ 2333 win_skip("no srw lock support.\n"); 2334 return; 2335 } 2336 2337 pInitializeSRWLock(&srwlock_base); 2338 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors)); 2339 2340 h1 = CreateThread(NULL, 0, srwlock_base_thread1, NULL, 0, &dummy); 2341 h2 = CreateThread(NULL, 0, srwlock_base_thread2, NULL, 0, &dummy); 2342 h3 = CreateThread(NULL, 0, srwlock_base_thread3, NULL, 0, &dummy); 2343 2344 srwlock_seq = 1; /* go */ 2345 while (srwlock_seq < 31) 2346 Sleep(5); 2347 2348 WaitForSingleObject(h1, 100); 2349 WaitForSingleObject(h2, 100); 2350 WaitForSingleObject(h3, 100); 2351 2352 ok(!srwlock_base_errors.wrong_execution_order, 2353 "thread commands were executed in the wrong order (occurred %d times).\n", 2354 srwlock_base_errors.wrong_execution_order); 2355 2356 ok(!srwlock_base_errors.samethread_excl_excl, 2357 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n", 2358 srwlock_base_errors.samethread_excl_excl); 2359 2360 ok(!srwlock_base_errors.samethread_excl_shared, 2361 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n", 2362 srwlock_base_errors.samethread_excl_shared); 2363 2364 ok(!srwlock_base_errors.samethread_shared_excl, 2365 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n", 2366 srwlock_base_errors.samethread_shared_excl); 2367 2368 ok(!srwlock_base_errors.multithread_excl_excl, 2369 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n", 2370 srwlock_base_errors.multithread_excl_excl); 2371 2372 ok(!srwlock_base_errors.excl_not_preferred, 2373 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n", 2374 srwlock_base_errors.excl_not_preferred); 2375 2376 ok(!srwlock_base_errors.trylock_excl, 2377 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n", 2378 srwlock_base_errors.trylock_excl); 2379 2380 ok(!srwlock_base_errors.trylock_shared, 2381 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n", 2382 srwlock_base_errors.trylock_shared); 2383 2384 } 2385 2386 static SRWLOCK srwlock_example; 2387 static LONG srwlock_protected_value = 0; 2388 static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0; 2389 static BOOL srwlock_stop = FALSE; 2390 2391 static DWORD WINAPI srwlock_example_thread(LPVOID x) { 2392 DWORD *cnt = x; 2393 LONG old; 2394 2395 while (!srwlock_stop) 2396 { 2397 2398 /* periodically request exclusive access */ 2399 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0) 2400 { 2401 pAcquireSRWLockExclusive(&srwlock_example); 2402 if (InterlockedIncrement(&srwlock_inside) != 1) 2403 InterlockedIncrement(&srwlock_example_errors); 2404 2405 InterlockedIncrement(&srwlock_protected_value); 2406 Sleep(1); 2407 2408 if (InterlockedDecrement(&srwlock_inside) != 0) 2409 InterlockedIncrement(&srwlock_example_errors); 2410 pReleaseSRWLockExclusive(&srwlock_example); 2411 } 2412 2413 /* request shared access */ 2414 pAcquireSRWLockShared(&srwlock_example); 2415 InterlockedIncrement(&srwlock_inside); 2416 old = srwlock_protected_value; 2417 2418 (*cnt)++; 2419 Sleep(1); 2420 2421 if (old != srwlock_protected_value) 2422 InterlockedIncrement(&srwlock_example_errors); 2423 InterlockedDecrement(&srwlock_inside); 2424 pReleaseSRWLockShared(&srwlock_example); 2425 } 2426 2427 return 0; 2428 } 2429 2430 static void test_srwlock_example(void) 2431 { 2432 HANDLE h1, h2, h3; 2433 DWORD dummy; 2434 DWORD cnt1, cnt2, cnt3; 2435 2436 if (!pInitializeSRWLock) { 2437 /* function is not yet in XP, only in newer Windows */ 2438 win_skip("no srw lock support.\n"); 2439 return; 2440 } 2441 2442 pInitializeSRWLock(&srwlock_example); 2443 2444 cnt1 = cnt2 = cnt3 = 0; 2445 2446 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy); 2447 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy); 2448 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy); 2449 2450 /* limit run to 1 second. */ 2451 Sleep(1000); 2452 2453 /* tear down start */ 2454 srwlock_stop = TRUE; 2455 2456 WaitForSingleObject(h1, 1000); 2457 WaitForSingleObject(h2, 1000); 2458 WaitForSingleObject(h3, 1000); 2459 2460 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside); 2461 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %d)\n", 2462 srwlock_example_errors); 2463 2464 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1, cnt2, cnt3); 2465 trace("number of total exclusive accesses is %d\n", srwlock_protected_value); 2466 } 2467 2468 static DWORD WINAPI alertable_wait_thread(void *param) 2469 { 2470 HANDLE *semaphores = param; 2471 LARGE_INTEGER timeout; 2472 NTSTATUS status; 2473 DWORD result; 2474 2475 ReleaseSemaphore(semaphores[0], 1, NULL); 2476 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE); 2477 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %u\n", result); 2478 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE); 2479 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2480 2481 ReleaseSemaphore(semaphores[0], 1, NULL); 2482 timeout.QuadPart = -10000000; 2483 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2484 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status); 2485 timeout.QuadPart = -2000000; 2486 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2487 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08x\n", status); 2488 2489 ReleaseSemaphore(semaphores[0], 1, NULL); 2490 timeout.QuadPart = -10000000; 2491 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2492 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status); 2493 result = WaitForSingleObject(semaphores[0], 0); 2494 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", result); 2495 2496 return 0; 2497 } 2498 2499 static void CALLBACK alertable_wait_apc(ULONG_PTR userdata) 2500 { 2501 HANDLE *semaphores = (void *)userdata; 2502 ReleaseSemaphore(semaphores[1], 1, NULL); 2503 } 2504 2505 static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata) 2506 { 2507 HANDLE *semaphores = (void *)userdata; 2508 DWORD result; 2509 2510 result = WaitForSingleObject(semaphores[0], 1000); 2511 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2512 } 2513 2514 static void test_alertable_wait(void) 2515 { 2516 HANDLE thread, semaphores[2]; 2517 DWORD result; 2518 2519 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL); 2520 ok(semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError()); 2521 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL); 2522 ok(semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError()); 2523 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL); 2524 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError()); 2525 2526 result = WaitForSingleObject(semaphores[0], 1000); 2527 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2528 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */ 2529 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores); 2530 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2531 2532 result = WaitForSingleObject(semaphores[0], 1000); 2533 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2534 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */ 2535 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores); 2536 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2537 2538 result = WaitForSingleObject(semaphores[0], 1000); 2539 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2540 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */ 2541 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores); 2542 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2543 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores); 2544 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2545 ReleaseSemaphore(semaphores[0], 2, NULL); 2546 2547 result = WaitForSingleObject(thread, 1000); 2548 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2549 CloseHandle(thread); 2550 CloseHandle(semaphores[0]); 2551 CloseHandle(semaphores[1]); 2552 } 2553 2554 struct apc_deadlock_info 2555 { 2556 PROCESS_INFORMATION *pi; 2557 HANDLE event; 2558 BOOL running; 2559 }; 2560 2561 static DWORD WINAPI apc_deadlock_thread(void *param) 2562 { 2563 struct apc_deadlock_info *info = param; 2564 PROCESS_INFORMATION *pi = info->pi; 2565 NTSTATUS status; 2566 SIZE_T size; 2567 void *base; 2568 2569 while (info->running) 2570 { 2571 base = NULL; 2572 size = 0x1000; 2573 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size, 2574 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 2575 disable_success_count 2576 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status); 2577 ok(base != NULL, "expected base != NULL, got %p\n", base); 2578 SetEvent(info->event); 2579 2580 size = 0; 2581 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE); 2582 disable_success_count 2583 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status); 2584 SetEvent(info->event); 2585 } 2586 2587 return 0; 2588 } 2589 2590 static void test_apc_deadlock(void) 2591 { 2592 struct apc_deadlock_info info; 2593 PROCESS_INFORMATION pi; 2594 STARTUPINFOA si = { sizeof(si) }; 2595 char cmdline[MAX_PATH]; 2596 HANDLE event, thread; 2597 DWORD result; 2598 BOOL success; 2599 char **argv; 2600 int i; 2601 2602 winetest_get_mainargs(&argv); 2603 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]); 2604 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2605 ok(success, "CreateProcess failed with %u\n", GetLastError()); 2606 2607 event = CreateEventA(NULL, FALSE, FALSE, NULL); 2608 ok(event != NULL, "CreateEvent failed with %u\n", GetLastError()); 2609 2610 info.pi = π 2611 info.event = event; 2612 info.running = TRUE; 2613 2614 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL); 2615 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError()); 2616 result = WaitForSingleObject(event, 1000); 2617 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2618 2619 disable_success_count 2620 for (i = 0; i < 1000; i++) 2621 { 2622 result = SuspendThread(pi.hThread); 2623 ok(result == 0, "expected 0, got %u\n", result); 2624 2625 WaitForSingleObject(event, 0); /* reset event */ 2626 result = WaitForSingleObject(event, 1000); 2627 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2628 2629 result = ResumeThread(pi.hThread); 2630 ok(result == 1, "expected 1, got %u\n", result); 2631 Sleep(1); 2632 } 2633 2634 info.running = FALSE; 2635 result = WaitForSingleObject(thread, 1000); 2636 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2637 CloseHandle(thread); 2638 CloseHandle(event); 2639 2640 TerminateProcess(pi.hProcess, 0); 2641 CloseHandle(pi.hThread); 2642 CloseHandle(pi.hProcess); 2643 } 2644 2645 START_TEST(sync) 2646 { 2647 char **argv; 2648 int argc; 2649 HMODULE hdll = GetModuleHandleA("kernel32.dll"); 2650 HMODULE hntdll = GetModuleHandleA("ntdll.dll"); 2651 #ifdef __REACTOS__ 2652 HMODULE hdll_vista = GetModuleHandleA("kernel32_vista.dll"); 2653 #endif 2654 2655 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize"); 2656 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce"); 2657 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize"); 2658 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete"); 2659 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable"); 2660 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS"); 2661 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW"); 2662 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable"); 2663 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable"); 2664 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock"); 2665 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive"); 2666 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared"); 2667 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive"); 2668 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared"); 2669 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive"); 2670 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); 2671 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); 2672 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); 2673 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); 2674 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); 2675 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); 2676 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx"); 2677 2678 #ifdef __REACTOS__ 2679 if (!pInitializeConditionVariable) 2680 { 2681 pInitializeConditionVariable = (void *)GetProcAddress(hdll_vista, "InitializeConditionVariable"); 2682 pSleepConditionVariableCS = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableCS"); 2683 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableSRW"); 2684 pWakeAllConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeAllConditionVariable"); 2685 pWakeConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeConditionVariable"); 2686 } 2687 2688 if (!pInitializeSRWLock) 2689 { 2690 pInitializeSRWLock = (void *)GetProcAddress(hdll_vista, "InitializeSRWLock"); 2691 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockExclusive"); 2692 pAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockShared"); 2693 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockExclusive"); 2694 pReleaseSRWLockShared = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockShared"); 2695 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockExclusive"); 2696 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockShared"); 2697 } 2698 #endif 2699 2700 argc = winetest_get_mainargs( &argv ); 2701 if (argc >= 3) 2702 { 2703 if (!strcmp(argv[2], "apc_deadlock")) 2704 { 2705 for (;;) SleepEx(INFINITE, TRUE); 2706 } 2707 return; 2708 } 2709 2710 init_fastcall_thunk(); 2711 test_signalandwait(); 2712 test_mutex(); 2713 test_slist(); 2714 test_event(); 2715 test_semaphore(); 2716 test_waitable_timer(); 2717 test_iocp_callback(); 2718 test_timer_queue(); 2719 test_WaitForSingleObject(); 2720 test_WaitForMultipleObjects(); 2721 test_initonce(); 2722 test_condvars_base(); 2723 test_condvars_consumer_producer(); 2724 test_srwlock_base(); 2725 test_srwlock_example(); 2726 test_alertable_wait(); 2727 test_apc_deadlock(); 2728 } 2729