Reactos

[KERNEL32][ROSTESTS][SDK] Enable threadpooling [NTDLL] Init KeyedEvents even on NT5.2 dll_export [MEDIA] Update winesync.txt accordingly [SDK][DLL] Initialize crtical sections at runtime

authored by

Justin Miller and committed by
Justin Miller
0bf42067 88a63011

+249 -842
+35 -33
dll/ntdll/def/ntdll.spec
··· 1311 1311 @ stub -version=0x600+ ShipAssertMsgA 1312 1312 @ stub -version=0x600+ ShipAssertMsgW 1313 1313 @ stub -version=0x600+ TpAllocAlpcCompletion 1314 - @ stub -version=0x600+ TpAllocCleanupGroup 1315 - @ stub -version=0x600+ TpAllocIoCompletion 1316 - @ stub -version=0x600+ TpAllocPool 1317 - @ stub -version=0x600+ TpAllocTimer 1318 - @ stub -version=0x600+ TpAllocWait 1319 - @ stub -version=0x600+ TpAllocWork 1320 - @ stub -version=0x600+ TpCallbackLeaveCriticalSectionOnCompletion 1321 - @ stub -version=0x600+ TpCallbackMayRunLong 1322 - @ stub -version=0x600+ TpCallbackReleaseMutexOnCompletion 1323 - @ stub -version=0x600+ TpCallbackReleaseSemaphoreOnCompletion 1324 - @ stub -version=0x600+ TpCallbackSetEventOnCompletion 1325 - @ stub -version=0x600+ TpCallbackUnloadDllOnCompletion 1326 - @ stub -version=0x600+ TpCancelAsyncIoOperation 1314 + @ stdcall -version=0x600+ TpAllocCleanupGroup(ptr) 1315 + @ stdcall -version=0x600+ TpAllocIoCompletion(ptr ptr ptr ptr ptr) 1316 + @ stdcall -version=0x600+ TpAllocPool(ptr ptr) 1317 + @ stdcall -version=0x600+ TpAllocTimer(ptr ptr ptr ptr) 1318 + @ stdcall -version=0x600+ TpAllocWait(ptr ptr ptr ptr) 1319 + @ stdcall -version=0x600+ TpAllocWork(ptr ptr ptr ptr) 1320 + @ stdcall -version=0x600+ TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) 1321 + @ stdcall -version=0x600+ TpCallbackMayRunLong(ptr) 1322 + @ stdcall -version=0x600+ TpCallbackReleaseMutexOnCompletion(ptr ptr) 1323 + @ stdcall -version=0x600+ TpCallbackReleaseSemaphoreOnCompletion(ptr ptr long) 1324 + @ stdcall -version=0x600+ TpCallbackSetEventOnCompletion(ptr ptr) 1325 + @ stdcall -version=0x600+ TpCallbackUnloadDllOnCompletion(ptr ptr) 1326 + @ stdcall -version=0x600+ TpCancelAsyncIoOperation(ptr) 1327 1327 @ stub -version=0x600+ TpCaptureCaller 1328 1328 @ stub -version=0x600+ TpCheckTerminateWorker 1329 1329 @ stub -version=0x600+ TpDbgDumpHeapUsage 1330 1330 @ stub -version=0x600+ TpDbgSetLogRoutine 1331 - @ stub -version=0x600+ TpDisassociateCallback 1332 - @ stub -version=0x600+ TpIsTimerSet 1333 - @ stub -version=0x600+ TpPostWork 1331 + @ stdcall -version=0x600+ TpDisassociateCallback(ptr) 1332 + @ stdcall -version=0x600+ TpIsTimerSet(ptr) 1333 + @ stdcall -version=0x600+ TpPostWork(ptr) 1334 + @ stdcall -version=0x600+ TpQueryPoolStackInformation(ptr ptr) 1334 1335 @ stub -version=0x600+ TpReleaseAlpcCompletion 1335 - @ stub -version=0x600+ TpReleaseCleanupGroup 1336 - @ stub -version=0x600+ TpReleaseCleanupGroupMembers 1337 - @ stub -version=0x600+ TpReleaseIoCompletion 1338 - @ stub -version=0x600+ TpReleasePool 1339 - @ stub -version=0x600+ TpReleaseTimer 1340 - @ stub -version=0x600+ TpReleaseWait 1341 - @ stub -version=0x600+ TpReleaseWork 1342 - @ stub -version=0x600+ TpSetPoolMaxThreads 1343 - @ stub -version=0x600+ TpSetPoolMinThreads 1344 - @ stub -version=0x600+ TpSetTimer 1345 - @ stub -version=0x600+ TpSetWait 1346 - @ stub -version=0x600+ TpSimpleTryPost 1347 - @ stub -version=0x600+ TpStartAsyncIoOperation 1336 + @ stdcall -version=0x600+ TpReleaseCleanupGroup(ptr) 1337 + @ stdcall -version=0x600+ TpReleaseCleanupGroupMembers(ptr long ptr) 1338 + @ stdcall -version=0x600+ TpReleaseIoCompletion(ptr) 1339 + @ stdcall -version=0x600+ TpReleasePool(ptr) 1340 + @ stdcall -version=0x600+ TpReleaseTimer(ptr) 1341 + @ stdcall -version=0x600+ TpReleaseWait(ptr) 1342 + @ stdcall -version=0x600+ TpReleaseWork(ptr) 1343 + @ stdcall -version=0x600+ TpSetPoolMaxThreads(ptr long) 1344 + @ stdcall -version=0x600+ TpSetPoolMinThreads(ptr long) 1345 + @ stdcall -version=0x600+ TpSetPoolStackInformation(ptr ptr) 1346 + @ stdcall -version=0x600+ TpSetTimer(ptr ptr long long) 1347 + @ stdcall -version=0x600+ TpSetWait(ptr long ptr) 1348 + @ stdcall -version=0x600+ TpSimpleTryPost(ptr ptr ptr) 1349 + @ stdcall -version=0x600+ TpStartAsyncIoOperation(ptr) 1348 1350 @ stub -version=0x600+ TpWaitForAlpcCompletion 1349 - @ stub -version=0x600+ TpWaitForIoCompletion 1350 - @ stub -version=0x600+ TpWaitForTimer 1351 - @ stub -version=0x600+ TpWaitForWait 1352 - @ stub -version=0x600+ TpWaitForWork 1351 + @ stdcall -version=0x600+ TpWaitForIoCompletion(ptr long) 1352 + @ stdcall -version=0x600+ TpWaitForTimer(ptr long) 1353 + @ stdcall -version=0x600+ TpWaitForWait(ptr long) 1354 + @ stdcall -version=0x600+ TpWaitForWork(ptr long) 1353 1355 @ stdcall -ret64 VerSetConditionMask(double long long) 1354 1356 @ stub -version=0x600+ WerCheckEventEscalation 1355 1357 @ stub -version=0x600+ WerReportSQMEvent
+5
dll/ntdll/include/ntdllp.h
··· 242 242 RtlpInitializeKeyedEvent( 243 243 VOID); 244 244 245 + VOID 246 + NTAPI 247 + RtlpInitializeThreadPooling( 248 + VOID); 249 + 245 250 /* EOF */
+2 -2
dll/ntdll/ldr/ldrinit.c
··· 2415 2415 /* Check whether all static imports were properly loaded and return here */ 2416 2416 if (!NT_SUCCESS(ImportStatus)) return ImportStatus; 2417 2417 2418 - #if (DLL_EXPORT_VERSION >= _WIN32_WINNT_VISTA) 2418 + /* Following two calls are for Vista+ support, required for winesync */ 2419 2419 /* Initialize the keyed event for condition variables */ 2420 2420 RtlpInitializeKeyedEvent(); 2421 - #endif 2421 + RtlpInitializeThreadPooling(); 2422 2422 2423 2423 /* Initialize TLS */ 2424 2424 Status = LdrpInitializeTls();
-29
dll/ntdll/nt_0600/ntdll_vista.spec
··· 13 13 @ stdcall RtlRunOnceComplete(ptr long ptr) 14 14 @ stdcall RtlRunOnceExecuteOnce(ptr ptr ptr ptr) 15 15 16 - @ stdcall TpAllocCleanupGroup(ptr) 17 - @ stdcall TpAllocPool(ptr ptr) 18 - @ stdcall TpAllocTimer(ptr ptr ptr ptr) 19 - @ stdcall TpAllocWait(ptr ptr ptr ptr) 20 - @ stdcall TpAllocWork(ptr ptr ptr ptr) 21 - @ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) 22 - @ stdcall TpCallbackMayRunLong(ptr) 23 - @ stdcall TpCallbackReleaseMutexOnCompletion(ptr ptr) 24 - @ stdcall TpCallbackReleaseSemaphoreOnCompletion(ptr ptr long) 25 - @ stdcall TpCallbackSetEventOnCompletion(ptr ptr) 26 - @ stdcall TpCallbackUnloadDllOnCompletion(ptr ptr) 27 - @ stdcall TpDisassociateCallback(ptr) 28 - @ stdcall TpIsTimerSet(ptr) 29 - @ stdcall TpPostWork(ptr) 30 - @ stdcall TpReleaseCleanupGroup(ptr) 31 - @ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) 32 - @ stdcall TpReleasePool(ptr) 33 - @ stdcall TpReleaseTimer(ptr) 34 - @ stdcall TpReleaseWait(ptr) 35 - @ stdcall TpReleaseWork(ptr) 36 - @ stdcall TpSetPoolMaxThreads(ptr long) 37 - @ stdcall TpSetPoolMinThreads(ptr long) 38 - @ stdcall TpSetTimer(ptr ptr long long) 39 - @ stdcall TpSetWait(ptr long ptr) 40 - @ stdcall TpSimpleTryPost(ptr ptr ptr) 41 - @ stdcall TpWaitForTimer(ptr long) 42 - @ stdcall TpWaitForWait(ptr long) 43 - @ stdcall TpWaitForWork(ptr long) 44 - 45 16 @ stdcall RtlConnectToSm(ptr ptr long ptr) SmConnectToSm 46 17 @ stdcall RtlSendMsgToSm(ptr ptr) SmSendMsgToSm
+2 -2
media/doc/WINESYNC.txt
··· 267 267 268 268 sdk/lib/3rdparty/strmbase # Synced to WineStaging-3.3 269 269 270 - sdk/lib/rtl/actctx.c # Synced to wine-5.18 271 - sdk/lib/rtl/threadpool.c # Synced with wine-9.7 270 + sdk/lib/rtl/actctx.c # Partly synced with WineStaging-1.9.16 271 + sdk/lib/rtl/threadpool.c # Synced with Wine-9.7 272 272 273 273 advapi32 - 274 274 dll/win32/advapi32/wine/cred.c # Synced to WineStaging-3.3
+1
modules/rostests/winetests/ntdll/CMakeLists.txt
··· 23 23 rtlstr.c 24 24 string.c 25 25 testlist.c 26 + threadpool.c 26 27 time.c) 27 28 28 29 if(ARCH STREQUAL "i386")
+2
modules/rostests/winetests/ntdll/testlist.c
··· 23 23 extern void func_rtlbitmap(void); 24 24 extern void func_rtlstr(void); 25 25 extern void func_string(void); 26 + extern void func_threadpool(void); 26 27 extern void func_time(void); 27 28 28 29 const struct test winetest_testlist[] = ··· 49 50 { "rtlbitmap", func_rtlbitmap }, 50 51 { "rtlstr", func_rtlstr }, 51 52 { "string", func_string }, 53 + { "threadpool", func_threadpool}, 52 54 { "time", func_time }, 53 55 { 0, 0 } 54 56 };
+16
modules/rostests/winetests/ntdll/threadpool.c
··· 20 20 21 21 #include "ntdll_test.h" 22 22 23 + #ifdef __REACTOS__ 24 + typedef void (CALLBACK *PTP_IO_CALLBACK)(PTP_CALLBACK_INSTANCE,void*,void*,IO_STATUS_BLOCK*,PTP_IO); 25 + #endif 26 + 23 27 static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **); 24 28 static NTSTATUS (WINAPI *pTpAllocIoCompletion)(TP_IO **,HANDLE,PTP_IO_CALLBACK,void *,TP_CALLBACK_ENVIRON *); 25 29 static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID); ··· 580 584 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); 581 585 TP_POOL_STACK_INFORMATION stack_info; 582 586 TP_CALLBACK_ENVIRON environment; 587 + #ifndef __REACTOS__ 583 588 TP_CALLBACK_ENVIRON_V3 environment3; 589 + #endif 584 590 TP_CLEANUP_GROUP *group; 585 591 HANDLE semaphore; 586 592 NTSTATUS status; ··· 616 622 result = WaitForSingleObject(semaphore, 1000); 617 623 ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", result); 618 624 625 + #ifndef __REACTOS__ // Windows 7 619 626 /* test with environment version 3 */ 620 627 memset(&environment3, 0, sizeof(environment3)); 621 628 environment3.Version = 3; ··· 635 642 status = pTpSimpleTryPost(simple_cb, semaphore, (TP_CALLBACK_ENVIRON *)&environment3); 636 643 ok(status == STATUS_INVALID_PARAMETER || broken(!status) /* Vista does not support priorities */, 637 644 "TpSimpleTryPost failed with status %lx\n", status); 645 + #endif 638 646 639 647 /* test with invalid version number */ 640 648 memset(&environment, 0, sizeof(environment)); ··· 2031 2039 static void test_tp_io(void) 2032 2040 { 2033 2041 TP_CALLBACK_ENVIRON environment = {.Version = 1}; 2042 + #ifdef __REACTOS__ 2043 + OVERLAPPED ovl = {0}, ovl2 = {0}; 2044 + #else 2034 2045 OVERLAPPED ovl = {}, ovl2 = {}; 2046 + #endif 2035 2047 HANDLE client, server, thread; 2036 2048 struct io_cb_ctx userdata; 2037 2049 char in[1], in2[1]; ··· 2251 2263 static void test_kernel32_tp_io(void) 2252 2264 { 2253 2265 TP_CALLBACK_ENVIRON environment = {.Version = 1}; 2266 + #ifdef __REACTOS__ 2267 + OVERLAPPED ovl = {0}, ovl2 = {0}; 2268 + #else 2254 2269 OVERLAPPED ovl = {}, ovl2 = {}; 2270 + #endif 2255 2271 HANDLE client, server, thread; 2256 2272 struct io_cb_ctx userdata; 2257 2273 char in[1], in2[1];
+5
sdk/include/ndk/rtlfuncs.h
··· 4748 4748 // 4749 4749 // Synchronization functions 4750 4750 // 4751 + NTSYSAPI 4751 4752 VOID 4752 4753 NTAPI 4753 4754 RtlInitializeConditionVariable(OUT PRTL_CONDITION_VARIABLE ConditionVariable); 4754 4755 4756 + NTSYSAPI 4755 4757 VOID 4756 4758 NTAPI 4757 4759 RtlWakeConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable); 4758 4760 4761 + NTSYSAPI 4759 4762 VOID 4760 4763 NTAPI 4761 4764 RtlWakeAllConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable); 4762 4765 4766 + NTSYSAPI 4763 4767 NTSTATUS 4764 4768 NTAPI 4765 4769 RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, 4766 4770 IN OUT PRTL_CRITICAL_SECTION CriticalSection, 4767 4771 IN const PLARGE_INTEGER TimeOut OPTIONAL); 4768 4772 4773 + NTSYSAPI 4769 4774 NTSTATUS 4770 4775 NTAPI 4771 4776 RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
+6
sdk/include/xdk/winnt_old.h
··· 4495 4495 TP_CALLBACK_PRIORITY_COUNT = TP_CALLBACK_PRIORITY_INVALID 4496 4496 } TP_CALLBACK_PRIORITY; 4497 4497 4498 + typedef struct _TP_POOL_STACK_INFORMATION 4499 + { 4500 + SIZE_T StackReserve; 4501 + SIZE_T StackCommit; 4502 + } TP_POOL_STACK_INFORMATION,*PTP_POOL_STACK_INFORMATION; 4503 + 4498 4504 typedef VOID 4499 4505 (NTAPI *PTP_WORK_CALLBACK)( 4500 4506 _Inout_ PTP_CALLBACK_INSTANCE Instance,
+7 -2
sdk/lib/rtl/CMakeLists.txt
··· 8 8 if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") 9 9 # Enable this again. CORE-17637 10 10 add_compile_options(-Wunused-result) 11 + 12 + add_compile_options(-Wno-incompatible-pointer-types) 13 + add_compile_options(-Wno-missing-braces) 11 14 endif() 12 15 16 + include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) 17 + 13 18 list(APPEND RTL_WINE_SOURCE 14 19 actctx.c 15 20 timerqueue.c 16 - wait.c 21 + threadpool.c 17 22 ) 23 + set_source_files_properties(threadpool.c PROPERTIES COMPILE_DEFINITIONS __WINESRC__) 18 24 19 25 if(MSVC) 20 26 # Silence warning C4267: 'initializing': conversion from 'size_t' to 'const int', possible loss of data ··· 127 133 condvar.c 128 134 runonce.c 129 135 srw.c 130 - threadpool.c 131 136 utf8.c) 132 137 133 138 add_library(rtl_vista ${SOURCE_VISTA})
+2
sdk/lib/rtl/rtl.h
··· 56 56 57 57 /* Use intrinsics for x86 and x64 */ 58 58 #if defined(_M_IX86) || defined(_M_AMD64) 59 + #ifndef InterlockedCompareExchange 59 60 #define InterlockedCompareExchange _InterlockedCompareExchange 60 61 #define InterlockedIncrement _InterlockedIncrement 61 62 #define InterlockedDecrement _InterlockedDecrement ··· 63 64 #define InterlockedExchange _InterlockedExchange 64 65 #define InterlockedBitTestAndSet _interlockedbittestandset 65 66 #define InterlockedBitTestAndSet64 _interlockedbittestandset64 67 + #endif 66 68 #endif 67 69 68 70 #endif /* RTL_H */
+166 -6
sdk/lib/rtl/threadpool.c
··· 19 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 20 */ 21 21 22 + 23 + #ifdef __REACTOS__ 24 + #include <rtl_vista.h> 25 + #define NDEBUG 26 + #include "wine/list.h" 27 + #include <debug.h> 28 + 29 + #define ERR(fmt, ...) DPRINT1(fmt, ##__VA_ARGS__) 30 + #define FIXME(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) 31 + #define WARN(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) 32 + #define TRACE(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) 33 + #ifndef ARRAY_SIZE 34 + #define ARRAY_SIZE(_x) (sizeof((_x))/sizeof((_x)[0])) 35 + #endif 36 + 37 + typedef struct _THREAD_NAME_INFORMATION 38 + { 39 + UNICODE_STRING ThreadName; 40 + } THREAD_NAME_INFORMATION, *PTHREAD_NAME_INFORMATION; 41 + 42 + typedef void (CALLBACK *PNTAPCFUNC)(ULONG_PTR,ULONG_PTR,ULONG_PTR); 43 + typedef void (CALLBACK *PRTL_THREAD_START_ROUTINE)(LPVOID); 44 + typedef DWORD (CALLBACK *PRTL_WORK_ITEM_ROUTINE)(LPVOID); 45 + typedef void (NTAPI *RTL_WAITORTIMERCALLBACKFUNC)(PVOID,BOOLEAN); 46 + typedef VOID (CALLBACK *PRTL_OVERLAPPED_COMPLETION_ROUTINE)(DWORD,DWORD,LPVOID); 47 + 48 + typedef void (CALLBACK *PTP_IO_CALLBACK)(PTP_CALLBACK_INSTANCE,void*,void*,IO_STATUS_BLOCK*,PTP_IO); 49 + NTSYSAPI NTSTATUS WINAPI TpSimpleTryPost(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *); 50 + #define PRTL_WORK_ITEM_ROUTINE WORKERCALLBACKFUNC 51 + 52 + #define CRITICAL_SECTION RTL_CRITICAL_SECTION 53 + #define GetProcessHeap() RtlGetProcessHeap() 54 + #define GetCurrentProcess() NtCurrentProcess() 55 + #define GetCurrentThread() NtCurrentThread() 56 + #define GetCurrentThreadId() HandleToULong(NtCurrentTeb()->ClientId.UniqueThread) 57 + #else 22 58 #include <assert.h> 23 59 #include <stdarg.h> 24 60 #include <limits.h> ··· 33 69 #include "ntdll_misc.h" 34 70 35 71 WINE_DEFAULT_DEBUG_CHANNEL(threadpool); 72 + #endif 36 73 37 74 /* 38 75 * Old thread pooling API ··· 47 84 #define EXPIRE_NEVER (~(ULONGLONG)0) 48 85 #define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */ 49 86 87 + #ifndef __REACTOS__ 50 88 static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug; 89 + #endif 51 90 52 91 static struct 53 92 { ··· 57 96 old_threadpool = 58 97 { 59 98 NULL, /* compl_port */ 99 + #ifdef __REACTOS__ 100 + {0}, /* threadpool_compl_cs */ 101 + #else 60 102 { &critsect_compl_debug, -1, 0, 0, 0, 0 }, /* threadpool_compl_cs */ 103 + #endif 61 104 }; 62 105 106 + #ifndef __REACTOS__ 63 107 static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug = 64 108 { 65 109 0, 0, &old_threadpool.threadpool_compl_cs, 66 110 { &critsect_compl_debug.ProcessLocksList, &critsect_compl_debug.ProcessLocksList }, 67 111 0, 0, { (DWORD_PTR)(__FILE__ ": threadpool_compl_cs") } 68 112 }; 113 + #endif 69 114 70 115 struct timer_queue; 71 116 struct queue_timer ··· 235 280 struct list members; 236 281 }; 237 282 283 + #ifndef __REACTOS__ 238 284 /* global timerqueue object */ 239 285 static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug; 286 + #endif 240 287 241 288 static struct 242 289 { ··· 248 295 } 249 296 timerqueue = 250 297 { 298 + #ifdef __REACTOS__ 299 + {0}, /* cs */ 300 + #else 251 301 { &timerqueue_debug, -1, 0, 0, 0, 0 }, /* cs */ 302 + #endif 252 303 0, /* objcount */ 253 304 FALSE, /* thread_running */ 254 305 LIST_INIT( timerqueue.pending_timers ), /* pending_timers */ 306 + #if __REACTOS__ 307 + 0, 308 + #else 255 309 RTL_CONDITION_VARIABLE_INIT /* update_event */ 310 + #endif 256 311 }; 257 312 313 + #ifndef __REACTOS__ 258 314 static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug = 259 315 { 260 316 0, 0, &timerqueue.cs, ··· 264 320 265 321 /* global waitqueue object */ 266 322 static RTL_CRITICAL_SECTION_DEBUG waitqueue_debug; 323 + #endif 267 324 268 325 static struct 269 326 { ··· 273 330 } 274 331 waitqueue = 275 332 { 333 + #ifdef __REACTOS__ 334 + {0}, /* cs */ 335 + #else 276 336 { &waitqueue_debug, -1, 0, 0, 0, 0 }, /* cs */ 337 + #endif 277 338 0, /* num_buckets */ 278 339 LIST_INIT( waitqueue.buckets ) /* buckets */ 279 340 }; 280 341 342 + #ifndef __REACTOS__ 281 343 static RTL_CRITICAL_SECTION_DEBUG waitqueue_debug = 282 344 { 283 345 0, 0, &waitqueue.cs, 284 346 { &waitqueue_debug.ProcessLocksList, &waitqueue_debug.ProcessLocksList }, 285 347 0, 0, { (DWORD_PTR)(__FILE__ ": waitqueue.cs") } 286 348 }; 349 + #endif 287 350 288 351 struct waitqueue_bucket 289 352 { ··· 295 358 BOOL alertable; 296 359 }; 297 360 361 + #ifndef __REACTOS__ 298 362 /* global I/O completion queue object */ 299 363 static RTL_CRITICAL_SECTION_DEBUG ioqueue_debug; 364 + #endif 300 365 301 366 static struct 302 367 { ··· 308 373 } 309 374 ioqueue = 310 375 { 376 + #ifdef __REACTOS__ 377 + .cs = {0}, 378 + #else 311 379 .cs = { &ioqueue_debug, -1, 0, 0, 0, 0 }, 380 + #endif 312 381 }; 313 382 383 + #ifndef __REACTOS__ 314 384 static RTL_CRITICAL_SECTION_DEBUG ioqueue_debug = 315 385 { 316 386 0, 0, &ioqueue.cs, 317 387 { &ioqueue_debug.ProcessLocksList, &ioqueue_debug.ProcessLocksList }, 318 388 0, 0, { (DWORD_PTR)(__FILE__ ": ioqueue.cs") } 319 389 }; 390 + #endif 320 391 321 392 static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) 322 393 { ··· 361 432 return (struct threadpool_instance *)instance; 362 433 } 363 434 435 + #ifdef __REACTOS__ 436 + ULONG NTAPI threadpool_worker_proc(PVOID param ); 437 + #else 364 438 static void CALLBACK threadpool_worker_proc( void *param ); 439 + #endif 365 440 static void tp_object_submit( struct threadpool_object *object, BOOL signaled ); 366 441 static void tp_object_execute( struct threadpool_object *object, BOOL wait_thread ); 367 442 static void tp_object_prepare_shutdown( struct threadpool_object *object ); ··· 397 472 398 473 static void set_thread_name(const WCHAR *name) 399 474 { 475 + #ifndef __REACTOS__ // This is impossible on non vista+ 400 476 THREAD_NAME_INFORMATION info; 401 477 402 478 RtlInitUnicodeString(&info.ThreadName, name); 403 479 NtSetInformationThread(GetCurrentThread(), ThreadNameInformation, &info, sizeof(info)); 480 + #endif 404 481 } 405 482 483 + #ifndef __REACTOS__ 406 484 static void CALLBACK process_rtl_work_item( TP_CALLBACK_INSTANCE *instance, void *userdata ) 407 485 { 408 486 struct rtl_work_item *item = userdata; ··· 472 550 PRTL_OVERLAPPED_COMPLETION_ROUTINE callback; 473 551 LPVOID overlapped; 474 552 IO_STATUS_BLOCK iosb; 553 + #ifdef __REACTOS__ 554 + NTSTATUS res = NtRemoveIoCompletion( cport, (PVOID)&callback, (PVOID)&overlapped, &iosb, NULL ); 555 + #else 475 556 NTSTATUS res = NtRemoveIoCompletion( cport, (PULONG_PTR)&callback, (PULONG_PTR)&overlapped, &iosb, NULL ); 557 + #endif 476 558 if (res) 477 559 { 478 560 ERR("NtRemoveIoCompletion failed: 0x%lx\n", res); ··· 545 627 546 628 return NtSetInformationFile( FileHandle, &iosb, &info, sizeof(info), FileCompletionInformation ); 547 629 } 630 + #endif 548 631 549 632 static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout ) 550 633 { ··· 552 635 pTime->QuadPart = (ULONGLONG)timeout * -10000; 553 636 return pTime; 554 637 } 555 - 556 638 557 639 /************************** Timer Queue Impl **************************/ 558 640 ··· 705 787 return timeout; 706 788 } 707 789 790 + #ifdef __REACTOS__ 791 + ULONG NTAPI timer_queue_thread_proc(PVOID p) 792 + #else 708 793 static void WINAPI timer_queue_thread_proc(LPVOID p) 794 + #endif 709 795 { 710 796 struct timer_queue *q = p; 711 797 ULONG timeout_ms; ··· 746 832 q->magic = 0; 747 833 RtlFreeHeap(GetProcessHeap(), 0, q); 748 834 RtlExitUserThread( 0 ); 835 + #ifdef __REACTOS__ 836 + return STATUS_SUCCESS; 837 + #endif 749 838 } 750 839 751 840 static void queue_destroy_timer(struct queue_timer *t) ··· 1052 1141 /*********************************************************************** 1053 1142 * timerqueue_thread_proc (internal) 1054 1143 */ 1144 + #ifdef __REACTOS__ 1145 + ULONG NTAPI timerqueue_thread_proc(PVOID param ) 1146 + #else 1055 1147 static void CALLBACK timerqueue_thread_proc( void *param ) 1148 + #endif 1056 1149 { 1057 1150 ULONGLONG timeout_lower, timeout_upper, new_timeout; 1058 1151 struct threadpool_object *other_timer; ··· 1139 1232 1140 1233 TRACE( "terminating timer queue thread\n" ); 1141 1234 RtlExitUserThread( 0 ); 1235 + #ifdef __REACTOS__ 1236 + return STATUS_SUCCESS; 1237 + #endif 1142 1238 } 1143 1239 1144 1240 /*********************************************************************** ··· 1240 1336 /*********************************************************************** 1241 1337 * waitqueue_thread_proc (internal) 1242 1338 */ 1339 + #ifdef __REACTOS__ 1340 + void NTAPI waitqueue_thread_proc(PVOID param ) 1341 + #else 1243 1342 static void CALLBACK waitqueue_thread_proc( void *param ) 1343 + #endif 1244 1344 { 1245 1345 struct threadpool_object *objects[MAXIMUM_WAITQUEUE_OBJECTS]; 1246 1346 HANDLE handles[MAXIMUM_WAITQUEUE_OBJECTS + 1]; ··· 1467 1567 } 1468 1568 1469 1569 status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0, 1470 - waitqueue_thread_proc, bucket, &thread, NULL ); 1570 + (PTHREAD_START_ROUTINE)waitqueue_thread_proc, bucket, &thread, NULL ); 1471 1571 if (status == STATUS_SUCCESS) 1472 1572 { 1473 1573 list_add_tail( &waitqueue.buckets, &bucket->bucket_entry ); ··· 1512 1612 RtlLeaveCriticalSection( &waitqueue.cs ); 1513 1613 } 1514 1614 1615 + #ifdef __REACTOS__ 1616 + ULONG NTAPI ioqueue_thread_proc(PVOID param ) 1617 + #else 1515 1618 static void CALLBACK ioqueue_thread_proc( void *param ) 1619 + #endif 1516 1620 { 1517 1621 struct io_completion *completion; 1518 1622 struct threadpool_object *io; 1519 1623 IO_STATUS_BLOCK iosb; 1624 + #ifdef __REACTOS__ 1625 + PVOID key, value; 1626 + #else 1520 1627 ULONG_PTR key, value; 1628 + #endif 1521 1629 BOOL destroy, skip; 1522 1630 NTSTATUS status; 1523 1631 ··· 1581 1689 1582 1690 completion = &io->u.io.completions[io->u.io.completion_count++]; 1583 1691 completion->iosb = iosb; 1692 + #ifdef __REACTOS__ 1693 + completion->cvalue = (ULONG_PTR)value; 1694 + #else 1584 1695 completion->cvalue = value; 1696 + #endif 1585 1697 1586 1698 tp_object_submit( io, FALSE ); 1587 1699 } ··· 1606 1718 TRACE( "terminating I/O completion thread\n" ); 1607 1719 1608 1720 RtlExitUserThread( 0 ); 1721 + 1722 + #ifdef __REACTOS__ 1723 + return STATUS_SUCCESS; 1724 + #endif 1609 1725 } 1610 1726 1611 1727 static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) ··· 1640 1756 FILE_COMPLETION_INFORMATION info; 1641 1757 IO_STATUS_BLOCK iosb; 1642 1758 1759 + #ifdef __REACTOS__ 1760 + info.Port = ioqueue.port; 1761 + info.Key = io; 1762 + #else 1643 1763 info.CompletionPort = ioqueue.port; 1644 1764 info.CompletionKey = (ULONG_PTR)io; 1765 + #endif 1645 1766 1646 1767 status = NtSetInformationFile( file, &iosb, &info, sizeof(info), FileCompletionInformation ); 1647 1768 } ··· 1663 1784 */ 1664 1785 static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) 1665 1786 { 1787 + #ifdef __REACTOS__ 1788 + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress ); 1789 + #else 1666 1790 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); 1791 + #endif 1667 1792 struct threadpool *pool; 1668 1793 unsigned int i; 1669 1794 ··· 1675 1800 pool->objcount = 0; 1676 1801 pool->shutdown = FALSE; 1677 1802 1803 + #ifdef __REACTOS__ 1804 + RtlInitializeCriticalSection( &pool->cs ); 1805 + #else 1678 1806 RtlInitializeCriticalSectionEx( &pool->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); 1807 + 1679 1808 pool->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool.cs"); 1809 + #endif 1680 1810 1681 1811 for (i = 0; i < ARRAY_SIZE(pool->pools); ++i) 1682 1812 list_init( &pool->pools[i] ); ··· 1728 1858 assert( !pool->objcount ); 1729 1859 for (i = 0; i < ARRAY_SIZE(pool->pools); ++i) 1730 1860 assert( list_empty( &pool->pools[i] ) ); 1731 - 1861 + #ifndef __REACTOS__ 1732 1862 pool->cs.DebugInfo->Spare[0] = 0; 1863 + #endif 1733 1864 RtlDeleteCriticalSection( &pool->cs ); 1734 1865 1735 1866 RtlFreeHeap( GetProcessHeap(), 0, pool ); ··· 1750 1881 1751 1882 if (environment) 1752 1883 { 1884 + #ifndef __REACTOS__ //Windows 7 stuff 1753 1885 /* Validate environment parameters. */ 1754 1886 if (environment->Version == 3) 1755 1887 { ··· 1765 1897 return STATUS_INVALID_PARAMETER; 1766 1898 } 1767 1899 } 1768 - 1900 + #endif 1769 1901 pool = (struct threadpool *)environment->Pool; 1770 1902 } 1771 1903 ··· 1786 1918 1787 1919 pool = default_threadpool; 1788 1920 } 1789 - 1921 + 1790 1922 RtlEnterCriticalSection( &pool->cs ); 1791 1923 1792 1924 /* Make sure that the threadpool has at least one thread. */ ··· 1839 1971 group->refcount = 1; 1840 1972 group->shutdown = FALSE; 1841 1973 1974 + #ifdef __REACTOS__ 1975 + RtlInitializeCriticalSection( &group->cs ); 1976 + #else 1842 1977 RtlInitializeCriticalSectionEx( &group->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); 1978 + 1843 1979 group->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool_group.cs"); 1980 + #endif 1844 1981 1845 1982 list_init( &group->members ); 1846 1983 ··· 1875 2012 assert( group->shutdown ); 1876 2013 assert( list_empty( &group->members ) ); 1877 2014 2015 + #ifndef __REACTOS__ 1878 2016 group->cs.DebugInfo->Spare[0] = 0; 2017 + #endif 1879 2018 RtlDeleteCriticalSection( &group->cs ); 1880 2019 1881 2020 RtlFreeHeap( GetProcessHeap(), 0, group ); ··· 1925 2064 object->finalization_callback = environment->FinalizationCallback; 1926 2065 object->may_run_long = environment->u.s.LongFunction != 0; 1927 2066 object->race_dll = environment->RaceDll; 2067 + #ifndef __REACTOS__ //Windows 7 stuff 1928 2068 if (environment->Version == 3) 1929 2069 { 1930 2070 TP_CALLBACK_ENVIRON_V3 *environment_v3 = (TP_CALLBACK_ENVIRON_V3 *)environment; ··· 1932 2072 object->priority = environment_v3->CallbackPriority; 1933 2073 assert( object->priority < ARRAY_SIZE(pool->pools) ); 1934 2074 } 1935 - 2075 + #endif 1936 2076 if (environment->ActivationContext) 1937 2077 FIXME( "activation context not supported yet\n" ); 1938 2078 ··· 2328 2468 /*********************************************************************** 2329 2469 * threadpool_worker_proc (internal) 2330 2470 */ 2471 + #ifdef __REACTOS__ 2472 + ULONG NTAPI threadpool_worker_proc(PVOID param ) 2473 + #else 2331 2474 static void CALLBACK threadpool_worker_proc( void *param ) 2475 + #endif 2332 2476 { 2333 2477 struct threadpool *pool = param; 2334 2478 LARGE_INTEGER timeout; ··· 2382 2526 TRACE( "terminating worker thread for pool %p\n", pool ); 2383 2527 tp_threadpool_release( pool ); 2384 2528 RtlExitUserThread( 0 ); 2529 + #ifdef __REACTOS__ 2530 + return STATUS_SUCCESS; 2531 + #endif 2385 2532 } 2386 2533 2387 2534 /*********************************************************************** ··· 3355 3502 { 3356 3503 return RtlDeregisterWaitEx(WaitHandle, NULL); 3357 3504 } 3505 + 3506 + #ifdef __REACTOS__ 3507 + VOID 3508 + NTAPI 3509 + RtlpInitializeThreadPooling( 3510 + VOID) 3511 + { 3512 + RtlInitializeCriticalSection(&old_threadpool.threadpool_compl_cs); 3513 + RtlInitializeCriticalSection(&timerqueue.cs); 3514 + RtlInitializeCriticalSection(&waitqueue.cs); 3515 + RtlInitializeCriticalSection(&ioqueue.cs); 3516 + } 3517 + #endif
-493
sdk/lib/rtl/timerqueue.c
··· 64 64 #define EXPIRE_NEVER (~(ULONGLONG) 0) 65 65 #define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */ 66 66 67 - static void queue_remove_timer(struct queue_timer *t) 68 - { 69 - /* We MUST hold the queue cs while calling this function. This ensures 70 - that we cannot queue another callback for this timer. The runcount 71 - being zero makes sure we don't have any already queued. */ 72 - struct timer_queue *q = t->q; 73 - 74 - assert(t->runcount == 0); 75 - assert(t->destroy); 76 - 77 - list_remove(&t->entry); 78 - if (t->event) 79 - NtSetEvent(t->event, NULL); 80 - RtlFreeHeap(RtlGetProcessHeap(), 0, t); 81 - 82 - if (q->quit && list_empty(&q->timers)) 83 - NtSetEvent(q->event, NULL); 84 - } 85 - 86 - static void timer_cleanup_callback(struct queue_timer *t) 87 - { 88 - struct timer_queue *q = t->q; 89 - RtlEnterCriticalSection(&q->cs); 90 - 91 - assert(0 < t->runcount); 92 - --t->runcount; 93 - 94 - if (t->destroy && t->runcount == 0) 95 - queue_remove_timer(t); 96 - 97 - RtlLeaveCriticalSection(&q->cs); 98 - } 99 - 100 - static VOID WINAPI timer_callback_wrapper(LPVOID p) 101 - { 102 - struct queue_timer *t = p; 103 - t->callback(t->param, TRUE); 104 - timer_cleanup_callback(t); 105 - } 106 - 107 - static inline ULONGLONG queue_current_time(void) 108 - { 109 - LARGE_INTEGER now, freq; 110 - NtQueryPerformanceCounter(&now, &freq); 111 - return now.QuadPart * 1000 / freq.QuadPart; 112 - } 113 - 114 - static void queue_add_timer(struct queue_timer *t, ULONGLONG time, 115 - BOOL set_event) 116 - { 117 - /* We MUST hold the queue cs while calling this function. */ 118 - struct timer_queue *q = t->q; 119 - struct list *ptr = &q->timers; 120 - 121 - assert(!q->quit || (t->destroy && time == EXPIRE_NEVER)); 122 - 123 - if (time != EXPIRE_NEVER) 124 - LIST_FOR_EACH(ptr, &q->timers) 125 - { 126 - struct queue_timer *cur = LIST_ENTRY(ptr, struct queue_timer, entry); 127 - if (time < cur->expire) 128 - break; 129 - } 130 - list_add_before(ptr, &t->entry); 131 - 132 - t->expire = time; 133 - 134 - /* If we insert at the head of the list, we need to expire sooner 135 - than expected. */ 136 - if (set_event && &t->entry == list_head(&q->timers)) 137 - NtSetEvent(q->event, NULL); 138 - } 139 - 140 - static inline void queue_move_timer(struct queue_timer *t, ULONGLONG time, 141 - BOOL set_event) 142 - { 143 - /* We MUST hold the queue cs while calling this function. */ 144 - list_remove(&t->entry); 145 - queue_add_timer(t, time, set_event); 146 - } 147 - 148 - static void queue_timer_expire(struct timer_queue *q) 149 - { 150 - struct queue_timer *t = NULL; 151 - 152 - RtlEnterCriticalSection(&q->cs); 153 - if (list_head(&q->timers)) 154 - { 155 - ULONGLONG now, next; 156 - t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); 157 - if (!t->destroy && t->expire <= ((now = queue_current_time()))) 158 - { 159 - ++t->runcount; 160 - if (t->period) 161 - { 162 - next = t->expire + t->period; 163 - /* avoid trigger cascade if overloaded / hibernated */ 164 - if (next < now) 165 - next = now + t->period; 166 - } 167 - else 168 - next = EXPIRE_NEVER; 169 - queue_move_timer(t, next, FALSE); 170 - } 171 - else 172 - t = NULL; 173 - } 174 - RtlLeaveCriticalSection(&q->cs); 175 - 176 - if (t) 177 - { 178 - if (t->flags & WT_EXECUTEINTIMERTHREAD) 179 - timer_callback_wrapper(t); 180 - else 181 - { 182 - ULONG flags 183 - = (t->flags 184 - & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD 185 - | WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION)); 186 - NTSTATUS status = RtlQueueWorkItem(timer_callback_wrapper, t, flags); 187 - if (status != STATUS_SUCCESS) 188 - timer_cleanup_callback(t); 189 - } 190 - } 191 - } 192 - 193 - static ULONG queue_get_timeout(struct timer_queue *q) 194 - { 195 - struct queue_timer *t; 196 - ULONG timeout = INFINITE; 197 - 198 - RtlEnterCriticalSection(&q->cs); 199 - if (list_head(&q->timers)) 200 - { 201 - t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); 202 - assert(!t->destroy || t->expire == EXPIRE_NEVER); 203 - 204 - if (t->expire != EXPIRE_NEVER) 205 - { 206 - ULONGLONG time = queue_current_time(); 207 - timeout = t->expire < time ? 0 : (ULONG)(t->expire - time); 208 - } 209 - } 210 - RtlLeaveCriticalSection(&q->cs); 211 - 212 - return timeout; 213 - } 214 - 215 - static DWORD WINAPI timer_queue_thread_proc(LPVOID p) 216 - { 217 - struct timer_queue *q = p; 218 - ULONG timeout_ms; 219 - 220 - timeout_ms = INFINITE; 221 - for (;;) 222 - { 223 - LARGE_INTEGER timeout; 224 - NTSTATUS status; 225 - BOOL done = FALSE; 226 - 227 - status = NtWaitForSingleObject( 228 - q->event, FALSE, get_nt_timeout(&timeout, timeout_ms)); 229 - 230 - if (status == STATUS_WAIT_0) 231 - { 232 - /* There are two possible ways to trigger the event. Either 233 - we are quitting and the last timer got removed, or a new 234 - timer got put at the head of the list so we need to adjust 235 - our timeout. */ 236 - RtlEnterCriticalSection(&q->cs); 237 - if (q->quit && list_empty(&q->timers)) 238 - done = TRUE; 239 - RtlLeaveCriticalSection(&q->cs); 240 - } 241 - else if (status == STATUS_TIMEOUT) 242 - queue_timer_expire(q); 243 - 244 - if (done) 245 - break; 246 - 247 - timeout_ms = queue_get_timeout(q); 248 - } 249 - 250 - NtClose(q->event); 251 - RtlDeleteCriticalSection(&q->cs); 252 - q->magic = 0; 253 - RtlFreeHeap(RtlGetProcessHeap(), 0, q); 254 - RtlpExitThreadFunc(STATUS_SUCCESS); 255 - return 0; 256 - } 257 - 258 - static void queue_destroy_timer(struct queue_timer *t) 259 - { 260 - /* We MUST hold the queue cs while calling this function. */ 261 - t->destroy = TRUE; 262 - if (t->runcount == 0) 263 - /* Ensure a timer is promptly removed. If callbacks are pending, 264 - it will be removed after the last one finishes by the callback 265 - cleanup wrapper. */ 266 - queue_remove_timer(t); 267 - else 268 - /* Make sure no destroyed timer masks an active timer at the head 269 - of the sorted list. */ 270 - queue_move_timer(t, EXPIRE_NEVER, FALSE); 271 - } 272 - 273 - /*********************************************************************** 274 - * RtlCreateTimerQueue (NTDLL.@) 275 - * 276 - * Creates a timer queue object and returns a handle to it. 277 - * 278 - * PARAMS 279 - * NewTimerQueue [O] The newly created queue. 280 - * 281 - * RETURNS 282 - * Success: STATUS_SUCCESS. 283 - * Failure: Any NTSTATUS code. 284 - */ 285 - NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue) 286 - { 287 - NTSTATUS status; 288 - struct timer_queue *q = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof *q); 289 - if (!q) 290 - return STATUS_NO_MEMORY; 291 - 292 - RtlInitializeCriticalSection(&q->cs); 293 - list_init(&q->timers); 294 - q->quit = FALSE; 295 - q->magic = TIMER_QUEUE_MAGIC; 296 - status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); 297 - if (status != STATUS_SUCCESS) 298 - { 299 - RtlFreeHeap(RtlGetProcessHeap(), 0, q); 300 - return status; 301 - } 302 - status = RtlpStartThreadFunc(timer_queue_thread_proc, q, &q->thread); 303 - if (status != STATUS_SUCCESS) 304 - { 305 - NtClose(q->event); 306 - RtlFreeHeap(RtlGetProcessHeap(), 0, q); 307 - return status; 308 - } 309 - 310 - NtResumeThread(q->thread, NULL); 311 - *NewTimerQueue = q; 312 - return STATUS_SUCCESS; 313 - } 314 - 315 - /*********************************************************************** 316 - * RtlDeleteTimerQueueEx (NTDLL.@) 317 - * 318 - * Deletes a timer queue object. 319 - * 320 - * PARAMS 321 - * TimerQueue [I] The timer queue to destroy. 322 - * CompletionEvent [I] If NULL, return immediately. If INVALID_HANDLE_VALUE, 323 - * wait until all timers are finished firing before 324 - * returning. Otherwise, return immediately and set the 325 - * event when all timers are done. 326 - * 327 - * RETURNS 328 - * Success: STATUS_SUCCESS if synchronous, STATUS_PENDING if not. 329 - * Failure: Any NTSTATUS code. 330 - */ 331 - NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) 332 - { 333 - struct timer_queue *q = TimerQueue; 334 - struct queue_timer *t, *temp; 335 - HANDLE thread; 336 - NTSTATUS status; 337 - 338 - if (!q || q->magic != TIMER_QUEUE_MAGIC) 339 - return STATUS_INVALID_HANDLE; 340 - 341 - thread = q->thread; 342 - 343 - RtlEnterCriticalSection(&q->cs); 344 - q->quit = TRUE; 345 - if (list_head(&q->timers)) 346 - /* When the last timer is removed, it will signal the timer thread to 347 - exit... */ 348 - LIST_FOR_EACH_ENTRY_SAFE(t, temp, &q->timers, struct queue_timer, entry) 349 - queue_destroy_timer(t); 350 - else 351 - /* However if we have none, we must do it ourselves. */ 352 - NtSetEvent(q->event, NULL); 353 - RtlLeaveCriticalSection(&q->cs); 354 - 355 - if (CompletionEvent == INVALID_HANDLE_VALUE) 356 - { 357 - NtWaitForSingleObject(thread, FALSE, NULL); 358 - status = STATUS_SUCCESS; 359 - } 360 - else 361 - { 362 - if (CompletionEvent) 363 - { 364 - DPRINT1("asynchronous return on completion event unimplemented\n"); 365 - NtWaitForSingleObject(thread, FALSE, NULL); 366 - NtSetEvent(CompletionEvent, NULL); 367 - } 368 - status = STATUS_PENDING; 369 - } 370 - 371 - NtClose(thread); 372 - return status; 373 - } 374 - 375 - static struct timer_queue *get_timer_queue(HANDLE TimerQueue) 376 - { 377 - static struct timer_queue *default_timer_queue; 378 - 379 - if (TimerQueue) 380 - return TimerQueue; 381 - else 382 - { 383 - if (!default_timer_queue) 384 - { 385 - HANDLE q; 386 - NTSTATUS status = RtlCreateTimerQueue(&q); 387 - if (status == STATUS_SUCCESS) 388 - { 389 - PVOID p = InterlockedCompareExchangePointer( 390 - (void **) &default_timer_queue, q, NULL); 391 - if (p) 392 - /* Got beat to the punch. */ 393 - RtlDeleteTimerQueueEx(q, NULL); 394 - } 395 - } 396 - return default_timer_queue; 397 - } 398 - } 399 - 400 - /*********************************************************************** 401 - * RtlCreateTimer (NTDLL.@) 402 - * 403 - * Creates a new timer associated with the given queue. 404 - * 405 - * PARAMS 406 - * NewTimer [O] The newly created timer. 407 - * TimerQueue [I] The queue to hold the timer. 408 - * Callback [I] The callback to fire. 409 - * Parameter [I] The argument for the callback. 410 - * DueTime [I] The delay, in milliseconds, before first firing the 411 - * timer. 412 - * Period [I] The period, in milliseconds, at which to fire the timer 413 - * after the first callback. If zero, the timer will only 414 - * fire once. It still needs to be deleted with 415 - * RtlDeleteTimer. 416 - * Flags [I] Flags controlling the execution of the callback. In 417 - * addition to the WT_* thread pool flags (see 418 - * RtlQueueWorkItem), WT_EXECUTEINTIMERTHREAD and 419 - * WT_EXECUTEONLYONCE are supported. 420 - * 421 - * RETURNS 422 - * Success: STATUS_SUCCESS. 423 - * Failure: Any NTSTATUS code. 424 - */ 425 - NTSTATUS WINAPI RtlCreateTimer(HANDLE TimerQueue, PHANDLE NewTimer, 426 - WAITORTIMERCALLBACKFUNC Callback, 427 - PVOID Parameter, DWORD DueTime, DWORD Period, 428 - ULONG Flags) 429 - { 430 - NTSTATUS status; 431 - struct queue_timer *t; 432 - struct timer_queue *q = get_timer_queue(TimerQueue); 433 - 434 - if (!q) return STATUS_NO_MEMORY; 435 - if (q->magic != TIMER_QUEUE_MAGIC) return STATUS_INVALID_HANDLE; 436 - 437 - t = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof *t); 438 - if (!t) 439 - return STATUS_NO_MEMORY; 440 - 441 - t->q = q; 442 - t->runcount = 0; 443 - t->callback = Callback; 444 - t->param = Parameter; 445 - t->period = Period; 446 - t->flags = Flags; 447 - t->destroy = FALSE; 448 - t->event = NULL; 449 - 450 - status = STATUS_SUCCESS; 451 - RtlEnterCriticalSection(&q->cs); 452 - if (q->quit) 453 - status = STATUS_INVALID_HANDLE; 454 - else 455 - queue_add_timer(t, queue_current_time() + DueTime, TRUE); 456 - RtlLeaveCriticalSection(&q->cs); 457 - 458 - if (status == STATUS_SUCCESS) 459 - *NewTimer = t; 460 - else 461 - RtlFreeHeap(RtlGetProcessHeap(), 0, t); 462 - 463 - return status; 464 - } 465 - 466 67 NTSTATUS 467 68 WINAPI 468 69 RtlSetTimer( ··· 481 82 DueTime, 482 83 Period, 483 84 Flags); 484 - } 485 - 486 - /*********************************************************************** 487 - * RtlUpdateTimer (NTDLL.@) 488 - * 489 - * Changes the time at which a timer expires. 490 - * 491 - * PARAMS 492 - * TimerQueue [I] The queue that holds the timer. 493 - * Timer [I] The timer to update. 494 - * DueTime [I] The delay, in milliseconds, before next firing the timer. 495 - * Period [I] The period, in milliseconds, at which to fire the timer 496 - * after the first callback. If zero, the timer will not 497 - * refire once. It still needs to be deleted with 498 - * RtlDeleteTimer. 499 - * 500 - * RETURNS 501 - * Success: STATUS_SUCCESS. 502 - * Failure: Any NTSTATUS code. 503 - */ 504 - NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, 505 - DWORD DueTime, DWORD Period) 506 - { 507 - struct queue_timer *t = Timer; 508 - struct timer_queue *q = t->q; 509 - 510 - RtlEnterCriticalSection(&q->cs); 511 - /* Can't change a timer if it was once-only or destroyed. */ 512 - if (t->expire != EXPIRE_NEVER) 513 - { 514 - t->period = Period; 515 - queue_move_timer(t, queue_current_time() + DueTime, TRUE); 516 - } 517 - RtlLeaveCriticalSection(&q->cs); 518 - 519 - return STATUS_SUCCESS; 520 - } 521 - 522 - /*********************************************************************** 523 - * RtlDeleteTimer (NTDLL.@) 524 - * 525 - * Cancels a timer-queue timer. 526 - * 527 - * PARAMS 528 - * TimerQueue [I] The queue that holds the timer. 529 - * Timer [I] The timer to update. 530 - * CompletionEvent [I] If NULL, return immediately. If INVALID_HANDLE_VALUE, 531 - * wait until the timer is finished firing all pending 532 - * callbacks before returning. Otherwise, return 533 - * immediately and set the timer is done. 534 - * 535 - * RETURNS 536 - * Success: STATUS_SUCCESS if the timer is done, STATUS_PENDING if not, 537 - or if the completion event is NULL. 538 - * Failure: Any NTSTATUS code. 539 - */ 540 - NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, 541 - HANDLE CompletionEvent) 542 - { 543 - struct queue_timer *t = Timer; 544 - struct timer_queue *q; 545 - NTSTATUS status = STATUS_PENDING; 546 - HANDLE event = NULL; 547 - 548 - if (!Timer) 549 - return STATUS_INVALID_PARAMETER_1; 550 - q = t->q; 551 - if (CompletionEvent == INVALID_HANDLE_VALUE) 552 - { 553 - status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); 554 - if (status == STATUS_SUCCESS) 555 - status = STATUS_PENDING; 556 - } 557 - else if (CompletionEvent) 558 - event = CompletionEvent; 559 - 560 - RtlEnterCriticalSection(&q->cs); 561 - t->event = event; 562 - if (t->runcount == 0 && event) 563 - status = STATUS_SUCCESS; 564 - queue_destroy_timer(t); 565 - RtlLeaveCriticalSection(&q->cs); 566 - 567 - if (CompletionEvent == INVALID_HANDLE_VALUE && event) 568 - { 569 - if (status == STATUS_PENDING) 570 - { 571 - NtWaitForSingleObject(event, FALSE, NULL); 572 - status = STATUS_SUCCESS; 573 - } 574 - NtClose(event); 575 - } 576 - 577 - return status; 578 85 } 579 86 580 87 /*
-275
sdk/lib/rtl/wait.c
··· 1 - /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS system libraries 4 - * PURPOSE: Rtl user wait functions 5 - * FILE: lib/rtl/wait.c 6 - * PROGRAMERS: 7 - * Alex Ionescu (alex@relsoft.net) 8 - * Eric Kohl 9 - * KJK::Hyperion 10 - */ 11 - 12 - /* INCLUDES *****************************************************************/ 13 - 14 - #include <rtl.h> 15 - 16 - #define NDEBUG 17 - #include <debug.h> 18 - 19 - typedef struct _RTLP_WAIT 20 - { 21 - HANDLE Object; 22 - BOOLEAN CallbackInProgress; 23 - HANDLE CancelEvent; 24 - LONG DeleteCount; 25 - HANDLE CompletionEvent; 26 - ULONG Flags; 27 - WAITORTIMERCALLBACKFUNC Callback; 28 - PVOID Context; 29 - ULONG Milliseconds; 30 - } RTLP_WAIT, *PRTLP_WAIT; 31 - 32 - /* PRIVATE FUNCTIONS *******************************************************/ 33 - 34 - static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout ) 35 - { 36 - if (timeout == INFINITE) return NULL; 37 - pTime->QuadPart = (ULONGLONG)timeout * -10000; 38 - return pTime; 39 - } 40 - 41 - static VOID 42 - NTAPI 43 - Wait_thread_proc(LPVOID Arg) 44 - { 45 - PRTLP_WAIT Wait = (PRTLP_WAIT) Arg; 46 - NTSTATUS Status; 47 - BOOLEAN alertable = (Wait->Flags & WT_EXECUTEINIOTHREAD) != 0; 48 - HANDLE handles[2] = { Wait->CancelEvent, Wait->Object }; 49 - LARGE_INTEGER timeout; 50 - HANDLE completion_event; 51 - 52 - // TRACE("\n"); 53 - 54 - while (TRUE) 55 - { 56 - Status = NtWaitForMultipleObjects( 2, 57 - handles, 58 - WaitAny, 59 - alertable, 60 - get_nt_timeout( &timeout, Wait->Milliseconds ) ); 61 - 62 - if (Status == STATUS_WAIT_1 || Status == STATUS_TIMEOUT) 63 - { 64 - BOOLEAN TimerOrWaitFired; 65 - 66 - if (Status == STATUS_WAIT_1) 67 - { 68 - // TRACE( "object %p signaled, calling callback %p with context %p\n", 69 - // Wait->Object, Wait->Callback, 70 - // Wait->Context ); 71 - TimerOrWaitFired = FALSE; 72 - } 73 - else 74 - { 75 - // TRACE( "wait for object %p timed out, calling callback %p with context %p\n", 76 - // Wait->Object, Wait->Callback, 77 - // Wait->Context ); 78 - TimerOrWaitFired = TRUE; 79 - } 80 - Wait->CallbackInProgress = TRUE; 81 - Wait->Callback( Wait->Context, TimerOrWaitFired ); 82 - Wait->CallbackInProgress = FALSE; 83 - 84 - if (Wait->Flags & WT_EXECUTEONLYONCE) 85 - break; 86 - } 87 - else if (Status != STATUS_USER_APC) 88 - break; 89 - } 90 - 91 - completion_event = Wait->CompletionEvent; 92 - if (completion_event) NtSetEvent( completion_event, NULL ); 93 - 94 - if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) 95 - { 96 - NtClose( Wait->CancelEvent ); 97 - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 98 - } 99 - } 100 - 101 - 102 - /* FUNCTIONS ***************************************************************/ 103 - 104 - 105 - /*********************************************************************** 106 - * RtlRegisterWait 107 - * 108 - * Registers a wait for a handle to become signaled. 109 - * 110 - * PARAMS 111 - * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it. 112 - * Object [I] Object to wait to become signaled. 113 - * Callback [I] Callback function to execute when the wait times out or the handle is signaled. 114 - * Context [I] Context to pass to the callback function when it is executed. 115 - * Milliseconds [I] Number of milliseconds to wait before timing out. 116 - * Flags [I] Flags. See notes. 117 - * 118 - * RETURNS 119 - * Success: STATUS_SUCCESS. 120 - * Failure: Any NTSTATUS code. 121 - * 122 - * NOTES 123 - * Flags can be one or more of the following: 124 - *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread. 125 - *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread. 126 - *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent. 127 - *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time. 128 - *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token. 129 - */ 130 - NTSTATUS 131 - NTAPI 132 - RtlRegisterWait(PHANDLE NewWaitObject, 133 - HANDLE Object, 134 - WAITORTIMERCALLBACKFUNC Callback, 135 - PVOID Context, 136 - ULONG Milliseconds, 137 - ULONG Flags) 138 - { 139 - PRTLP_WAIT Wait; 140 - NTSTATUS Status; 141 - 142 - //TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags ); 143 - 144 - Wait = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(RTLP_WAIT) ); 145 - if (!Wait) 146 - return STATUS_NO_MEMORY; 147 - 148 - Wait->Object = Object; 149 - Wait->Callback = Callback; 150 - Wait->Context = Context; 151 - Wait->Milliseconds = Milliseconds; 152 - Wait->Flags = Flags; 153 - Wait->CallbackInProgress = FALSE; 154 - Wait->DeleteCount = 0; 155 - Wait->CompletionEvent = NULL; 156 - 157 - Status = NtCreateEvent( &Wait->CancelEvent, 158 - EVENT_ALL_ACCESS, 159 - NULL, 160 - NotificationEvent, 161 - FALSE ); 162 - 163 - if (Status != STATUS_SUCCESS) 164 - { 165 - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 166 - return Status; 167 - } 168 - 169 - Flags = Flags & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD | 170 - WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION); 171 - 172 - Status = RtlQueueWorkItem( Wait_thread_proc, 173 - Wait, 174 - Flags ); 175 - 176 - if (Status != STATUS_SUCCESS) 177 - { 178 - NtClose( Wait->CancelEvent ); 179 - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 180 - return Status; 181 - } 182 - 183 - *NewWaitObject = Wait; 184 - return Status; 185 - } 186 - 187 - /*********************************************************************** 188 - * RtlDeregisterWaitEx 189 - * 190 - * Cancels a wait operation and frees the resources associated with calling 191 - * RtlRegisterWait(). 192 - * 193 - * PARAMS 194 - * WaitObject [I] Handle to the wait object to free. 195 - * 196 - * RETURNS 197 - * Success: STATUS_SUCCESS. 198 - * Failure: Any NTSTATUS code. 199 - */ 200 - NTSTATUS 201 - NTAPI 202 - RtlDeregisterWaitEx(HANDLE WaitHandle, 203 - HANDLE CompletionEvent) 204 - { 205 - PRTLP_WAIT Wait = (PRTLP_WAIT) WaitHandle; 206 - NTSTATUS Status = STATUS_SUCCESS; 207 - 208 - //TRACE( "(%p)\n", WaitHandle ); 209 - 210 - NtSetEvent( Wait->CancelEvent, NULL ); 211 - if (Wait->CallbackInProgress) 212 - { 213 - if (CompletionEvent != NULL) 214 - { 215 - if (CompletionEvent == INVALID_HANDLE_VALUE) 216 - { 217 - Status = NtCreateEvent( &CompletionEvent, 218 - EVENT_ALL_ACCESS, 219 - NULL, 220 - NotificationEvent, 221 - FALSE ); 222 - 223 - if (Status != STATUS_SUCCESS) 224 - return Status; 225 - 226 - (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); 227 - 228 - if (Wait->CallbackInProgress) 229 - NtWaitForSingleObject( CompletionEvent, FALSE, NULL ); 230 - 231 - NtClose( CompletionEvent ); 232 - } 233 - else 234 - { 235 - (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); 236 - 237 - if (Wait->CallbackInProgress) 238 - Status = STATUS_PENDING; 239 - } 240 - } 241 - else 242 - Status = STATUS_PENDING; 243 - } 244 - 245 - if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) 246 - { 247 - Status = STATUS_SUCCESS; 248 - NtClose( Wait->CancelEvent ); 249 - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 250 - } 251 - 252 - return Status; 253 - } 254 - 255 - /*********************************************************************** 256 - * RtlDeregisterWait 257 - * 258 - * Cancels a wait operation and frees the resources associated with calling 259 - * RtlRegisterWait(). 260 - * 261 - * PARAMS 262 - * WaitObject [I] Handle to the wait object to free. 263 - * 264 - * RETURNS 265 - * Success: STATUS_SUCCESS. 266 - * Failure: Any NTSTATUS code. 267 - */ 268 - NTSTATUS 269 - NTAPI 270 - RtlDeregisterWait(HANDLE WaitHandle) 271 - { 272 - return RtlDeregisterWaitEx(WaitHandle, NULL); 273 - } 274 - 275 - /* EOF */