From 0bf42067d28ea488e03c9955632d2a614c4262c2 Mon Sep 17 00:00:00 2001 From: Justin Miller Date: Fri, 26 Apr 2024 01:03:15 -0700 Subject: [PATCH] [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 --- dll/ntdll/def/ntdll.spec | 68 +-- dll/ntdll/include/ntdllp.h | 5 + dll/ntdll/ldr/ldrinit.c | 4 +- dll/ntdll/nt_0600/ntdll_vista.spec | 29 -- media/doc/WINESYNC.txt | 4 +- .../rostests/winetests/ntdll/CMakeLists.txt | 1 + modules/rostests/winetests/ntdll/testlist.c | 2 + modules/rostests/winetests/ntdll/threadpool.c | 16 + sdk/include/ndk/rtlfuncs.h | 5 + sdk/include/xdk/winnt_old.h | 6 + sdk/lib/rtl/CMakeLists.txt | 9 +- sdk/lib/rtl/rtl.h | 2 + sdk/lib/rtl/threadpool.c | 172 +++++- sdk/lib/rtl/timerqueue.c | 493 ------------------ sdk/lib/rtl/wait.c | 275 ---------- 15 files changed, 249 insertions(+), 842 deletions(-) delete mode 100644 sdk/lib/rtl/wait.c diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index de23297ea55..b023b06f9c3 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -1311,45 +1311,47 @@ @ stub -version=0x600+ ShipAssertMsgA @ stub -version=0x600+ ShipAssertMsgW @ stub -version=0x600+ TpAllocAlpcCompletion -@ stub -version=0x600+ TpAllocCleanupGroup -@ stub -version=0x600+ TpAllocIoCompletion -@ stub -version=0x600+ TpAllocPool -@ stub -version=0x600+ TpAllocTimer -@ stub -version=0x600+ TpAllocWait -@ stub -version=0x600+ TpAllocWork -@ stub -version=0x600+ TpCallbackLeaveCriticalSectionOnCompletion -@ stub -version=0x600+ TpCallbackMayRunLong -@ stub -version=0x600+ TpCallbackReleaseMutexOnCompletion -@ stub -version=0x600+ TpCallbackReleaseSemaphoreOnCompletion -@ stub -version=0x600+ TpCallbackSetEventOnCompletion -@ stub -version=0x600+ TpCallbackUnloadDllOnCompletion -@ stub -version=0x600+ TpCancelAsyncIoOperation +@ stdcall -version=0x600+ TpAllocCleanupGroup(ptr) +@ stdcall -version=0x600+ TpAllocIoCompletion(ptr ptr ptr ptr ptr) +@ stdcall -version=0x600+ TpAllocPool(ptr ptr) +@ stdcall -version=0x600+ TpAllocTimer(ptr ptr ptr ptr) +@ stdcall -version=0x600+ TpAllocWait(ptr ptr ptr ptr) +@ stdcall -version=0x600+ TpAllocWork(ptr ptr ptr ptr) +@ stdcall -version=0x600+ TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) +@ stdcall -version=0x600+ TpCallbackMayRunLong(ptr) +@ stdcall -version=0x600+ TpCallbackReleaseMutexOnCompletion(ptr ptr) +@ stdcall -version=0x600+ TpCallbackReleaseSemaphoreOnCompletion(ptr ptr long) +@ stdcall -version=0x600+ TpCallbackSetEventOnCompletion(ptr ptr) +@ stdcall -version=0x600+ TpCallbackUnloadDllOnCompletion(ptr ptr) +@ stdcall -version=0x600+ TpCancelAsyncIoOperation(ptr) @ stub -version=0x600+ TpCaptureCaller @ stub -version=0x600+ TpCheckTerminateWorker @ stub -version=0x600+ TpDbgDumpHeapUsage @ stub -version=0x600+ TpDbgSetLogRoutine -@ stub -version=0x600+ TpDisassociateCallback -@ stub -version=0x600+ TpIsTimerSet -@ stub -version=0x600+ TpPostWork +@ stdcall -version=0x600+ TpDisassociateCallback(ptr) +@ stdcall -version=0x600+ TpIsTimerSet(ptr) +@ stdcall -version=0x600+ TpPostWork(ptr) +@ stdcall -version=0x600+ TpQueryPoolStackInformation(ptr ptr) @ stub -version=0x600+ TpReleaseAlpcCompletion -@ stub -version=0x600+ TpReleaseCleanupGroup -@ stub -version=0x600+ TpReleaseCleanupGroupMembers -@ stub -version=0x600+ TpReleaseIoCompletion -@ stub -version=0x600+ TpReleasePool -@ stub -version=0x600+ TpReleaseTimer -@ stub -version=0x600+ TpReleaseWait -@ stub -version=0x600+ TpReleaseWork -@ stub -version=0x600+ TpSetPoolMaxThreads -@ stub -version=0x600+ TpSetPoolMinThreads -@ stub -version=0x600+ TpSetTimer -@ stub -version=0x600+ TpSetWait -@ stub -version=0x600+ TpSimpleTryPost -@ stub -version=0x600+ TpStartAsyncIoOperation +@ stdcall -version=0x600+ TpReleaseCleanupGroup(ptr) +@ stdcall -version=0x600+ TpReleaseCleanupGroupMembers(ptr long ptr) +@ stdcall -version=0x600+ TpReleaseIoCompletion(ptr) +@ stdcall -version=0x600+ TpReleasePool(ptr) +@ stdcall -version=0x600+ TpReleaseTimer(ptr) +@ stdcall -version=0x600+ TpReleaseWait(ptr) +@ stdcall -version=0x600+ TpReleaseWork(ptr) +@ stdcall -version=0x600+ TpSetPoolMaxThreads(ptr long) +@ stdcall -version=0x600+ TpSetPoolMinThreads(ptr long) +@ stdcall -version=0x600+ TpSetPoolStackInformation(ptr ptr) +@ stdcall -version=0x600+ TpSetTimer(ptr ptr long long) +@ stdcall -version=0x600+ TpSetWait(ptr long ptr) +@ stdcall -version=0x600+ TpSimpleTryPost(ptr ptr ptr) +@ stdcall -version=0x600+ TpStartAsyncIoOperation(ptr) @ stub -version=0x600+ TpWaitForAlpcCompletion -@ stub -version=0x600+ TpWaitForIoCompletion -@ stub -version=0x600+ TpWaitForTimer -@ stub -version=0x600+ TpWaitForWait -@ stub -version=0x600+ TpWaitForWork +@ stdcall -version=0x600+ TpWaitForIoCompletion(ptr long) +@ stdcall -version=0x600+ TpWaitForTimer(ptr long) +@ stdcall -version=0x600+ TpWaitForWait(ptr long) +@ stdcall -version=0x600+ TpWaitForWork(ptr long) @ stdcall -ret64 VerSetConditionMask(double long long) @ stub -version=0x600+ WerCheckEventEscalation @ stub -version=0x600+ WerReportSQMEvent diff --git a/dll/ntdll/include/ntdllp.h b/dll/ntdll/include/ntdllp.h index bd5cc9ea91c..c5ea35a2761 100644 --- a/dll/ntdll/include/ntdllp.h +++ b/dll/ntdll/include/ntdllp.h @@ -242,4 +242,9 @@ NTAPI RtlpInitializeKeyedEvent( VOID); +VOID +NTAPI +RtlpInitializeThreadPooling( + VOID); + /* EOF */ diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index 4fbc4f293aa..cde86383759 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -2415,10 +2415,10 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Check whether all static imports were properly loaded and return here */ if (!NT_SUCCESS(ImportStatus)) return ImportStatus; -#if (DLL_EXPORT_VERSION >= _WIN32_WINNT_VISTA) + /* Following two calls are for Vista+ support, required for winesync */ /* Initialize the keyed event for condition variables */ RtlpInitializeKeyedEvent(); -#endif + RtlpInitializeThreadPooling(); /* Initialize TLS */ Status = LdrpInitializeTls(); diff --git a/dll/ntdll/nt_0600/ntdll_vista.spec b/dll/ntdll/nt_0600/ntdll_vista.spec index 23fd88e02c4..d36c6449d8e 100644 --- a/dll/ntdll/nt_0600/ntdll_vista.spec +++ b/dll/ntdll/nt_0600/ntdll_vista.spec @@ -13,34 +13,5 @@ @ stdcall RtlRunOnceComplete(ptr long ptr) @ stdcall RtlRunOnceExecuteOnce(ptr ptr ptr ptr) -@ stdcall TpAllocCleanupGroup(ptr) -@ stdcall TpAllocPool(ptr ptr) -@ stdcall TpAllocTimer(ptr ptr ptr ptr) -@ stdcall TpAllocWait(ptr ptr ptr ptr) -@ stdcall TpAllocWork(ptr ptr ptr ptr) -@ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) -@ stdcall TpCallbackMayRunLong(ptr) -@ stdcall TpCallbackReleaseMutexOnCompletion(ptr ptr) -@ stdcall TpCallbackReleaseSemaphoreOnCompletion(ptr ptr long) -@ stdcall TpCallbackSetEventOnCompletion(ptr ptr) -@ stdcall TpCallbackUnloadDllOnCompletion(ptr ptr) -@ stdcall TpDisassociateCallback(ptr) -@ stdcall TpIsTimerSet(ptr) -@ stdcall TpPostWork(ptr) -@ stdcall TpReleaseCleanupGroup(ptr) -@ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) -@ stdcall TpReleasePool(ptr) -@ stdcall TpReleaseTimer(ptr) -@ stdcall TpReleaseWait(ptr) -@ stdcall TpReleaseWork(ptr) -@ stdcall TpSetPoolMaxThreads(ptr long) -@ stdcall TpSetPoolMinThreads(ptr long) -@ stdcall TpSetTimer(ptr ptr long long) -@ stdcall TpSetWait(ptr long ptr) -@ stdcall TpSimpleTryPost(ptr ptr ptr) -@ stdcall TpWaitForTimer(ptr long) -@ stdcall TpWaitForWait(ptr long) -@ stdcall TpWaitForWork(ptr long) - @ stdcall RtlConnectToSm(ptr ptr long ptr) SmConnectToSm @ stdcall RtlSendMsgToSm(ptr ptr) SmSendMsgToSm diff --git a/media/doc/WINESYNC.txt b/media/doc/WINESYNC.txt index 61e11c67f15..44f5cb523ae 100644 --- a/media/doc/WINESYNC.txt +++ b/media/doc/WINESYNC.txt @@ -267,8 +267,8 @@ check Wine current sources first as it may already be fixed. sdk/lib/3rdparty/strmbase # Synced to WineStaging-3.3 -sdk/lib/rtl/actctx.c # Synced to wine-5.18 -sdk/lib/rtl/threadpool.c # Synced with wine-9.7 +sdk/lib/rtl/actctx.c # Partly synced with WineStaging-1.9.16 +sdk/lib/rtl/threadpool.c # Synced with Wine-9.7 advapi32 - dll/win32/advapi32/wine/cred.c # Synced to WineStaging-3.3 diff --git a/modules/rostests/winetests/ntdll/CMakeLists.txt b/modules/rostests/winetests/ntdll/CMakeLists.txt index c5a886481e7..dbcf2116039 100644 --- a/modules/rostests/winetests/ntdll/CMakeLists.txt +++ b/modules/rostests/winetests/ntdll/CMakeLists.txt @@ -23,6 +23,7 @@ list(APPEND SOURCE rtlstr.c string.c testlist.c + threadpool.c time.c) if(ARCH STREQUAL "i386") diff --git a/modules/rostests/winetests/ntdll/testlist.c b/modules/rostests/winetests/ntdll/testlist.c index 989040c562a..1c9edc99e86 100644 --- a/modules/rostests/winetests/ntdll/testlist.c +++ b/modules/rostests/winetests/ntdll/testlist.c @@ -23,6 +23,7 @@ extern void func_rtl(void); extern void func_rtlbitmap(void); extern void func_rtlstr(void); extern void func_string(void); +extern void func_threadpool(void); extern void func_time(void); const struct test winetest_testlist[] = @@ -49,6 +50,7 @@ const struct test winetest_testlist[] = { "rtlbitmap", func_rtlbitmap }, { "rtlstr", func_rtlstr }, { "string", func_string }, + { "threadpool", func_threadpool}, { "time", func_time }, { 0, 0 } }; diff --git a/modules/rostests/winetests/ntdll/threadpool.c b/modules/rostests/winetests/ntdll/threadpool.c index 1dd96bfd2f3..88f4e55fa97 100644 --- a/modules/rostests/winetests/ntdll/threadpool.c +++ b/modules/rostests/winetests/ntdll/threadpool.c @@ -20,6 +20,10 @@ #include "ntdll_test.h" +#ifdef __REACTOS__ +typedef void (CALLBACK *PTP_IO_CALLBACK)(PTP_CALLBACK_INSTANCE,void*,void*,IO_STATUS_BLOCK*,PTP_IO); +#endif + static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **); static NTSTATUS (WINAPI *pTpAllocIoCompletion)(TP_IO **,HANDLE,PTP_IO_CALLBACK,void *,TP_CALLBACK_ENVIRON *); static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID); @@ -580,7 +584,9 @@ static void test_tp_simple(void) IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); TP_POOL_STACK_INFORMATION stack_info; TP_CALLBACK_ENVIRON environment; +#ifndef __REACTOS__ TP_CALLBACK_ENVIRON_V3 environment3; +#endif TP_CLEANUP_GROUP *group; HANDLE semaphore; NTSTATUS status; @@ -616,6 +622,7 @@ static void test_tp_simple(void) result = WaitForSingleObject(semaphore, 1000); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", result); +#ifndef __REACTOS__ // Windows 7 /* test with environment version 3 */ memset(&environment3, 0, sizeof(environment3)); environment3.Version = 3; @@ -635,6 +642,7 @@ static void test_tp_simple(void) status = pTpSimpleTryPost(simple_cb, semaphore, (TP_CALLBACK_ENVIRON *)&environment3); ok(status == STATUS_INVALID_PARAMETER || broken(!status) /* Vista does not support priorities */, "TpSimpleTryPost failed with status %lx\n", status); +#endif /* test with invalid version number */ memset(&environment, 0, sizeof(environment)); @@ -2031,7 +2039,11 @@ static DWORD WINAPI io_wait_thread(void *arg) static void test_tp_io(void) { TP_CALLBACK_ENVIRON environment = {.Version = 1}; +#ifdef __REACTOS__ + OVERLAPPED ovl = {0}, ovl2 = {0}; +#else OVERLAPPED ovl = {}, ovl2 = {}; +#endif HANDLE client, server, thread; struct io_cb_ctx userdata; char in[1], in2[1]; @@ -2251,7 +2263,11 @@ static void CALLBACK kernel32_io_cb(TP_CALLBACK_INSTANCE *instance, void *userda static void test_kernel32_tp_io(void) { TP_CALLBACK_ENVIRON environment = {.Version = 1}; +#ifdef __REACTOS__ + OVERLAPPED ovl = {0}, ovl2 = {0}; +#else OVERLAPPED ovl = {}, ovl2 = {}; +#endif HANDLE client, server, thread; struct io_cb_ctx userdata; char in[1], in2[1]; diff --git a/sdk/include/ndk/rtlfuncs.h b/sdk/include/ndk/rtlfuncs.h index 7b128cd440b..c9135cfc909 100644 --- a/sdk/include/ndk/rtlfuncs.h +++ b/sdk/include/ndk/rtlfuncs.h @@ -4748,24 +4748,29 @@ RtlSleepConditionVariableSRW( // // Synchronization functions // +NTSYSAPI VOID NTAPI RtlInitializeConditionVariable(OUT PRTL_CONDITION_VARIABLE ConditionVariable); +NTSYSAPI VOID NTAPI RtlWakeConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable); +NTSYSAPI VOID NTAPI RtlWakeAllConditionVariable(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable); +NTSYSAPI NTSTATUS NTAPI RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_CRITICAL_SECTION CriticalSection, IN const PLARGE_INTEGER TimeOut OPTIONAL); +NTSYSAPI NTSTATUS NTAPI RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, diff --git a/sdk/include/xdk/winnt_old.h b/sdk/include/xdk/winnt_old.h index ee28a933347..3de049071bf 100644 --- a/sdk/include/xdk/winnt_old.h +++ b/sdk/include/xdk/winnt_old.h @@ -4495,6 +4495,12 @@ typedef enum _TP_CALLBACK_PRIORITY { TP_CALLBACK_PRIORITY_COUNT = TP_CALLBACK_PRIORITY_INVALID } TP_CALLBACK_PRIORITY; +typedef struct _TP_POOL_STACK_INFORMATION +{ + SIZE_T StackReserve; + SIZE_T StackCommit; +} TP_POOL_STACK_INFORMATION,*PTP_POOL_STACK_INFORMATION; + typedef VOID (NTAPI *PTP_WORK_CALLBACK)( _Inout_ PTP_CALLBACK_INSTANCE Instance, diff --git a/sdk/lib/rtl/CMakeLists.txt b/sdk/lib/rtl/CMakeLists.txt index 78077605a91..202857437d5 100644 --- a/sdk/lib/rtl/CMakeLists.txt +++ b/sdk/lib/rtl/CMakeLists.txt @@ -8,13 +8,19 @@ add_definitions( if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") # Enable this again. CORE-17637 add_compile_options(-Wunused-result) + + add_compile_options(-Wno-incompatible-pointer-types) + add_compile_options(-Wno-missing-braces) endif() +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) + list(APPEND RTL_WINE_SOURCE actctx.c timerqueue.c - wait.c + threadpool.c ) +set_source_files_properties(threadpool.c PROPERTIES COMPILE_DEFINITIONS __WINESRC__) if(MSVC) # Silence warning C4267: 'initializing': conversion from 'size_t' to 'const int', possible loss of data @@ -127,7 +133,6 @@ list(APPEND SOURCE_VISTA condvar.c runonce.c srw.c - threadpool.c utf8.c) add_library(rtl_vista ${SOURCE_VISTA}) diff --git a/sdk/lib/rtl/rtl.h b/sdk/lib/rtl/rtl.h index 037b2ee2c9b..d818fcad4dc 100644 --- a/sdk/lib/rtl/rtl.h +++ b/sdk/lib/rtl/rtl.h @@ -56,6 +56,7 @@ /* Use intrinsics for x86 and x64 */ #if defined(_M_IX86) || defined(_M_AMD64) +#ifndef InterlockedCompareExchange #define InterlockedCompareExchange _InterlockedCompareExchange #define InterlockedIncrement _InterlockedIncrement #define InterlockedDecrement _InterlockedDecrement @@ -64,5 +65,6 @@ #define InterlockedBitTestAndSet _interlockedbittestandset #define InterlockedBitTestAndSet64 _interlockedbittestandset64 #endif +#endif #endif /* RTL_H */ diff --git a/sdk/lib/rtl/threadpool.c b/sdk/lib/rtl/threadpool.c index c6e40fc78f4..efdfa454618 100644 --- a/sdk/lib/rtl/threadpool.c +++ b/sdk/lib/rtl/threadpool.c @@ -19,6 +19,42 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + +#ifdef __REACTOS__ +#include +#define NDEBUG +#include "wine/list.h" +#include + +#define ERR(fmt, ...) DPRINT1(fmt, ##__VA_ARGS__) +#define FIXME(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) +#define WARN(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) +#define TRACE(fmt, ...) DPRINT(fmt, ##__VA_ARGS__) +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(_x) (sizeof((_x))/sizeof((_x)[0])) +#endif + +typedef struct _THREAD_NAME_INFORMATION +{ + UNICODE_STRING ThreadName; +} THREAD_NAME_INFORMATION, *PTHREAD_NAME_INFORMATION; + +typedef void (CALLBACK *PNTAPCFUNC)(ULONG_PTR,ULONG_PTR,ULONG_PTR); +typedef void (CALLBACK *PRTL_THREAD_START_ROUTINE)(LPVOID); +typedef DWORD (CALLBACK *PRTL_WORK_ITEM_ROUTINE)(LPVOID); +typedef void (NTAPI *RTL_WAITORTIMERCALLBACKFUNC)(PVOID,BOOLEAN); +typedef VOID (CALLBACK *PRTL_OVERLAPPED_COMPLETION_ROUTINE)(DWORD,DWORD,LPVOID); + +typedef void (CALLBACK *PTP_IO_CALLBACK)(PTP_CALLBACK_INSTANCE,void*,void*,IO_STATUS_BLOCK*,PTP_IO); +NTSYSAPI NTSTATUS WINAPI TpSimpleTryPost(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *); +#define PRTL_WORK_ITEM_ROUTINE WORKERCALLBACKFUNC + +#define CRITICAL_SECTION RTL_CRITICAL_SECTION +#define GetProcessHeap() RtlGetProcessHeap() +#define GetCurrentProcess() NtCurrentProcess() +#define GetCurrentThread() NtCurrentThread() +#define GetCurrentThreadId() HandleToULong(NtCurrentTeb()->ClientId.UniqueThread) +#else #include #include #include @@ -33,6 +69,7 @@ #include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(threadpool); +#endif /* * Old thread pooling API @@ -47,7 +84,9 @@ struct rtl_work_item #define EXPIRE_NEVER (~(ULONGLONG)0) #define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */ +#ifndef __REACTOS__ static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug; +#endif static struct { @@ -57,15 +96,21 @@ static struct old_threadpool = { NULL, /* compl_port */ +#ifdef __REACTOS__ + {0}, /* threadpool_compl_cs */ +#else { &critsect_compl_debug, -1, 0, 0, 0, 0 }, /* threadpool_compl_cs */ +#endif }; +#ifndef __REACTOS__ static RTL_CRITICAL_SECTION_DEBUG critsect_compl_debug = { 0, 0, &old_threadpool.threadpool_compl_cs, { &critsect_compl_debug.ProcessLocksList, &critsect_compl_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": threadpool_compl_cs") } }; +#endif struct timer_queue; struct queue_timer @@ -235,8 +280,10 @@ struct threadpool_group struct list members; }; +#ifndef __REACTOS__ /* global timerqueue object */ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug; +#endif static struct { @@ -248,13 +295,22 @@ static struct } timerqueue = { +#ifdef __REACTOS__ + {0}, /* cs */ +#else { &timerqueue_debug, -1, 0, 0, 0, 0 }, /* cs */ +#endif 0, /* objcount */ FALSE, /* thread_running */ LIST_INIT( timerqueue.pending_timers ), /* pending_timers */ +#if __REACTOS__ + 0, +#else RTL_CONDITION_VARIABLE_INIT /* update_event */ +#endif }; +#ifndef __REACTOS__ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug = { 0, 0, &timerqueue.cs, @@ -264,6 +320,7 @@ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug = /* global waitqueue object */ static RTL_CRITICAL_SECTION_DEBUG waitqueue_debug; +#endif static struct { @@ -273,17 +330,23 @@ static struct } waitqueue = { +#ifdef __REACTOS__ + {0}, /* cs */ +#else { &waitqueue_debug, -1, 0, 0, 0, 0 }, /* cs */ +#endif 0, /* num_buckets */ LIST_INIT( waitqueue.buckets ) /* buckets */ }; +#ifndef __REACTOS__ static RTL_CRITICAL_SECTION_DEBUG waitqueue_debug = { 0, 0, &waitqueue.cs, { &waitqueue_debug.ProcessLocksList, &waitqueue_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": waitqueue.cs") } }; +#endif struct waitqueue_bucket { @@ -295,8 +358,10 @@ struct waitqueue_bucket BOOL alertable; }; +#ifndef __REACTOS__ /* global I/O completion queue object */ static RTL_CRITICAL_SECTION_DEBUG ioqueue_debug; +#endif static struct { @@ -308,15 +373,21 @@ static struct } ioqueue = { +#ifdef __REACTOS__ + .cs = {0}, +#else .cs = { &ioqueue_debug, -1, 0, 0, 0, 0 }, +#endif }; +#ifndef __REACTOS__ static RTL_CRITICAL_SECTION_DEBUG ioqueue_debug = { 0, 0, &ioqueue.cs, { &ioqueue_debug.ProcessLocksList, &ioqueue_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": ioqueue.cs") } }; +#endif static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) { @@ -361,7 +432,11 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL return (struct threadpool_instance *)instance; } +#ifdef __REACTOS__ +ULONG NTAPI threadpool_worker_proc(PVOID param ); +#else static void CALLBACK threadpool_worker_proc( void *param ); +#endif static void tp_object_submit( struct threadpool_object *object, BOOL signaled ); static void tp_object_execute( struct threadpool_object *object, BOOL wait_thread ); static void tp_object_prepare_shutdown( struct threadpool_object *object ); @@ -397,12 +472,15 @@ static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int static void set_thread_name(const WCHAR *name) { +#ifndef __REACTOS__ // This is impossible on non vista+ THREAD_NAME_INFORMATION info; RtlInitUnicodeString(&info.ThreadName, name); NtSetInformationThread(GetCurrentThread(), ThreadNameInformation, &info, sizeof(info)); +#endif } +#ifndef __REACTOS__ static void CALLBACK process_rtl_work_item( TP_CALLBACK_INSTANCE *instance, void *userdata ) { struct rtl_work_item *item = userdata; @@ -472,7 +550,11 @@ static DWORD CALLBACK iocp_poller(LPVOID Arg) PRTL_OVERLAPPED_COMPLETION_ROUTINE callback; LPVOID overlapped; IO_STATUS_BLOCK iosb; +#ifdef __REACTOS__ + NTSTATUS res = NtRemoveIoCompletion( cport, (PVOID)&callback, (PVOID)&overlapped, &iosb, NULL ); +#else NTSTATUS res = NtRemoveIoCompletion( cport, (PULONG_PTR)&callback, (PULONG_PTR)&overlapped, &iosb, NULL ); +#endif if (res) { ERR("NtRemoveIoCompletion failed: 0x%lx\n", res); @@ -545,6 +627,7 @@ NTSTATUS WINAPI RtlSetIoCompletionCallback(HANDLE FileHandle, PRTL_OVERLAPPED_CO return NtSetInformationFile( FileHandle, &iosb, &info, sizeof(info), FileCompletionInformation ); } +#endif static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout ) { @@ -553,7 +636,6 @@ static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout return pTime; } - /************************** Timer Queue Impl **************************/ static void queue_remove_timer(struct queue_timer *t) @@ -705,7 +787,11 @@ static ULONG queue_get_timeout(struct timer_queue *q) return timeout; } +#ifdef __REACTOS__ +ULONG NTAPI timer_queue_thread_proc(PVOID p) +#else static void WINAPI timer_queue_thread_proc(LPVOID p) +#endif { struct timer_queue *q = p; ULONG timeout_ms; @@ -746,6 +832,9 @@ static void WINAPI timer_queue_thread_proc(LPVOID p) q->magic = 0; RtlFreeHeap(GetProcessHeap(), 0, q); RtlExitUserThread( 0 ); +#ifdef __REACTOS__ + return STATUS_SUCCESS; +#endif } static void queue_destroy_timer(struct queue_timer *t) @@ -1052,7 +1141,11 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, /*********************************************************************** * timerqueue_thread_proc (internal) */ +#ifdef __REACTOS__ +ULONG NTAPI timerqueue_thread_proc(PVOID param ) +#else static void CALLBACK timerqueue_thread_proc( void *param ) +#endif { ULONGLONG timeout_lower, timeout_upper, new_timeout; struct threadpool_object *other_timer; @@ -1139,6 +1232,9 @@ static void CALLBACK timerqueue_thread_proc( void *param ) TRACE( "terminating timer queue thread\n" ); RtlExitUserThread( 0 ); +#ifdef __REACTOS__ + return STATUS_SUCCESS; +#endif } /*********************************************************************** @@ -1240,7 +1336,11 @@ static void tp_timerqueue_unlock( struct threadpool_object *timer ) /*********************************************************************** * waitqueue_thread_proc (internal) */ +#ifdef __REACTOS__ +void NTAPI waitqueue_thread_proc(PVOID param ) +#else static void CALLBACK waitqueue_thread_proc( void *param ) +#endif { struct threadpool_object *objects[MAXIMUM_WAITQUEUE_OBJECTS]; HANDLE handles[MAXIMUM_WAITQUEUE_OBJECTS + 1]; @@ -1467,7 +1567,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) } status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0, - waitqueue_thread_proc, bucket, &thread, NULL ); + (PTHREAD_START_ROUTINE)waitqueue_thread_proc, bucket, &thread, NULL ); if (status == STATUS_SUCCESS) { list_add_tail( &waitqueue.buckets, &bucket->bucket_entry ); @@ -1512,12 +1612,20 @@ static void tp_waitqueue_unlock( struct threadpool_object *wait ) RtlLeaveCriticalSection( &waitqueue.cs ); } +#ifdef __REACTOS__ +ULONG NTAPI ioqueue_thread_proc(PVOID param ) +#else static void CALLBACK ioqueue_thread_proc( void *param ) +#endif { struct io_completion *completion; struct threadpool_object *io; IO_STATUS_BLOCK iosb; +#ifdef __REACTOS__ + PVOID key, value; +#else ULONG_PTR key, value; +#endif BOOL destroy, skip; NTSTATUS status; @@ -1581,7 +1689,11 @@ static void CALLBACK ioqueue_thread_proc( void *param ) completion = &io->u.io.completions[io->u.io.completion_count++]; completion->iosb = iosb; +#ifdef __REACTOS__ + completion->cvalue = (ULONG_PTR)value; +#else completion->cvalue = value; +#endif tp_object_submit( io, FALSE ); } @@ -1606,6 +1718,10 @@ static void CALLBACK ioqueue_thread_proc( void *param ) TRACE( "terminating I/O completion thread\n" ); RtlExitUserThread( 0 ); + +#ifdef __REACTOS__ + return STATUS_SUCCESS; +#endif } static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) @@ -1640,8 +1756,13 @@ static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) FILE_COMPLETION_INFORMATION info; IO_STATUS_BLOCK iosb; +#ifdef __REACTOS__ + info.Port = ioqueue.port; + info.Key = io; +#else info.CompletionPort = ioqueue.port; info.CompletionKey = (ULONG_PTR)io; +#endif status = NtSetInformationFile( file, &iosb, &info, sizeof(info), FileCompletionInformation ); } @@ -1663,7 +1784,11 @@ static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) */ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) { +#ifdef __REACTOS__ + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress ); +#else IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); +#endif struct threadpool *pool; unsigned int i; @@ -1675,8 +1800,13 @@ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) pool->objcount = 0; pool->shutdown = FALSE; +#ifdef __REACTOS__ + RtlInitializeCriticalSection( &pool->cs ); +#else RtlInitializeCriticalSectionEx( &pool->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); + pool->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool.cs"); +#endif for (i = 0; i < ARRAY_SIZE(pool->pools); ++i) list_init( &pool->pools[i] ); @@ -1728,8 +1858,9 @@ static BOOL tp_threadpool_release( struct threadpool *pool ) assert( !pool->objcount ); for (i = 0; i < ARRAY_SIZE(pool->pools); ++i) assert( list_empty( &pool->pools[i] ) ); - +#ifndef __REACTOS__ pool->cs.DebugInfo->Spare[0] = 0; +#endif RtlDeleteCriticalSection( &pool->cs ); RtlFreeHeap( GetProcessHeap(), 0, pool ); @@ -1750,6 +1881,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON if (environment) { +#ifndef __REACTOS__ //Windows 7 stuff /* Validate environment parameters. */ if (environment->Version == 3) { @@ -1765,7 +1897,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON return STATUS_INVALID_PARAMETER; } } - +#endif pool = (struct threadpool *)environment->Pool; } @@ -1786,7 +1918,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON pool = default_threadpool; } - + RtlEnterCriticalSection( &pool->cs ); /* Make sure that the threadpool has at least one thread. */ @@ -1839,8 +1971,13 @@ static NTSTATUS tp_group_alloc( struct threadpool_group **out ) group->refcount = 1; group->shutdown = FALSE; +#ifdef __REACTOS__ + RtlInitializeCriticalSection( &group->cs ); +#else RtlInitializeCriticalSectionEx( &group->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); + group->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool_group.cs"); +#endif list_init( &group->members ); @@ -1875,7 +2012,9 @@ static BOOL tp_group_release( struct threadpool_group *group ) assert( group->shutdown ); assert( list_empty( &group->members ) ); +#ifndef __REACTOS__ group->cs.DebugInfo->Spare[0] = 0; +#endif RtlDeleteCriticalSection( &group->cs ); RtlFreeHeap( GetProcessHeap(), 0, group ); @@ -1925,6 +2064,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->finalization_callback = environment->FinalizationCallback; object->may_run_long = environment->u.s.LongFunction != 0; object->race_dll = environment->RaceDll; +#ifndef __REACTOS__ //Windows 7 stuff if (environment->Version == 3) { TP_CALLBACK_ENVIRON_V3 *environment_v3 = (TP_CALLBACK_ENVIRON_V3 *)environment; @@ -1932,7 +2072,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->priority = environment_v3->CallbackPriority; assert( object->priority < ARRAY_SIZE(pool->pools) ); } - +#endif if (environment->ActivationContext) FIXME( "activation context not supported yet\n" ); @@ -2328,7 +2468,11 @@ skip_cleanup: /*********************************************************************** * threadpool_worker_proc (internal) */ +#ifdef __REACTOS__ +ULONG NTAPI threadpool_worker_proc(PVOID param ) +#else static void CALLBACK threadpool_worker_proc( void *param ) +#endif { struct threadpool *pool = param; LARGE_INTEGER timeout; @@ -2382,6 +2526,9 @@ static void CALLBACK threadpool_worker_proc( void *param ) TRACE( "terminating worker thread for pool %p\n", pool ); tp_threadpool_release( pool ); RtlExitUserThread( 0 ); +#ifdef __REACTOS__ + return STATUS_SUCCESS; +#endif } /*********************************************************************** @@ -3355,3 +3502,16 @@ NTSTATUS WINAPI RtlDeregisterWait(HANDLE WaitHandle) { return RtlDeregisterWaitEx(WaitHandle, NULL); } + +#ifdef __REACTOS__ +VOID +NTAPI +RtlpInitializeThreadPooling( + VOID) +{ + RtlInitializeCriticalSection(&old_threadpool.threadpool_compl_cs); + RtlInitializeCriticalSection(&timerqueue.cs); + RtlInitializeCriticalSection(&waitqueue.cs); + RtlInitializeCriticalSection(&ioqueue.cs); +} +#endif diff --git a/sdk/lib/rtl/timerqueue.c b/sdk/lib/rtl/timerqueue.c index 596588bdafd..195059ae1ea 100644 --- a/sdk/lib/rtl/timerqueue.c +++ b/sdk/lib/rtl/timerqueue.c @@ -64,405 +64,6 @@ struct timer_queue #define EXPIRE_NEVER (~(ULONGLONG) 0) #define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */ -static void queue_remove_timer(struct queue_timer *t) -{ - /* We MUST hold the queue cs while calling this function. This ensures - that we cannot queue another callback for this timer. The runcount - being zero makes sure we don't have any already queued. */ - struct timer_queue *q = t->q; - - assert(t->runcount == 0); - assert(t->destroy); - - list_remove(&t->entry); - if (t->event) - NtSetEvent(t->event, NULL); - RtlFreeHeap(RtlGetProcessHeap(), 0, t); - - if (q->quit && list_empty(&q->timers)) - NtSetEvent(q->event, NULL); -} - -static void timer_cleanup_callback(struct queue_timer *t) -{ - struct timer_queue *q = t->q; - RtlEnterCriticalSection(&q->cs); - - assert(0 < t->runcount); - --t->runcount; - - if (t->destroy && t->runcount == 0) - queue_remove_timer(t); - - RtlLeaveCriticalSection(&q->cs); -} - -static VOID WINAPI timer_callback_wrapper(LPVOID p) -{ - struct queue_timer *t = p; - t->callback(t->param, TRUE); - timer_cleanup_callback(t); -} - -static inline ULONGLONG queue_current_time(void) -{ - LARGE_INTEGER now, freq; - NtQueryPerformanceCounter(&now, &freq); - return now.QuadPart * 1000 / freq.QuadPart; -} - -static void queue_add_timer(struct queue_timer *t, ULONGLONG time, - BOOL set_event) -{ - /* We MUST hold the queue cs while calling this function. */ - struct timer_queue *q = t->q; - struct list *ptr = &q->timers; - - assert(!q->quit || (t->destroy && time == EXPIRE_NEVER)); - - if (time != EXPIRE_NEVER) - LIST_FOR_EACH(ptr, &q->timers) - { - struct queue_timer *cur = LIST_ENTRY(ptr, struct queue_timer, entry); - if (time < cur->expire) - break; - } - list_add_before(ptr, &t->entry); - - t->expire = time; - - /* If we insert at the head of the list, we need to expire sooner - than expected. */ - if (set_event && &t->entry == list_head(&q->timers)) - NtSetEvent(q->event, NULL); -} - -static inline void queue_move_timer(struct queue_timer *t, ULONGLONG time, - BOOL set_event) -{ - /* We MUST hold the queue cs while calling this function. */ - list_remove(&t->entry); - queue_add_timer(t, time, set_event); -} - -static void queue_timer_expire(struct timer_queue *q) -{ - struct queue_timer *t = NULL; - - RtlEnterCriticalSection(&q->cs); - if (list_head(&q->timers)) - { - ULONGLONG now, next; - t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); - if (!t->destroy && t->expire <= ((now = queue_current_time()))) - { - ++t->runcount; - if (t->period) - { - next = t->expire + t->period; - /* avoid trigger cascade if overloaded / hibernated */ - if (next < now) - next = now + t->period; - } - else - next = EXPIRE_NEVER; - queue_move_timer(t, next, FALSE); - } - else - t = NULL; - } - RtlLeaveCriticalSection(&q->cs); - - if (t) - { - if (t->flags & WT_EXECUTEINTIMERTHREAD) - timer_callback_wrapper(t); - else - { - ULONG flags - = (t->flags - & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD - | WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION)); - NTSTATUS status = RtlQueueWorkItem(timer_callback_wrapper, t, flags); - if (status != STATUS_SUCCESS) - timer_cleanup_callback(t); - } - } -} - -static ULONG queue_get_timeout(struct timer_queue *q) -{ - struct queue_timer *t; - ULONG timeout = INFINITE; - - RtlEnterCriticalSection(&q->cs); - if (list_head(&q->timers)) - { - t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); - assert(!t->destroy || t->expire == EXPIRE_NEVER); - - if (t->expire != EXPIRE_NEVER) - { - ULONGLONG time = queue_current_time(); - timeout = t->expire < time ? 0 : (ULONG)(t->expire - time); - } - } - RtlLeaveCriticalSection(&q->cs); - - return timeout; -} - -static DWORD WINAPI timer_queue_thread_proc(LPVOID p) -{ - struct timer_queue *q = p; - ULONG timeout_ms; - - timeout_ms = INFINITE; - for (;;) - { - LARGE_INTEGER timeout; - NTSTATUS status; - BOOL done = FALSE; - - status = NtWaitForSingleObject( - q->event, FALSE, get_nt_timeout(&timeout, timeout_ms)); - - if (status == STATUS_WAIT_0) - { - /* There are two possible ways to trigger the event. Either - we are quitting and the last timer got removed, or a new - timer got put at the head of the list so we need to adjust - our timeout. */ - RtlEnterCriticalSection(&q->cs); - if (q->quit && list_empty(&q->timers)) - done = TRUE; - RtlLeaveCriticalSection(&q->cs); - } - else if (status == STATUS_TIMEOUT) - queue_timer_expire(q); - - if (done) - break; - - timeout_ms = queue_get_timeout(q); - } - - NtClose(q->event); - RtlDeleteCriticalSection(&q->cs); - q->magic = 0; - RtlFreeHeap(RtlGetProcessHeap(), 0, q); - RtlpExitThreadFunc(STATUS_SUCCESS); - return 0; -} - -static void queue_destroy_timer(struct queue_timer *t) -{ - /* We MUST hold the queue cs while calling this function. */ - t->destroy = TRUE; - if (t->runcount == 0) - /* Ensure a timer is promptly removed. If callbacks are pending, - it will be removed after the last one finishes by the callback - cleanup wrapper. */ - queue_remove_timer(t); - else - /* Make sure no destroyed timer masks an active timer at the head - of the sorted list. */ - queue_move_timer(t, EXPIRE_NEVER, FALSE); -} - -/*********************************************************************** - * RtlCreateTimerQueue (NTDLL.@) - * - * Creates a timer queue object and returns a handle to it. - * - * PARAMS - * NewTimerQueue [O] The newly created queue. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - */ -NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue) -{ - NTSTATUS status; - struct timer_queue *q = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof *q); - if (!q) - return STATUS_NO_MEMORY; - - RtlInitializeCriticalSection(&q->cs); - list_init(&q->timers); - q->quit = FALSE; - q->magic = TIMER_QUEUE_MAGIC; - status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); - if (status != STATUS_SUCCESS) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, q); - return status; - } - status = RtlpStartThreadFunc(timer_queue_thread_proc, q, &q->thread); - if (status != STATUS_SUCCESS) - { - NtClose(q->event); - RtlFreeHeap(RtlGetProcessHeap(), 0, q); - return status; - } - - NtResumeThread(q->thread, NULL); - *NewTimerQueue = q; - return STATUS_SUCCESS; -} - -/*********************************************************************** - * RtlDeleteTimerQueueEx (NTDLL.@) - * - * Deletes a timer queue object. - * - * PARAMS - * TimerQueue [I] The timer queue to destroy. - * CompletionEvent [I] If NULL, return immediately. If INVALID_HANDLE_VALUE, - * wait until all timers are finished firing before - * returning. Otherwise, return immediately and set the - * event when all timers are done. - * - * RETURNS - * Success: STATUS_SUCCESS if synchronous, STATUS_PENDING if not. - * Failure: Any NTSTATUS code. - */ -NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) -{ - struct timer_queue *q = TimerQueue; - struct queue_timer *t, *temp; - HANDLE thread; - NTSTATUS status; - - if (!q || q->magic != TIMER_QUEUE_MAGIC) - return STATUS_INVALID_HANDLE; - - thread = q->thread; - - RtlEnterCriticalSection(&q->cs); - q->quit = TRUE; - if (list_head(&q->timers)) - /* When the last timer is removed, it will signal the timer thread to - exit... */ - LIST_FOR_EACH_ENTRY_SAFE(t, temp, &q->timers, struct queue_timer, entry) - queue_destroy_timer(t); - else - /* However if we have none, we must do it ourselves. */ - NtSetEvent(q->event, NULL); - RtlLeaveCriticalSection(&q->cs); - - if (CompletionEvent == INVALID_HANDLE_VALUE) - { - NtWaitForSingleObject(thread, FALSE, NULL); - status = STATUS_SUCCESS; - } - else - { - if (CompletionEvent) - { - DPRINT1("asynchronous return on completion event unimplemented\n"); - NtWaitForSingleObject(thread, FALSE, NULL); - NtSetEvent(CompletionEvent, NULL); - } - status = STATUS_PENDING; - } - - NtClose(thread); - return status; -} - -static struct timer_queue *get_timer_queue(HANDLE TimerQueue) -{ - static struct timer_queue *default_timer_queue; - - if (TimerQueue) - return TimerQueue; - else - { - if (!default_timer_queue) - { - HANDLE q; - NTSTATUS status = RtlCreateTimerQueue(&q); - if (status == STATUS_SUCCESS) - { - PVOID p = InterlockedCompareExchangePointer( - (void **) &default_timer_queue, q, NULL); - if (p) - /* Got beat to the punch. */ - RtlDeleteTimerQueueEx(q, NULL); - } - } - return default_timer_queue; - } -} - -/*********************************************************************** - * RtlCreateTimer (NTDLL.@) - * - * Creates a new timer associated with the given queue. - * - * PARAMS - * NewTimer [O] The newly created timer. - * TimerQueue [I] The queue to hold the timer. - * Callback [I] The callback to fire. - * Parameter [I] The argument for the callback. - * DueTime [I] The delay, in milliseconds, before first firing the - * timer. - * Period [I] The period, in milliseconds, at which to fire the timer - * after the first callback. If zero, the timer will only - * fire once. It still needs to be deleted with - * RtlDeleteTimer. - * Flags [I] Flags controlling the execution of the callback. In - * addition to the WT_* thread pool flags (see - * RtlQueueWorkItem), WT_EXECUTEINTIMERTHREAD and - * WT_EXECUTEONLYONCE are supported. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - */ -NTSTATUS WINAPI RtlCreateTimer(HANDLE TimerQueue, PHANDLE NewTimer, - WAITORTIMERCALLBACKFUNC Callback, - PVOID Parameter, DWORD DueTime, DWORD Period, - ULONG Flags) -{ - NTSTATUS status; - struct queue_timer *t; - struct timer_queue *q = get_timer_queue(TimerQueue); - - if (!q) return STATUS_NO_MEMORY; - if (q->magic != TIMER_QUEUE_MAGIC) return STATUS_INVALID_HANDLE; - - t = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof *t); - if (!t) - return STATUS_NO_MEMORY; - - t->q = q; - t->runcount = 0; - t->callback = Callback; - t->param = Parameter; - t->period = Period; - t->flags = Flags; - t->destroy = FALSE; - t->event = NULL; - - status = STATUS_SUCCESS; - RtlEnterCriticalSection(&q->cs); - if (q->quit) - status = STATUS_INVALID_HANDLE; - else - queue_add_timer(t, queue_current_time() + DueTime, TRUE); - RtlLeaveCriticalSection(&q->cs); - - if (status == STATUS_SUCCESS) - *NewTimer = t; - else - RtlFreeHeap(RtlGetProcessHeap(), 0, t); - - return status; -} - NTSTATUS WINAPI RtlSetTimer( @@ -483,100 +84,6 @@ RtlSetTimer( Flags); } -/*********************************************************************** - * RtlUpdateTimer (NTDLL.@) - * - * Changes the time at which a timer expires. - * - * PARAMS - * TimerQueue [I] The queue that holds the timer. - * Timer [I] The timer to update. - * DueTime [I] The delay, in milliseconds, before next firing the timer. - * Period [I] The period, in milliseconds, at which to fire the timer - * after the first callback. If zero, the timer will not - * refire once. It still needs to be deleted with - * RtlDeleteTimer. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - */ -NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, - DWORD DueTime, DWORD Period) -{ - struct queue_timer *t = Timer; - struct timer_queue *q = t->q; - - RtlEnterCriticalSection(&q->cs); - /* Can't change a timer if it was once-only or destroyed. */ - if (t->expire != EXPIRE_NEVER) - { - t->period = Period; - queue_move_timer(t, queue_current_time() + DueTime, TRUE); - } - RtlLeaveCriticalSection(&q->cs); - - return STATUS_SUCCESS; -} - -/*********************************************************************** - * RtlDeleteTimer (NTDLL.@) - * - * Cancels a timer-queue timer. - * - * PARAMS - * TimerQueue [I] The queue that holds the timer. - * Timer [I] The timer to update. - * CompletionEvent [I] If NULL, return immediately. If INVALID_HANDLE_VALUE, - * wait until the timer is finished firing all pending - * callbacks before returning. Otherwise, return - * immediately and set the timer is done. - * - * RETURNS - * Success: STATUS_SUCCESS if the timer is done, STATUS_PENDING if not, - or if the completion event is NULL. - * Failure: Any NTSTATUS code. - */ -NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, - HANDLE CompletionEvent) -{ - struct queue_timer *t = Timer; - struct timer_queue *q; - NTSTATUS status = STATUS_PENDING; - HANDLE event = NULL; - - if (!Timer) - return STATUS_INVALID_PARAMETER_1; - q = t->q; - if (CompletionEvent == INVALID_HANDLE_VALUE) - { - status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); - if (status == STATUS_SUCCESS) - status = STATUS_PENDING; - } - else if (CompletionEvent) - event = CompletionEvent; - - RtlEnterCriticalSection(&q->cs); - t->event = event; - if (t->runcount == 0 && event) - status = STATUS_SUCCESS; - queue_destroy_timer(t); - RtlLeaveCriticalSection(&q->cs); - - if (CompletionEvent == INVALID_HANDLE_VALUE && event) - { - if (status == STATUS_PENDING) - { - NtWaitForSingleObject(event, FALSE, NULL); - status = STATUS_SUCCESS; - } - NtClose(event); - } - - return status; -} - /* * @implemented */ diff --git a/sdk/lib/rtl/wait.c b/sdk/lib/rtl/wait.c deleted file mode 100644 index bab26365d5c..00000000000 --- a/sdk/lib/rtl/wait.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Rtl user wait functions - * FILE: lib/rtl/wait.c - * PROGRAMERS: - * Alex Ionescu (alex@relsoft.net) - * Eric Kohl - * KJK::Hyperion - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -typedef struct _RTLP_WAIT -{ - HANDLE Object; - BOOLEAN CallbackInProgress; - HANDLE CancelEvent; - LONG DeleteCount; - HANDLE CompletionEvent; - ULONG Flags; - WAITORTIMERCALLBACKFUNC Callback; - PVOID Context; - ULONG Milliseconds; -} RTLP_WAIT, *PRTLP_WAIT; - -/* PRIVATE FUNCTIONS *******************************************************/ - -static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout ) -{ - if (timeout == INFINITE) return NULL; - pTime->QuadPart = (ULONGLONG)timeout * -10000; - return pTime; -} - -static VOID -NTAPI -Wait_thread_proc(LPVOID Arg) -{ - PRTLP_WAIT Wait = (PRTLP_WAIT) Arg; - NTSTATUS Status; - BOOLEAN alertable = (Wait->Flags & WT_EXECUTEINIOTHREAD) != 0; - HANDLE handles[2] = { Wait->CancelEvent, Wait->Object }; - LARGE_INTEGER timeout; - HANDLE completion_event; - -// TRACE("\n"); - - while (TRUE) - { - Status = NtWaitForMultipleObjects( 2, - handles, - WaitAny, - alertable, - get_nt_timeout( &timeout, Wait->Milliseconds ) ); - - if (Status == STATUS_WAIT_1 || Status == STATUS_TIMEOUT) - { - BOOLEAN TimerOrWaitFired; - - if (Status == STATUS_WAIT_1) - { - // TRACE( "object %p signaled, calling callback %p with context %p\n", - // Wait->Object, Wait->Callback, - // Wait->Context ); - TimerOrWaitFired = FALSE; - } - else - { - // TRACE( "wait for object %p timed out, calling callback %p with context %p\n", - // Wait->Object, Wait->Callback, - // Wait->Context ); - TimerOrWaitFired = TRUE; - } - Wait->CallbackInProgress = TRUE; - Wait->Callback( Wait->Context, TimerOrWaitFired ); - Wait->CallbackInProgress = FALSE; - - if (Wait->Flags & WT_EXECUTEONLYONCE) - break; - } - else if (Status != STATUS_USER_APC) - break; - } - - completion_event = Wait->CompletionEvent; - if (completion_event) NtSetEvent( completion_event, NULL ); - - if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) - { - NtClose( Wait->CancelEvent ); - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); - } -} - - -/* FUNCTIONS ***************************************************************/ - - -/*********************************************************************** - * RtlRegisterWait - * - * Registers a wait for a handle to become signaled. - * - * PARAMS - * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it. - * Object [I] Object to wait to become signaled. - * Callback [I] Callback function to execute when the wait times out or the handle is signaled. - * Context [I] Context to pass to the callback function when it is executed. - * Milliseconds [I] Number of milliseconds to wait before timing out. - * Flags [I] Flags. See notes. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - * - * NOTES - * Flags can be one or more of the following: - *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread. - *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread. - *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent. - *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time. - *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token. - */ -NTSTATUS -NTAPI -RtlRegisterWait(PHANDLE NewWaitObject, - HANDLE Object, - WAITORTIMERCALLBACKFUNC Callback, - PVOID Context, - ULONG Milliseconds, - ULONG Flags) -{ - PRTLP_WAIT Wait; - NTSTATUS Status; - - //TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags ); - - Wait = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(RTLP_WAIT) ); - if (!Wait) - return STATUS_NO_MEMORY; - - Wait->Object = Object; - Wait->Callback = Callback; - Wait->Context = Context; - Wait->Milliseconds = Milliseconds; - Wait->Flags = Flags; - Wait->CallbackInProgress = FALSE; - Wait->DeleteCount = 0; - Wait->CompletionEvent = NULL; - - Status = NtCreateEvent( &Wait->CancelEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE ); - - if (Status != STATUS_SUCCESS) - { - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); - return Status; - } - - Flags = Flags & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD | - WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION); - - Status = RtlQueueWorkItem( Wait_thread_proc, - Wait, - Flags ); - - if (Status != STATUS_SUCCESS) - { - NtClose( Wait->CancelEvent ); - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); - return Status; - } - - *NewWaitObject = Wait; - return Status; -} - -/*********************************************************************** - * RtlDeregisterWaitEx - * - * Cancels a wait operation and frees the resources associated with calling - * RtlRegisterWait(). - * - * PARAMS - * WaitObject [I] Handle to the wait object to free. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - */ -NTSTATUS -NTAPI -RtlDeregisterWaitEx(HANDLE WaitHandle, - HANDLE CompletionEvent) -{ - PRTLP_WAIT Wait = (PRTLP_WAIT) WaitHandle; - NTSTATUS Status = STATUS_SUCCESS; - - //TRACE( "(%p)\n", WaitHandle ); - - NtSetEvent( Wait->CancelEvent, NULL ); - if (Wait->CallbackInProgress) - { - if (CompletionEvent != NULL) - { - if (CompletionEvent == INVALID_HANDLE_VALUE) - { - Status = NtCreateEvent( &CompletionEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE ); - - if (Status != STATUS_SUCCESS) - return Status; - - (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); - - if (Wait->CallbackInProgress) - NtWaitForSingleObject( CompletionEvent, FALSE, NULL ); - - NtClose( CompletionEvent ); - } - else - { - (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); - - if (Wait->CallbackInProgress) - Status = STATUS_PENDING; - } - } - else - Status = STATUS_PENDING; - } - - if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) - { - Status = STATUS_SUCCESS; - NtClose( Wait->CancelEvent ); - RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); - } - - return Status; -} - -/*********************************************************************** - * RtlDeregisterWait - * - * Cancels a wait operation and frees the resources associated with calling - * RtlRegisterWait(). - * - * PARAMS - * WaitObject [I] Handle to the wait object to free. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any NTSTATUS code. - */ -NTSTATUS -NTAPI -RtlDeregisterWait(HANDLE WaitHandle) -{ - return RtlDeregisterWaitEx(WaitHandle, NULL); -} - -/* EOF */