From a1a2d654886fe71af49f9f64210e21d743976ffe Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 30 Apr 2021 18:09:47 -0500 Subject: [PATCH] ntdll-NtAlertThreadByThreadId: Use flat two-dimensional arrays indexed by thread ID on both the PE and Unix side. This should be less invasive and hopefully improve performance. --- ...Move-some-tests-to-a-new-sync.c-file.patch | 306 ++++++++++++++---- ...sts-Add-some-tests-for-Rtl-resources.patch | 70 ++-- ...NtAlertThreadByThreadId-and-NtWaitFo.patch | 174 ++++++++++ ...-separate-mutex-to-lock-the-TEB-list.patch | 81 ----- ...NtAlertThreadByThreadId-and-NtWaitFo.patch | 172 ---------- ...asic-tests-for-thread-id-alert-func.patch} | 80 +++-- ...hread-ID-alerts-using-futexes-if-po.patch} | 98 +++--- ...thread-ID-alerts-using-Mach-semaphor.patch | 131 ++++++++ ...thread-id-alerts-on-top-of-Mach-sema.patch | 139 -------- ...-Win32-futexes-on-top-of-thread-ID-.patch} | 197 ++++------- ...dll-Merge-critsection.c-into-sync.c.patch} | 12 +- ...-the-critical-section-fast-path-on-.patch} | 22 +- ...the-direct-futex-path-for-condition.patch} | 20 +- ...t-SRW-locks-on-top-of-Win32-futexes.patch} | 74 ++--- patches/patchinstall.sh | 26 +- 15 files changed, 816 insertions(+), 786 deletions(-) create mode 100644 patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch delete mode 100644 patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch delete mode 100644 patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch rename patches/ntdll-NtAlertThreadByThreadId/{0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch => 0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch} (62%) rename patches/ntdll-NtAlertThreadByThreadId/{0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch => 0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch} (50%) create mode 100644 patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch delete mode 100644 patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch rename patches/ntdll-NtAlertThreadByThreadId/{0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch => 0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch} (67%) rename patches/ntdll-NtAlertThreadByThreadId/{0010-ntdll-Merge-critsection.c-into-sync.c.patch => 0008-ntdll-Merge-critsection.c-into-sync.c.patch} (99%) rename patches/ntdll-NtAlertThreadByThreadId/{0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch => 0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch} (93%) rename patches/ntdll-NtAlertThreadByThreadId/{0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch => 0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch} (93%) rename patches/ntdll-NtAlertThreadByThreadId/{0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch => 0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch} (97%) diff --git a/patches/ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch b/patches/ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch index 91b178f3..6b3c6a56 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch @@ -1,13 +1,14 @@ -From b2fef9e91f2625ccb700963ac87b47eeb3138a9a Mon Sep 17 00:00:00 2001 +From 339c0672e50344eabb605e13f3c58f7f534417dc Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 9 Jan 2020 13:44:01 -0600 Subject: [PATCH] ntdll/tests: Move some tests to a new sync.c file. +Signed-off-by: Zebediah Figura --- dlls/ntdll/tests/Makefile.in | 1 + - dlls/ntdll/tests/om.c | 494 ------------------------------- - dlls/ntdll/tests/sync.c | 547 +++++++++++++++++++++++++++++++++++ - 3 files changed, 548 insertions(+), 494 deletions(-) + dlls/ntdll/tests/om.c | 573 ------------------------------- + dlls/ntdll/tests/sync.c | 630 +++++++++++++++++++++++++++++++++++ + 3 files changed, 631 insertions(+), 573 deletions(-) create mode 100644 dlls/ntdll/tests/sync.c diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in @@ -23,7 +24,7 @@ index ed15c51339f..9a99c01bd7c 100644 time.c \ virtual.c diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c -index 7d9ca47be12..7759736ca1c 100644 +index 7d9ca47be12..d06812a9529 100644 --- a/dlls/ntdll/tests/om.c +++ b/dlls/ntdll/tests/om.c @@ -30,10 +30,6 @@ @@ -37,7 +38,7 @@ index 7d9ca47be12..7759736ca1c 100644 static NTSTATUS (WINAPI *pNtCreateJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES ); static NTSTATUS (WINAPI *pNtOpenJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES ); static NTSTATUS (WINAPI *pNtCreateKey)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG, -@@ -44,8 +40,6 @@ static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ACCESS_MASK, POBJECT_A +@@ -44,11 +40,8 @@ static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ACCESS_MASK, POBJECT_A ULONG, ULONG, ULONG, PLARGE_INTEGER ); static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN ); static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES ); @@ -45,8 +46,11 @@ index 7d9ca47be12..7759736ca1c 100644 -static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, PLONG ); static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG ); static NTSTATUS (WINAPI *pNtOpenSemaphore)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES ); - static NTSTATUS (WINAPI *pNtQuerySemaphore)( PHANDLE, SEMAPHORE_INFORMATION_CLASS, PVOID, ULONG, PULONG ); -@@ -67,15 +61,9 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U +-static NTSTATUS (WINAPI *pNtQuerySemaphore)( PHANDLE, SEMAPHORE_INFORMATION_CLASS, PVOID, ULONG, PULONG ); + static NTSTATUS (WINAPI *pNtCreateTimer) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, TIMER_TYPE ); + static NTSTATUS (WINAPI *pNtOpenTimer)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES ); + static NTSTATUS (WINAPI *pNtCreateSection)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, const PLARGE_INTEGER, +@@ -67,15 +60,9 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG); static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG ); static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * ); @@ -62,7 +66,7 @@ index 7d9ca47be12..7759736ca1c 100644 static NTSTATUS (WINAPI *pNtOpenProcess)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID * ); static NTSTATUS (WINAPI *pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG ); static NTSTATUS (WINAPI *pNtGetNextThread)(HANDLE process, HANDLE thread, ACCESS_MASK access, ULONG attributes, -@@ -1722,286 +1710,6 @@ static void test_type_mismatch(void) +@@ -1722,286 +1709,6 @@ static void test_type_mismatch(void) pNtClose( h ); } @@ -349,7 +353,7 @@ index 7d9ca47be12..7759736ca1c 100644 static void test_null_device(void) { OBJECT_ATTRIBUTES attr; -@@ -2075,119 +1783,6 @@ static void test_null_device(void) +@@ -2075,268 +1782,6 @@ static void test_null_device(void) CloseHandle(ov.hEvent); } @@ -466,13 +470,82 @@ index 7d9ca47be12..7759736ca1c 100644 - NtClose( mutant ); -} - - static void test_semaphore(void) - { - SEMAPHORE_BASIC_INFORMATION info; -@@ -2264,79 +1859,6 @@ static void test_semaphore(void) - NtClose( semaphore ); - } - +-static void test_semaphore(void) +-{ +- SEMAPHORE_BASIC_INFORMATION info; +- OBJECT_ATTRIBUTES attr; +- UNICODE_STRING str; +- NTSTATUS status; +- HANDLE semaphore; +- ULONG prev; +- ULONG len; +- DWORD ret; +- +- pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore"); +- InitializeObjectAttributes(&attr, &str, 0, 0, NULL); +- +- status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1); +- ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status ); +- status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2); +- ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status ); +- +- /* bogus */ +- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL); +- ok( status == STATUS_INFO_LENGTH_MISMATCH, +- "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status ); +- status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL); +- ok( status == STATUS_INVALID_INFO_CLASS, +- "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status ); +- status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL); +- ok( status == STATUS_INVALID_HANDLE, +- "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status ); +- +- len = -1; +- memset(&info, 0xcc, sizeof(info)); +- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len); +- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); +- ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount ); +- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); +- ok( len == sizeof(info), "got %u\n", len ); +- +- ret = WaitForSingleObject( semaphore, 1000 ); +- ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret ); +- +- memset(&info, 0xcc, sizeof(info)); +- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL); +- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); +- ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount ); +- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); +- +- prev = 0xdeadbeef; +- status = pNtReleaseSemaphore(semaphore, 3, &prev); +- ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status ); +- ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev ); +- +- prev = 0xdeadbeef; +- status = pNtReleaseSemaphore(semaphore, 1, &prev); +- ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status ); +- ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev ); +- +- prev = 0xdeadbeef; +- status = pNtReleaseSemaphore(semaphore, 1, &prev); +- ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status ); +- ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev ); +- +- prev = 0xdeadbeef; +- status = pNtReleaseSemaphore(semaphore, 1, &prev); +- ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status ); +- ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev ); +- +- memset(&info, 0xcc, sizeof(info)); +- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL); +- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); +- ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount ); +- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); +- +- NtClose( semaphore ); +-} +- -static void test_wait_on_address(void) -{ - DWORD ticks; @@ -549,7 +622,7 @@ index 7d9ca47be12..7759736ca1c 100644 static void test_process(void) { OBJECT_ATTRIBUTES attr; -@@ -2668,13 +2190,7 @@ START_TEST(om) +@@ -2668,13 +2113,7 @@ START_TEST(om) pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile"); pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant"); pNtOpenEvent = (void *)GetProcAddress(hntdll, "NtOpenEvent"); @@ -563,7 +636,15 @@ index 7d9ca47be12..7759736ca1c 100644 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile"); pNtClose = (void *)GetProcAddress(hntdll, "NtClose"); pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString"); -@@ -2695,15 +2211,9 @@ START_TEST(om) +@@ -2686,7 +2125,6 @@ START_TEST(om) + pNtQuerySymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtQuerySymbolicLinkObject"); + pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore"); + pNtOpenSemaphore = (void *)GetProcAddress(hntdll, "NtOpenSemaphore"); +- pNtQuerySemaphore = (void *)GetProcAddress(hntdll, "NtQuerySemaphore"); + pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer"); + pNtOpenTimer = (void *)GetProcAddress(hntdll, "NtOpenTimer"); + pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection"); +@@ -2695,15 +2133,9 @@ START_TEST(om) pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore"); pNtCreateKeyedEvent = (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent"); pNtOpenKeyedEvent = (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent"); @@ -579,13 +660,13 @@ index 7d9ca47be12..7759736ca1c 100644 pNtOpenProcess = (void *)GetProcAddress(hntdll, "NtOpenProcess"); pNtCreateDebugObject = (void *)GetProcAddress(hntdll, "NtCreateDebugObject"); pNtGetNextThread = (void *)GetProcAddress(hntdll, "NtGetNextThread"); -@@ -2716,12 +2226,8 @@ START_TEST(om) +@@ -2716,12 +2148,7 @@ START_TEST(om) test_symboliclink(); test_query_object(); test_type_mismatch(); - test_event(); - test_mutant(); - test_semaphore(); +- test_semaphore(); - test_keyed_events(); test_null_device(); - test_wait_on_address(); @@ -594,10 +675,10 @@ index 7d9ca47be12..7759736ca1c 100644 test_get_next_thread(); diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c new file mode 100644 -index 00000000000..3f41cdfeedd +index 00000000000..3d6b6a3a04d --- /dev/null +++ b/dlls/ntdll/tests/sync.c -@@ -0,0 +1,547 @@ +@@ -0,0 +1,630 @@ +/* + * Unit tests for NT synchronization objects + * @@ -627,17 +708,20 @@ index 00000000000..3f41cdfeedd +#include "wine/test.h" + +static NTSTATUS (WINAPI *pNtClose)( HANDLE ); -+static NTSTATUS (WINAPI *pNtCreateEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN ); ++static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN); +static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG ); +static NTSTATUS (WINAPI *pNtCreateMutant)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, BOOLEAN ); ++static NTSTATUS (WINAPI *pNtCreateSemaphore)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, LONG, LONG ); +static NTSTATUS (WINAPI *pNtOpenEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * ); +static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * ); +static NTSTATUS (WINAPI *pNtPulseEvent)( HANDLE, LONG * ); +static NTSTATUS (WINAPI *pNtQueryEvent)( HANDLE, EVENT_INFORMATION_CLASS, void *, ULONG, ULONG * ); +static NTSTATUS (WINAPI *pNtQueryMutant)( HANDLE, MUTANT_INFORMATION_CLASS, void *, ULONG, ULONG * ); ++static NTSTATUS (WINAPI *pNtQuerySemaphore)( HANDLE, SEMAPHORE_INFORMATION_CLASS, void *, ULONG, ULONG * ); +static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * ); +static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * ); +static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * ); ++static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * ); +static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * ); +static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * ); +static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * ); @@ -652,89 +736,89 @@ index 00000000000..3f41cdfeedd + +static void test_event(void) +{ -+ HANDLE Event; -+ HANDLE Event2; ++ HANDLE event; ++ HANDLE event2; + LONG prev_state = 0xdeadbeef; + NTSTATUS status; + UNICODE_STRING str; + OBJECT_ATTRIBUTES attr; + EVENT_BASIC_INFORMATION info; + -+ pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\testEvent"); ++ pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" ); + InitializeObjectAttributes(&attr, &str, 0, 0, NULL); + -+ status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 2, 0); ++ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, 2, 0); + ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08x\n", status ); + -+ status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, NotificationEvent, 0); ++ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, NotificationEvent, 0); + ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status ); + memset(&info, 0xcc, sizeof(info)); -+ status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL); ++ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL); + ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status ); + ok( info.EventType == NotificationEvent && info.EventState == 0, + "NtQueryEvent failed, expected 0 0, got %d %d\n", info.EventType, info.EventState ); -+ pNtClose(Event); ++ pNtClose(event); + -+ status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, SynchronizationEvent, 0); ++ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, SynchronizationEvent, 0); + ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status ); + -+ status = pNtPulseEvent(Event, &prev_state); ++ status = pNtPulseEvent(event, &prev_state); + ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status ); + ok( !prev_state, "prev_state = %x\n", prev_state ); + + memset(&info, 0xcc, sizeof(info)); -+ status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL); ++ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL); + ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status ); + ok( info.EventType == SynchronizationEvent && info.EventState == 0, + "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState ); + -+ status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr); ++ status = pNtOpenEvent(&event2, GENERIC_ALL, &attr); + ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status ); + -+ pNtClose(Event); -+ Event = Event2; ++ pNtClose(event); ++ event = event2; + + memset(&info, 0xcc, sizeof(info)); -+ status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL); ++ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL); + ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status ); + ok( info.EventType == SynchronizationEvent && info.EventState == 0, + "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState ); + -+ status = pNtSetEvent( Event, &prev_state ); ++ status = pNtSetEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status ); + ok( !prev_state, "prev_state = %x\n", prev_state ); + + memset(&info, 0xcc, sizeof(info)); -+ status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL); ++ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL); + ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status ); + ok( info.EventType == SynchronizationEvent && info.EventState == 1, + "NtQueryEvent failed, expected 1 1, got %d %d\n", info.EventType, info.EventState ); + -+ status = pNtSetEvent( Event, &prev_state ); ++ status = pNtSetEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status ); + ok( prev_state == 1, "prev_state = %x\n", prev_state ); + -+ status = pNtResetEvent( Event, &prev_state ); ++ status = pNtResetEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status ); + ok( prev_state == 1, "prev_state = %x\n", prev_state ); + -+ status = pNtResetEvent( Event, &prev_state ); ++ status = pNtResetEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status ); + ok( !prev_state, "prev_state = %x\n", prev_state ); + -+ status = pNtPulseEvent( Event, &prev_state ); ++ status = pNtPulseEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status ); + ok( !prev_state, "prev_state = %x\n", prev_state ); + -+ status = pNtSetEvent( Event, &prev_state ); ++ status = pNtSetEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status ); + ok( !prev_state, "prev_state = %x\n", prev_state ); + -+ status = pNtPulseEvent( Event, &prev_state ); ++ status = pNtPulseEvent( event, &prev_state ); + ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status ); + ok( prev_state == 1, "prev_state = %x\n", prev_state ); + -+ pNtClose(Event); ++ pNtClose(event); +} + +static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent"; @@ -916,7 +1000,7 @@ index 00000000000..3f41cdfeedd + ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status ); + + status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE ); -+ ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH, ++ ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH /* 7+ */, + "CreateEvent %x\n", status ); + + NtClose( handle ); @@ -1002,13 +1086,13 @@ index 00000000000..3f41cdfeedd + + prev = 0xdeadbeef; + status = pNtReleaseMutant(mutant, &prev); -+ ok( status == STATUS_SUCCESS, "NtQueryRelease failed %08x\n", status ); -+ ok( prev == -1, "NtQueryRelease failed, expected -1, got %d\n", prev ); ++ ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status ); ++ ok( prev == -1, "NtReleaseMutant failed, expected -1, got %d\n", prev ); + + prev = 0xdeadbeef; + status = pNtReleaseMutant(mutant, &prev); -+ ok( status == STATUS_SUCCESS, "NtQueryRelease failed %08x\n", status ); -+ ok( prev == 0, "NtQueryRelease failed, expected 0, got %d\n", prev ); ++ ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status ); ++ ok( prev == 0, "NtReleaseMutant failed, expected 0, got %d\n", prev ); + + memset(&info, 0xcc, sizeof(info)); + status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL); @@ -1043,6 +1127,82 @@ index 00000000000..3f41cdfeedd + NtClose( mutant ); +} + ++static void test_semaphore(void) ++{ ++ SEMAPHORE_BASIC_INFORMATION info; ++ OBJECT_ATTRIBUTES attr; ++ UNICODE_STRING str; ++ NTSTATUS status; ++ HANDLE semaphore; ++ ULONG prev; ++ ULONG len; ++ DWORD ret; ++ ++ pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore"); ++ InitializeObjectAttributes(&attr, &str, 0, 0, NULL); ++ ++ status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1); ++ ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status ); ++ status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2); ++ ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status ); ++ ++ /* bogus */ ++ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL); ++ ok( status == STATUS_INFO_LENGTH_MISMATCH, ++ "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status ); ++ status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL); ++ ok( status == STATUS_INVALID_INFO_CLASS, ++ "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status ); ++ status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL); ++ ok( status == STATUS_INVALID_HANDLE, ++ "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status ); ++ ++ len = -1; ++ memset(&info, 0xcc, sizeof(info)); ++ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len); ++ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); ++ ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount ); ++ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); ++ ok( len == sizeof(info), "got %u\n", len ); ++ ++ ret = WaitForSingleObject( semaphore, 1000 ); ++ ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret ); ++ ++ memset(&info, 0xcc, sizeof(info)); ++ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL); ++ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); ++ ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount ); ++ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); ++ ++ prev = 0xdeadbeef; ++ status = pNtReleaseSemaphore(semaphore, 3, &prev); ++ ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status ); ++ ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev ); ++ ++ prev = 0xdeadbeef; ++ status = pNtReleaseSemaphore(semaphore, 1, &prev); ++ ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status ); ++ ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev ); ++ ++ prev = 0xdeadbeef; ++ status = pNtReleaseSemaphore(semaphore, 1, &prev); ++ ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status ); ++ ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev ); ++ ++ prev = 0xdeadbeef; ++ status = pNtReleaseSemaphore(semaphore, 1, &prev); ++ ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status ); ++ ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev ); ++ ++ memset(&info, 0xcc, sizeof(info)); ++ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL); ++ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status ); ++ ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount ); ++ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount ); ++ ++ NtClose( semaphore ); ++} ++ +static void test_wait_on_address(void) +{ + DWORD ticks; @@ -1120,29 +1280,33 @@ index 00000000000..3f41cdfeedd +{ + HMODULE module = GetModuleHandleA("ntdll.dll"); + -+ pNtClose = (void *)GetProcAddress(module, "NtClose"); -+ pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent"); -+ pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent"); -+ pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant"); -+ pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent"); -+ pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent"); -+ pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent"); -+ pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent"); -+ pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant"); -+ pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime"); -+ pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent"); -+ pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant"); -+ pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); -+ pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); -+ pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); -+ pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString"); -+ pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress"); -+ pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll"); -+ pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle"); ++ pNtClose = (void *)GetProcAddress(module, "NtClose"); ++ pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent"); ++ pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent"); ++ pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant"); ++ pNtCreateSemaphore = (void *)GetProcAddress(module, "NtCreateSemaphore"); ++ pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent"); ++ pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent"); ++ pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent"); ++ pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent"); ++ pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant"); ++ pNtQuerySemaphore = (void *)GetProcAddress(module, "NtQuerySemaphore"); ++ pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime"); ++ pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent"); ++ pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant"); ++ pNtReleaseSemaphore = (void *)GetProcAddress(module, "NtReleaseSemaphore"); ++ pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); ++ pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); ++ pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); ++ pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString"); ++ pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress"); ++ pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll"); ++ pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle"); + + test_wait_on_address(); + test_event(); + test_mutant(); ++ test_semaphore(); + test_keyed_events(); +} -- diff --git a/patches/ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch b/patches/ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch index c8c8ada7..78ea5529 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch @@ -1,18 +1,18 @@ -From 2107fb9f59bb2beef3b8c12a2adf9cb2be469036 Mon Sep 17 00:00:00 2001 +From 2cecfc6394a63db07b92c572d0702cf2a8bf0f31 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 9 Jan 2020 14:51:05 -0600 -Subject: [PATCH 02/13] ntdll/tests: Add some tests for Rtl* resources. +Subject: [PATCH] ntdll/tests: Add some tests for Rtl* resources. Signed-off-by: Zebediah Figura --- - dlls/ntdll/tests/sync.c | 202 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 183 insertions(+), 19 deletions(-) + dlls/ntdll/tests/sync.c | 164 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 164 insertions(+) diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c -index 9967a2be257..152cdd1530d 100644 +index 3d6b6a3a04d..21124dae922 100644 --- a/dlls/ntdll/tests/sync.c +++ b/dlls/ntdll/tests/sync.c -@@ -41,7 +41,12 @@ static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * ); +@@ -44,7 +44,12 @@ static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * ); static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * ); static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * ); static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * ); @@ -25,11 +25,11 @@ index 9967a2be257..152cdd1530d 100644 static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * ); static void (WINAPI *pRtlWakeAddressAll)( const void * ); static void (WINAPI *pRtlWakeAddressSingle)( const void * ); -@@ -496,32 +501,191 @@ static void test_wait_on_address(void) +@@ -595,6 +600,159 @@ static void test_wait_on_address(void) ok(address == 0, "got %s\n", wine_dbgstr_longlong(address)); } -+HANDLE thread_ready, thread_done; ++static HANDLE thread_ready, thread_done; + +static DWORD WINAPI resource_shared_thread(void *arg) +{ @@ -185,57 +185,25 @@ index 9967a2be257..152cdd1530d 100644 START_TEST(sync) { HMODULE module = GetModuleHandleA("ntdll.dll"); - -- pNtClose = (void *)GetProcAddress(module, "NtClose"); -- pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent"); -- pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent"); -- pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant"); -- pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent"); -- pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent"); -- pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent"); -- pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent"); -- pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant"); -- pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime"); -- pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent"); -- pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant"); -- pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); -- pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); -- pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); -- pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString"); -- pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress"); -- pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll"); -- pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle"); -+ pNtClose = (void *)GetProcAddress(module, "NtClose"); -+ pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent"); -+ pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent"); -+ pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant"); -+ pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent"); -+ pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent"); -+ pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent"); -+ pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent"); -+ pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant"); -+ pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime"); -+ pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent"); -+ pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant"); -+ pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); -+ pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); -+ pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); +@@ -617,7 +775,12 @@ START_TEST(sync) + pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); + pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); + pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); + pRtlAcquireResourceExclusive = (void *)GetProcAddress(module, "RtlAcquireResourceExclusive"); + pRtlAcquireResourceShared = (void *)GetProcAddress(module, "RtlAcquireResourceShared"); + pRtlDeleteResource = (void *)GetProcAddress(module, "RtlDeleteResource"); + pRtlInitializeResource = (void *)GetProcAddress(module, "RtlInitializeResource"); -+ pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString"); + pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString"); + pRtlReleaseResource = (void *)GetProcAddress(module, "RtlReleaseResource"); -+ pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress"); -+ pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll"); -+ pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle"); - - test_wait_on_address(); - test_event(); + pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress"); + pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll"); + pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle"); +@@ -627,4 +790,5 @@ START_TEST(sync) test_mutant(); + test_semaphore(); test_keyed_events(); + test_resource(); } -- -2.29.2 +2.30.2 diff --git a/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch b/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch new file mode 100644 index 00000000..8b8020e0 --- /dev/null +++ b/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch @@ -0,0 +1,174 @@ +From b14229169f51d73f36bd5821388a3ba455ee5c99 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Fri, 30 Apr 2021 15:07:04 -0500 +Subject: [PATCH] ntdll: Implement NtAlertThreadByThreadId and + NtWaitForAlertByThreadId. + +Signed-off-by: Zebediah Figura +--- + dlls/ntdll/ntdll.spec | 2 + + dlls/ntdll/unix/sync.c | 93 ++++++++++++++++++++++++++++++++++++++++++ + include/winternl.h | 2 + + 3 files changed, 97 insertions(+) + +diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec +index a9cf662a29a..c9cd6fb59fd 100644 +--- a/dlls/ntdll/ntdll.spec ++++ b/dlls/ntdll/ntdll.spec +@@ -137,6 +137,7 @@ + @ stdcall -syscall NtAdjustPrivilegesToken(long long ptr long ptr ptr) + @ stdcall -syscall NtAlertResumeThread(long ptr) + @ stdcall -syscall NtAlertThread(long) ++@ stdcall -syscall NtAlertThreadByThreadId(ptr) + @ stdcall -syscall NtAllocateLocallyUniqueId(ptr) + # @ stub NtAllocateUserPhysicalPages + @ stdcall -syscall NtAllocateUuids(ptr ptr ptr ptr) +@@ -423,6 +424,7 @@ + @ stdcall -syscall NtUnmapViewOfSection(long ptr) + @ stub NtVdmControl + @ stub NtW32Call ++@ stdcall -syscall NtWaitForAlertByThreadId(ptr ptr) + @ stdcall -syscall NtWaitForDebugEvent(long long ptr ptr) + @ stdcall -syscall NtWaitForKeyedEvent(long ptr long ptr) + @ stdcall -syscall NtWaitForMultipleObjects(long ptr long long ptr) +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 16635ee42fa..014e5e5d0a7 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -32,6 +32,9 @@ + #include + #include + #include ++#ifdef HAVE_SYS_MMAN_H ++#include ++#endif + #ifdef HAVE_SYS_SYSCALL_H + #include + #endif +@@ -81,6 +84,12 @@ static const LARGE_INTEGER zero_timeout; + + static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER; + ++static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) ++{ ++ if (!timeout) return "(infinite)"; ++ return wine_dbgstr_longlong( timeout->QuadPart ); ++} ++ + /* return a monotonic time counter, in Win32 ticks */ + static inline ULONGLONG monotonic_counter(void) + { +@@ -2277,6 +2286,90 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl + } + + ++union tid_alert_entry ++{ ++ HANDLE event; ++}; ++ ++#define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry)) ++static union tid_alert_entry *tid_alert_blocks[4096]; ++ ++static unsigned int handle_to_index( HANDLE handle, unsigned int *block_idx ) ++{ ++ unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; ++ *block_idx = idx / TID_ALERT_BLOCK_SIZE; ++ return idx % TID_ALERT_BLOCK_SIZE; ++} ++ ++static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) ++{ ++ unsigned int block_idx, idx = handle_to_index( tid, &block_idx ); ++ union tid_alert_entry *entry; ++ ++ if (block_idx > ARRAY_SIZE(tid_alert_blocks)) ++ { ++ FIXME( "tid %p is too high\n", tid ); ++ return NULL; ++ } ++ ++ if (!tid_alert_blocks[block_idx]) ++ { ++ static const size_t size = TID_ALERT_BLOCK_SIZE * sizeof(union tid_alert_entry); ++ void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); ++ if (ptr == MAP_FAILED) return NULL; ++ if (InterlockedCompareExchangePointer( (void **)&tid_alert_blocks[block_idx], ptr, NULL )) ++ munmap( ptr, size ); /* someone beat us to it */ ++ } ++ ++ entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE]; ++ ++ if (!entry->event) ++ { ++ HANDLE event; ++ ++ if (NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE )) ++ return NULL; ++ if (InterlockedCompareExchangePointer( &entry->event, event, NULL )) ++ NtClose( event ); ++ } ++ ++ return entry; ++} ++ ++ ++/*********************************************************************** ++ * NtAlertThreadByThreadId (NTDLL.@) ++ */ ++NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) ++{ ++ union tid_alert_entry *entry = get_tid_alert_entry( tid ); ++ ++ TRACE( "%p\n", tid ); ++ ++ if (!entry) return STATUS_INVALID_CID; ++ ++ return NtSetEvent( entry->event, NULL ); ++} ++ ++ ++/*********************************************************************** ++ * NtWaitForAlertByThreadId (NTDLL.@) ++ */ ++NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout ) ++{ ++ union tid_alert_entry *entry = get_tid_alert_entry( NtCurrentTeb()->ClientId.UniqueThread ); ++ NTSTATUS status; ++ ++ TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); ++ ++ if (!entry) return STATUS_INVALID_CID; ++ ++ status = NtWaitForSingleObject( entry->event, FALSE, timeout ); ++ if (!status) return STATUS_ALERTED; ++ return status; ++} ++ ++ + #ifdef __linux__ + + NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) +diff --git a/include/winternl.h b/include/winternl.h +index 69d0e32f1d4..a6c22a5711d 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -3639,6 +3639,7 @@ NTSYSAPI NTSTATUS WINAPI NtAdjustGroupsToken(HANDLE,BOOLEAN,PTOKEN_GROUPS,ULONG + NTSYSAPI NTSTATUS WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD); + NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG); + NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle); ++NTSYSAPI NTSTATUS WINAPI NtAlertThreadByThreadId(HANDLE); + NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid); + NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR); + NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG_PTR,SIZE_T*,ULONG,ULONG); +@@ -3876,6 +3877,7 @@ NTSYSAPI NTSTATUS WINAPI NtUnlockFile(HANDLE,PIO_STATUS_BLOCK,PLARGE_INTEGER,PL + NTSYSAPI NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); + NTSYSAPI NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID); + NTSYSAPI NTSTATUS WINAPI NtVdmControl(ULONG,PVOID); ++NTSYSAPI NTSTATUS WINAPI NtWaitForAlertByThreadId(const void*,const LARGE_INTEGER*); + NTSYSAPI NTSTATUS WINAPI NtWaitForDebugEvent(HANDLE,BOOLEAN,LARGE_INTEGER*,DBGUI_WAIT_STATE_CHANGE*); + NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE,const void*,BOOLEAN,const LARGE_INTEGER*); + NTSYSAPI NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*); +-- +2.30.2 + diff --git a/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch b/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch deleted file mode 100644 index 9f49a205..00000000 --- a/patches/ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 5ac57c442cc9ce10ee8b8e0e82d3e3c199bd3862 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 31 Aug 2020 22:56:03 -0500 -Subject: [PATCH] ntdll: Use a separate mutex to lock the TEB list. - -Signed-off-by: Zebediah Figura ---- - dlls/ntdll/unix/virtual.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index f3e6b612b93..f0cec5e1347 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -175,6 +175,7 @@ static void *teb_block; - static void **next_free_teb; - static int teb_block_pos; - static struct list teb_list = LIST_INIT( teb_list ); -+static pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER; - - #define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask))) - #define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask) -@@ -2880,7 +2881,9 @@ static TEB *init_teb( void *ptr, PEB *peb ) - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ pthread_rwlock_wrlock( &teb_list_lock ); - list_add_head( &teb_list, &thread_data->entry ); -+ pthread_rwlock_unlock( &teb_list_lock ); - return teb; - } - -@@ -2997,7 +3000,9 @@ void virtual_free_teb( TEB *teb ) - } - - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -+ pthread_rwlock_wrlock( &teb_list_lock ); - list_remove( &thread_data->entry ); -+ pthread_rwlock_unlock( &teb_list_lock ); - if (!is_win64) ptr = (char *)ptr - teb_offset; - *(void **)ptr = next_free_teb; - next_free_teb = ptr; -@@ -3011,17 +3016,16 @@ void virtual_free_teb( TEB *teb ) - NTSTATUS virtual_clear_tls_index( ULONG index ) - { - struct ntdll_thread_data *thread_data; -- sigset_t sigset; - - if (index < TLS_MINIMUM_AVAILABLE) - { -- server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -+ pthread_rwlock_rdlock( &teb_list_lock ); - LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry ) - { - TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch ); - teb->TlsSlots[index] = 0; - } -- server_leave_uninterrupted_section( &virtual_mutex, &sigset ); -+ pthread_rwlock_unlock( &teb_list_lock ); - } - else - { -@@ -3029,13 +3033,13 @@ NTSTATUS virtual_clear_tls_index( ULONG index ) - if (index >= 8 * sizeof(NtCurrentTeb()->Peb->TlsExpansionBitmapBits)) - return STATUS_INVALID_PARAMETER; - -- server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -+ pthread_rwlock_rdlock( &teb_list_lock ); - LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry ) - { - TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch ); - if (teb->TlsExpansionSlots) teb->TlsExpansionSlots[index] = 0; - } -- server_leave_uninterrupted_section( &virtual_mutex, &sigset ); -+ pthread_rwlock_unlock( &teb_list_lock ); - } - return STATUS_SUCCESS; - } --- -2.30.2 - diff --git a/patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch b/patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch deleted file mode 100644 index 41cc5edb..00000000 --- a/patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 94c6132d79ee02079fc952e33cccf0d1f456a1ec Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 31 Aug 2020 23:00:16 -0500 -Subject: [PATCH] ntdll: Implement NtAlertThreadByThreadId() and - NtWaitForAlertByThreadId(). - -Signed-off-by: Zebediah Figura ---- - dlls/ntdll/ntdll.spec | 2 ++ - dlls/ntdll/unix/sync.c | 45 ++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/thread.c | 2 ++ - dlls/ntdll/unix/unix_private.h | 3 +++ - dlls/ntdll/unix/virtual.c | 5 ++-- - include/winternl.h | 2 ++ - 6 files changed, 57 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index ac7365a84b6..91959e19149 100644 ---- a/dlls/ntdll/ntdll.spec -+++ b/dlls/ntdll/ntdll.spec -@@ -137,6 +137,7 @@ - @ stdcall -syscall NtAdjustPrivilegesToken(long long ptr long ptr ptr) - @ stdcall -syscall NtAlertResumeThread(long ptr) - @ stdcall -syscall NtAlertThread(long) -+@ stdcall -syscall NtAlertThreadByThreadId(ptr) - @ stdcall -syscall NtAllocateLocallyUniqueId(ptr) - # @ stub NtAllocateUserPhysicalPages - @ stdcall -syscall NtAllocateUuids(ptr ptr ptr ptr) -@@ -423,6 +424,7 @@ - @ stub NtVdmControl - @ stub NtW32Call - @ stdcall -syscall NtWaitForDebugEvent(long long ptr ptr) -+@ stdcall -syscall NtWaitForAlertByThreadId(ptr ptr) - @ stdcall -syscall NtWaitForKeyedEvent(long ptr long ptr) - @ stdcall -syscall NtWaitForMultipleObjects(long ptr long long ptr) - @ stub NtWaitForProcessMutant -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 16635ee42fa..7e19fab1e97 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -81,6 +81,12 @@ static const LARGE_INTEGER zero_timeout; - - static pthread_mutex_t addr_mutex = PTHREAD_MUTEX_INITIALIZER; - -+static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) -+{ -+ if (!timeout) return "(infinite)"; -+ return wine_dbgstr_longlong( timeout->QuadPart ); -+} -+ - /* return a monotonic time counter, in Win32 ticks */ - static inline ULONGLONG monotonic_counter(void) - { -@@ -2277,6 +2283,45 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl - } - - -+/*********************************************************************** -+ * NtAlertThreadByThreadId (NTDLL.@) -+ */ -+NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) -+{ -+ struct ntdll_thread_data *thread_data; -+ -+ TRACE( "%p\n", tid ); -+ -+ pthread_rwlock_rdlock( &teb_list_lock ); -+ -+ LIST_FOR_EACH_ENTRY( thread_data, &teb_list, struct ntdll_thread_data, entry ) -+ { -+ TEB *teb = CONTAINING_RECORD( thread_data, TEB, GdiTebBatch ); -+ -+ if (teb->ClientId.UniqueThread == tid) -+ { -+ pthread_rwlock_unlock( &teb_list_lock ); -+ NtSetEvent( thread_data->tid_alert_event, NULL ); -+ return STATUS_SUCCESS; -+ } -+ } -+ -+ pthread_rwlock_unlock( &teb_list_lock ); -+ return STATUS_INVALID_CID; -+} -+ -+ -+/*********************************************************************** -+ * NtWaitForAlertByThreadId (NTDLL.@) -+ */ -+NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEGER *timeout ) -+{ -+ TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); -+ -+ return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); -+} -+ -+ - #ifdef __linux__ - - NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 00d29ae706b..87f5a97131e 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -252,6 +252,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT - thread_data->start = start; - thread_data->param = param; - -+ NtCreateEvent( &thread_data->tid_alert_event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); -+ - pthread_attr_init( &pthread_attr ); - pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, - (char *)teb->Tib.StackBase + extra_stack - (char *)teb->DeallocationStack ); -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index b8b6619c0a9..ae178fadd8b 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -58,6 +58,7 @@ struct ntdll_thread_data - struct list entry; /* entry in TEB list */ - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ -+ HANDLE tid_alert_event; /* event for thread-id alerts */ - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -105,6 +106,8 @@ extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN; - extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispatch, - CONTEXT *context ) DECLSPEC_HIDDEN; - -+extern struct list teb_list DECLSPEC_HIDDEN; -+extern pthread_rwlock_t teb_list_lock DECLSPEC_HIDDEN; - extern const char *home_dir DECLSPEC_HIDDEN; - extern const char *data_dir DECLSPEC_HIDDEN; - extern const char *build_dir DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index d1d00b91345..3e3c9b5f00e 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -162,8 +162,9 @@ struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000; - static void *teb_block; - static void **next_free_teb; - static int teb_block_pos; --static struct list teb_list = LIST_INIT( teb_list ); --static pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER; -+ -+struct list teb_list = LIST_INIT( teb_list ); -+pthread_rwlock_t teb_list_lock = PTHREAD_RWLOCK_INITIALIZER; - - #define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask))) - #define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask) -diff --git a/include/winternl.h b/include/winternl.h -index f0ab223ef2e..9a5a1b541b7 100644 ---- a/include/winternl.h -+++ b/include/winternl.h -@@ -3229,6 +3229,7 @@ NTSYSAPI NTSTATUS WINAPI NtAdjustGroupsToken(HANDLE,BOOLEAN,PTOKEN_GROUPS,ULONG - NTSYSAPI NTSTATUS WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD); - NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG); - NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle); -+NTSYSAPI NTSTATUS WINAPI NtAlertThreadByThreadId(HANDLE); - NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid); - NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR); - NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG_PTR,SIZE_T*,ULONG,ULONG); -@@ -3467,6 +3468,7 @@ NTSYSAPI NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); - NTSYSAPI NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID); - NTSYSAPI NTSTATUS WINAPI NtVdmControl(ULONG,PVOID); - NTSYSAPI NTSTATUS WINAPI NtWaitForDebugEvent(HANDLE,BOOLEAN,LARGE_INTEGER*,DBGUI_WAIT_STATE_CHANGE*); -+NTSYSAPI NTSTATUS WINAPI NtWaitForAlertByThreadId(const void*,const LARGE_INTEGER*); - NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE,const void*,BOOLEAN,const LARGE_INTEGER*); - NTSYSAPI NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*); - NTSYSAPI NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); --- -2.20.1 - diff --git a/patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch b/patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch similarity index 62% rename from patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch rename to patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch index 54a8c1f9..845db309 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch @@ -1,15 +1,15 @@ -From a993ebacecfcaa3370b7661baef6767d987ffed2 Mon Sep 17 00:00:00 2001 +From 775dcb8ca2ee8f16de16193570995dfe306be24d Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:01:25 -0500 Subject: [PATCH] ntdll/tests: Add basic tests for thread-id alert functions. Signed-off-by: Zebediah Figura --- - dlls/ntdll/tests/sync.c | 59 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 59 insertions(+) + dlls/ntdll/tests/sync.c | 95 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c -index 2ebdbd1b6f5..0c04c450948 100644 +index 21124dae922..be49405d8de 100644 --- a/dlls/ntdll/tests/sync.c +++ b/dlls/ntdll/tests/sync.c @@ -26,6 +26,7 @@ @@ -18,27 +18,42 @@ index 2ebdbd1b6f5..0c04c450948 100644 +static NTSTATUS (WINAPI *pNtAlertThreadByThreadId)( HANDLE ); static NTSTATUS (WINAPI *pNtClose)( HANDLE ); - static NTSTATUS (WINAPI *pNtCreateEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN ); + static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN); static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG ); -@@ -40,6 +41,7 @@ static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, c - static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * ); +@@ -43,6 +44,7 @@ static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * ); + static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * ); static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * ); static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * ); +static NTSTATUS (WINAPI *pNtWaitForAlertByThreadId)( void *, const LARGE_INTEGER * ); static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * ); static BOOLEAN (WINAPI *pRtlAcquireResourceExclusive)( RTL_RWLOCK *, BOOLEAN ); static BOOLEAN (WINAPI *pRtlAcquireResourceShared)( RTL_RWLOCK *, BOOLEAN ); -@@ -674,10 +676,65 @@ static void test_resource(void) +@@ -753,10 +755,101 @@ static void test_resource(void) pRtlDeleteResource(&resource); } -+static void test_thread_id_alert( char **argv ) ++static DWORD WINAPI tid_alert_thread( void *arg ) +{ -+ static const LARGE_INTEGER zero; ++ NTSTATUS ret; ++ ++ ret = pNtAlertThreadByThreadId( arg ); ++ ok(!ret, "got %#x\n", ret); ++ ++ ret = pNtWaitForAlertByThreadId( (void *)0x123, NULL ); ++ ok(ret == STATUS_ALERTED, "got %#x\n", ret); ++ ++ return 0; ++} ++ ++static void test_tid_alert( char **argv ) ++{ ++ LARGE_INTEGER timeout = {0}; + char cmdline[MAX_PATH]; + STARTUPINFOA si = {0}; + PROCESS_INFORMATION pi; ++ HANDLE thread; + NTSTATUS ret; ++ DWORD tid; + + if (!pNtWaitForAlertByThreadId) + { @@ -46,7 +61,7 @@ index 2ebdbd1b6f5..0c04c450948 100644 + return; + } + -+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero ); ++ ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout ); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + + ret = pNtAlertThreadByThreadId( 0 ); @@ -61,15 +76,36 @@ index 2ebdbd1b6f5..0c04c450948 100644 + ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)GetCurrentThreadId() ); + ok(!ret, "got %#x\n", ret); + -+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero ); ++ ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout ); + ok(ret == STATUS_ALERTED, "got %#x\n", ret); + -+ ret = pNtWaitForAlertByThreadId( (void *)0x123, &zero ); ++ ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout ); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + -+ ret = pNtWaitForAlertByThreadId( (void *)0x321, &zero ); ++ ret = pNtWaitForAlertByThreadId( (void *)0x321, &timeout ); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + ++ thread = CreateThread( NULL, 0, tid_alert_thread, (HANDLE)(DWORD_PTR)GetCurrentThreadId(), 0, &tid ); ++ timeout.QuadPart = -1000 * 10000; ++ ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout ); ++ ok(ret == STATUS_ALERTED, "got %#x\n", ret); ++ ++ ret = WaitForSingleObject( thread, 100 ); ++ ok(ret == WAIT_TIMEOUT, "got %d\n", ret); ++ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid ); ++ ok(!ret, "got %#x\n", ret); ++ ++ ret = WaitForSingleObject( thread, 1000 ); ++ ok(!ret, "got %d\n", ret); ++ ++ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid ); ++ ok(!ret, "got %#x\n", ret); ++ ++ CloseHandle(thread); ++ ++ ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid ); ++ todo_wine ok(ret == STATUS_INVALID_CID, "got %#x\n", ret); ++ + sprintf( cmdline, "%s %s subprocess", argv[0], argv[1] ); + ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); + ok(ret, "failed to create process, error %u\n", GetLastError()); @@ -85,29 +121,29 @@ index 2ebdbd1b6f5..0c04c450948 100644 HMODULE module = GetModuleHandleA("ntdll.dll"); + char **argv; + int argc; -+ + + argc = winetest_get_mainargs( &argv ); + + if (argc > 2) return; - ++ + pNtAlertThreadByThreadId = (void *)GetProcAddress(module, "NtAlertThreadByThreadId"); pNtClose = (void *)GetProcAddress(module, "NtClose"); pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent"); pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent"); -@@ -692,6 +749,7 @@ START_TEST(sync) - pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant"); +@@ -774,6 +867,7 @@ START_TEST(sync) + pNtReleaseSemaphore = (void *)GetProcAddress(module, "NtReleaseSemaphore"); pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent"); pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent"); + pNtWaitForAlertByThreadId = (void *)GetProcAddress(module, "NtWaitForAlertByThreadId"); pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent"); pRtlAcquireResourceExclusive = (void *)GetProcAddress(module, "RtlAcquireResourceExclusive"); pRtlAcquireResourceShared = (void *)GetProcAddress(module, "RtlAcquireResourceShared"); -@@ -708,4 +766,5 @@ START_TEST(sync) - test_mutant(); +@@ -791,4 +885,5 @@ START_TEST(sync) + test_semaphore(); test_keyed_events(); test_resource(); -+ test_thread_id_alert( argv ); ++ test_tid_alert( argv ); } -- -2.29.2 +2.30.2 diff --git a/patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch b/patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch similarity index 50% rename from patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch rename to patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch index 1a14e1ff..624ecb82 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch @@ -1,39 +1,58 @@ -From c6423d645d002113fce7b3194023ec507549c39a Mon Sep 17 00:00:00 2001 +From f910f81d3c8f3c01f7582738e61071ae7a24dfea Mon Sep 17 00:00:00 2001 From: Zebediah Figura -Date: Mon, 31 Aug 2020 23:02:56 -0500 -Subject: [PATCH 06/13] ntdll: Implement thread-id alerts on top of futexes if - possible. +Date: Fri, 30 Apr 2021 16:35:13 -0500 +Subject: [PATCH] ntdll: Implement thread-ID alerts using futexes if possible. Signed-off-by: Zebediah Figura --- - dlls/ntdll/unix/sync.c | 65 ++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/unix_private.h | 3 ++ - 2 files changed, 68 insertions(+) + dlls/ntdll/unix/sync.c | 76 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 76 insertions(+) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 2ed164368b9..3fd3545bbbb 100644 +index 014e5e5d0a7..058262ac0ad 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -2143,6 +2143,15 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) - if (teb->ClientId.UniqueThread == tid) - { - pthread_rwlock_unlock( &teb_list_lock ); +@@ -2289,6 +2289,9 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl + union tid_alert_entry + { + HANDLE event; +#ifdef __linux__ -+ if (use_futexes()) -+ { -+ int *futex = &thread_data->tid_alert_futex; -+ if (!InterlockedExchange( futex, 1 )) -+ futex_wake( futex, 1 ); -+ return STATUS_SUCCESS; -+ } ++ int futex; +#endif - NtSetEvent( thread_data->tid_alert_event, NULL ); - return STATUS_SUCCESS; - } -@@ -2153,6 +2162,28 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) + }; + + #define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry)) +@@ -2323,6 +2326,11 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) + + entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE]; + ++#ifdef __linux__ ++ if (use_futexes()) ++ return entry; ++#endif ++ + if (!entry->event) + { + HANDLE event; +@@ -2348,10 +2356,43 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) + + if (!entry) return STATUS_INVALID_CID; + ++#ifdef __linux__ ++ if (use_futexes()) ++ { ++ int *futex = &entry->futex; ++ if (!InterlockedExchange( futex, 1 )) ++ futex_wake( futex, 1 ); ++ return STATUS_SUCCESS; ++ } ++#endif ++ + return NtSetEvent( entry->event, NULL ); } ++#ifdef __linux__ +static LONGLONG get_absolute_timeout( const LARGE_INTEGER *timeout ) +{ + LARGE_INTEGER now; @@ -43,7 +62,6 @@ index 2ed164368b9..3fd3545bbbb 100644 + return now.QuadPart - timeout->QuadPart; +} + -+ +static LONGLONG update_timeout( ULONGLONG end ) +{ + LARGE_INTEGER now; @@ -54,19 +72,20 @@ index 2ed164368b9..3fd3545bbbb 100644 + if (timeleft < 0) timeleft = 0; + return timeleft; +} ++#endif + + /*********************************************************************** * NtWaitForAlertByThreadId (NTDLL.@) */ -@@ -2160,6 +2191,40 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG - { - TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); +@@ -2364,6 +2405,41 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG + + if (!entry) return STATUS_INVALID_CID; +#ifdef __linux__ + if (use_futexes()) + { -+ int *futex = &ntdll_get_thread_data()->tid_alert_futex; ++ int *futex = &entry->futex; + ULONGLONG end; + int ret; + @@ -97,23 +116,10 @@ index 2ed164368b9..3fd3545bbbb 100644 + return STATUS_ALERTED; + } +#endif - return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); - } - -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 9ae7cba34a7..327e12519a0 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -57,6 +57,9 @@ struct ntdll_thread_data - struct list entry; /* entry in TEB list */ - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ -+#ifdef __linux__ -+ int tid_alert_futex; /* futex for thread-id alerts */ -+#endif - HANDLE tid_alert_event; /* event for thread-id alerts */ - }; - ++ + status = NtWaitForSingleObject( entry->event, FALSE, timeout ); + if (!status) return STATUS_ALERTED; + return status; -- -2.29.2 +2.30.2 diff --git a/patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch b/patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch new file mode 100644 index 00000000..60f75521 --- /dev/null +++ b/patches/ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch @@ -0,0 +1,131 @@ +From adc9f55669d56782cdc7336d2f10f4aa6ac16355 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Fri, 30 Apr 2021 16:43:08 -0500 +Subject: [PATCH] ntdll: Implement thread-ID alerts using Mach semaphores on + Mac. + +Signed-off-by: Zebediah Figura +--- + dlls/ntdll/unix/sync.c | 60 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 058262ac0ad..4fa890e5acc 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -2288,10 +2288,14 @@ NTSTATUS WINAPI NtQueryInformationAtom( RTL_ATOM atom, ATOM_INFORMATION_CLASS cl + + union tid_alert_entry + { ++#ifdef __APPLE__ ++ semaphore_t sem; ++#else + HANDLE event; + #ifdef __linux__ + int futex; + #endif ++#endif + }; + + #define TID_ALERT_BLOCK_SIZE (65536 / sizeof(union tid_alert_entry)) +@@ -2326,6 +2330,17 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) + + entry = &tid_alert_blocks[block_idx][idx % TID_ALERT_BLOCK_SIZE]; + ++#ifdef __APPLE__ ++ if (!entry->sem) ++ { ++ semaphore_t sem; ++ ++ if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) ++ return NULL; ++ if (InterlockedCompareExchangePointer( (void **)&entry->sem, sem, NULL )) ++ semaphore_destroy( sem ); ++ } ++#else + #ifdef __linux__ + if (use_futexes()) + return entry; +@@ -2340,6 +2355,7 @@ static union tid_alert_entry *get_tid_alert_entry( HANDLE tid ) + if (InterlockedCompareExchangePointer( &entry->event, event, NULL )) + NtClose( event ); + } ++#endif + + return entry; + } +@@ -2356,6 +2372,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) + + if (!entry) return STATUS_INVALID_CID; + ++#ifdef __APPLE__ ++ semaphore_signal( entry->sem ); ++ return STATUS_SUCCESS; ++#else + #ifdef __linux__ + if (use_futexes()) + { +@@ -2367,6 +2387,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) + #endif + + return NtSetEvent( entry->event, NULL ); ++#endif + } + + +@@ -2405,6 +2426,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG + + if (!entry) return STATUS_INVALID_CID; + ++#ifdef __APPLE__ ++ { ++ semaphore_t sem = entry->sem; ++ ULONGLONG end; ++ kern_return_t ret; ++ ++ if (timeout) ++ { ++ if (timeout->QuadPart == TIMEOUT_INFINITE) ++ timeout = NULL; ++ else ++ end = get_absolute_timeout( timeout ); ++ } ++ ++ for (;;) ++ { ++ if (timeout) ++ { ++ LONGLONG timeleft = update_timeout( end ); ++ mach_timespec_t timespec; ++ ++ timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; ++ timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100; ++ ret = semaphore_timedwait( sem, timespec ); ++ } ++ else ++ ret = semaphore_wait( sem ); ++ ++ switch (ret) ++ { ++ case KERN_SUCCESS: return STATUS_ALERTED; ++ case KERN_ABORTED: continue; ++ case KERN_OPERATION_TIMED_OUT: return STATUS_TIMEOUT; ++ default: return STATUS_INVALID_HANDLE; ++ } ++ } ++ } ++#else + #ifdef __linux__ + if (use_futexes()) + { +@@ -2443,6 +2502,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG + status = NtWaitForSingleObject( entry->event, FALSE, timeout ); + if (!status) return STATUS_ALERTED; + return status; ++#endif + } + + +-- +2.30.2 + diff --git a/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch b/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch deleted file mode 100644 index c60bc638..00000000 --- a/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 32902deea99f78645f82f283f5cde453607cec1d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 31 Aug 2020 23:03:34 -0500 -Subject: [PATCH] ntdll: Implement thread-id alerts on top of Mach semaphores - on Mac. - -Signed-off-by: Zebediah Figura ---- - dlls/ntdll/unix/sync.c | 44 ++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/thread.c | 4 ++++ - dlls/ntdll/unix/unix_private.h | 9 +++++++ - 3 files changed, 57 insertions(+) - -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index f4f87ba5642..7d6423083e1 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -2301,6 +2301,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) - if (teb->ClientId.UniqueThread == tid) - { - pthread_rwlock_unlock( &teb_list_lock ); -+#ifdef __APPLE__ -+ semaphore_signal( thread_data->tid_alert_sem ); -+ return STATUS_SUCCESS; -+#else - #ifdef __linux__ - if (use_futexes()) - { -@@ -2312,6 +2316,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) - #endif - NtSetEvent( thread_data->tid_alert_event, NULL ); - return STATUS_SUCCESS; -+#endif - } - } - -@@ -2349,6 +2354,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG - { - TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); - -+#ifdef __APPLE__ -+ { -+ semaphore_t sem = ntdll_get_thread_data()->tid_alert_sem; -+ ULONGLONG end; -+ kern_return_t ret; -+ -+ if (timeout) -+ { -+ if (timeout->QuadPart == TIMEOUT_INFINITE) -+ timeout = NULL; -+ else -+ end = get_absolute_timeout( timeout ); -+ } -+ -+ for (;;) -+ { -+ if (timeout) -+ { -+ LONGLONG timeleft = update_timeout( end ); -+ mach_timespec_t timespec; -+ -+ timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; -+ timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100; -+ ret = semaphore_timedwait( sem, timespec ); -+ } -+ else -+ ret = semaphore_wait( sem ); -+ -+ switch (ret) -+ { -+ case KERN_SUCCESS: return STATUS_ALERTED; -+ case KERN_ABORTED: continue; -+ case KERN_OPERATION_TIMED_OUT: return STATUS_TIMEOUT; -+ default: return STATUS_INVALID_HANDLE; -+ } -+ } -+ } -+#else - #ifdef __linux__ - if (use_futexes()) - { -@@ -2384,6 +2427,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG - } - #endif - return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); -+#endif - } - - -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index bfcd7bf04a7..9b3c9a91abc 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -262,7 +262,11 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT - thread_data->start = start; - thread_data->param = param; - -+#ifdef __APPLE__ -+ semaphore_create( mach_task_self(), &thread_data->tid_alert_sem, SYNC_POLICY_FIFO, 0 ); -+#else - NtCreateEvent( &thread_data->tid_alert_event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); -+#endif - - pthread_attr_init( &pthread_attr ); - pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 4c38ed8ef29..3d629de09b2 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -27,6 +27,11 @@ - #include "wine/server.h" - #include "wine/list.h" - -+#ifdef __APPLE__ -+# include -+# include -+#endif -+ - #ifdef __i386__ - static const WORD current_machine = IMAGE_FILE_MACHINE_I386; - #elif defined(__x86_64__) -@@ -60,10 +65,14 @@ struct ntdll_thread_data - struct list entry; /* entry in TEB list */ - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ -+#ifdef __APPLE__ -+ semaphore_t tid_alert_sem; /* Mach semaphore for thread-id alerts */ -+#else - #ifdef __linux__ - int tid_alert_futex; /* futex for thread-id alerts */ - #endif - HANDLE tid_alert_event; /* event for thread-id alerts */ -+#endif - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); --- -2.30.2 - diff --git a/patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch b/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch similarity index 67% rename from patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch rename to patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch index 5452f573..7de5d54b 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch @@ -1,33 +1,18 @@ -From b41fc553cecc9ba5c81cda41bb85e2ee1937586e Mon Sep 17 00:00:00 2001 +From 4c99070bbd7dd897a6e27bd94e8f50206b3ad49c Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 2 Nov 2020 20:24:07 -0600 Subject: [PATCH] ntdll: Reimplement Win32 futexes on top of thread-ID alerts. Signed-off-by: Zebediah Figura --- - dlls/ntdll/ntdll_misc.h | 2 + - dlls/ntdll/sync.c | 185 ++++++++++++++++++++++++++++++++++++++- - dlls/ntdll/thread.c | 2 + + dlls/ntdll/sync.c | 158 +++++++++++++++++++++++++++++++++++++- dlls/ntdll/unix/loader.c | 3 - - dlls/ntdll/unix/sync.c | 162 ---------------------------------- + dlls/ntdll/unix/sync.c | 162 --------------------------------------- dlls/ntdll/unixlib.h | 6 +- - 6 files changed, 187 insertions(+), 173 deletions(-) + 4 files changed, 156 insertions(+), 173 deletions(-) -diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index b8f9dc28e63..eab3b5e5248 100644 ---- a/dlls/ntdll/ntdll_misc.h -+++ b/dlls/ntdll/ntdll_misc.h -@@ -85,6 +85,8 @@ extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN; - - extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; - -+extern void addr_wait_free_entry(void) DECLSPEC_HIDDEN; -+ - extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args ) DECLSPEC_HIDDEN; - extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args ) DECLSPEC_HIDDEN; - diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index f1263ae33fd..d652f55b630 100644 +index f1263ae33fd..348f260c3b0 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -36,6 +36,13 @@ @@ -44,75 +29,48 @@ index f1263ae33fd..d652f55b630 100644 /****************************************************************** * RtlRunOnceInitialize (NTDLL.@) -@@ -530,13 +537,143 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, +@@ -530,13 +537,111 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, return status; } -+/* The following functions define a lock-free array mapping thread IDs to -+ * values, which can be grown but not shrunk. We do this by allocating one slice -+ * of the array at a time, and storing a pointer to the next slice at the end. -+ * -+ * This is both for efficiency (we want this function to be as fast as possible) -+ * and because locking the TEB list is hard otherwise—we need to safely access -+ * the TEB list, but cannot do so using any of these synchronization primitives, -+ * and we may need to access the TEB list before being inserted into it (e.g. -+ * from heap locks, or the TEB list lock itself.) -+ */ + -+struct addr_wait_entry ++#define FUTEX_ADDR_BLOCK_SIZE (65536 / sizeof(void *)) ++static void **futex_addr_blocks[4096]; ++ ++static unsigned int tid_to_index( DWORD tid, unsigned int *block_idx ) +{ -+ void *addr; -+ HANDLE tid; -+}; -+ -+struct addr_wait_array -+{ -+ struct addr_wait_entry entries[(0x1000 - sizeof(struct addr_wait_entry *)) / sizeof(struct addr_wait_entry)]; -+ struct addr_wait_array *next; -+}; -+ -+static struct addr_wait_array first_addr_wait_array; -+ -+static struct addr_wait_entry *addr_wait_allocate_entry( HANDLE tid ) -+{ -+ struct addr_wait_array *array = &first_addr_wait_array; -+ -+ for (;;) -+ { -+ struct addr_wait_array *new_array = NULL; -+ SIZE_T size = sizeof(*new_array); -+ unsigned int i; -+ -+ for (;;) -+ { -+ for (i = 0; i < ARRAY_SIZE(array->entries); ++i) -+ { -+ if (!array->entries[i].tid && !InterlockedCompareExchangePointer( &array->entries[i].tid, tid, NULL )) -+ return &array->entries[i]; -+ } -+ -+ if (!array->next) break; -+ array = array->next; -+ } -+ -+ if (NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&new_array, 0, &size, MEM_COMMIT, PAGE_READWRITE )) -+ return NULL; -+ -+ if (InterlockedCompareExchangePointer( (void **)&array->next, new_array, NULL )) -+ { -+ /* another thread beat us to it */ -+ NtFreeVirtualMemory( NtCurrentProcess(), (void **)&new_array, &size, MEM_RELEASE ); -+ } -+ /* start searching again from the new array */ -+ array = array->next; -+ } ++ unsigned int idx = (tid >> 2) - 1; ++ *block_idx = idx / FUTEX_ADDR_BLOCK_SIZE; ++ return idx % FUTEX_ADDR_BLOCK_SIZE; +} + -+void addr_wait_free_entry(void) ++static HANDLE index_to_tid( unsigned int block_idx, unsigned int idx ) +{ -+ struct addr_wait_entry *entry = NtCurrentTeb()->ReservedForPerf; -+ if (entry) -+ InterlockedExchangePointer( &entry->tid, NULL ); ++ return (HANDLE)((((block_idx * FUTEX_ADDR_BLOCK_SIZE) + idx) + 1) << 2); ++} ++ ++static void **get_futex_entry( DWORD tid ) ++{ ++ unsigned int block_idx, idx = tid_to_index( tid, &block_idx ); ++ ++ if (block_idx > ARRAY_SIZE(futex_addr_blocks)) ++ { ++ FIXME( "tid %#x is too high\n", tid ); ++ return NULL; ++ } ++ ++ if (!futex_addr_blocks[block_idx]) ++ { ++ SIZE_T size = FUTEX_ADDR_BLOCK_SIZE * sizeof(void *); ++ void *ptr = NULL; ++ ++ if (NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &size, MEM_COMMIT, PAGE_READWRITE )) ++ return NULL; ++ if (InterlockedCompareExchangePointer( (void **)&futex_addr_blocks[block_idx], ptr, NULL )) ++ NtFreeVirtualMemory( NtCurrentProcess(), &ptr, &size, MEM_RELEASE ); /* someone beat us to it */ ++ } ++ ++ return &futex_addr_blocks[block_idx][idx % FUTEX_ADDR_BLOCK_SIZE]; +} + +static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size ) @@ -139,7 +97,7 @@ index f1263ae33fd..d652f55b630 100644 const LARGE_INTEGER *timeout ) { - return unix_funcs->RtlWaitOnAddress( addr, cmp, size, timeout ); -+ struct addr_wait_entry *entry = NtCurrentTeb()->ReservedForPerf; ++ void **entry = get_futex_entry( GetCurrentThreadId() ); + NTSTATUS ret; + + TRACE("addr %p cmp %p size %#Ix timeout %s\n", addr, cmp, size, debugstr_timeout( timeout )); @@ -147,14 +105,9 @@ index f1263ae33fd..d652f55b630 100644 + if (size != 1 && size != 2 && size != 4 && size != 8) + return STATUS_INVALID_PARAMETER; + -+ if (!entry) -+ { -+ if (!(entry = addr_wait_allocate_entry( NtCurrentTeb()->ClientId.UniqueThread ))) -+ return STATUS_NO_MEMORY; -+ NtCurrentTeb()->ReservedForPerf = entry; -+ } ++ if (!entry) return STATUS_NO_MEMORY; + -+ InterlockedExchangePointer( &entry->addr, (void *)addr ); ++ InterlockedExchangePointer( entry, (void *)addr ); + + /* Ensure that the compare-and-swap above is ordered before the comparison + * below. This barrier is paired with another in RtlWakeByAddress*(). @@ -178,24 +131,24 @@ index f1263ae33fd..d652f55b630 100644 + + if (!compare_addr( addr, cmp, size )) + { -+ InterlockedExchangePointer( &entry->addr, NULL ); ++ InterlockedExchangePointer( entry, NULL ); + return STATUS_SUCCESS; + } + + ret = NtWaitForAlertByThreadId( NULL, timeout ); -+ InterlockedExchangePointer( &entry->addr, NULL ); ++ InterlockedExchangePointer( entry, NULL ); + if (ret == STATUS_ALERTED) ret = STATUS_SUCCESS; + return ret; } /*********************************************************************** -@@ -544,7 +681,26 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size +@@ -544,7 +649,29 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size */ void WINAPI RtlWakeAddressAll( const void *addr ) { - return unix_funcs->RtlWakeAddressAll( addr ); -+ struct addr_wait_array *array; -+ unsigned int i; ++ unsigned int i, j; ++ void **block; + + TRACE("%p\n", addr); + @@ -206,24 +159,27 @@ index f1263ae33fd..d652f55b630 100644 + */ + MemoryBarrier(); + -+ for (array = &first_addr_wait_array; array != NULL; array = array->next) ++ for (i = 0; i < ARRAY_SIZE(futex_addr_blocks); ++i) + { -+ for (i = 0; i < ARRAY_SIZE(array->entries); ++i) ++ block = futex_addr_blocks[i]; ++ if (!block) continue; ++ ++ for (j = 0; j < FUTEX_ADDR_BLOCK_SIZE; ++j) + { -+ if (array->entries[i].addr == addr) -+ NtAlertThreadByThreadId( array->entries[i].tid ); ++ if (block[j] == addr) ++ NtAlertThreadByThreadId( index_to_tid( i, j ) ); + } + } } /*********************************************************************** -@@ -552,5 +708,28 @@ void WINAPI RtlWakeAddressAll( const void *addr ) +@@ -552,5 +679,30 @@ void WINAPI RtlWakeAddressAll( const void *addr ) */ void WINAPI RtlWakeAddressSingle( const void *addr ) { - return unix_funcs->RtlWakeAddressSingle( addr ); -+ struct addr_wait_array *array; -+ unsigned int i; ++ unsigned int i, j; ++ void **block; + + TRACE("%p\n", addr); + @@ -234,37 +190,26 @@ index f1263ae33fd..d652f55b630 100644 + */ + MemoryBarrier(); + -+ for (array = &first_addr_wait_array; array != NULL; array = array->next) ++ for (i = 0; i < ARRAY_SIZE(futex_addr_blocks); ++i) + { -+ for (i = 0; i < ARRAY_SIZE(array->entries); ++i) ++ block = futex_addr_blocks[i]; ++ if (!block) continue; ++ ++ for (j = 0; j < FUTEX_ADDR_BLOCK_SIZE; ++j) + { -+ if (array->entries[i].addr == addr -+ && InterlockedCompareExchangePointer( &array->entries[i].addr, NULL, (void *)addr ) == addr) ++ if (block[j] == addr && InterlockedCompareExchangePointer( &block[j], NULL, (void *)addr ) == addr) + { -+ NtAlertThreadByThreadId( array->entries[i].tid ); ++ NtAlertThreadByThreadId( index_to_tid( i, j ) ); + return; + } + } + } } -diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c -index 25496609f08..4f395336428 100644 ---- a/dlls/ntdll/thread.c -+++ b/dlls/ntdll/thread.c -@@ -84,6 +84,8 @@ void WINAPI RtlExitUserThread( ULONG status ) - NtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread, &last, sizeof(last), NULL ); - if (last) RtlExitUserProcess( status ); - LdrShutdownThread(); -+ /* must be done last, in particular after any heap allocations */ -+ addr_wait_free_entry(); - for (;;) NtTerminateThread( GetCurrentThread(), status ); - } - diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index 4c76865019b..d7fc60cad2f 100644 +index e4c062cea98..3a4a943c65f 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c -@@ -1753,9 +1753,6 @@ static struct unix_funcs unix_funcs = +@@ -1816,9 +1816,6 @@ static struct unix_funcs unix_funcs = #endif DbgUiIssueRemoteBreakin, RtlGetSystemTimePrecise, @@ -275,10 +220,10 @@ index 4c76865019b..d7fc60cad2f 100644 fast_RtlpUnWaitCriticalSection, fast_RtlDeleteCriticalSection, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 7d6423083e1..41005425a90 100644 +index 4fa890e5acc..8394a1b8601 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -77,10 +77,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync); +@@ -80,10 +80,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync); HANDLE keyed_event = 0; @@ -289,7 +234,7 @@ index 7d6423083e1..41005425a90 100644 static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) { if (!timeout) return "(infinite)"; -@@ -190,24 +186,6 @@ static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGE +@@ -193,24 +189,6 @@ static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGE #endif @@ -314,7 +259,7 @@ index 7d6423083e1..41005425a90 100644 /* create a struct security_descriptor and contained information in one contiguous piece of memory */ NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, data_size_t *ret_len ) -@@ -2836,71 +2814,6 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, +@@ -2911,71 +2889,6 @@ NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, return STATUS_SUCCESS; } @@ -386,7 +331,7 @@ index 7d6423083e1..41005425a90 100644 #else NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) -@@ -2943,79 +2856,4 @@ NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value +@@ -3018,79 +2931,4 @@ NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value return STATUS_NOT_IMPLEMENTED; } diff --git a/patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Merge-critsection.c-into-sync.c.patch b/patches/ntdll-NtAlertThreadByThreadId/0008-ntdll-Merge-critsection.c-into-sync.c.patch similarity index 99% rename from patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Merge-critsection.c-into-sync.c.patch rename to patches/ntdll-NtAlertThreadByThreadId/0008-ntdll-Merge-critsection.c-into-sync.c.patch index 51906d25..10523fda 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Merge-critsection.c-into-sync.c.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0008-ntdll-Merge-critsection.c-into-sync.c.patch @@ -1,4 +1,4 @@ -From 9141708f675ec4aca0551249082dc7b494135bad Mon Sep 17 00:00:00 2001 +From fd8bfe5f17e0c95cdaf5125f4f4a18ad7b06cfd8 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:30:52 -0500 Subject: [PATCH] ntdll: Merge critsection.c into sync.c. @@ -12,7 +12,7 @@ Signed-off-by: Zebediah Figura delete mode 100644 dlls/ntdll/critsection.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in -index b2f63d9f63a..5ef28d2f722 100644 +index 0fdfb83df15..2e79843890d 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -9,7 +9,6 @@ EXTRADLLFLAGS = -mno-cygwin -nodefaultlibs -Wl,--image-base,0x7bc00000 @@ -573,7 +573,7 @@ index fe7d933c0fa..00000000000 - return STATUS_SUCCESS; -} diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index be462f27881..b8465c53832 100644 +index 348f260c3b0..c73fb09da47 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -2,7 +2,7 @@ @@ -585,7 +585,7 @@ index be462f27881..b8465c53832 100644 * Copyright 1999, 2000 Juergen Schmied * Copyright 2003 Eric Pouech * -@@ -38,6 +38,7 @@ +@@ -37,6 +37,7 @@ #include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(sync); @@ -593,7 +593,7 @@ index be462f27881..b8465c53832 100644 static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) { -@@ -696,3 +697,334 @@ void WINAPI RtlWakeAddressSingle( const void *addr ) +@@ -706,3 +707,334 @@ void WINAPI RtlWakeAddressSingle( const void *addr ) } } } @@ -929,5 +929,5 @@ index be462f27881..b8465c53832 100644 + return STATUS_SUCCESS; +} -- -2.29.2 +2.30.2 diff --git a/patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch b/patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch similarity index 93% rename from patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch rename to patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch index 487ef059..f76a0103 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch @@ -1,4 +1,4 @@ -From 7ac2eff4652e8ce16550c27b2378e2dc64d54122 Mon Sep 17 00:00:00 2001 +From 098b4dc3d374b5ed26dbcd0be643c961f1fa156f Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:38:09 -0500 Subject: [PATCH] ntdll: Reimplement the critical section fast path on top of @@ -14,10 +14,10 @@ Signed-off-by: Zebediah Figura 5 files changed, 24 insertions(+), 131 deletions(-) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 09975ac3d45..97a5ce7fffa 100644 +index c73fb09da47..6edf104c5e9 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c -@@ -765,19 +765,26 @@ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit ) +@@ -738,19 +738,26 @@ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit ) static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout ) { @@ -52,7 +52,7 @@ index 09975ac3d45..97a5ce7fffa 100644 } /****************************************************************************** -@@ -867,8 +874,6 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) +@@ -840,8 +847,6 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo ); crit->DebugInfo = NULL; } @@ -61,7 +61,7 @@ index 09975ac3d45..97a5ce7fffa 100644 } else NtClose( crit->LockSemaphore ); crit->LockSemaphore = 0; -@@ -944,12 +949,18 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) +@@ -917,12 +922,18 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS ret; /* debug info is cleared by MakeCriticalSectionGlobal */ @@ -83,10 +83,10 @@ index 09975ac3d45..97a5ce7fffa 100644 return ret; } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index d7fc60cad2f..fe710e9d1f5 100644 +index 3a4a943c65f..579c73b2ad7 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c -@@ -1753,9 +1753,6 @@ static struct unix_funcs unix_funcs = +@@ -1816,9 +1816,6 @@ static struct unix_funcs unix_funcs = #endif DbgUiIssueRemoteBreakin, RtlGetSystemTimePrecise, @@ -97,10 +97,10 @@ index d7fc60cad2f..fe710e9d1f5 100644 fast_RtlAcquireSRWLockExclusive, fast_RtlTryAcquireSRWLockShared, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 41005425a90..6b97028fb68 100644 +index 8394a1b8601..a7cce945e97 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -2409,115 +2409,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG +@@ -2484,115 +2484,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG } @@ -217,10 +217,10 @@ index 41005425a90..6b97028fb68 100644 /* Futex-based SRW lock implementation: diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 923b888ce68..1524a532a88 100644 +index a5bade02b8a..bd7c4a8068c 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -105,9 +105,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON +@@ -82,9 +82,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN; extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN; extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN; diff --git a/patches/ntdll-NtAlertThreadByThreadId/0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch b/patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch similarity index 93% rename from patches/ntdll-NtAlertThreadByThreadId/0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch rename to patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch index 708fd99c..0b49ef17 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch @@ -1,4 +1,4 @@ -From 65b24120d7a4bb05712bcb559d55a30d5a498002 Mon Sep 17 00:00:00 2001 +From 83486871ac972952b78519bd68579919de8f51d2 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:55:29 -0500 Subject: [PATCH] ntdll: Get rid of the direct futex path for condition @@ -14,7 +14,7 @@ Signed-off-by: Zebediah Figura 5 files changed, 9 insertions(+), 96 deletions(-) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 97a5ce7fffa..1e6afc4cfc8 100644 +index 6edf104c5e9..4b92379a0ff 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -449,11 +449,8 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable ) @@ -80,10 +80,10 @@ index 97a5ce7fffa..1e6afc4cfc8 100644 if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) RtlAcquireSRWLockShared( lock ); diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index fe710e9d1f5..36899ba57e3 100644 +index 579c73b2ad7..90fb4e4a899 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c -@@ -1759,8 +1759,6 @@ static struct unix_funcs unix_funcs = +@@ -1822,8 +1822,6 @@ static struct unix_funcs unix_funcs = fast_RtlAcquireSRWLockShared, fast_RtlReleaseSRWLockExclusive, fast_RtlReleaseSRWLockShared, @@ -93,10 +93,10 @@ index fe710e9d1f5..36899ba57e3 100644 ntdll_ceil, ntdll_cos, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 6b97028fb68..d4092438644 100644 +index a7cce945e97..e3c957e1181 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -166,23 +166,6 @@ static int *get_futex(void **ptr) +@@ -169,23 +169,6 @@ static int *get_futex(void **ptr) return NULL; } @@ -120,7 +120,7 @@ index 6b97028fb68..d4092438644 100644 #endif -@@ -2661,50 +2644,6 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) +@@ -2736,50 +2719,6 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) return STATUS_SUCCESS; } @@ -171,7 +171,7 @@ index 6b97028fb68..d4092438644 100644 #else NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) -@@ -2737,14 +2676,4 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) +@@ -2812,14 +2751,4 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) return STATUS_NOT_IMPLEMENTED; } @@ -187,10 +187,10 @@ index 6b97028fb68..d4092438644 100644 - #endif diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 1524a532a88..91b6451ade1 100644 +index bd7c4a8068c..6a67dbd9445 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -111,10 +111,7 @@ extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLS +@@ -88,10 +88,7 @@ extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLS extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; diff --git a/patches/ntdll-NtAlertThreadByThreadId/0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch b/patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch similarity index 97% rename from patches/ntdll-NtAlertThreadByThreadId/0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch rename to patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch index e835f7b1..a3986a06 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch @@ -1,4 +1,4 @@ -From ddc8ae251a344ad7e7e11844b03fe0eaaa553084 Mon Sep 17 00:00:00 2001 +From cfb789e5a0b1f5ac624cc98be68694168fec4503 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 22 Nov 2020 20:51:10 -0600 Subject: [PATCH] ntdll: Reimplement SRW locks on top of Win32 futexes. @@ -13,7 +13,7 @@ Signed-off-by: Zebediah Figura 5 files changed, 142 insertions(+), 502 deletions(-) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 1e6afc4cfc8..93a6a5fd7de 100644 +index 4b92379a0ff..2edc9f8d558 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -160,127 +160,24 @@ DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN fu @@ -74,13 +74,15 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 -#endif - -static inline void srwlock_check_invalid( unsigned int val ) --{ ++struct srw_lock + { - /* Throw exception if it's impossible to acquire/release this lock. */ - if ((val & SRWLOCK_MASK_EXCLUSIVE_QUEUE) == SRWLOCK_MASK_EXCLUSIVE_QUEUE || - (val & SRWLOCK_MASK_SHARED_QUEUE) == SRWLOCK_MASK_SHARED_QUEUE) - RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED); -} -- ++ short exclusive_waiters; + -static inline unsigned int srwlock_lock_exclusive( unsigned int *dest, int incr ) -{ - unsigned int val, tmp; @@ -120,8 +122,7 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 -} - -static inline void srwlock_leave_exclusive( RTL_SRWLOCK *lock, unsigned int val ) -+struct srw_lock - { +-{ - /* Used when a thread leaves an exclusive section. If there are other - * exclusive access threads they are processed first, followed by - * the shared waiters. */ @@ -134,8 +135,7 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 - NtReleaseKeyedEvent( 0, srwlock_key_shared(lock), FALSE, NULL ); - } -} -+ short exclusive_waiters; - +- -static inline void srwlock_leave_shared( RTL_SRWLOCK *lock, unsigned int val ) -{ - /* Wake up one exclusive thread as soon as the last shared access thread @@ -167,7 +167,9 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 - if (unix_funcs->fast_RtlAcquireSRWLockExclusive( lock ) != STATUS_NOT_IMPLEMENTED) - return; + union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock }; -+ + +- if (srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, SRWLOCK_RES_EXCLUSIVE )) +- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL ); + InterlockedIncrement16( &u.s->exclusive_waiters ); + + for (;;) @@ -192,9 +194,7 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 + wait = TRUE; + } + } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l); - -- if (srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, SRWLOCK_RES_EXCLUSIVE )) -- NtWaitForKeyedEvent( 0, srwlock_key_exclusive(lock), FALSE, NULL ); ++ + if (!wait) return; + RtlWaitOnAddress( &u.s->owners, &new.s.owners, sizeof(short), NULL ); + } @@ -206,11 +206,11 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 void WINAPI RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) { - unsigned int val, tmp; -- -- if (unix_funcs->fast_RtlAcquireSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED) -- return; + union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock }; +- if (unix_funcs->fast_RtlAcquireSRWLockShared( lock ) != STATUS_NOT_IMPLEMENTED) +- return; +- - /* Acquires a shared lock. If it's currently not possible to add elements to - * the shared queue, then request exclusive access instead. */ - for (val = *(unsigned int *)&lock->Ptr;; val = tmp) @@ -268,14 +268,14 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 - return; + union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock }; + union { struct srw_lock s; LONG l; } old, new; -+ + +- srwlock_leave_exclusive( lock, srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr, +- - SRWLOCK_RES_EXCLUSIVE ) - SRWLOCK_RES_EXCLUSIVE ); + do + { + old.s = *u.s; + new = old; - -- srwlock_leave_exclusive( lock, srwlock_unlock_exclusive( (unsigned int *)&lock->Ptr, -- - SRWLOCK_RES_EXCLUSIVE ) - SRWLOCK_RES_EXCLUSIVE ); ++ + if (old.s.owners != -1) ERR("Lock %p is not owned exclusive!\n", lock); + + new.s.owners = 0; @@ -296,14 +296,14 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 - return; + union { RTL_SRWLOCK *rtl; struct srw_lock *s; LONG *l; } u = { lock }; + union { struct srw_lock s; LONG l; } old, new; -+ + +- srwlock_leave_shared( lock, srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, +- - SRWLOCK_RES_SHARED ) - SRWLOCK_RES_SHARED ); + do + { + old.s = *u.s; + new = old; - -- srwlock_leave_shared( lock, srwlock_lock_exclusive( (unsigned int *)&lock->Ptr, -- - SRWLOCK_RES_SHARED ) - SRWLOCK_RES_SHARED ); ++ + if (old.s.owners == -1) ERR("Lock %p is owned exclusive!\n", lock); + else if (!old.s.owners) ERR("Lock %p is not owned shared!\n", lock); + @@ -330,7 +330,9 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 + { + old.s = *u.s; + new.s = old.s; -+ + +- return InterlockedCompareExchange( (int *)&lock->Ptr, SRWLOCK_MASK_IN_EXCLUSIVE | +- SRWLOCK_RES_EXCLUSIVE, 0 ) == 0; + if (!old.s.owners) + { + /* Not locked exclusive or shared. We can try to grab it. */ @@ -342,9 +344,7 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 + ret = FALSE; + } + } while (InterlockedCompareExchange( u.l, new.l, old.l ) != old.l); - -- return InterlockedCompareExchange( (int *)&lock->Ptr, SRWLOCK_MASK_IN_EXCLUSIVE | -- SRWLOCK_RES_EXCLUSIVE, 0 ) == 0; ++ + return ret; } @@ -392,10 +392,10 @@ index 1e6afc4cfc8..93a6a5fd7de 100644 /*********************************************************************** diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index 36899ba57e3..6a7eb5d7af1 100644 +index 90fb4e4a899..26bfa961794 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c -@@ -1753,12 +1753,6 @@ static struct unix_funcs unix_funcs = +@@ -1816,12 +1816,6 @@ static struct unix_funcs unix_funcs = #endif DbgUiIssueRemoteBreakin, RtlGetSystemTimePrecise, @@ -409,10 +409,10 @@ index 36899ba57e3..6a7eb5d7af1 100644 ntdll_ceil, ntdll_cos, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index d4092438644..b67f5fc8f10 100644 +index e3c957e1181..97dcd5b5026 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -114,8 +114,6 @@ static inline ULONGLONG monotonic_counter(void) +@@ -117,8 +117,6 @@ static inline ULONGLONG monotonic_counter(void) #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 @@ -421,7 +421,7 @@ index d4092438644..b67f5fc8f10 100644 static int futex_private = 128; -@@ -129,16 +127,6 @@ static inline int futex_wake( const int *addr, int val ) +@@ -132,16 +130,6 @@ static inline int futex_wake( const int *addr, int val ) return syscall( __NR_futex, addr, FUTEX_WAKE | futex_private, val, NULL, 0, 0 ); } @@ -438,7 +438,7 @@ index d4092438644..b67f5fc8f10 100644 static inline int use_futexes(void) { static int supported = -1; -@@ -156,16 +144,6 @@ static inline int use_futexes(void) +@@ -159,16 +147,6 @@ static inline int use_futexes(void) return supported; } @@ -455,8 +455,8 @@ index d4092438644..b67f5fc8f10 100644 #endif -@@ -2390,290 +2368,3 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG - return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); +@@ -2465,290 +2443,3 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG + return status; #endif } - @@ -747,10 +747,10 @@ index d4092438644..b67f5fc8f10 100644 - -#endif diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 91b6451ade1..ffce7328600 100644 +index 6a67dbd9445..8184d8e5e79 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -105,12 +105,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON +@@ -82,12 +82,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN; extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN; extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN; diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 183ce988..05e07a62 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -2938,24 +2938,22 @@ fi # | * [#50292] Process-local synchronization objects use private interfaces into the Unix library # | # | Modified files: -# | * dlls/ntdll/Makefile.in, dlls/ntdll/critsection.c, dlls/ntdll/ntdll.spec, dlls/ntdll/ntdll_misc.h, dlls/ntdll/sync.c, -# | dlls/ntdll/tests/Makefile.in, dlls/ntdll/tests/om.c, dlls/ntdll/tests/sync.c, dlls/ntdll/thread.c, -# | dlls/ntdll/unix/loader.c, dlls/ntdll/unix/sync.c, dlls/ntdll/unix/thread.c, dlls/ntdll/unix/unix_private.h, -# | dlls/ntdll/unix/virtual.c, dlls/ntdll/unixlib.h, include/winternl.h +# | * dlls/ntdll/Makefile.in, dlls/ntdll/critsection.c, dlls/ntdll/ntdll.spec, dlls/ntdll/sync.c, +# | dlls/ntdll/tests/Makefile.in, dlls/ntdll/tests/om.c, dlls/ntdll/tests/sync.c, dlls/ntdll/unix/loader.c, +# | dlls/ntdll/unix/sync.c, dlls/ntdll/unix/unix_private.h, dlls/ntdll/unixlib.h, include/winternl.h # | if test "$enable_ntdll_NtAlertThreadByThreadId" -eq 1; then patch_apply ntdll-NtAlertThreadByThreadId/0001-ntdll-tests-Move-some-tests-to-a-new-sync.c-file.patch patch_apply ntdll-NtAlertThreadByThreadId/0002-ntdll-tests-Add-some-tests-for-Rtl-resources.patch - patch_apply ntdll-NtAlertThreadByThreadId/0003-ntdll-Use-a-separate-mutex-to-lock-the-TEB-list.patch - patch_apply ntdll-NtAlertThreadByThreadId/0004-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch - patch_apply ntdll-NtAlertThreadByThreadId/0005-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch - patch_apply ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-id-alerts-on-top-of-futexes-i.patch - patch_apply ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch - patch_apply ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch - patch_apply ntdll-NtAlertThreadByThreadId/0010-ntdll-Merge-critsection.c-into-sync.c.patch - patch_apply ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-the-critical-section-fast-path-on-.patch - patch_apply ntdll-NtAlertThreadByThreadId/0012-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch - patch_apply ntdll-NtAlertThreadByThreadId/0013-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch + patch_apply ntdll-NtAlertThreadByThreadId/0003-ntdll-Implement-NtAlertThreadByThreadId-and-NtWaitFo.patch + patch_apply ntdll-NtAlertThreadByThreadId/0004-ntdll-tests-Add-basic-tests-for-thread-id-alert-func.patch + patch_apply ntdll-NtAlertThreadByThreadId/0005-ntdll-Implement-thread-ID-alerts-using-futexes-if-po.patch + patch_apply ntdll-NtAlertThreadByThreadId/0006-ntdll-Implement-thread-ID-alerts-using-Mach-semaphor.patch + patch_apply ntdll-NtAlertThreadByThreadId/0007-ntdll-Reimplement-Win32-futexes-on-top-of-thread-ID-.patch + patch_apply ntdll-NtAlertThreadByThreadId/0008-ntdll-Merge-critsection.c-into-sync.c.patch + patch_apply ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch + patch_apply ntdll-NtAlertThreadByThreadId/0010-ntdll-Get-rid-of-the-direct-futex-path-for-condition.patch + patch_apply ntdll-NtAlertThreadByThreadId/0011-ntdll-Reimplement-SRW-locks-on-top-of-Win32-futexes.patch fi # Patchset ntdll-NtQuerySection