File patches.obscpio of Package wine-pure

07070100B68EA6000081A4000003E8000003E80000000168AA560300000624000001030000000200000000000000000000004400000000patches/Do-not-handle-IMAGE_FILE_LARGE_ADDRESS_AWARE-on-WoW64.patchFrom 617fbfeac720552802bdb704d162d5de1f99ccdb Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sun, 27 Jul 2025 22:34:45 +0300
Subject: [PATCH] Do not handle IMAGE_FILE_LARGE_ADDRESS_AWARE on WoW64
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The header IMAGE_FILE_LARGE_ADDRESS_AWARE SOMEHOW breaks the work of a number of pirates and not
very installers. Without WoW64 they aren't broken, just because IMAGE_FILE_LARGE_ADDRESS_AWARE is
not processed, instead there is a hardcoded user_space_limit to 0x7fff0000 with which everything
works. I don’t know what’s wrong with the Wine implementation, but I prefer all applications to work
out of box. However, you can still force the use of LAA by using the WINE_LARGE_ADDRESS_AWARE
environment variable.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/virtual.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index c5d73456762..7edf597349e 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4921,8 +4921,7 @@ BOOL WINAPI __wine_needs_override_large_address_aware(void)
 
 static BOOL is_large_address_aware(void)
 {
-    return (main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
-           || __wine_needs_override_large_address_aware();
+    return __wine_needs_override_large_address_aware();
 }
 
 /***********************************************************************
-- 
2.50.1

07070100B69336000081A4000003E8000003E80000000168AA560300000363000001030000000200000000000000000000003A00000000patches/explorer-prefer-wayland-over-x11-by-default.patchFrom 9ad3e7bbfbc635c6146d0eee664fca868dfde5d8 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sun, 24 Nov 2024 13:39:52 +0300
Subject: [PATCH 2/2] explorer: Prefer Wayland over X11 by default

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 programs/explorer/desktop.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index e526b468b7d..060104427ce 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer);
 #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769))
 #define DESKTOP_ALL_ACCESS 0x01ff
 
-static const WCHAR default_driver[] = L"mac,x11,wayland";
+static const WCHAR default_driver[] = L"mac,wayland,x11";
 
 static BOOL using_root = TRUE;
 
-- 
2.47.0

07070100B69337000081A4000003E8000003E80000000168AA560300000C3A000001030000000200000000000000000000003C00000000patches/Avoid-winemenubuilder-to-startup-explorer.exe.patchFrom cc622577f11883628a4f13b567b1884cc8bb576d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3FBernhard=3D20=3DC3=3D9Cbelacker=3F=3D?=
 <bernhardu@mailbox.org>
Date: Sat, 12 Dec 2020 22:36:59 +0100
Subject: [PATCH] Avoid winemenubuilder to startup explorer.exe.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/win32u/defwnd.c                       | 19 +++++++++++++++++++
 programs/winemenubuilder/winemenubuilder.c | 11 +++++++++++
 2 files changed, 30 insertions(+)

diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c
index 0cbb41d8604..ae982be0c0d 100644
--- a/dlls/win32u/defwnd.c
+++ b/dlls/win32u/defwnd.c
@@ -26,6 +26,7 @@
 
 #include "ntgdi_private.h"
 #include "ntuser_private.h"
+#include "ntstatus.h"
 #include "wine/server.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(win);
@@ -2984,6 +2985,24 @@ LRESULT desktop_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
                       guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
             NtAddAtom( bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR), &atom );
             NtUserSetProp( hwnd, wine_display_device_guidW, ULongToHandle( atom ) );
+
+            {
+                char full_name[60];
+                WCHAR full_nameW[60];
+                UNICODE_STRING name_str;
+                OBJECT_ATTRIBUTES event_attr;
+                HANDLE event;
+
+                sprintf( full_name, "\\BaseNamedObjects\\Session\\%u\\__wine_desktop_created", NtCurrentTeb()->Peb->SessionId );
+                name_str.Buffer = full_nameW;
+                name_str.MaximumLength = asciiz_to_unicode( full_nameW, full_name );
+                name_str.Length = name_str.MaximumLength - sizeof(WCHAR);
+                InitializeObjectAttributes( &event_attr, &name_str, OBJ_OPENIF, NULL, NULL );
+                if (NtCreateEvent( &event, EVENT_ALL_ACCESS, &event_attr, NotificationEvent, FALSE ) != STATUS_SUCCESS)
+                    ERR("Creating event %s failed.\n", debugstr_w(full_nameW));
+                else if (NtSetEvent( event, NULL ) != STATUS_SUCCESS)
+                    ERR("Setting event %s failed.\n", debugstr_w(full_nameW));
+            }
         }
         return TRUE;
     }
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 36569fa9d5f..103cb1de328 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -2895,6 +2895,17 @@ int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int sh
     if (!init_xdg())
         return 1;
 
+    {
+        const WCHAR event_name[] = L"__wine_desktop_created";
+        HANDLE event;
+        event = CreateEventW(NULL, TRUE, FALSE, event_name);
+        if (!event)
+            ERR("Creating event %s failed.\n", debugstr_w(event_name));
+        else if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED)
+            ERR("Waiting on event %s failed.\n", debugstr_w(event_name));
+        CloseHandle(event);
+    }
+
     hr = CoInitialize(NULL);
     if (FAILED(hr))
     {
-- 
2.48.1

07070100B69338000081A4000003E8000003E80000000168AA560300000B4A000001030000000200000000000000000000003D00000000patches/0004-wineboot-Generate-better-DigitalProductId.patchFrom cdf0ced4bfbffcccbca1957b1c8904794d27db0e Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Fri, 7 Feb 2025 22:28:26 +0300
Subject: [PATCH 4/5] wineboot: Generate better DigitalProductId.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 programs/wineboot/wineboot.c | 46 ++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 7a428479959..682614b28ed 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -79,6 +79,8 @@
 #include <setupapi.h>
 #include <wininet.h>
 #include <newdev.h>
+#include <wincrypt.h>
+#include "ntsecapi.h"
 #include "resource.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(wineboot);
@@ -1958,6 +1960,49 @@ static void usage( int status )
     exit( status );
 }
 
+static void create_digitalproductid(void)
+{
+    BYTE digital_product_id[0xa4];
+    char product_id[256];
+    LSTATUS status;
+    unsigned int i;
+    DWORD size;
+    DWORD type;
+    HKEY key;
+    if ((status = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion",
+                       0, KEY_ALL_ACCESS, &key )))
+        return;
+    size = sizeof(product_id);
+    status = RegQueryValueExA( key, "ProductId", NULL, &type, (BYTE *)product_id, &size );
+    if (status) goto done;
+    if (!size) goto done;
+    if (product_id[size - 1])
+    {
+        if (size == sizeof(product_id)) goto done;
+        product_id[size++] = 0;
+    }
+    if (!RegQueryValueExA( key, "DigitalProductId", NULL, &type, NULL, &size ) && size == sizeof(digital_product_id))
+    {
+        if (RegQueryValueExA( key, "DigitalProductId", NULL, &type, digital_product_id, &size ))
+            goto done;
+        for (i = 0; i < size; ++i)
+            if (digital_product_id[i]) break;
+        if (i < size) goto done;
+    }
+    memset( digital_product_id, 0, sizeof(digital_product_id) );
+    *(DWORD *)digital_product_id = sizeof(digital_product_id);
+    digital_product_id[4] = 3;
+    strcpy( (char *)digital_product_id + 8, product_id );
+    *(DWORD *)(digital_product_id + 0x20) = 0x0cec;
+    *(DWORD *)(digital_product_id + 0x34) = 0x0cec;
+    strcpy( (char *)digital_product_id + 0x24, "[TH] X19-99481" );
+    digital_product_id[0x42] = 8;
+    RtlGenRandom( digital_product_id + 0x38, 0x18 );
+    RegSetValueExA( key, "DigitalProductId", 0, REG_BINARY, digital_product_id, sizeof(digital_product_id) );
+done:
+    RegCloseKey( key );
+}
+
 int __cdecl main( int argc, char *argv[] )
 {
     /* First, set the current directory to SystemRoot */
@@ -2067,6 +2112,7 @@ int __cdecl main( int argc, char *argv[] )
     }
     if (init || update) update_wineprefix( update );
 
+    create_digitalproductid();
     create_volatile_environment_registry_key();
     create_proxy_settings();
 
-- 
2.48.1

07070100B69339000081A4000003E8000003E80000000168AA560300001188000001030000000200000000000000000000004300000000patches/winex11.drv-Recognize-the-keyboard-in-a-locale-indep.patchFrom 4023d07595072cc6f78f87d1c1c22eaaab910216 Mon Sep 17 00:00:00 2001
From: Giovanni Mascellani <gmascellani@codeweavers.com>
Date: Mon, 7 Dec 2020 09:31:52 +0100
Subject: [PATCH] winex11.drv: Recognize the keyboard in a locale-independent
 way.

Try to recognize the keyboard comparing keysyms instead of converting
them to multibyte strings, which makes the process locale-dependent and
therefore more fragile.

Unfortunately this means that the layout tables might need to be
updated. However, this change is known to fix the recognitions of a few
keys in the French layout.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=30984
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45605
CW-Bug-Id: #16793
Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/winex11.drv/keyboard.c | 62 +++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 30 deletions(-)

diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 18437c8a7f4..4b0abef9c15 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1500,6 +1500,35 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
     return TRUE;
 }
 
+/* From the point of view of this function there are two types of
+ * keys: those for which the mapping to vkey and scancode depends on
+ * the keyboard layout (i.e., letters, numbers, punctuation) and those
+ * for which it doesn't (control keys); since this function is used to
+ * recognize the keyboard layout and map keysyms to vkeys and
+ * scancodes, we are only concerned about the first type, and map
+ * everything in the second type to zero.
+ */
+static char keysym_to_char( KeySym keysym )
+{
+    /* Dead keys */
+    if (0xfe50 <= keysym && keysym < 0xfed0)
+        return KEYBOARD_MapDeadKeysym( keysym );
+
+    /* Control keys (there is nothing allocated below 0xfc00, but I
+       take some margin in case something is added in the future) */
+    if (0xf000 <= keysym && keysym < 0x10000)
+        return 0;
+
+    /* XFree86 vendor keys */
+    if (0x10000000 <= keysym)
+        return 0;
+
+    /* "Normal" keys: return last octet, because our tables don't have
+       more than that; it would be better to extend the tables and
+       compare the whole keysym, but it's a lot of work... */
+    return keysym & 0xff;
+}
+
 /**********************************************************************
  *		X11DRV_KEYBOARD_DetectLayout
  *
@@ -1530,22 +1559,7 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
       /* get data for keycode from X server */
       for (i = 0; i < syms; i++) {
         if (!(keysym = XkbKeycodeToKeysym( display, keyc, 0, i ))) continue;
-	/* Allow both one-byte and two-byte national keysyms */
-	if ((keysym < 0x8000) && (keysym != ' '))
-        {
-            if (!XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
-            {
-                TRACE("XKB could not translate keysym %04lx\n", keysym);
-                /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
-                 * with appropriate ShiftMask and Mode_switch, use XLookupString
-                 * to get character in the local encoding.
-                 */
-                ckey[keyc][i] = keysym & 0xFF;
-            }
-        }
-	else {
-	  ckey[keyc][i] = KEYBOARD_MapDeadKeysym(keysym);
-	}
+        ckey[keyc][i] = keysym_to_char(keysym);
       }
   }
 
@@ -1721,20 +1735,8 @@ void X11DRV_InitKeyboard( Display *display )
 	      /* we seem to need to search the layout-dependent scancodes */
 	      int maxlen=0,maxval=-1,ok;
 	      for (i=0; i<syms; i++) {
-		keysym = XkbKeycodeToKeysym( display, keyc, 0, i );
-		if ((keysym<0x8000) && (keysym!=' '))
-                {
-                    if (!XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
-                    {
-                        /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
-                         * with appropriate ShiftMask and Mode_switch, use XLookupString
-                         * to get character in the local encoding.
-                         */
-                        ckey[i] = (keysym <= 0x7F) ? keysym : 0;
-                    }
-		} else {
-		  ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
-		}
+    keysym = XkbKeycodeToKeysym( display, keyc, 0, i );
+                ckey[i] = keysym_to_char(keysym);
 	      }
 	      /* find key with longest match streak */
 	      for (keyn=0; keyn<MAIN_LEN; keyn++) {
-- 
2.48.1

07070100B6933A000081A4000003E8000003E80000000168AA560300000C13000001030000000200000000000000000000004800000000patches/0003-wineboot-On-prefix-upgrade-update-win10-build-number.patchFrom 8e7dd70648183eef1e6e089ea36ad7f869a15b84 Mon Sep 17 00:00:00 2001
From: Andrew Eikum <aeikum@codeweavers.com>
Date: Fri, 7 Feb 2025 22:27:12 +0300
Subject: [PATCH 3/5] wineboot: On prefix upgrade, update win10 build number

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 programs/wineboot/wineboot.c | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 698648548a1..7a428479959 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -1761,6 +1761,43 @@ static void update_user_profile(void)
     LocalFree(sid);
 }
 
+static void update_win_version(void)
+{
+    static const WCHAR win10_buildW[] = L"19045";
+    static const WCHAR win10_ntW[] = L"6.3";
+    HKEY cv_h;
+    DWORD type, sz;
+    WCHAR current_version[256];
+    if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion",
+                0, KEY_ALL_ACCESS, &cv_h) == ERROR_SUCCESS){
+        /* get the current windows version */
+        sz = sizeof(current_version);
+        if(RegQueryValueExW(cv_h, L"CurrentVersion", NULL, &type, (BYTE *)current_version, &sz) == ERROR_SUCCESS &&
+                type == REG_SZ){
+            if(!wcscmp(current_version, L"6.3") || !wcscmp(current_version, L"10.0")){
+                RegSetValueExW(cv_h, L"CurrentVersion", 0, REG_SZ, (const BYTE *)win10_ntW, sizeof(win10_ntW));
+                RegSetValueExW(cv_h, L"CurrentBuild", 0, REG_SZ, (const BYTE *)win10_buildW, sizeof(win10_buildW));
+                RegSetValueExW(cv_h, L"CurrentBuildNumber", 0, REG_SZ, (const BYTE *)win10_buildW, sizeof(win10_buildW));
+            }
+        }
+        RegCloseKey(cv_h);
+    }
+    if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion",
+                0, KEY_ALL_ACCESS, &cv_h) == ERROR_SUCCESS){
+        /* get the current windows version */
+        sz = sizeof(current_version);
+        if(RegQueryValueExW(cv_h, L"CurrentVersion", NULL, &type, (BYTE *)current_version, &sz) == ERROR_SUCCESS &&
+                type == REG_SZ){
+            if(!wcscmp(current_version, L"6.3") || !wcscmp(current_version, L"10.0")){
+                RegSetValueExW(cv_h, L"CurrentVersion", 0, REG_SZ, (const BYTE *)win10_ntW, sizeof(win10_ntW));
+                RegSetValueExW(cv_h, L"CurrentBuild", 0, REG_SZ, (const BYTE *)win10_buildW, sizeof(win10_buildW));
+                RegSetValueExW(cv_h, L"CurrentBuildNumber", 0, REG_SZ, (const BYTE *)win10_buildW, sizeof(win10_buildW));
+            }
+        }
+        RegCloseKey(cv_h);
+    }
+}
+
 /* execute rundll32 on the wine.inf file if necessary */
 static void update_wineprefix( BOOL force )
 {
@@ -1819,6 +1856,7 @@ static void update_wineprefix( BOOL force )
         }
         install_root_pnp_devices();
         update_user_profile();
+        update_win_version();
 
         TRACE( "wine: configuration in %s has been updated.\n", debugstr_w(prettyprint_configdir()) );
     }
-- 
2.48.1

07070100B6933B000081A4000003E8000003E80000000168AA5603000001FF000001030000000200000000000000000000004100000000patches/kernelbase-Fix-uninitialized-structs-in-OpenThread.patchdiff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index bc8210bd43a..c3b3f020ad6 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -344,6 +344,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH OpenThread( DWORD access, BOOL inherit, DWORD id
     OBJECT_ATTRIBUTES attr;
     CLIENT_ID cid;
 
+    memset(&attr, 0, sizeof(attr));
     InitializeObjectAttributes( &attr, NULL, inherit ? OBJ_INHERIT : 0, 0, NULL );
     cid.UniqueProcess = 0;
     cid.UniqueThread = ULongToHandle( id );
07070100B6933C000081A4000003E8000003E80000000168AA56030000074B000001030000000200000000000000000000004400000000patches/0005-wineboot-Load-root-certificates-on-prefix-update.patchFrom 4a154c6dda5dae012871d4487ceb18de95090052 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Fri, 7 Feb 2025 22:29:49 +0300
Subject: [PATCH 5/5] wineboot: Load root certificates on prefix update.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 programs/wineboot/Makefile.in | 2 +-
 programs/wineboot/wineboot.c  | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in
index d346b8984b1..9eaa95c9ad5 100644
--- a/programs/wineboot/Makefile.in
+++ b/programs/wineboot/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = wineboot.exe
 IMPORTS   = uuid advapi32 ws2_32 kernelbase
-DELAYIMPORTS = shell32 shlwapi version user32 gdi32 setupapi newdev wininet
+DELAYIMPORTS = shell32 shlwapi version user32 gdi32 setupapi newdev wininet crypt32
 
 EXTRADLLFLAGS = -mconsole
 
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index cb036c9853a..b8171a973f9 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -1798,6 +1798,14 @@ static void update_win_version(void)
     }
 }
 
+static void update_root_certs(void)
+{
+    HCERTSTORE store;
+    store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG
+                           | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root");
+    CertCloseStore( store, 0 );
+}
+
 /* execute rundll32 on the wine.inf file if necessary */
 static void update_wineprefix( BOOL force )
 {
@@ -1857,6 +1865,7 @@ static void update_wineprefix( BOOL force )
         install_root_pnp_devices();
         update_user_profile();
         update_win_version();
+        update_root_certs();
 
         TRACE( "wine: configuration in %s has been updated.\n", debugstr_w(prettyprint_configdir()) );
     }
-- 
2.48.1

07070100B6933D000081A4000003E8000003E80000000168AA5603000671BC000001030000000200000000000000000000002300000000patches/ntsync-10.13-staging.patchFrom 494478eea1899f8b6224d0213d3bae5d9dd4fc36 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:07 +0300
Subject: [PATCH 01/57] Revert "server: Keep owned mutex syncs alive until
 abandoned."

This reverts commit 934514db7c2d080672f9db56212afe5550928af2.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/kernel32/tests/sync.c | 27 ++-------------------------
 server/mutex.c             |  5 ++---
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index 49f5002f651..5023b9540e5 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -230,35 +230,12 @@ static void test_temporary_objects(void)
     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
 }
 
-struct test_mutex_thread_params
-{
-    HANDLE mutex;
-    HANDLE start_event;
-    HANDLE stop_event;
-    BOOL owner;
-};
-
-static DWORD WINAPI test_mutex_thread(void *arg)
-{
-    struct test_mutex_thread_params *params = arg;
-    DWORD ret;
-
-    ret = WaitForSingleObject(params->mutex, INFINITE);
-    if (params->owner) ok(!ret, "got %#lx\n", ret);
-    else ok(ret == WAIT_ABANDONED, "got %#lx\n", ret);
-    SetEvent(params->start_event);
-
-    ret = WaitForSingleObject(params->stop_event, INFINITE);
-    ok(!ret, "got %#lx\n", ret);
-    return 0;
-}
-
 static void test_mutex(void)
 {
     DWORD wait_ret;
     BOOL ret;
-    HANDLE hCreated, hOpened, owner_thread, waiter_thread;
-    struct test_mutex_thread_params params;
+    HANDLE hCreated;
+    HANDLE hOpened;
     int i;
     DWORD failed = 0;
 
diff --git a/server/mutex.c b/server/mutex.c
index e370d301472..573fcda1083 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -97,7 +97,6 @@ static void do_grab( struct mutex_sync *mutex, struct thread *thread )
     if (!mutex->count++)  /* FIXME: avoid wrap-around */
     {
         assert( !mutex->owner );
-        grab_object( mutex );
         mutex->owner = thread;
         list_add_head( &thread->mutex_list, &mutex->entry );
     }
@@ -117,7 +116,6 @@ static int do_release( struct mutex_sync *mutex, struct thread *thread, int coun
         list_remove( &mutex->entry );
         mutex->owner = NULL;
         wake_up( &mutex->obj, 0 );
-        release_object( mutex );
     }
     return 1;
 }
@@ -133,7 +131,8 @@ static void mutex_sync_destroy( struct object *obj )
 {
     struct mutex_sync *mutex = (struct mutex_sync *)obj;
     assert( obj->ops == &mutex_sync_ops );
-    assert( !mutex->count );
+
+    if (mutex->count) do_release( mutex, current, mutex->count );
 }
 
 static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry )
-- 
2.50.1


From 979aefdc5bf5b0f033f83b1d28cb14ef0728e745 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:24 +0300
Subject: [PATCH 02/57] Revert "server: Use a signaled flag for message queue
 sync."

This reverts commit 991bf42f1052db41bb9b2e178b8af7a51be95ca7.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/queue.c | 62 +++++++++++++++++++++++---------------------------
 1 file changed, 29 insertions(+), 33 deletions(-)

diff --git a/server/queue.c b/server/queue.c
index 18fe5bee82d..523733e7e9b 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -116,7 +116,6 @@ struct msg_queue
 {
     struct object          obj;             /* object header */
     struct fd             *fd;              /* optional file descriptor to poll */
-    int                    signaled;        /* queue is signaled from fd POLLIN or masks */
     int                    paint_count;     /* pending paint messages count */
     int                    hotkey_count;    /* pending hotkey messages count */
     int                    quit_message;    /* is there a pending quit message? */
@@ -307,7 +306,6 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
     if ((queue = alloc_object( &msg_queue_ops )))
     {
         queue->fd              = NULL;
-        queue->signaled        = 0;
         queue->paint_count     = 0;
         queue->hotkey_count    = 0;
         queue->quit_message    = 0;
@@ -711,18 +709,6 @@ void add_queue_hook_count( struct thread *thread, unsigned int index, int count
     assert( thread->queue->shared->hooks_count[index] >= 0 );
 }
 
-static void signal_queue_sync( struct msg_queue *queue )
-{
-    if (queue->signaled) return;
-    queue->signaled = 1;
-    wake_up( &queue->obj, 0 );
-}
-
-static void reset_queue_sync( struct msg_queue *queue )
-{
-    queue->signaled = 0;
-}
-
 /* check the queue status */
 static inline int is_signaled( struct msg_queue *queue )
 {
@@ -749,7 +735,7 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
     }
     SHARED_WRITE_END;
 
-    if (is_signaled( queue )) signal_queue_sync( queue );
+    if (is_signaled( queue )) wake_up( &queue->obj, 0 );
 }
 
 /* clear some queue bits */
@@ -769,7 +755,6 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
         if (queue->keystate_lock) unlock_input_keystate( queue->input );
         queue->keystate_lock = 0;
     }
-    if (!is_signaled( queue )) reset_queue_sync( queue );
 }
 
 /* check if message is matched by the filter */
@@ -1302,11 +1287,7 @@ static int msg_queue_select( struct msg_queue *queue, int events )
     }
     queue->waiting = !!events;
 
-    if (queue->fd)
-    {
-        if (events && check_fd_events( queue->fd, POLLIN )) signal_queue_sync( queue );
-        else set_fd_events( queue->fd, events );
-    }
+    if (queue->fd) set_fd_events( queue->fd, events );
     return 1;
 }
 
@@ -1345,8 +1326,18 @@ static void msg_queue_dump( struct object *obj, int verbose )
 static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct msg_queue *queue = (struct msg_queue *)obj;
-    assert( obj->ops == &msg_queue_ops );
-    return queue->signaled;
+    int ret = 0;
+
+    if (queue->fd)
+    {
+        if ((ret = check_fd_events( queue->fd, POLLIN )))
+            /* stop waiting on select() if we are signaled */
+            set_fd_events( queue->fd, 0 );
+        else if (queue->waiting)
+            /* restart waiting on poll() if we are no longer signaled */
+            set_fd_events( queue->fd, POLLIN );
+    }
+    return ret || is_signaled( queue );
 }
 
 static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry )
@@ -1360,7 +1351,6 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en
         shared->changed_mask = 0;
     }
     SHARED_WRITE_END;
-    reset_queue_sync( queue );
 }
 
 static void msg_queue_destroy( struct object *obj )
@@ -1415,7 +1405,7 @@ static void msg_queue_poll_event( struct fd *fd, int event )
 
     if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
     else set_fd_events( queue->fd, 0 );
-    signal_queue_sync( queue );
+    wake_up( &queue->obj, 0 );
 }
 
 static void thread_input_dump( struct object *obj, int verbose )
@@ -3188,9 +3178,20 @@ DECL_HANDLER(set_queue_mask)
         reply->wake_bits    = queue_shm->wake_bits;
         reply->changed_bits = queue_shm->changed_bits;
 
-        if (!is_signaled( queue )) reset_queue_sync( queue );
-        else if (!req->skip_wait) signal_queue_sync( queue );
-        else msg_queue_satisfied( &queue->obj, NULL );
+        if (is_signaled( queue ))
+        {
+            /* if skip wait is set, do what would have been done in the subsequent wait */
+            if (req->skip_wait)
+            {
+                SHARED_WRITE_BEGIN( queue_shm, queue_shm_t )
+                {
+                    shared->wake_mask = 0;
+                    shared->changed_mask = 0;
+                }
+                SHARED_WRITE_END;
+            }
+            else wake_up( &queue->obj, 0 );
+        }
     }
 }
 
@@ -3211,8 +3212,6 @@ DECL_HANDLER(get_queue_status)
             shared->changed_bits &= ~req->clear_bits;
         }
         SHARED_WRITE_END;
-
-        if (!is_signaled( queue )) reset_queue_sync( queue );
     }
     else reply->wake_bits = reply->changed_bits = 0;
 }
@@ -3411,8 +3410,6 @@ DECL_HANDLER(get_message)
     }
     SHARED_WRITE_END;
 
-    if (!is_signaled( queue )) reset_queue_sync( queue );
-
     /* then check for posted messages */
     if ((filter & QS_POSTMESSAGE) &&
         get_posted_message( queue, queue->ignore_post_msg, get_win, req->get_first, req->get_last, req->flags, reply ))
@@ -3482,7 +3479,6 @@ DECL_HANDLER(get_message)
     }
     SHARED_WRITE_END;
 
-    reset_queue_sync( queue );
     set_error( STATUS_PENDING );  /* FIXME */
     return;
 
-- 
2.50.1


From 4a1c2a26c070c196d82bd2857f38787b2715d1b8 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:30 +0300
Subject: [PATCH 03/57] Revert "server: Use a flag to keep track of message
 queue waits."

This reverts commit 1f033324c34021fc594d7886c6d92262adcf816a.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/queue.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/server/queue.c b/server/queue.c
index 523733e7e9b..4b8fdf677fd 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -133,7 +133,6 @@ struct msg_queue
     struct hook_table     *hooks;           /* hook table */
     timeout_t              last_get_msg;    /* time of last get message call */
     int                    keystate_lock;   /* owns an input keystate lock */
-    int                    waiting;         /* is thread waiting on queue */
     queue_shm_t           *shared;          /* queue in session shared memory */
     unsigned int           ignore_post_msg; /* ignore post messages newer than this unique id */
 };
@@ -318,7 +317,6 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
         queue->last_get_msg    = current_time;
         queue->keystate_lock   = 0;
         queue->ignore_post_msg = 0;
-        queue->waiting         = 0;
         list_init( &queue->send_result );
         list_init( &queue->callback_result );
         list_init( &queue->pending_timers );
@@ -1273,21 +1271,16 @@ static void cleanup_results( struct msg_queue *queue )
 /* check if the thread owning the queue is hung (not checking for messages) */
 static int is_queue_hung( struct msg_queue *queue )
 {
+    struct wait_queue_entry *entry;
+
     if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC)
         return 0;  /* less than 5 seconds since last get message -> not hung */
-    return !queue->waiting;
-}
 
-static int msg_queue_select( struct msg_queue *queue, int events )
-{
-    if (queue->waiting == !!events)
+    LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry )
     {
-        set_error( STATUS_ACCESS_DENIED );
-        return 0;
+        if (get_wait_queue_thread(entry)->queue == queue)
+            return 0;  /* thread is waiting on queue -> not hung */
     }
-    queue->waiting = !!events;
-
-    if (queue->fd) set_fd_events( queue->fd, events );
     return 1;
 }
 
@@ -1302,7 +1295,8 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
         return 0;
     }
 
-    if (!msg_queue_select( queue, POLLIN )) return 0;
+    if (queue->fd && list_empty( &obj->wait_queue ))  /* first on the queue */
+        set_fd_events( queue->fd, POLLIN );
     add_queue( obj, entry );
     return 1;
 }
@@ -1312,7 +1306,8 @@ static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *
     struct msg_queue *queue = (struct msg_queue *)obj;
 
     remove_queue( obj, entry );
-    msg_queue_select( queue, 0 );
+    if (queue->fd && list_empty( &obj->wait_queue ))  /* last on the queue is gone */
+        set_fd_events( queue->fd, 0 );
 }
 
 static void msg_queue_dump( struct object *obj, int verbose )
@@ -1333,7 +1328,7 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr
         if ((ret = check_fd_events( queue->fd, POLLIN )))
             /* stop waiting on select() if we are signaled */
             set_fd_events( queue->fd, 0 );
-        else if (queue->waiting)
+        else if (!list_empty( &obj->wait_queue ))
             /* restart waiting on poll() if we are no longer signaled */
             set_fd_events( queue->fd, POLLIN );
     }
-- 
2.50.1


From ef5d1db29f0b86a0b9ec91833a11c7500c196730 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:36 +0300
Subject: [PATCH 04/57] Revert "server: Split semaphore to a dedicated sync
 object."

This reverts commit 9e05682f68fe20fb4df029ae39ecace786b3571a.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/semaphore.c | 172 ++++++++++++++-------------------------------
 1 file changed, 51 insertions(+), 121 deletions(-)

diff --git a/server/semaphore.c b/server/semaphore.c
index 4b31bfe806c..304a821bcec 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -50,119 +50,30 @@ struct type_descr semaphore_type =
     },
 };
 
-struct semaphore_sync
-{
-    struct object       obj;                /* object header */
-    unsigned int        count;              /* current count */
-    unsigned int        max;                /* maximum possible count */
-};
-
-static void semaphore_sync_dump( struct object *obj, int verbose );
-static int semaphore_sync_signaled( struct object *obj, struct wait_queue_entry *entry );
-static void semaphore_sync_satisfied( struct object *obj, struct wait_queue_entry *entry );
-
-static const struct object_ops semaphore_sync_ops =
-{
-    sizeof(struct semaphore_sync), /* size */
-    &no_type,                      /* type */
-    semaphore_sync_dump,           /* dump */
-    add_queue,                     /* add_queue */
-    remove_queue,                  /* remove_queue */
-    semaphore_sync_signaled,       /* signaled */
-    semaphore_sync_satisfied,      /* satisfied */
-    no_signal,                     /* signal */
-    no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
-    default_map_access,            /* map_access */
-    default_get_sd,                /* get_sd */
-    default_set_sd,                /* set_sd */
-    default_get_full_name,         /* get_full_name */
-    no_lookup_name,                /* lookup_name */
-    directory_link_name,           /* link_name */
-    default_unlink_name,           /* unlink_name */
-    no_open_file,                  /* open_file */
-    no_kernel_obj_list,            /* get_kernel_obj_list */
-    no_close_handle,               /* close_handle */
-    no_destroy                     /* destroy */
-};
-
-static int release_semaphore( struct semaphore_sync *sem, unsigned int count,
-                              unsigned int *prev )
-{
-    if (prev) *prev = sem->count;
-    if (sem->count + count < sem->count || sem->count + count > sem->max)
-    {
-        set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
-        return 0;
-    }
-    else if (sem->count)
-    {
-        /* there cannot be any thread to wake up if the count is != 0 */
-        sem->count += count;
-    }
-    else
-    {
-        sem->count = count;
-        wake_up( &sem->obj, count );
-    }
-    return 1;
-}
-
-static void semaphore_sync_dump( struct object *obj, int verbose )
-{
-    struct semaphore_sync *sem = (struct semaphore_sync *)obj;
-    assert( obj->ops == &semaphore_sync_ops );
-    fprintf( stderr, "Semaphore count=%d max=%d\n", sem->count, sem->max );
-}
-
-static int semaphore_sync_signaled( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct semaphore_sync *sem = (struct semaphore_sync *)obj;
-    assert( obj->ops == &semaphore_sync_ops );
-    return (sem->count > 0);
-}
-
-static void semaphore_sync_satisfied( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct semaphore_sync *sem = (struct semaphore_sync *)obj;
-    assert( obj->ops == &semaphore_sync_ops );
-    assert( sem->count );
-    sem->count--;
-}
-
-static struct semaphore_sync *create_semaphore_sync( unsigned int initial, unsigned int max )
-{
-    struct semaphore_sync *sem;
-
-    if (!(sem = alloc_object( &semaphore_sync_ops ))) return NULL;
-    sem->count = initial;
-    sem->max   = max;
-    return sem;
-}
-
 struct semaphore
 {
-    struct object          obj;    /* object header */
-    struct semaphore_sync *sync;   /* semaphore sync object */
+    struct object  obj;    /* object header */
+    unsigned int   count;  /* current count */
+    unsigned int   max;    /* maximum possible count */
 };
 
 static void semaphore_dump( struct object *obj, int verbose );
-static struct object *semaphore_get_sync( struct object *obj );
+static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry );
+static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static int semaphore_signal( struct object *obj, unsigned int access );
-static void semaphore_destroy( struct object *obj );
 
 static const struct object_ops semaphore_ops =
 {
     sizeof(struct semaphore),      /* size */
     &semaphore_type,               /* type */
     semaphore_dump,                /* dump */
-    NULL,                          /* add_queue */
-    NULL,                          /* remove_queue */
-    NULL,                          /* signaled */
-    NULL,                          /* satisfied */
+    add_queue,                     /* add_queue */
+    remove_queue,                  /* remove_queue */
+    semaphore_signaled,            /* signaled */
+    semaphore_satisfied,           /* satisfied */
     semaphore_signal,              /* signal */
     no_get_fd,                     /* get_fd */
-    semaphore_get_sync,            /* get_sync */
+    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -173,9 +84,10 @@ static const struct object_ops semaphore_ops =
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
     no_close_handle,               /* close_handle */
-    semaphore_destroy,             /* destroy */
+    no_destroy                     /* destroy */
 };
 
+
 static struct semaphore *create_semaphore( struct object *root, const struct unicode_str *name,
                                            unsigned int attr, unsigned int initial, unsigned int max,
                                            const struct security_descriptor *sd )
@@ -192,30 +104,55 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            sem->sync = NULL;
-
-            if (!(sem->sync = create_semaphore_sync( initial, max )))
-            {
-                release_object( sem );
-                return NULL;
-            }
+            sem->count = initial;
+            sem->max   = max;
         }
     }
     return sem;
 }
 
+static int release_semaphore( struct semaphore *sem, unsigned int count,
+                              unsigned int *prev )
+{
+    if (prev) *prev = sem->count;
+    if (sem->count + count < sem->count || sem->count + count > sem->max)
+    {
+        set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
+        return 0;
+    }
+    else if (sem->count)
+    {
+        /* there cannot be any thread to wake up if the count is != 0 */
+        sem->count += count;
+    }
+    else
+    {
+        sem->count = count;
+        wake_up( &sem->obj, count );
+    }
+    return 1;
+}
+
 static void semaphore_dump( struct object *obj, int verbose )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
-    sem->sync->obj.ops->dump( &sem->sync->obj, verbose );
+    fprintf( stderr, "Semaphore count=%d max=%d\n", sem->count, sem->max );
 }
 
-static struct object *semaphore_get_sync( struct object *obj )
+static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
-    return grab_object( sem->sync );
+    return (sem->count > 0);
+}
+
+static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct semaphore *sem = (struct semaphore *)obj;
+    assert( obj->ops == &semaphore_ops );
+    assert( sem->count );
+    sem->count--;
 }
 
 static int semaphore_signal( struct object *obj, unsigned int access )
@@ -228,14 +165,7 @@ static int semaphore_signal( struct object *obj, unsigned int access )
         set_error( STATUS_ACCESS_DENIED );
         return 0;
     }
-    return release_semaphore( sem->sync, 1, NULL );
-}
-
-static void semaphore_destroy( struct object *obj )
-{
-    struct semaphore *sem = (struct semaphore *)obj;
-    assert( obj->ops == &semaphore_ops );
-    if (sem->sync) release_object( sem->sync );
+    return release_semaphore( sem, 1, NULL );
 }
 
 /* create a semaphore */
@@ -279,7 +209,7 @@ DECL_HANDLER(release_semaphore)
     if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle,
                                                    SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
     {
-        release_semaphore( sem->sync, req->count, &reply->prev_count );
+        release_semaphore( sem, req->count, &reply->prev_count );
         release_object( sem );
     }
 }
@@ -292,8 +222,8 @@ DECL_HANDLER(query_semaphore)
     if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle,
                                                    SEMAPHORE_QUERY_STATE, &semaphore_ops )))
     {
-        reply->current = sem->sync->count;
-        reply->max = sem->sync->max;
+        reply->current = sem->count;
+        reply->max = sem->max;
         release_object( sem );
     }
 }
-- 
2.50.1


From 318f661c117daee8897bf46d066c99e1febba196 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:42 +0300
Subject: [PATCH 05/57] Revert "server: Split mutex to a dedicated sync
 object."

This reverts commit 672c3a561f5cd1cd6937c702fe2fe05397f41375.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/mutex.c | 166 ++++++++++++++-----------------------------------
 1 file changed, 47 insertions(+), 119 deletions(-)

diff --git a/server/mutex.c b/server/mutex.c
index 573fcda1083..90cc594c741 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -50,30 +50,31 @@ struct type_descr mutex_type =
     },
 };
 
-struct mutex_sync
+struct mutex
 {
-    struct object       obj;                /* object header */
-    struct thread      *owner;              /* mutex owner */
-    unsigned int        count;              /* recursion count */
-    int                 abandoned;          /* has it been abandoned? */
-    struct list         entry;              /* entry in owner thread mutex list */
+    struct object  obj;             /* object header */
+    struct thread *owner;           /* mutex owner */
+    unsigned int   count;           /* recursion count */
+    int            abandoned;       /* has it been abandoned? */
+    struct list    entry;           /* entry in owner thread mutex list */
 };
 
-static void mutex_sync_dump( struct object *obj, int verbose );
-static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry );
-static void mutex_sync_satisfied( struct object *obj, struct wait_queue_entry *entry );
-static void mutex_sync_destroy( struct object *obj );
+static void mutex_dump( struct object *obj, int verbose );
+static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry );
+static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry );
+static void mutex_destroy( struct object *obj );
+static int mutex_signal( struct object *obj, unsigned int access );
 
-static const struct object_ops mutex_sync_ops =
+static const struct object_ops mutex_ops =
 {
-    sizeof(struct mutex_sync), /* size */
-    &no_type,                  /* type */
-    mutex_sync_dump,           /* dump */
+    sizeof(struct mutex),      /* size */
+    &mutex_type,               /* type */
+    mutex_dump,                /* dump */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
-    mutex_sync_signaled,       /* signaled */
-    mutex_sync_satisfied,      /* satisfied */
-    no_signal,                 /* signal */
+    mutex_signaled,            /* signaled */
+    mutex_satisfied,           /* satisfied */
+    mutex_signal,              /* signal */
     no_get_fd,                 /* get_fd */
     default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
@@ -86,11 +87,12 @@ static const struct object_ops mutex_sync_ops =
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
     no_close_handle,           /* close_handle */
-    mutex_sync_destroy,        /* destroy */
+    mutex_destroy              /* destroy */
 };
 
+
 /* grab a mutex for a given thread */
-static void do_grab( struct mutex_sync *mutex, struct thread *thread )
+static void do_grab( struct mutex *mutex, struct thread *thread )
 {
     assert( !mutex->count || (mutex->owner == thread) );
 
@@ -103,7 +105,7 @@ static void do_grab( struct mutex_sync *mutex, struct thread *thread )
 }
 
 /* release a mutex once the recursion count is 0 */
-static int do_release( struct mutex_sync *mutex, struct thread *thread, int count )
+static int do_release( struct mutex *mutex, struct thread *thread, int count )
 {
     if (!mutex->count || (mutex->owner != thread))
     {
@@ -120,87 +122,6 @@ static int do_release( struct mutex_sync *mutex, struct thread *thread, int coun
     return 1;
 }
 
-static void mutex_sync_dump( struct object *obj, int verbose )
-{
-    struct mutex_sync *mutex = (struct mutex_sync *)obj;
-    assert( obj->ops == &mutex_sync_ops );
-    fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
-}
-
-static void mutex_sync_destroy( struct object *obj )
-{
-    struct mutex_sync *mutex = (struct mutex_sync *)obj;
-    assert( obj->ops == &mutex_sync_ops );
-
-    if (mutex->count) do_release( mutex, current, mutex->count );
-}
-
-static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct mutex_sync *mutex = (struct mutex_sync *)obj;
-    assert( obj->ops == &mutex_sync_ops );
-    return (!mutex->count || (mutex->owner == get_wait_queue_thread( entry )));
-}
-
-static void mutex_sync_satisfied( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct mutex_sync *mutex = (struct mutex_sync *)obj;
-    assert( obj->ops == &mutex_sync_ops );
-
-    do_grab( mutex, get_wait_queue_thread( entry ));
-    if (mutex->abandoned) make_wait_abandoned( entry );
-    mutex->abandoned = 0;
-}
-
-static struct mutex_sync *create_mutex_sync( int owned )
-{
-    struct mutex_sync *mutex;
-
-    if (!(mutex = alloc_object( &mutex_sync_ops ))) return NULL;
-    mutex->count = 0;
-    mutex->owner = NULL;
-    mutex->abandoned = 0;
-    if (owned) do_grab( mutex, current );
-
-    return mutex;
-}
-
-struct mutex
-{
-    struct object       obj;             /* object header */
-    struct mutex_sync  *sync;            /* mutex sync object */
-};
-
-static void mutex_dump( struct object *obj, int verbose );
-static struct object *mutex_get_sync( struct object *obj );
-static int mutex_signal( struct object *obj, unsigned int access );
-static void mutex_destroy( struct object *obj );
-
-static const struct object_ops mutex_ops =
-{
-    sizeof(struct mutex),      /* size */
-    &mutex_type,               /* type */
-    mutex_dump,                /* dump */
-    NULL,                      /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
-    mutex_signal,              /* signal */
-    no_get_fd,                 /* get_fd */
-    mutex_get_sync,            /* get_sync */
-    default_map_access,        /* map_access */
-    default_get_sd,            /* get_sd */
-    default_set_sd,            /* set_sd */
-    default_get_full_name,     /* get_full_name */
-    no_lookup_name,            /* lookup_name */
-    directory_link_name,       /* link_name */
-    default_unlink_name,       /* unlink_name */
-    no_open_file,              /* open_file */
-    no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_close_handle,           /* close_handle */
-    mutex_destroy,             /* destroy */
-};
-
 static struct mutex *create_mutex( struct object *root, const struct unicode_str *name,
                                    unsigned int attr, int owned, const struct security_descriptor *sd )
 {
@@ -211,13 +132,10 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            mutex->sync = NULL;
-
-            if (!(mutex->sync = create_mutex_sync( owned )))
-            {
-                release_object( mutex );
-                return NULL;
-            }
+            mutex->count = 0;
+            mutex->owner = NULL;
+            mutex->abandoned = 0;
+            if (owned) do_grab( mutex, current );
         }
     }
     return mutex;
@@ -229,7 +147,7 @@ void abandon_mutexes( struct thread *thread )
 
     while ((ptr = list_head( &thread->mutex_list )) != NULL)
     {
-        struct mutex_sync *mutex = LIST_ENTRY( ptr, struct mutex_sync, entry );
+        struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry );
         assert( mutex->owner == thread );
         mutex->abandoned = 1;
         do_release( mutex, thread, mutex->count );
@@ -240,14 +158,24 @@ static void mutex_dump( struct object *obj, int verbose )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    mutex->sync->obj.ops->dump( &mutex->sync->obj, verbose );
+    fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
 }
 
-static struct object *mutex_get_sync( struct object *obj )
+static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    return grab_object( mutex->sync );
+    return (!mutex->count || (mutex->owner == get_wait_queue_thread( entry )));
+}
+
+static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct mutex *mutex = (struct mutex *)obj;
+    assert( obj->ops == &mutex_ops );
+
+    do_grab( mutex, get_wait_queue_thread( entry ));
+    if (mutex->abandoned) make_wait_abandoned( entry );
+    mutex->abandoned = 0;
 }
 
 static int mutex_signal( struct object *obj, unsigned int access )
@@ -260,14 +188,14 @@ static int mutex_signal( struct object *obj, unsigned int access )
         set_error( STATUS_ACCESS_DENIED );
         return 0;
     }
-    return do_release( mutex->sync, current, 1 );
+    return do_release( mutex, current, 1 );
 }
 
 static void mutex_destroy( struct object *obj )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    if (mutex->sync) release_object( mutex->sync );
+    if (mutex->count) do_release( mutex, current, mutex->count );
 }
 
 /* create a mutex */
@@ -311,8 +239,8 @@ DECL_HANDLER(release_mutex)
     if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle,
                                                  0, &mutex_ops )))
     {
-        reply->prev_count = mutex->sync->count;
-        do_release( mutex->sync, current, 1 );
+        reply->prev_count = mutex->count;
+        do_release( mutex, current, 1 );
         release_object( mutex );
     }
 }
@@ -325,9 +253,9 @@ DECL_HANDLER(query_mutex)
     if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle,
                                                  MUTANT_QUERY_STATE, &mutex_ops )))
     {
-        reply->count = mutex->sync->count;
-        reply->owned = (mutex->sync->owner == current);
-        reply->abandoned = mutex->sync->abandoned;
+        reply->count = mutex->count;
+        reply->owned = (mutex->owner == current);
+        reply->abandoned = mutex->abandoned;
 
         release_object( mutex );
     }
-- 
2.50.1


From 29aa3ca8d8db7b6d293d8cd5bd211d15615fa25d Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 15:59:48 +0300
Subject: [PATCH 06/57] Revert "server: Move some checks inside of mutex
 do_release."

This reverts commit e9f795e0663c7761cdbf69dc37b227a6645a3711.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/mutex.c | 44 +++++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/server/mutex.c b/server/mutex.c
index 90cc594c741..4737b6f711b 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -105,21 +105,13 @@ static void do_grab( struct mutex *mutex, struct thread *thread )
 }
 
 /* release a mutex once the recursion count is 0 */
-static int do_release( struct mutex *mutex, struct thread *thread, int count )
+static void do_release( struct mutex *mutex )
 {
-    if (!mutex->count || (mutex->owner != thread))
-    {
-        set_error( STATUS_MUTANT_NOT_OWNED );
-        return 0;
-    }
-    if (!(mutex->count -= count))
-    {
-        /* remove the mutex from the thread list of owned mutexes */
-        list_remove( &mutex->entry );
-        mutex->owner = NULL;
-        wake_up( &mutex->obj, 0 );
-    }
-    return 1;
+    assert( !mutex->count );
+    /* remove the mutex from the thread list of owned mutexes */
+    list_remove( &mutex->entry );
+    mutex->owner = NULL;
+    wake_up( &mutex->obj, 0 );
 }
 
 static struct mutex *create_mutex( struct object *root, const struct unicode_str *name,
@@ -149,8 +141,9 @@ void abandon_mutexes( struct thread *thread )
     {
         struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry );
         assert( mutex->owner == thread );
+        mutex->count = 0;
         mutex->abandoned = 1;
-        do_release( mutex, thread, mutex->count );
+        do_release( mutex );
     }
 }
 
@@ -188,14 +181,23 @@ static int mutex_signal( struct object *obj, unsigned int access )
         set_error( STATUS_ACCESS_DENIED );
         return 0;
     }
-    return do_release( mutex, current, 1 );
+    if (!mutex->count || (mutex->owner != current))
+    {
+        set_error( STATUS_MUTANT_NOT_OWNED );
+        return 0;
+    }
+    if (!--mutex->count) do_release( mutex );
+    return 1;
 }
 
 static void mutex_destroy( struct object *obj )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    if (mutex->count) do_release( mutex, current, mutex->count );
+
+    if (!mutex->count) return;
+    mutex->count = 0;
+    do_release( mutex );
 }
 
 /* create a mutex */
@@ -239,8 +241,12 @@ DECL_HANDLER(release_mutex)
     if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle,
                                                  0, &mutex_ops )))
     {
-        reply->prev_count = mutex->count;
-        do_release( mutex, current, 1 );
+        if (!mutex->count || (mutex->owner != current)) set_error( STATUS_MUTANT_NOT_OWNED );
+        else
+        {
+            reply->prev_count = mutex->count;
+            if (!--mutex->count) do_release( mutex );
+        }
         release_object( mutex );
     }
 }
-- 
2.50.1


From 3526d932262001e27a7849115d8b81931085412c Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:01:41 +0300
Subject: [PATCH 07/57] Revert "server: Get rid of the console signaled flag."

This reverts commit ddc15b268365533cae7cc8108cb7114c00f41657.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/server/console.c b/server/console.c
index f0cb6689d4b..8c9c395ab41 100644
--- a/server/console.c
+++ b/server/console.c
@@ -54,6 +54,7 @@ struct console
 {
     struct object                obj;           /* object header */
     struct event_sync           *sync;          /* sync object for wait/signal */
+    int                          signaled;      /* is console signaled */
     struct thread               *renderer;      /* console renderer thread */
     struct screen_buffer        *active;        /* active screen buffer */
     struct console_server       *server;        /* console server object */
@@ -544,6 +545,7 @@ static struct object *create_console(void)
     if (!(console = alloc_object( &console_ops ))) return NULL;
     console->sync          = NULL;
     console->renderer      = NULL;
+    console->signaled      = 0;
     console->active        = NULL;
     console->server        = NULL;
     console->fd            = NULL;
@@ -1588,8 +1590,16 @@ DECL_HANDLER(get_next_console_request)
 
     if (!server->console->renderer) server->console->renderer = current;
 
-    if (!req->signal) reset_sync( server->console->sync );
-    else signal_sync( server->console->sync );
+    if (!req->signal)
+    {
+        server->console->signaled = 0;
+        reset_sync( server->console->sync );
+    }
+    else if (!server->console->signaled)
+    {
+        server->console->signaled = 1;
+        signal_sync( server->console->sync );
+    }
 
     if (req->read)
     {
-- 
2.50.1


From a27628cae3820cdd7339e6efba6d971fde5489a6 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:01:47 +0300
Subject: [PATCH 08/57] Revert "server: Use the console sync for console output
 objects."

This reverts commit 1154224db42bedbec7b1b14239245d0ce0699d27.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/server/console.c b/server/console.c
index 8c9c395ab41..54cb091d452 100644
--- a/server/console.c
+++ b/server/console.c
@@ -365,15 +365,14 @@ static const struct fd_ops console_input_fd_ops =
 struct console_output
 {
     struct object         obj;         /* object header */
-    struct event_sync    *sync;        /* sync object for wait/signal */
     struct fd            *fd;          /* pseudo-fd */
     struct list           entry;       /* entry in console->outputs */
     struct console       *console;     /* associated console at creation time */
 };
 
 static void console_output_dump( struct object *obj, int verbose );
+static int console_output_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *console_output_get_fd( struct object *obj );
-static struct object *console_output_get_sync( struct object *obj );
 static struct object *console_output_open_file( struct object *obj, unsigned int access,
                                                 unsigned int sharing, unsigned int options );
 static void console_output_destroy( struct object *obj );
@@ -383,13 +382,13 @@ static const struct object_ops console_output_ops =
     sizeof(struct console_output),    /* size */
     &device_type,                     /* type */
     console_output_dump,              /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    console_output_signaled,          /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_output_get_fd,            /* get_fd */
-    console_output_get_sync,          /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -1377,7 +1376,6 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
 
         name->len = 0;
         if (!(console_output = alloc_object( &console_output_ops ))) return NULL;
-        console_output->sync = (struct event_sync *)grab_object( current->process->console->sync );
         console_output->fd = alloc_pseudo_fd( &console_output_fd_ops, &console_output->obj,
                                              FILE_SYNCHRONOUS_IO_NONALERT );
         if (!console_output->fd)
@@ -1511,18 +1509,19 @@ static void console_output_dump( struct object *obj, int verbose )
     fputs( "console Output device\n", stderr );
 }
 
-static struct fd *console_output_get_fd( struct object *obj )
+static int console_output_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct console_output *console_output = (struct console_output *)obj;
     assert( obj->ops == &console_output_ops );
-    return (struct fd *)grab_object( console_output->fd );
+    if (!console_output->console) return 0;
+    return console_output->console->signaled;
 }
 
-static struct object *console_output_get_sync( struct object *obj )
+static struct fd *console_output_get_fd( struct object *obj )
 {
     struct console_output *console_output = (struct console_output *)obj;
     assert( obj->ops == &console_output_ops );
-    return grab_object( console_output->sync );
+    return (struct fd *)grab_object( console_output->fd );
 }
 
 static struct object *console_output_open_file( struct object *obj, unsigned int access,
@@ -1538,7 +1537,6 @@ static void console_output_destroy( struct object *obj )
     assert( obj->ops == &console_output_ops );
     if (console_output->fd) release_object( console_output->fd );
     if (console_output->console) list_remove( &console_output->entry );
-    if (console_output->sync) release_object( console_output->sync );
 }
 
 static void console_output_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
@@ -1576,6 +1574,7 @@ DECL_HANDLER(get_next_console_request)
 {
     struct console_host_ioctl *ioctl = NULL, *next;
     struct console_server *server;
+    struct console_output *output;
     struct iosb *iosb = NULL;
 
     server = (struct console_server *)get_handle_obj( current->process, req->handle, 0, &console_server_ops );
@@ -1599,6 +1598,8 @@ DECL_HANDLER(get_next_console_request)
     {
         server->console->signaled = 1;
         signal_sync( server->console->sync );
+        LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
+            wake_up( &output->obj, 0 );
     }
 
     if (req->read)
-- 
2.50.1


From 36759c9c71f26ab3d031fab1e761347995321fb8 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:01:51 +0300
Subject: [PATCH 09/57] Revert "server: Use the console sync for console input
 objects."

This reverts commit abcf0d172fd930a6cd3596696965cb6fefb71c32.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/server/console.c b/server/console.c
index 54cb091d452..343ccfa7463 100644
--- a/server/console.c
+++ b/server/console.c
@@ -304,17 +304,16 @@ static const struct object_ops console_device_ops =
 struct console_input
 {
     struct object         obj;         /* object header */
-    struct event_sync    *sync;        /* sync object for wait/signal */
     struct fd            *fd;          /* pseudo-fd */
     struct list           entry;       /* entry in console->inputs */
     struct console       *console;     /* associated console at creation time */
 };
 
 static void console_input_dump( struct object *obj, int verbose );
+static int console_input_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct object *console_input_open_file( struct object *obj, unsigned int access,
                                                unsigned int sharing, unsigned int options );
 static struct fd *console_input_get_fd( struct object *obj );
-static struct object *console_input_get_sync( struct object *obj );
 static void console_input_destroy( struct object *obj );
 
 static const struct object_ops console_input_ops =
@@ -322,13 +321,13 @@ static const struct object_ops console_input_ops =
     sizeof(struct console_input),     /* size */
     &device_type,                     /* type */
     console_input_dump,               /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    console_input_signaled,           /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_input_get_fd,             /* get_fd */
-    console_input_get_sync,           /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -1351,7 +1350,6 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
 
         name->len = 0;
         if (!(console_input = alloc_object( &console_input_ops ))) return NULL;
-        console_input->sync = (struct event_sync *)grab_object( current->process->console->sync );
         console_input->fd = alloc_pseudo_fd( &console_input_fd_ops, &console_input->obj,
                                              FILE_SYNCHRONOUS_IO_NONALERT );
         if (!console_input->fd)
@@ -1438,18 +1436,19 @@ static void console_input_dump( struct object *obj, int verbose )
     fputs( "console Input device\n", stderr );
 }
 
-static struct fd *console_input_get_fd( struct object *obj )
+static int console_input_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct console_input *console_input = (struct console_input *)obj;
     assert( obj->ops == &console_input_ops );
-    return (struct fd *)grab_object( console_input->fd );
+    if (!console_input->console) return 0;
+    return console_input->console->signaled;
 }
 
-static struct object *console_input_get_sync( struct object *obj )
+static struct fd *console_input_get_fd( struct object *obj )
 {
     struct console_input *console_input = (struct console_input *)obj;
     assert( obj->ops == &console_input_ops );
-    return grab_object( console_input->sync );
+    return (struct fd *)grab_object( console_input->fd );
 }
 
 static struct object *console_input_open_file( struct object *obj, unsigned int access,
@@ -1465,7 +1464,6 @@ static void console_input_destroy( struct object *obj )
     assert( obj->ops == &console_input_ops );
     if (console_input->fd) release_object( console_input->fd );
     if (console_input->console) list_remove( &console_input->entry );
-    if (console_input->sync) release_object( console_input->sync );
 }
 
 static void console_input_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
@@ -1575,6 +1573,7 @@ DECL_HANDLER(get_next_console_request)
     struct console_host_ioctl *ioctl = NULL, *next;
     struct console_server *server;
     struct console_output *output;
+    struct console_input *input;
     struct iosb *iosb = NULL;
 
     server = (struct console_server *)get_handle_obj( current->process, req->handle, 0, &console_server_ops );
@@ -1598,6 +1597,8 @@ DECL_HANDLER(get_next_console_request)
     {
         server->console->signaled = 1;
         signal_sync( server->console->sync );
+        LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
+            wake_up( &input->obj, 0 );
         LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
             wake_up( &output->obj, 0 );
     }
-- 
2.50.1


From aaf8269b74b29b1105435d48af76c67514292b80 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:01:55 +0300
Subject: [PATCH 10/57] Revert "server: Use the console sync for screen buffers
 objects."

This reverts commit ab6e72ea054df8e2e3917a71521527dd215eab61.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 43 +++++++++++++++++++++----------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/server/console.c b/server/console.c
index 343ccfa7463..6b85ecc8a54 100644
--- a/server/console.c
+++ b/server/console.c
@@ -211,7 +211,6 @@ struct font_info
 struct screen_buffer
 {
     struct object         obj;           /* object header */
-    struct event_sync    *sync;          /* sync object for wait/signal */
     struct list           entry;         /* entry in list of all screen buffers */
     struct console       *input;         /* associated console input */
     unsigned int          id;            /* buffer id */
@@ -221,8 +220,8 @@ struct screen_buffer
 
 static void screen_buffer_dump( struct object *obj, int verbose );
 static void screen_buffer_destroy( struct object *obj );
+static int screen_buffer_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *screen_buffer_get_fd( struct object *obj );
-static struct object *screen_buffer_get_sync( struct object *obj );
 static struct object *screen_buffer_open_file( struct object *obj, unsigned int access,
                                                unsigned int sharing, unsigned int options );
 
@@ -231,13 +230,13 @@ static const struct object_ops screen_buffer_ops =
     sizeof(struct screen_buffer),     /* size */
     &file_type,                       /* type */
     screen_buffer_dump,               /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    screen_buffer_signaled,           /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     screen_buffer_get_fd,             /* get_fd */
-    screen_buffer_get_sync,           /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -645,8 +644,9 @@ static struct object *create_screen_buffer( struct console *console )
         return NULL;
     }
 
-    if (!(screen_buffer = alloc_object( &screen_buffer_ops ))) return NULL;
-    screen_buffer->sync  = (struct event_sync *)grab_object( console->sync );
+    if (!(screen_buffer = alloc_object( &screen_buffer_ops )))
+        return NULL;
+
     screen_buffer->id    = ++console->last_id;
     screen_buffer->input = console;
     init_async_queue( &screen_buffer->ioctl_q );
@@ -777,11 +777,7 @@ static void console_destroy( struct object *obj )
     LIST_FOR_EACH_ENTRY( output, &console->outputs, struct console_output, entry )
         output->console = NULL;
 
-    if (console->sync)
-    {
-        reset_sync( console->sync );
-        release_object( console->sync );
-    }
+    if (console->sync) release_object( console->sync );
 
     free_async_queue( &console->ioctl_q );
     free_async_queue( &console->read_q );
@@ -862,10 +858,17 @@ static void screen_buffer_destroy( struct object *obj )
                               screen_buffer->id, NULL, NULL );
     }
     free_async_queue( &screen_buffer->ioctl_q );
-    if (screen_buffer->sync) release_object( screen_buffer->sync );
     if (screen_buffer->fd) release_object( screen_buffer->fd );
 }
 
+static int screen_buffer_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
+    if (!screen_buffer->input) return 0;
+    return screen_buffer->input->signaled;
+}
+
 static struct object *screen_buffer_open_file( struct object *obj, unsigned int access,
                                                unsigned int sharing, unsigned int options )
 {
@@ -882,13 +885,6 @@ static struct fd *screen_buffer_get_fd( struct object *obj )
     return NULL;
 }
 
-static struct object *screen_buffer_get_sync( struct object *obj )
-{
-    struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
-    assert( obj->ops == &screen_buffer_ops );
-    return grab_object( screen_buffer->sync );
-}
-
 static void console_server_dump( struct object *obj, int verbose )
 {
     assert( obj->ops == &console_server_ops );
@@ -1571,6 +1567,7 @@ struct object *create_console_device( struct object *root, const struct unicode_
 DECL_HANDLER(get_next_console_request)
 {
     struct console_host_ioctl *ioctl = NULL, *next;
+    struct screen_buffer *screen_buffer;
     struct console_server *server;
     struct console_output *output;
     struct console_input *input;
@@ -1597,6 +1594,8 @@ DECL_HANDLER(get_next_console_request)
     {
         server->console->signaled = 1;
         signal_sync( server->console->sync );
+        LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
+            wake_up( &screen_buffer->obj, 0 );
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
             wake_up( &input->obj, 0 );
         LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
-- 
2.50.1


From 68918e3522f48a9b0023406f9b20007060621480 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:03 +0300
Subject: [PATCH 11/57] Revert "server: Use an event sync for console server
 objects."

This reverts commit 2c7b34959e701aabb528b5271fc97c67eb5f5bb4.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 53 +++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/server/console.c b/server/console.c
index 6b85ecc8a54..6665d0a0836 100644
--- a/server/console.c
+++ b/server/console.c
@@ -135,7 +135,6 @@ struct console_host_ioctl
 struct console_server
 {
     struct object         obj;            /* object header */
-    struct event_sync    *sync;           /* sync object for wait/signal */
     struct fd            *fd;             /* pseudo-fd for ioctls */
     struct console       *console;        /* attached console */
     struct list           queue;          /* ioctl queue */
@@ -148,8 +147,8 @@ struct console_server
 
 static void console_server_dump( struct object *obj, int verbose );
 static void console_server_destroy( struct object *obj );
+static int console_server_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *console_server_get_fd( struct object *obj );
-static struct object *console_server_get_sync( struct object *obj );
 static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name,
                                                 unsigned int attr, struct object *root );
 static struct object *console_server_open_file( struct object *obj, unsigned int access,
@@ -160,13 +159,13 @@ static const struct object_ops console_server_ops =
     sizeof(struct console_server),    /* size */
     &file_type,                       /* type */
     console_server_dump,              /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    console_server_signaled,          /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_server_get_fd,            /* get_fd */
-    console_server_get_sync,          /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -588,7 +587,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u
         queue_async( queue, async );
     }
     list_add_tail( &server->queue, &ioctl->entry );
-    signal_sync( server->sync );
+    wake_up( &server->obj, 0 );
     if (async) set_error( STATUS_PENDING );
     return 1;
 }
@@ -620,7 +619,7 @@ static void disconnect_console_server( struct console_server *server )
         assert( server->console->server == server );
         server->console->server = NULL;
         server->console = NULL;
-        signal_sync( server->sync );
+        wake_up( &server->obj, 0 );
     }
 }
 
@@ -896,7 +895,6 @@ static void console_server_destroy( struct object *obj )
     struct console_server *server = (struct console_server *)obj;
     assert( obj->ops == &console_server_ops );
     disconnect_console_server( server );
-    if (server->sync) release_object( server->sync );
     if (server->fd) release_object( server->fd );
 }
 
@@ -932,25 +930,24 @@ static struct object *console_server_lookup_name( struct object *obj, struct uni
         release_object( screen_buffer );
         server->console->server = server;
 
-        if (list_empty( &server->queue )) reset_sync( server->sync );
         return &server->console->obj;
     }
 
     return NULL;
 }
 
-static struct fd *console_server_get_fd( struct object* obj )
+static int console_server_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct console_server *server = (struct console_server*)obj;
     assert( obj->ops == &console_server_ops );
-    return (struct fd *)grab_object( server->fd );
+    return !server->console || !list_empty( &server->queue );
 }
 
-static struct object *console_server_get_sync( struct object *obj )
+static struct fd *console_server_get_fd( struct object* obj )
 {
-    struct console_server *server = (struct console_server *)obj;
+    struct console_server *server = (struct console_server*)obj;
     assert( obj->ops == &console_server_ops );
-    return grab_object( server->sync );
+    return (struct fd *)grab_object( server->fd );
 }
 
 static struct object *console_server_open_file( struct object *obj, unsigned int access,
@@ -964,23 +961,21 @@ static struct object *create_console_server( void )
     struct console_server *server;
 
     if (!(server = alloc_object( &console_server_ops ))) return NULL;
-    server->sync       = NULL;
-    server->fd         = NULL;
     server->console    = NULL;
     server->busy       = 0;
     server->once_input = 0;
     server->term_fd    = -1;
     list_init( &server->queue );
     list_init( &server->read_queue );
-
-    if (!(server->sync = create_event_sync( 1, 1 ))) goto error;
-    if (!(server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error;
+    server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT );
+    if (!server->fd)
+    {
+        release_object( server );
+        return NULL;
+    }
     allow_fd_caching(server->fd);
-    return &server->obj;
 
-error:
-    release_object( server );
-    return NULL;
+    return &server->obj;
 }
 
 static int is_blocking_read_ioctl( unsigned int code )
@@ -1644,7 +1639,11 @@ DECL_HANDLER(get_next_console_request)
         free( ioctl );
         if (iosb) release_object( iosb );
 
-        if (req->read) goto done;
+        if (req->read)
+        {
+            release_object( server );
+            return;
+        }
         server->busy = 0;
     }
 
@@ -1703,7 +1702,5 @@ DECL_HANDLER(get_next_console_request)
         set_error( STATUS_PENDING );
     }
 
-done:
-    if (list_empty( &server->queue )) reset_sync( server->sync );
     release_object( server );
 }
-- 
2.50.1


From dc77362bd5e6fe3ac99963b90b9344cc305f8bbf Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:08 +0300
Subject: [PATCH 12/57] Revert "server: Use an event sync for console objects."

This reverts commit 3cbcd8de50ce97cd65bc5a3b6ccf09f0110b7a31.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 67 ++++++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 34 deletions(-)

diff --git a/server/console.c b/server/console.c
index 6665d0a0836..d3c5317728e 100644
--- a/server/console.c
+++ b/server/console.c
@@ -53,7 +53,6 @@ struct history_line
 struct console
 {
     struct object                obj;           /* object header */
-    struct event_sync           *sync;          /* sync object for wait/signal */
     int                          signaled;      /* is console signaled */
     struct thread               *renderer;      /* console renderer thread */
     struct screen_buffer        *active;        /* active screen buffer */
@@ -69,25 +68,26 @@ struct console
 
 static void console_dump( struct object *obj, int verbose );
 static void console_destroy( struct object *obj );
+static int console_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *console_get_fd( struct object *obj );
-static struct object *console_get_sync( struct object *obj );
 static struct object *console_lookup_name( struct object *obj, struct unicode_str *name,
                                            unsigned int attr, struct object *root );
 static struct object *console_open_file( struct object *obj, unsigned int access,
                                          unsigned int sharing, unsigned int options );
+static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
 
 static const struct object_ops console_ops =
 {
     sizeof(struct console),           /* size */
     &file_type,                       /* type */
     console_dump,                     /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    console_add_queue,                /* add_queue */
+    remove_queue,                     /* remove_queue */
+    console_signaled,                 /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_get_fd,                   /* get_fd */
-    console_get_sync,                 /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -479,18 +479,10 @@ static const struct fd_ops console_connection_fd_ops =
 static int queue_host_ioctl( struct console_server *server, unsigned int code, unsigned int output,
                              struct async *async, struct async_queue *queue );
 
-static struct fd *console_get_fd( struct object *obj )
+static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
 {
-    struct console *console = (struct console *)obj;
+    struct console *console = (struct console*)obj;
     assert( obj->ops == &console_ops );
-    return (struct fd *)grab_object( console->fd );
-}
-
-static struct object *console_get_sync( struct object *obj )
-{
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
-
     /* before waiting, ensure conhost's input thread has been started */
     if (console->server && !console->server->once_input)
     {
@@ -498,8 +490,20 @@ static struct object *console_get_sync( struct object *obj )
         if (console->server->term_fd == -1)
             queue_host_ioctl( console->server, IOCTL_CONDRV_PEEK, 0, NULL, NULL );
     }
+    return add_queue( &console->obj, entry );
+}
+
+static int console_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct console *console = (struct console*)obj;
+    return console->signaled;
+}
 
-    return grab_object( console->sync );
+static struct fd *console_get_fd( struct object *obj )
+{
+    struct console *console = (struct console *)obj;
+    assert( obj->ops == &console_ops );
+    return (struct fd *)grab_object( console->fd );
 }
 
 static enum server_fd_type console_get_fd_type( struct fd *fd )
@@ -538,8 +542,9 @@ static struct object *create_console(void)
 {
     struct console *console;
 
-    if (!(console = alloc_object( &console_ops ))) return NULL;
-    console->sync          = NULL;
+    if (!(console = alloc_object( &console_ops )))
+        return NULL;
+
     console->renderer      = NULL;
     console->signaled      = 0;
     console->active        = NULL;
@@ -552,14 +557,14 @@ static struct object *create_console(void)
     init_async_queue( &console->ioctl_q );
     init_async_queue( &console->read_q );
 
-    if (!(console->sync = create_event_sync( 1, 0 ))) goto error;
-    if (!(console->fd = alloc_pseudo_fd( &console_fd_ops, &console->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error;
+    console->fd = alloc_pseudo_fd( &console_fd_ops, &console->obj, FILE_SYNCHRONOUS_IO_NONALERT );
+    if (!console->fd)
+    {
+        release_object( console );
+        return NULL;
+    }
     allow_fd_caching( console->fd );
     return &console->obj;
-
-error:
-    release_object( console );
-    return NULL;
 }
 
 static void console_host_ioctl_terminate( struct console_host_ioctl *call, unsigned int status )
@@ -776,8 +781,6 @@ static void console_destroy( struct object *obj )
     LIST_FOR_EACH_ENTRY( output, &console->outputs, struct console_output, entry )
         output->console = NULL;
 
-    if (console->sync) release_object( console->sync );
-
     free_async_queue( &console->ioctl_q );
     free_async_queue( &console->read_q );
     if (console->fd)
@@ -1580,15 +1583,11 @@ DECL_HANDLER(get_next_console_request)
 
     if (!server->console->renderer) server->console->renderer = current;
 
-    if (!req->signal)
-    {
-        server->console->signaled = 0;
-        reset_sync( server->console->sync );
-    }
+    if (!req->signal) server->console->signaled = 0;
     else if (!server->console->signaled)
     {
         server->console->signaled = 1;
-        signal_sync( server->console->sync );
+        wake_up( &server->console->obj, 0 );
         LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
             wake_up( &screen_buffer->obj, 0 );
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
-- 
2.50.1


From cea799238cf44c3fa600cd1549d8d550a80497ec Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:18 +0300
Subject: [PATCH 13/57] Revert "server: Use an event sync for timer objects."

This reverts commit 2cf619e2e4bf5695770d75482a1302fa7279c944.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/timer.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/server/timer.c b/server/timer.c
index 522fc6a7113..f85fa66ed47 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -53,7 +53,6 @@ struct type_descr timer_type =
 struct timer
 {
     struct object        obj;       /* object header */
-    struct event_sync   *sync;      /* sync object for wait/signal */
     int                  manual;    /* manual reset */
     int                  signaled;  /* current signaled state */
     unsigned int         period;    /* timer period in ms */
@@ -65,7 +64,8 @@ struct timer
 };
 
 static void timer_dump( struct object *obj, int verbose );
-static struct object *timer_get_sync( struct object *obj );
+static int timer_signaled( struct object *obj, struct wait_queue_entry *entry );
+static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static void timer_destroy( struct object *obj );
 
 static const struct object_ops timer_ops =
@@ -73,13 +73,13 @@ static const struct object_ops timer_ops =
     sizeof(struct timer),      /* size */
     &timer_type,               /* type */
     timer_dump,                /* dump */
-    NULL,                      /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
+    timer_signaled,            /* signaled */
+    timer_satisfied,           /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    timer_get_sync,            /* get_sync */
+    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -105,19 +105,12 @@ static struct timer *create_timer( struct object *root, const struct unicode_str
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            timer->sync     = NULL;
             timer->manual   = manual;
             timer->signaled = 0;
             timer->when     = 0;
             timer->period   = 0;
             timer->timeout  = NULL;
             timer->thread   = NULL;
-
-            if (!(timer->sync = create_event_sync( manual, 0 )))
-            {
-                release_object( timer );
-                return NULL;
-            }
         }
     }
     return timer;
@@ -157,8 +150,9 @@ static void timer_callback( void *private )
     }
     else timer->timeout = NULL;
 
+    /* wake up waiters */
     timer->signaled = 1;
-    signal_sync( timer->sync );
+    wake_up( &timer->obj, 0 );
 }
 
 /* cancel a running timer */
@@ -189,7 +183,6 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period
     {
         period = 0;  /* period doesn't make any sense for a manual timer */
         timer->signaled = 0;
-        reset_sync( timer->sync );
     }
     timer->when     = (expire <= 0) ? expire - monotonic_time : max( expire, current_time );
     timer->period   = period;
@@ -210,11 +203,18 @@ static void timer_dump( struct object *obj, int verbose )
              timer->manual, get_timeout_str(timeout), timer->period );
 }
 
-static struct object *timer_get_sync( struct object *obj )
+static int timer_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct timer *timer = (struct timer *)obj;
+    assert( obj->ops == &timer_ops );
+    return timer->signaled;
+}
+
+static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry )
 {
     struct timer *timer = (struct timer *)obj;
     assert( obj->ops == &timer_ops );
-    return grab_object( timer->sync );
+    if (!timer->manual) timer->signaled = 0;
 }
 
 static void timer_destroy( struct object *obj )
@@ -224,7 +224,6 @@ static void timer_destroy( struct object *obj )
 
     if (timer->timeout) remove_timeout_user( timer->timeout );
     if (timer->thread) release_object( timer->thread );
-    if (timer->sync) release_object( timer->sync );
 }
 
 /* create a timer */
-- 
2.50.1


From 0bd35d3c4cd372af6b41af64cc13975c9bca9889 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:22 +0300
Subject: [PATCH 14/57] Revert "server: Use an event sync for completion port
 objects."

This reverts commit 863366bb5e5dcb6779574e5c4ee2c22c2dae925d.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/completion.c | 44 ++++++++++++++++++--------------------------
 1 file changed, 18 insertions(+), 26 deletions(-)

diff --git a/server/completion.c b/server/completion.c
index a2028a89823..fd623b36d5a 100644
--- a/server/completion.c
+++ b/server/completion.c
@@ -72,11 +72,11 @@ struct completion_wait
 
 struct completion
 {
-    struct object       obj;
-    struct event_sync  *sync;
-    struct list         queue;
-    struct list         wait_queue;
-    unsigned int        depth;
+    struct object  obj;
+    struct list    queue;
+    struct list    wait_queue;
+    unsigned int   depth;
+    int            closed;
 };
 
 static void completion_wait_dump( struct object*, int );
@@ -155,7 +155,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent
 }
 
 static void completion_dump( struct object*, int );
-static struct object *completion_get_sync( struct object * );
+static int completion_signaled( struct object *obj, struct wait_queue_entry *entry );
 static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static void completion_destroy( struct object * );
 
@@ -164,13 +164,13 @@ static const struct object_ops completion_ops =
     sizeof(struct completion), /* size */
     &completion_type,          /* type */
     completion_dump,           /* dump */
-    NULL,                      /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
+    completion_signaled,       /* signaled */
+    no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    completion_get_sync,       /* get_sync */
+    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -193,8 +193,6 @@ static void completion_destroy( struct object *obj)
     {
         free( tmp );
     }
-
-    if (completion->sync) release_object( completion->sync );
 }
 
 static void completion_dump( struct object *obj, int verbose )
@@ -205,11 +203,11 @@ static void completion_dump( struct object *obj, int verbose )
     fprintf( stderr, "Completion depth=%u\n", completion->depth );
 }
 
-static struct object *completion_get_sync( struct object *obj )
+static int completion_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct completion *completion = (struct completion *)obj;
-    assert( obj->ops == &completion_ops );
-    return grab_object( completion->sync );
+
+    return !list_empty( &completion->queue ) || completion->closed;
 }
 
 static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -230,7 +228,8 @@ static int completion_close_handle( struct object *obj, struct process *process,
             cleanup_thread_completion( wait->thread );
         }
     }
-    signal_sync( completion->sync );
+    completion->closed = 1;
+    wake_up( obj, 0 );
     return 1;
 }
 
@@ -274,16 +273,10 @@ static struct completion *create_completion( struct object *root, const struct u
     {
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
-            completion->sync = NULL;
             list_init( &completion->queue );
             list_init( &completion->wait_queue );
             completion->depth = 0;
-
-            if (!(completion->sync = create_event_sync( 1, 0 )))
-            {
-                release_object( completion );
-                return NULL;
-            }
+            completion->closed = 0;
         }
     }
 
@@ -316,7 +309,7 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_
         wake_up( &wait->obj, 1 );
         if (list_empty( &completion->queue )) return;
     }
-    if (!list_empty( &completion->queue )) signal_sync( completion->sync );
+    if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 );
 }
 
 /* create a completion */
@@ -417,7 +410,6 @@ DECL_HANDLER(remove_completion)
         reply->information = msg->information;
         free( msg );
         reply->wait_handle = 0;
-        if (list_empty( &completion->queue )) reset_sync( completion->sync );
     }
 
     release_object( completion );
-- 
2.50.1


From 4e5ebe8dd41014b0113eb0aa47a1277a765af416 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:26 +0300
Subject: [PATCH 15/57] Revert "server: Use an event sync for device manager
 objects."

This reverts commit a508517830acca5246f7a70a9f2730d1c4977a3b.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/device.c | 34 ++++++++++------------------------
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/server/device.c b/server/device.c
index f4b3f19028b..892ec98c44f 100644
--- a/server/device.c
+++ b/server/device.c
@@ -89,7 +89,6 @@ static const struct object_ops irp_call_ops =
 struct device_manager
 {
     struct object          obj;            /* object header */
-    struct event_sync     *sync;           /* sync object for wait/signal */
     struct list            devices;        /* list of devices */
     struct list            requests;       /* list of pending irps across all devices */
     struct irp_call       *current_call;   /* call currently executed on client side */
@@ -97,7 +96,7 @@ struct device_manager
 };
 
 static void device_manager_dump( struct object *obj, int verbose );
-static struct object *device_manager_get_sync( struct object *obj );
+static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void device_manager_destroy( struct object *obj );
 
 static const struct object_ops device_manager_ops =
@@ -105,13 +104,13 @@ static const struct object_ops device_manager_ops =
     sizeof(struct device_manager),    /* size */
     &no_type,                         /* type */
     device_manager_dump,              /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    device_manager_signaled,          /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    device_manager_get_sync,          /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -423,7 +422,7 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i
     irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL;
     if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry );
     list_add_tail( &manager->requests, &irp->mgr_entry );
-    if (list_head( &manager->requests ) == &irp->mgr_entry) signal_sync( manager->sync );
+    if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 );  /* first one */
 }
 
 static struct object *device_open_file( struct object *obj, unsigned int access,
@@ -753,7 +752,6 @@ struct object *create_unix_device( struct object *root, const struct unicode_str
 /* terminate requests when the underlying device is deleted */
 static void delete_file( struct device_file *file )
 {
-    struct device_manager *manager = file->device->manager;
     struct irp_call *irp, *next;
 
     /* the pending requests may be the only thing holding a reference to the file */
@@ -766,7 +764,6 @@ static void delete_file( struct device_file *file )
         set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 );
     }
 
-    if (list_empty( &manager->requests )) reset_sync( manager->sync );
     release_object( file );
 }
 
@@ -791,11 +788,11 @@ static void device_manager_dump( struct object *obj, int verbose )
     fprintf( stderr, "Device manager\n" );
 }
 
-static struct object *device_manager_get_sync( struct object *obj )
+static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct device_manager *manager = (struct device_manager *)obj;
-    assert( obj->ops == &device_manager_ops );
-    return grab_object( manager->sync );
+
+    return !list_empty( &manager->requests );
 }
 
 static void device_manager_destroy( struct object *obj )
@@ -832,8 +829,6 @@ static void device_manager_destroy( struct object *obj )
         assert( !irp->file && !irp->async );
         release_object( irp );
     }
-
-    if (manager->sync) release_object( manager->sync );
 }
 
 static struct device_manager *create_device_manager(void)
@@ -842,17 +837,10 @@ static struct device_manager *create_device_manager(void)
 
     if ((manager = alloc_object( &device_manager_ops )))
     {
-        manager->sync         = NULL;
         manager->current_call = NULL;
         list_init( &manager->devices );
         list_init( &manager->requests );
         wine_rb_init( &manager->kernel_objects, compare_kernel_object );
-
-        if (!(manager->sync = create_event_sync( 1, 0 )))
-        {
-            release_object( manager );
-            return NULL;
-        }
     }
     return manager;
 }
@@ -1039,8 +1027,6 @@ DECL_HANDLER(get_next_device_request)
                 }
                 list_remove( &irp->mgr_entry );
                 list_init( &irp->mgr_entry );
-                if (list_empty( &manager->requests )) reset_sync( manager->sync );
-
                 /* we already own the object if it's only on manager queue */
                 if (irp->file) grab_object( irp );
                 manager->current_call = irp;
-- 
2.50.1


From 5158d277e0432aa836a90d3ccb63b51842772e2e Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:31 +0300
Subject: [PATCH 16/57] Revert "server: Use an event sync for debug objects."

This reverts commit 3e1da591b28da1c8736962b9d1e4faaccdaa9f54.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/debugger.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/server/debugger.c b/server/debugger.c
index 2956ee17b8e..5f8b0ffc8fe 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -70,7 +70,6 @@ struct type_descr debug_obj_type =
 struct debug_obj
 {
     struct object        obj;         /* object header */
-    struct event_sync   *sync;       /* sync object for wait/signal */
     struct list          event_queue; /* pending events queue */
     unsigned int         flags;       /* debug flags */
 };
@@ -106,7 +105,7 @@ static const struct object_ops debug_event_ops =
 };
 
 static void debug_obj_dump( struct object *obj, int verbose );
-static struct object *debug_obj_get_sync( struct object *obj );
+static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void debug_obj_destroy( struct object *obj );
 
 static const struct object_ops debug_obj_ops =
@@ -114,13 +113,13 @@ static const struct object_ops debug_obj_ops =
     sizeof(struct debug_obj),      /* size */
     &debug_obj_type,               /* type */
     debug_obj_dump,                /* dump */
-    NULL,                          /* add_queue */
-    NULL,                          /* remove_queue */
-    NULL,                          /* signaled */
-    NULL,                          /* satisfied */
+    add_queue,                     /* add_queue */
+    remove_queue,                  /* remove_queue */
+    debug_obj_signaled,            /* signaled */
+    no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    debug_obj_get_sync,            /* get_sync */
+    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -256,7 +255,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event )
     {
         /* grab reference since debugger could be killed while trying to wake up */
         grab_object( debug_obj );
-        signal_sync( debug_obj->sync );
+        wake_up( &debug_obj->obj, 0 );
         release_object( debug_obj );
     }
 }
@@ -269,7 +268,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event
     if (!event->sender->process->debug_event)
     {
         grab_object( debug_obj );
-        signal_sync( debug_obj->sync );
+        wake_up( &debug_obj->obj, 0 );
         release_object( debug_obj );
     }
 }
@@ -330,11 +329,11 @@ static void debug_obj_dump( struct object *obj, int verbose )
              debug_obj->event_queue.next, debug_obj->event_queue.prev );
 }
 
-static struct object *debug_obj_get_sync( struct object *obj )
+static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct debug_obj *debug_obj = (struct debug_obj *)obj;
     assert( obj->ops == &debug_obj_ops );
-    return grab_object( debug_obj->sync );
+    return find_event_to_send( debug_obj ) != NULL;
 }
 
 static void debug_obj_destroy( struct object *obj )
@@ -349,8 +348,6 @@ static void debug_obj_destroy( struct object *obj )
     /* free all pending events */
     while ((ptr = list_head( &debug_obj->event_queue )))
         unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry ));
-
-    if (debug_obj->sync) release_object( debug_obj->sync );
 }
 
 struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access )
@@ -368,15 +365,8 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni
     {
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
-            debug_obj->sync  = NULL;
             debug_obj->flags = flags;
             list_init( &debug_obj->event_queue );
-
-            if (!(debug_obj->sync = create_event_sync( 1, 0 )))
-            {
-                release_object( debug_obj );
-                return NULL;
-            }
         }
     }
     return debug_obj;
@@ -594,7 +584,6 @@ DECL_HANDLER(wait_debug_event)
         reply->tid = get_thread_id( event->sender );
         alloc_event_handles( event, current->process );
         set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) ));
-        if (!find_event_to_send( debug_obj )) reset_sync( debug_obj->sync );
     }
     else
     {
-- 
2.50.1


From 7a982b335129bb5c23820e0555711ec065ee0636 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:35 +0300
Subject: [PATCH 17/57] Revert "server: Use an event sync for debug event
 objects."

This reverts commit 61e52ce7674a82248623bab434eecff8402fecd7.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/debugger.c | 33 ++++++++++-----------------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/server/debugger.c b/server/debugger.c
index 5f8b0ffc8fe..43d01fbf246 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -43,7 +43,6 @@ enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_DELAYED, EVENT_CONTINUE
 struct debug_event
 {
     struct object          obj;       /* object header */
-    struct event_sync     *sync;      /* sync object for wait/signal */
     struct list            entry;     /* entry in event queue */
     struct thread         *sender;    /* thread which sent this event */
     struct file           *file;      /* file object for events that need one */
@@ -76,7 +75,7 @@ struct debug_obj
 
 
 static void debug_event_dump( struct object *obj, int verbose );
-static struct object *debug_event_get_sync( struct object *obj );
+static int debug_event_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void debug_event_destroy( struct object *obj );
 
 static const struct object_ops debug_event_ops =
@@ -84,13 +83,13 @@ static const struct object_ops debug_event_ops =
     sizeof(struct debug_event),    /* size */
     &no_type,                      /* type */
     debug_event_dump,              /* dump */
-    NULL,                          /* add_queue */
-    NULL,                          /* remove_queue */
-    NULL,                          /* signaled */
-    NULL,                          /* satisfied */
+    add_queue,                     /* add_queue */
+    remove_queue,                  /* remove_queue */
+    debug_event_signaled,          /* signaled */
+    no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    debug_event_get_sync,          /* get_sync */
+    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -264,7 +263,6 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event )
 static void resume_event( struct debug_obj *debug_obj, struct debug_event *event )
 {
     event->state = EVENT_QUEUED;
-    reset_sync( event->sync );
     if (!event->sender->process->debug_event)
     {
         grab_object( debug_obj );
@@ -277,7 +275,6 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event
 static void delay_event( struct debug_obj *debug_obj, struct debug_event *event )
 {
     event->state = EVENT_DELAYED;
-    reset_sync( event->sync );
     if (event->sender->process->debug_event == event) event->sender->process->debug_event = NULL;
 }
 
@@ -304,11 +301,11 @@ static void debug_event_dump( struct object *obj, int verbose )
              debug_event->sender, debug_event->data.code, debug_event->state );
 }
 
-static struct object *debug_event_get_sync( struct object *obj )
+static int debug_event_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct debug_event *debug_event = (struct debug_event *)obj;
     assert( obj->ops == &debug_event_ops );
-    return grab_object( debug_event->sync );
+    return debug_event->state == EVENT_CONTINUED;
 }
 
 static void debug_event_destroy( struct object *obj )
@@ -316,7 +313,6 @@ static void debug_event_destroy( struct object *obj )
     struct debug_event *event = (struct debug_event *)obj;
     assert( obj->ops == &debug_event_ops );
 
-    if (event->sync) release_object( event->sync );
     if (event->file) release_object( event->file );
     release_object( event->sender );
 }
@@ -412,7 +408,7 @@ static int continue_debug_event( struct debug_obj *debug_obj, struct process *pr
                 assert( event->sender->process->debug_event == event );
                 event->status = status;
                 event->state  = EVENT_CONTINUED;
-                signal_sync( event->sync );
+                wake_up( &event->obj, 0 );
                 unlink_event( debug_obj, event );
                 resume_process( process );
                 return 1;
@@ -433,20 +429,12 @@ static struct debug_event *alloc_debug_event( struct thread *thread, int code, c
 
     /* build the event */
     if (!(event = alloc_object( &debug_event_ops ))) return NULL;
-    event->sync      = NULL;
     event->state     = EVENT_QUEUED;
     event->sender    = (struct thread *)grab_object( thread );
     event->file      = NULL;
     memset( &event->data, 0, sizeof(event->data) );
     fill_debug_event[code - DbgCreateThreadStateChange]( event, arg );
     event->data.code = code;
-
-    if (!(event->sync = create_event_sync( 1, 0 )))
-    {
-        release_object( event );
-        return NULL;
-    }
-
     return event;
 }
 
@@ -532,7 +520,7 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj )
         assert( event->state != EVENT_CONTINUED );
         event->status = DBG_CONTINUE;
         event->state  = EVENT_CONTINUED;
-        signal_sync( event->sync );
+        wake_up( &event->obj, 0 );
         unlink_event( debug_obj, event );
         /* from queued debug event */
         resume_process( process );
@@ -578,7 +566,6 @@ DECL_HANDLER(wait_debug_event)
     if ((event = find_event_to_send( debug_obj )))
     {
         event->state = EVENT_SENT;
-        reset_sync( event->sync );
         event->sender->process->debug_event = event;
         reply->pid = get_process_id( event->sender->process );
         reply->tid = get_thread_id( event->sender );
-- 
2.50.1


From 5b480686d652229fad9849f6ebd36f8609d90ac0 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:40 +0300
Subject: [PATCH 18/57] Revert "server: Use an event sync for file lock
 objects."

This reverts commit d71bddb52069b8b0a61cef5c2a65d5b30e9662a2.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/fd.c | 43 ++++++++++++++++---------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/server/fd.c b/server/fd.c
index 3febfdad266..8b9133e102b 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -278,7 +278,6 @@ static const struct object_ops inode_ops =
 struct file_lock
 {
     struct object       obj;         /* object header */
-    struct event_sync  *sync;        /* sync object for wait/signal */
     struct fd          *fd;          /* fd owning this lock */
     struct list         fd_entry;    /* entry in list of locks on a given fd */
     struct list         inode_entry; /* entry in inode list of locks */
@@ -290,21 +289,20 @@ struct file_lock
 };
 
 static void file_lock_dump( struct object *obj, int verbose );
-static struct object *file_lock_get_sync( struct object *obj );
-static void file_lock_destroy( struct object *obj );
+static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry );
 
 static const struct object_ops file_lock_ops =
 {
     sizeof(struct file_lock),   /* size */
     &no_type,                   /* type */
     file_lock_dump,             /* dump */
-    NULL,                       /* add_queue */
-    NULL,                       /* remove_queue */
-    NULL,                       /* signaled */
-    NULL,                       /* satisfied */
+    add_queue,                  /* add_queue */
+    remove_queue,               /* remove_queue */
+    file_lock_signaled,         /* signaled */
+    no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    file_lock_get_sync,         /* get_sync */
+    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -315,7 +313,7 @@ static const struct object_ops file_lock_ops =
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
     no_close_handle,            /* close_handle */
-    file_lock_destroy,          /* destroy */
+    no_destroy                  /* destroy */
 };
 
 
@@ -1323,18 +1321,11 @@ static void file_lock_dump( struct object *obj, int verbose )
     fprintf( stderr, "\n" );
 }
 
-static struct object *file_lock_get_sync( struct object *obj )
+static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct file_lock *lock = (struct file_lock *)obj;
-    assert( obj->ops == &file_lock_ops );
-    return grab_object( lock->sync );
-}
-
-static void file_lock_destroy( struct object *obj )
-{
-    struct file_lock *lock = (struct file_lock *)obj;
-    assert( obj->ops == &file_lock_ops );
-    if (lock->sync) release_object( lock->sync );
+    /* lock is signaled if it has lost its owner */
+    return !lock->process;
 }
 
 /* set (or remove) a Unix lock if possible for the given range */
@@ -1516,24 +1507,22 @@ static struct file_lock *add_lock( struct fd *fd, int shared, file_pos_t start,
     struct file_lock *lock;
 
     if (!(lock = alloc_object( &file_lock_ops ))) return NULL;
-    lock->sync    = NULL;
     lock->shared  = shared;
     lock->start   = start;
     lock->end     = end;
     lock->fd      = fd;
     lock->process = current->process;
 
-    if (!(lock->sync = create_event_sync( 1, 0 ))) goto error;
     /* now try to set a Unix lock */
-    if (!set_unix_lock( lock->fd, lock->start, lock->end, lock->shared ? F_RDLCK : F_WRLCK )) goto error;
+    if (!set_unix_lock( lock->fd, lock->start, lock->end, lock->shared ? F_RDLCK : F_WRLCK ))
+    {
+        release_object( lock );
+        return NULL;
+    }
     list_add_tail( &fd->locks, &lock->fd_entry );
     list_add_tail( &fd->inode->locks, &lock->inode_entry );
     list_add_tail( &lock->process->locks, &lock->proc_entry );
     return lock;
-
-error:
-    release_object( lock );
-    return NULL;
 }
 
 /* remove an existing lock */
@@ -1547,7 +1536,7 @@ static void remove_lock( struct file_lock *lock, int remove_unix )
     if (remove_unix) remove_unix_locks( lock->fd, lock->start, lock->end );
     if (list_empty( &inode->locks )) inode_close_pending( inode, 1 );
     lock->process = NULL;
-    signal_sync( lock->sync );
+    wake_up( &lock->obj, 0 );
     release_object( lock );
 }
 
-- 
2.50.1


From 51360b00486f97898b2df5feb5b85abbabc14e5b Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:45 +0300
Subject: [PATCH 19/57] Revert "server: Use an event sync for startup info
 objects."

This reverts commit 3d8543646f9a43a81b7e51d927962e7eb0331c50.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/process.c | 38 ++++++++++++++------------------------
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/server/process.c b/server/process.c
index 37a75dc1c45..bc74c89600f 100644
--- a/server/process.c
+++ b/server/process.c
@@ -139,16 +139,15 @@ static const struct fd_ops process_fd_ops =
 
 struct startup_info
 {
-    struct object               obj;            /* object header */
-    struct event_sync          *sync;           /* sync object for wait/signal */
-    struct process             *process;        /* created process */
-    data_size_t                 info_size;      /* size of startup info */
-    data_size_t                 data_size;      /* size of whole startup data */
-    struct startup_info_data   *data;           /* data for startup info */
+    struct object       obj;          /* object header */
+    struct process     *process;      /* created process */
+    data_size_t         info_size;    /* size of startup info */
+    data_size_t         data_size;    /* size of whole startup data */
+    struct startup_info_data *data;   /* data for startup info */
 };
 
 static void startup_info_dump( struct object *obj, int verbose );
-static struct object *startup_info_get_sync( struct object *obj );
+static int startup_info_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void startup_info_destroy( struct object *obj );
 
 static const struct object_ops startup_info_ops =
@@ -156,13 +155,13 @@ static const struct object_ops startup_info_ops =
     sizeof(struct startup_info),   /* size */
     &no_type,                      /* type */
     startup_info_dump,             /* dump */
-    NULL,                          /* add_queue */
-    NULL,                          /* remove_queue */
-    NULL,                          /* signaled */
-    NULL,                          /* satisfied */
+    add_queue,                     /* add_queue */
+    remove_queue,                  /* remove_queue */
+    startup_info_signaled,         /* signaled */
+    no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    startup_info_get_sync,         /* get_sync */
+    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -564,7 +563,7 @@ static void set_process_startup_state( struct process *process, enum startup_sta
     if (process->startup_state == STARTUP_IN_PROGRESS) process->startup_state = state;
     if (process->startup_info)
     {
-        signal_sync( process->startup_info->sync );
+        wake_up( &process->startup_info->obj, 0 );
         release_object( process->startup_info );
         process->startup_info = NULL;
     }
@@ -889,7 +888,6 @@ static void startup_info_destroy( struct object *obj )
     assert( obj->ops == &startup_info_ops );
     free( info->data );
     if (info->process) release_object( info->process );
-    if (info->sync) release_object( info->sync );
 }
 
 static void startup_info_dump( struct object *obj, int verbose )
@@ -904,11 +902,10 @@ static void startup_info_dump( struct object *obj, int verbose )
     fputc( '\n', stderr );
 }
 
-static struct object *startup_info_get_sync( struct object *obj )
+static int startup_info_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct startup_info *info = (struct startup_info *)obj;
-    assert( obj->ops == &startup_info_ops );
-    return grab_object( info->sync );
+    return info->process && info->process->startup_state != STARTUP_IN_PROGRESS;
 }
 
 /* get a process from an id (and increment the refcount) */
@@ -1218,16 +1215,9 @@ DECL_HANDLER(new_process)
         release_object( parent );
         return;
     }
-    info->sync     = NULL;
     info->process  = NULL;
     info->data     = NULL;
 
-    if (!(info->sync = create_event_sync( 1, 0 )))
-    {
-        close( socket_fd );
-        goto done;
-    }
-
     info_ptr = get_req_data_after_objattr( objattr, &info->data_size );
 
     if ((req->handles_size & 3) || req->handles_size > info->data_size)
-- 
2.50.1


From 35d9372af8a8b47a62c189f5cdae4a0886b0bfc8 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:50 +0300
Subject: [PATCH 20/57] Revert "server: Use an event sync for process objects."

This reverts commit 712d996b829712f3e6cc80d085430a45b864fd6e.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/process.c | 22 +++++++++-------------
 server/process.h |  1 -
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/server/process.c b/server/process.c
index bc74c89600f..aefe077440a 100644
--- a/server/process.c
+++ b/server/process.c
@@ -90,7 +90,7 @@ struct type_descr process_type =
 };
 
 static void process_dump( struct object *obj, int verbose );
-static struct object *process_get_sync( struct object *obj );
+static int process_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int process_map_access( struct object *obj, unsigned int access );
 static struct security_descriptor *process_get_sd( struct object *obj );
 static void process_poll_event( struct fd *fd, int event );
@@ -103,13 +103,13 @@ static const struct object_ops process_ops =
     sizeof(struct process),      /* size */
     &process_type,               /* type */
     process_dump,                /* dump */
-    NULL,                        /* add_queue */
-    NULL,                        /* remove_queue */
-    NULL,                        /* signaled */
-    NULL,                        /* satisfied */
+    add_queue,                   /* add_queue */
+    remove_queue,                /* remove_queue */
+    process_signaled,            /* signaled */
+    no_satisfied,                /* satisfied */
     no_signal,                   /* signal */
     no_get_fd,                   /* get_fd */
-    process_get_sync,            /* get_sync */
+    default_get_sync,            /* get_sync */
     process_map_access,          /* map_access */
     process_get_sd,              /* get_sd */
     default_set_sd,              /* set_sd */
@@ -662,7 +662,6 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
         close( fd );
         goto error;
     }
-    process->sync            = NULL;
     process->parent_id       = 0;
     process->debug_obj       = NULL;
     process->debug_event     = NULL;
@@ -721,7 +720,6 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
         goto error;
     }
     if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj, 0 ))) goto error;
-    if (!(process->sync = create_event_sync( 1, 0 ))) goto error;
 
     /* create the handle table */
     if (!parent)
@@ -795,7 +793,6 @@ static void process_destroy( struct object *obj )
     if (process->idle_event) release_object( process->idle_event );
     if (process->id) free_ptid( process->id );
     if (process->token) release_object( process->token );
-    if (process->sync) release_object( process->sync );
     list_remove( &process->rawinput_entry );
     free( process->rawinput_devices );
     free( process->dir_cache );
@@ -811,11 +808,10 @@ static void process_dump( struct object *obj, int verbose )
     fprintf( stderr, "Process id=%04x handles=%p\n", process->id, process->handles );
 }
 
-static struct object *process_get_sync( struct object *obj )
+static int process_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct process *process = (struct process *)obj;
-    assert( obj->ops == &process_ops );
-    return grab_object( process->sync );
+    return !process->running_threads;
 }
 
 static unsigned int process_map_access( struct object *obj, unsigned int access )
@@ -997,7 +993,7 @@ static void process_killed( struct process *process )
     finish_process_tracing( process );
     release_job_process( process );
     start_sigkill_timer( process );
-    signal_sync( process->sync );
+    wake_up( &process->obj, 0 );
 }
 
 /* add a thread to a process running threads list */
diff --git a/server/process.h b/server/process.h
index 2564a4f96d1..dfe8d628538 100644
--- a/server/process.h
+++ b/server/process.h
@@ -36,7 +36,6 @@ enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
 struct process
 {
     struct object        obj;             /* object header */
-    struct event_sync   *sync;            /* sync object for wait/signal */
     struct list          entry;           /* entry in system-wide process list */
     process_id_t         parent_id;       /* parent process id (at the time of creation) */
     struct list          thread_list;     /* thread list */
-- 
2.50.1


From b535b420edd2081ab0193e571dcdb0ba7df44b84 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:02:57 +0300
Subject: [PATCH 21/57] Revert "server: Use an event sync for job objects."

This reverts commit ddb2e9d332cef8d7ea5811c6650ea06e8f68166c.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/process.c | 54 +++++++++++++++++++++---------------------------
 1 file changed, 23 insertions(+), 31 deletions(-)

diff --git a/server/process.c b/server/process.c
index aefe077440a..f90e725ca93 100644
--- a/server/process.c
+++ b/server/process.c
@@ -192,24 +192,24 @@ struct type_descr job_type =
 };
 
 static void job_dump( struct object *obj, int verbose );
-static struct object *job_get_sync( struct object *obj );
+static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
 static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static void job_destroy( struct object *obj );
 
 struct job
 {
-    struct object        obj;               /* object header */
-    struct event_sync   *sync;              /* sync object for wait/signal */
-    struct list          process_list;      /* list of processes */
-    int                  num_processes;     /* count of running processes */
-    int                  total_processes;   /* count of processes which have been assigned */
-    unsigned int         limit_flags;       /* limit flags */
-    int                  terminating;       /* job is terminating */
-    struct completion   *completion_port;   /* associated completion port */
-    apc_param_t          completion_key;    /* key to send with completion messages */
-    struct job          *parent;
-    struct list          parent_job_entry;  /* list entry for parent job */
-    struct list          child_job_list;    /* list of child jobs */
+    struct object obj;             /* object header */
+    struct list process_list;      /* list of processes */
+    int num_processes;             /* count of running processes */
+    int total_processes;           /* count of processes which have been assigned */
+    unsigned int limit_flags;      /* limit flags */
+    int terminating;               /* job is terminating */
+    int signaled;                  /* job is signaled */
+    struct completion *completion_port; /* associated completion port */
+    apc_param_t completion_key;    /* key to send with completion messages */
+    struct job *parent;
+    struct list parent_job_entry;  /* list entry for parent job */
+    struct list child_job_list;    /* list of child jobs */
 };
 
 static const struct object_ops job_ops =
@@ -217,13 +217,13 @@ static const struct object_ops job_ops =
     sizeof(struct job),            /* size */
     &job_type,                     /* type */
     job_dump,                      /* dump */
-    NULL,                          /* add_queue */
-    NULL,                          /* remove_queue */
-    NULL,                          /* signaled */
-    NULL,                          /* satisfied */
+    add_queue,                     /* add_queue */
+    remove_queue,                  /* remove_queue */
+    job_signaled,                  /* signaled */
+    no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    job_get_sync,                  /* get_sync */
+    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -247,22 +247,16 @@ static struct job *create_job_object( struct object *root, const struct unicode_
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            job->sync = NULL;
             list_init( &job->process_list );
             list_init( &job->child_job_list );
             job->num_processes = 0;
             job->total_processes = 0;
             job->limit_flags = 0;
             job->terminating = 0;
+            job->signaled = 0;
             job->completion_port = NULL;
             job->completion_key = 0;
             job->parent = NULL;
-
-            if (!(job->sync = create_event_sync( 1, 0 )))
-            {
-                release_object( job );
-                return NULL;
-            }
         }
     }
     return job;
@@ -417,7 +411,8 @@ static void terminate_job( struct job *job, int exit_code )
         if (process->running_threads) terminate_process( process, NULL, exit_code );
     }
     job->terminating = 0;
-    signal_sync( job->sync );
+    job->signaled = 1;
+    wake_up( &job->obj, 0 );
 }
 
 static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -448,8 +443,6 @@ static void job_destroy( struct object *obj )
         list_remove( &job->parent_job_entry );
         release_object( job->parent );
     }
-
-    if (job->sync) release_object( job->sync );
 }
 
 static void job_dump( struct object *obj, int verbose )
@@ -460,11 +453,10 @@ static void job_dump( struct object *obj, int verbose )
              list_count(&job->process_list), list_count(&job->child_job_list), job->parent );
 }
 
-static struct object *job_get_sync( struct object *obj )
+static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct job *job = (struct job *)obj;
-    assert( obj->ops == &job_ops );
-    return grab_object( job->sync );
+    return job->signaled;
 }
 
 struct ptid_entry
-- 
2.50.1


From 745e311670d5fe26475eeb473e8e28339ba9c8f7 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:02 +0300
Subject: [PATCH 22/57] Revert "server: Use an event sync for thread objects."

This reverts commit 7cdb776d4f0ab660e69a2e4169bbec5bbe0715c1.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/thread.c | 34 +++++++++++++++-------------------
 server/thread.h |  1 -
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index 3003c4bc930..2315e0a6115 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -189,7 +189,7 @@ struct type_descr thread_type =
 };
 
 static void dump_thread( struct object *obj, int verbose );
-static struct object *thread_get_sync( struct object *obj );
+static int thread_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int thread_map_access( struct object *obj, unsigned int access );
 static void thread_poll_event( struct fd *fd, int event );
 static struct list *thread_get_kernel_obj_list( struct object *obj );
@@ -200,13 +200,13 @@ static const struct object_ops thread_ops =
     sizeof(struct thread),      /* size */
     &thread_type,               /* type */
     dump_thread,                /* dump */
-    NULL,                       /* add_queue */
-    NULL,                       /* remove_queue */
-    NULL,                       /* signaled */
-    NULL,                       /* satisfied */
+    add_queue,                  /* add_queue */
+    remove_queue,               /* remove_queue */
+    thread_signaled,            /* signaled */
+    no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    thread_get_sync,            /* get_sync */
+    default_get_sync,           /* get_sync */
     thread_map_access,          /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -396,7 +396,6 @@ static inline void init_thread_structure( struct thread *thread )
 {
     int i;
 
-    thread->sync            = NULL;
     thread->unix_pid        = -1;  /* not known yet */
     thread->unix_tid        = -1;  /* not known yet */
     thread->context         = NULL;
@@ -557,8 +556,11 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
         release_object( thread );
         return NULL;
     }
-    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 ))) goto error;
-    if (!(thread->sync = create_event_sync( 1, 0 ))) goto error;
+    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 )))
+    {
+        release_object( thread );
+        return NULL;
+    }
 
     if (process->desktop)
     {
@@ -573,10 +575,6 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
     set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
     add_process_thread( thread->process, thread );
     return thread;
-
-error:
-    release_object( thread );
-    return NULL;
 }
 
 /* handle a client event */
@@ -653,7 +651,6 @@ static void destroy_thread( struct object *obj )
     release_object( thread->process );
     if (thread->id) free_ptid( thread->id );
     if (thread->token) release_object( thread->token );
-    if (thread->sync) release_object( thread->sync );
 }
 
 /* dump a thread on stdout for debugging purposes */
@@ -666,11 +663,10 @@ static void dump_thread( struct object *obj, int verbose )
              thread->id, thread->unix_pid, thread->unix_tid, thread->state );
 }
 
-static struct object *thread_get_sync( struct object *obj )
+static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
-    struct thread *thread = (struct thread *)obj;
-    assert( obj->ops == &thread_ops );
-    return grab_object( thread->sync );
+    struct thread *mythread = (struct thread *)obj;
+    return (mythread->state == TERMINATED);
 }
 
 static unsigned int thread_map_access( struct object *obj, unsigned int access )
@@ -1581,7 +1577,7 @@ void kill_thread( struct thread *thread, int violent_death )
     }
     kill_console_processes( thread, 0 );
     abandon_mutexes( thread );
-    signal_sync( thread->sync );
+    wake_up( &thread->obj, 0 );
     if (violent_death) send_thread_signal( thread, SIGQUIT );
     cleanup_thread( thread );
     remove_process_thread( thread->process, thread );
diff --git a/server/thread.h b/server/thread.h
index b33a00d9f26..7a4eb983733 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -50,7 +50,6 @@ struct inflight_fd
 struct thread
 {
     struct object          obj;           /* object header */
-    struct event_sync     *sync;          /* sync object for wait/signal */
     struct list            entry;         /* entry in system-wide thread list */
     struct list            proc_entry;    /* entry in per-process thread list */
     struct list            desktop_entry; /* entry in per-desktop thread list */
-- 
2.50.1


From af66a3c89ccf659b0c87ed85ba011da9d5080e92 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:07 +0300
Subject: [PATCH 23/57] Revert "server: Use an event sync for context objects."

This reverts commit ab9ebea38308ac9f8adf7824813b6b3f975ce872.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/thread.c | 45 ++++++++++++++-------------------------------
 1 file changed, 14 insertions(+), 31 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index 2315e0a6115..2f46f837df4 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -130,10 +130,9 @@ static const struct object_ops thread_apc_ops =
 
 struct context
 {
-    struct object           obj;        /* object header */
-    struct event_sync      *sync;       /* sync object for wait/signal */
-    unsigned int            status;     /* status of the context */
-    struct context_data     regs[2];    /* context data */
+    struct object   obj;        /* object header */
+    unsigned int    status;     /* status of the context */
+    struct context_data regs[2];/* context data */
 };
 #define CTX_NATIVE  0  /* context for native machine */
 #define CTX_WOW     1  /* context if thread is inside WoW */
@@ -142,21 +141,20 @@ struct context
 static const unsigned int system_flags = SERVER_CTX_DEBUG_REGISTERS;
 
 static void dump_context( struct object *obj, int verbose );
-static struct object *context_get_sync( struct object *obj );
-static void context_destroy( struct object *obj );
+static int context_signaled( struct object *obj, struct wait_queue_entry *entry );
 
 static const struct object_ops context_ops =
 {
     sizeof(struct context),     /* size */
     &no_type,                   /* type */
     dump_context,               /* dump */
-    NULL,                       /* add_queue */
-    NULL,                       /* remove_queue */
-    NULL,                       /* signaled */
-    NULL,                       /* satisfied */
+    add_queue,                  /* add_queue */
+    remove_queue,               /* remove_queue */
+    context_signaled,           /* signaled */
+    no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    context_get_sync,           /* get_sync */
+    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -167,7 +165,7 @@ static const struct object_ops context_ops =
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
     no_close_handle,            /* close_handle */
-    context_destroy,            /* destroy */
+    no_destroy                  /* destroy */
 };
 
 
@@ -462,35 +460,20 @@ static void dump_context( struct object *obj, int verbose )
 }
 
 
-static struct object *context_get_sync( struct object *obj )
+static int context_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct context *context = (struct context *)obj;
-    assert( obj->ops == &context_ops );
-    return grab_object( context->sync );
+    return context->status != STATUS_PENDING;
 }
 
-static void context_destroy( struct object *obj )
-{
-    struct context *context = (struct context *)obj;
-    assert( obj->ops == &context_ops );
-    if (context->sync) release_object( context->sync );
-}
 
 static struct context *create_thread_context( struct thread *thread )
 {
     struct context *context;
     if (!(context = alloc_object( &context_ops ))) return NULL;
-    context->sync   = NULL;
     context->status = STATUS_PENDING;
     memset( &context->regs, 0, sizeof(context->regs) );
     context->regs[CTX_NATIVE].machine = native_machine;
-
-    if (!(context->sync = create_event_sync( 1, 0 )))
-    {
-        release_object( context );
-        return NULL;
-    }
-
     return context;
 }
 
@@ -606,7 +589,7 @@ static void cleanup_thread( struct thread *thread )
     if (thread->context)
     {
         thread->context->status = STATUS_ACCESS_DENIED;
-        signal_sync( thread->context->sync );
+        wake_up( &thread->context->obj, 0 );
         release_object( thread->context );
         thread->context = NULL;
     }
@@ -1934,7 +1917,7 @@ DECL_HANDLER(select)
         }
         ctx->status = STATUS_SUCCESS;
         current->suspend_cookie = req->cookie;
-        signal_sync( ctx->sync );
+        wake_up( &ctx->obj, 0 );
     }
 
     if (!req->cookie) goto invalid_param;
-- 
2.50.1


From 3ab3463aeceb391ae685d648857e3e903716cdad Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:14 +0300
Subject: [PATCH 24/57] Revert "server: Use an event sync for thread apc
 objects."

This reverts commit 413a06dc4c0a6e90cf8faea0baf39d97fe7ff45b.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/thread.c | 34 ++++++++++++----------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index 2f46f837df4..033f7a1e801 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -85,7 +85,6 @@ struct thread_wait
 struct thread_apc
 {
     struct object       obj;      /* object header */
-    struct event_sync  *sync;     /* sync object for wait/signal */
     struct list         entry;    /* queue linked list */
     struct thread      *caller;   /* thread that queued this apc */
     struct object      *owner;    /* object that queued this apc */
@@ -96,7 +95,7 @@ struct thread_apc
 };
 
 static void dump_thread_apc( struct object *obj, int verbose );
-static struct object *thread_apc_get_sync( struct object *obj );
+static int thread_apc_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void thread_apc_destroy( struct object *obj );
 static void clear_apc_queue( struct list *queue );
 
@@ -105,13 +104,13 @@ static const struct object_ops thread_apc_ops =
     sizeof(struct thread_apc),  /* size */
     &no_type,                   /* type */
     dump_thread_apc,            /* dump */
-    NULL,                       /* add_queue */
-    NULL,                       /* remove_queue */
-    NULL,                       /* signaled */
-    NULL,                       /* satisfied */
+    add_queue,                  /* add_queue */
+    remove_queue,               /* remove_queue */
+    thread_apc_signaled,        /* signaled */
+    no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    thread_apc_get_sync,        /* get_sync */
+    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -668,11 +667,10 @@ static void dump_thread_apc( struct object *obj, int verbose )
     fprintf( stderr, "APC owner=%p type=%u\n", apc->owner, apc->call.type );
 }
 
-static struct object *thread_apc_get_sync( struct object *obj )
+static int thread_apc_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct thread_apc *apc = (struct thread_apc *)obj;
-    assert( obj->ops == &thread_apc_ops );
-    return grab_object( apc->sync );
+    return apc->executed;
 }
 
 static void thread_apc_destroy( struct object *obj )
@@ -688,7 +686,6 @@ static void thread_apc_destroy( struct object *obj )
             async_set_result( apc->owner, apc->call.async_io.status, 0 );
         release_object( apc->owner );
     }
-    if (apc->sync) release_object( apc->sync );
     reserve_obj_unbind( apc->reserve );
 }
 
@@ -699,7 +696,6 @@ static struct thread_apc *create_apc( struct object *owner, const union apc_call
 
     if ((apc = alloc_object( &thread_apc_ops )))
     {
-        apc->sync        = NULL;
         if (call_data) apc->call = *call_data;
         else apc->call.type = APC_NONE;
         apc->caller      = NULL;
@@ -708,12 +704,6 @@ static struct thread_apc *create_apc( struct object *owner, const union apc_call
         apc->executed    = 0;
         apc->result.type = APC_NONE;
         if (owner) grab_object( owner );
-
-        if (!(apc->sync = create_event_sync( 1, 0 )))
-        {
-            release_object( apc );
-            return NULL;
-        }
     }
     return apc;
 }
@@ -1448,7 +1438,7 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty
         if (apc->owner != owner) continue;
         list_remove( &apc->entry );
         apc->executed = 1;
-        signal_sync( apc->sync );
+        wake_up( &apc->obj, 0 );
         release_object( apc );
         return;
     }
@@ -1478,7 +1468,7 @@ static void clear_apc_queue( struct list *queue )
         struct thread_apc *apc = LIST_ENTRY( ptr, struct thread_apc, entry );
         list_remove( &apc->entry );
         apc->executed = 1;
-        signal_sync( apc->sync );
+        wake_up( &apc->obj, 0 );
         release_object( apc );
     }
 }
@@ -1941,7 +1931,7 @@ DECL_HANDLER(select)
             apc->result.create_thread.handle = handle;
             clear_error();  /* ignore errors from the above calls */
         }
-        signal_sync( apc->sync );
+        wake_up( &apc->obj, 0 );
         close_handle( current->process, req->prev_apc );
         release_object( apc );
     }
@@ -1964,7 +1954,7 @@ DECL_HANDLER(select)
         else
         {
             apc->executed = 1;
-            signal_sync( apc->sync );
+            wake_up( &apc->obj, 0 );
         }
         release_object( apc );
     }
-- 
2.50.1


From ab079fe05951759bfdad33eb80424ab6080d8af5 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:20 +0300
Subject: [PATCH 25/57] Revert "server: Use an event sync for fd objects."

This reverts commit 59b580e485cebfcea7d45c994addb3ca784998bf.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/event.c  |  6 +++---
 server/fd.c     | 54 +++++++++++++++++++++----------------------------
 server/object.h |  5 -----
 3 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/server/event.c b/server/event.c
index c69554fc657..e0fd122e6ad 100644
--- a/server/event.c
+++ b/server/event.c
@@ -87,7 +87,7 @@ static const struct object_ops event_sync_ops =
     no_destroy                 /* destroy */
 };
 
-struct event_sync *create_event_sync( int manual, int signaled )
+static struct event_sync *create_event_sync( int manual, int signaled )
 {
     struct event_sync *event;
 
@@ -113,14 +113,14 @@ static int event_sync_signaled( struct object *obj, struct wait_queue_entry *ent
     return event->signaled;
 }
 
-void signal_sync( struct event_sync *event )
+static void signal_sync( struct event_sync *event )
 {
     event->signaled = 1;
     /* wake up all waiters if manual reset, a single one otherwise */
     wake_up( &event->obj, !event->manual );
 }
 
-void reset_sync( struct event_sync *event )
+static void reset_sync( struct event_sync *event )
 {
     event->signaled = 0;
 }
diff --git a/server/fd.c b/server/fd.c
index 8b9133e102b..5f083a2df13 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -134,7 +134,6 @@ struct fd
 {
     struct object        obj;         /* object header */
     const struct fd_ops *fd_ops;      /* file descriptor operations */
-    struct event_sync   *sync;        /* sync object for wait/signal */
     struct inode        *inode;       /* inode that this fd belongs to */
     struct list          inode_entry; /* entry in inode fd list */
     struct closed_fd    *closed;      /* structure to store the unix fd at destroy time */
@@ -151,6 +150,7 @@ struct fd
     int                  unix_fd;     /* unix file descriptor */
     unsigned int         no_fd_status;/* status to return when unix_fd is -1 */
     unsigned int         cacheable :1;/* can the fd be cached on the client side? */
+    unsigned int         signaled :1; /* is the fd signaled? */
     unsigned int         fs_locks :1; /* can we use filesystem locks for this fd? */
     int                  poll_index;  /* index of fd in poll array */
     struct async_queue   read_q;      /* async readers of this fd */
@@ -162,7 +162,7 @@ struct fd
 };
 
 static void fd_dump( struct object *obj, int verbose );
-static struct object *fd_get_sync( struct object *obj );
+static int fd_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void fd_destroy( struct object *obj );
 
 static const struct object_ops fd_ops =
@@ -170,13 +170,13 @@ static const struct object_ops fd_ops =
     sizeof(struct fd),        /* size */
     &no_type,                 /* type */
     fd_dump,                  /* dump */
-    NULL,                     /* add_queue */
-    NULL,                     /* remove_queue */
-    NULL,                     /* signaled */
-    NULL,                     /* satisfied */
+    add_queue,                /* add_queue */
+    remove_queue,             /* remove_queue */
+    fd_signaled,              /* signaled */
+    no_satisfied,             /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    fd_get_sync,              /* get_sync */
+    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
@@ -1645,12 +1645,6 @@ static void fd_dump( struct object *obj, int verbose )
     fprintf( stderr, "\n" );
 }
 
-static struct object *fd_get_sync( struct object *obj )
-{
-    struct fd *fd = (struct fd *)obj;
-    return grab_object( fd->sync );
-}
-
 static void fd_destroy( struct object *obj )
 {
     struct fd *fd = (struct fd *)obj;
@@ -1675,7 +1669,6 @@ static void fd_destroy( struct object *obj )
         if (fd->unix_fd != -1) close( fd->unix_fd );
         free( fd->unix_name );
     }
-    if (fd->sync) release_object( fd->sync );
 }
 
 /* check if the desired access is possible without violating */
@@ -1776,7 +1769,6 @@ static struct fd *alloc_fd_object(void)
     if (!fd) return NULL;
 
     fd->fd_ops     = NULL;
-    fd->sync       = NULL;
     fd->user       = NULL;
     fd->inode      = NULL;
     fd->closed     = NULL;
@@ -1790,6 +1782,7 @@ static struct fd *alloc_fd_object(void)
     fd->nt_name    = NULL;
     fd->nt_namelen = 0;
     fd->cacheable  = 0;
+    fd->signaled   = 1;
     fd->fs_locks   = 1;
     fd->poll_index = -1;
     fd->completion = NULL;
@@ -1800,14 +1793,12 @@ static struct fd *alloc_fd_object(void)
     list_init( &fd->inode_entry );
     list_init( &fd->locks );
 
-    if (!(fd->sync = create_event_sync( 1, 1 ))) goto error;
-    if ((fd->poll_index = add_poll_user( fd )) == -1) goto error;
-
+    if ((fd->poll_index = add_poll_user( fd )) == -1)
+    {
+        release_object( fd );
+        return NULL;
+    }
     return fd;
-
-error:
-    release_object( fd );
-    return NULL;
 }
 
 /* allocate a pseudo fd object, for objects that need to behave like files but don't have a unix fd */
@@ -1818,7 +1809,6 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     if (!fd) return NULL;
 
     fd->fd_ops     = fd_user_ops;
-    fd->sync       = NULL;
     fd->user       = user;
     fd->inode      = NULL;
     fd->closed     = NULL;
@@ -1832,6 +1822,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     fd->nt_namelen = 0;
     fd->unix_fd    = -1;
     fd->cacheable  = 0;
+    fd->signaled   = 1;
     fd->fs_locks   = 0;
     fd->poll_index = -1;
     fd->completion = NULL;
@@ -1842,12 +1833,6 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     init_async_queue( &fd->wait_q );
     list_init( &fd->inode_entry );
     list_init( &fd->locks );
-
-    if (!(fd->sync = create_event_sync( 1, 1 )))
-    {
-        release_object( fd );
-        return NULL;
-    }
     return fd;
 }
 
@@ -2321,8 +2306,8 @@ int is_fd_removable( struct fd *fd )
 void set_fd_signaled( struct fd *fd, int signaled )
 {
     if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return;
-    if (signaled) signal_sync( fd->sync );
-    else reset_sync( fd->sync );
+    fd->signaled = signaled;
+    if (signaled) wake_up( &fd->obj, 0 );
 }
 
 /* check if events are pending and if yes return which one(s) */
@@ -2339,6 +2324,13 @@ int check_fd_events( struct fd *fd, int events )
     return pfd.revents;
 }
 
+static int fd_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct fd *fd = (struct fd *)obj;
+    assert( obj->ops == &fd_ops );
+    return fd->signaled;
+}
+
 /* default get_sync() routine for objects that poll() on an fd */
 struct object *default_fd_get_sync( struct object *obj )
 {
diff --git a/server/object.h b/server/object.h
index d8067b145c7..2ac54876ddf 100644
--- a/server/object.h
+++ b/server/object.h
@@ -221,14 +221,9 @@ static inline void *mem_append( void *ptr, const void *src, data_size_t len )
 
 /* event functions */
 
-struct event_sync;
 struct event;
 struct keyed_event;
 
-extern struct event_sync *create_event_sync( int manual, int signaled );
-extern void signal_sync( struct event_sync *sync );
-extern void reset_sync( struct event_sync *sync );
-
 extern struct event *create_event( struct object *root, const struct unicode_str *name,
                                    unsigned int attr, int manual_reset, int initial_state,
                                    const struct security_descriptor *sd );
-- 
2.50.1


From c7271a6338c36c7a72edcd73f8b42665be565716 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:25 +0300
Subject: [PATCH 26/57] Revert "server: Introduce a new event sync object."

This reverts commit 2d7fa762a4d36e379a76a1d964c0682d4da4f42c.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/event.c | 170 ++++++++++++-------------------------------------
 1 file changed, 42 insertions(+), 128 deletions(-)

diff --git a/server/event.c b/server/event.c
index e0fd122e6ad..8d4a78d988a 100644
--- a/server/event.c
+++ b/server/event.c
@@ -50,122 +50,32 @@ struct type_descr event_type =
     },
 };
 
-struct event_sync
-{
-    struct object  obj;             /* object header */
-    unsigned int   manual : 1;      /* is it a manual reset event? */
-    unsigned int   signaled : 1;    /* event has been signaled */
-};
-
-static void event_sync_dump( struct object *obj, int verbose );
-static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry );
-static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry );
-static int event_sync_signal( struct object *obj, unsigned int access );
-
-static const struct object_ops event_sync_ops =
-{
-    sizeof(struct event_sync), /* size */
-    &no_type,                  /* type */
-    event_sync_dump,           /* dump */
-    add_queue,                 /* add_queue */
-    remove_queue,              /* remove_queue */
-    event_sync_signaled,       /* signaled */
-    event_sync_satisfied,      /* satisfied */
-    event_sync_signal,         /* signal */
-    no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
-    default_map_access,        /* map_access */
-    default_get_sd,            /* get_sd */
-    default_set_sd,            /* set_sd */
-    default_get_full_name,     /* get_full_name */
-    no_lookup_name,            /* lookup_name */
-    directory_link_name,       /* link_name */
-    default_unlink_name,       /* unlink_name */
-    no_open_file,              /* open_file */
-    no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_close_handle,           /* close_handle */
-    no_destroy                 /* destroy */
-};
-
-static struct event_sync *create_event_sync( int manual, int signaled )
-{
-    struct event_sync *event;
-
-    if (!(event = alloc_object( &event_sync_ops ))) return NULL;
-    event->manual   = manual;
-    event->signaled = signaled;
-
-    return event;
-}
-
-static void event_sync_dump( struct object *obj, int verbose )
-{
-    struct event_sync *event = (struct event_sync *)obj;
-    assert( obj->ops == &event_sync_ops );
-    fprintf( stderr, "Event manual=%d signaled=%d\n",
-             event->manual, event->signaled );
-}
-
-static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct event_sync *event = (struct event_sync *)obj;
-    assert( obj->ops == &event_sync_ops );
-    return event->signaled;
-}
-
-static void signal_sync( struct event_sync *event )
-{
-    event->signaled = 1;
-    /* wake up all waiters if manual reset, a single one otherwise */
-    wake_up( &event->obj, !event->manual );
-}
-
-static void reset_sync( struct event_sync *event )
-{
-    event->signaled = 0;
-}
-
-static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct event_sync *event = (struct event_sync *)obj;
-    assert( obj->ops == &event_sync_ops );
-    /* Reset if it's an auto-reset event */
-    if (!event->manual) reset_sync( event );
-}
-
-static int event_sync_signal( struct object *obj, unsigned int access )
-{
-    struct event_sync *event = (struct event_sync *)obj;
-    assert( obj->ops == &event_sync_ops );
-    signal_sync( event );
-    return 1;
-}
-
 struct event
 {
-    struct object      obj;             /* object header */
-    struct event_sync *sync;            /* event sync object */
-    struct list        kernel_object;   /* list of kernel object pointers */
+    struct object  obj;             /* object header */
+    struct list    kernel_object;   /* list of kernel object pointers */
+    int            manual_reset;    /* is it a manual reset event? */
+    int            signaled;        /* event has been signaled */
 };
 
 static void event_dump( struct object *obj, int verbose );
-static struct object *event_get_sync( struct object *obj );
+static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
+static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static int event_signal( struct object *obj, unsigned int access);
 static struct list *event_get_kernel_obj_list( struct object *obj );
-static void event_destroy( struct object *obj );
 
 static const struct object_ops event_ops =
 {
     sizeof(struct event),      /* size */
     &event_type,               /* type */
     event_dump,                /* dump */
-    NULL,                      /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
+    event_signaled,            /* signaled */
+    event_satisfied,           /* satisfied */
     event_signal,              /* signal */
     no_get_fd,                 /* get_fd */
-    event_get_sync,            /* get_sync */
+    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -176,7 +86,7 @@ static const struct object_ops event_ops =
     no_open_file,              /* open_file */
     event_get_kernel_obj_list, /* get_kernel_obj_list */
     no_close_handle,           /* close_handle */
-    event_destroy,             /* destroy */
+    no_destroy                 /* destroy */
 };
 
 
@@ -239,14 +149,9 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            event->sync = NULL;
             list_init( &event->kernel_object );
-
-            if (!(event->sync = create_event_sync( manual_reset, initial_state )))
-            {
-                release_object( event );
-                return NULL;
-            }
+            event->manual_reset = manual_reset;
+            event->signaled     = initial_state;
         }
     }
     return event;
@@ -257,28 +162,47 @@ struct event *get_event_obj( struct process *process, obj_handle_t handle, unsig
     return (struct event *)get_handle_obj( process, handle, access, &event_ops );
 }
 
+static void pulse_event( struct event *event )
+{
+    event->signaled = 1;
+    /* wake up all waiters if manual reset, a single one otherwise */
+    wake_up( &event->obj, !event->manual_reset );
+    event->signaled = 0;
+}
+
 void set_event( struct event *event )
 {
-    signal_sync( event->sync );
+    event->signaled = 1;
+    /* wake up all waiters if manual reset, a single one otherwise */
+    wake_up( &event->obj, !event->manual_reset );
 }
 
 void reset_event( struct event *event )
 {
-    reset_sync( event->sync );
+    event->signaled = 0;
 }
 
 static void event_dump( struct object *obj, int verbose )
 {
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
-    event->sync->obj.ops->dump( &event->sync->obj, verbose );
+    fprintf( stderr, "Event manual=%d signaled=%d\n",
+             event->manual_reset, event->signaled );
 }
 
-static struct object *event_get_sync( struct object *obj )
+static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
-    return grab_object( event->sync );
+    return event->signaled;
+}
+
+static void event_satisfied( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct event *event = (struct event *)obj;
+    assert( obj->ops == &event_ops );
+    /* Reset if it's an auto-reset event */
+    if (!event->manual_reset) event->signaled = 0;
 }
 
 static int event_signal( struct object *obj, unsigned int access )
@@ -301,14 +225,6 @@ static struct list *event_get_kernel_obj_list( struct object *obj )
     return &event->kernel_object;
 }
 
-static void event_destroy( struct object *obj )
-{
-    struct event *event = (struct event *)obj;
-    assert( obj->ops == &event_ops );
-
-    if (event->sync) release_object( event->sync );
-}
-
 struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
                                         unsigned int attr, const struct security_descriptor *sd )
 {
@@ -402,13 +318,11 @@ DECL_HANDLER(event_op)
     struct event *event;
 
     if (!(event = get_event_obj( current->process, req->handle, EVENT_MODIFY_STATE ))) return;
-
-    reply->state = event->sync->signaled;
+    reply->state = event->signaled;
     switch(req->op)
     {
     case PULSE_EVENT:
-        set_event( event );
-        reset_event( event );
+        pulse_event( event );
         break;
     case SET_EVENT:
         set_event( event );
@@ -430,8 +344,8 @@ DECL_HANDLER(query_event)
 
     if (!(event = get_event_obj( current->process, req->handle, EVENT_QUERY_STATE ))) return;
 
-    reply->manual_reset = event->sync->manual;
-    reply->state = event->sync->signaled;
+    reply->manual_reset = event->manual_reset;
+    reply->state = event->signaled;
 
     release_object( event );
 }
-- 
2.50.1


From daa046be5f3fb42f419b7c0c6eb478e39633c47f Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:31 +0300
Subject: [PATCH 27/57] Revert "server: Redirect fd-based objects sync to the
 fd."

This reverts commit 4bd194a99c1440c117a19ff8b38e662ed39a186c.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/change.c     | 10 +++++-----
 server/device.c     | 10 +++++-----
 server/fd.c         | 26 +++++++++-----------------
 server/file.c       | 10 +++++-----
 server/file.h       |  2 +-
 server/mailslot.c   | 20 ++++++++++----------
 server/named_pipe.c | 40 ++++++++++++++++++++--------------------
 server/serial.c     | 10 +++++-----
 server/sock.c       | 10 +++++-----
 9 files changed, 65 insertions(+), 73 deletions(-)

diff --git a/server/change.c b/server/change.c
index be3251a1eef..eaa21732cbb 100644
--- a/server/change.c
+++ b/server/change.c
@@ -109,13 +109,13 @@ static const struct object_ops dir_ops =
     sizeof(struct dir),       /* size */
     &file_type,               /* type */
     dir_dump,                 /* dump */
-    NULL,                     /* add_queue */
-    NULL,                     /* remove_queue */
-    NULL,                     /* signaled */
-    NULL,                     /* satisfied */
+    add_queue,                /* add_queue */
+    remove_queue,             /* remove_queue */
+    default_fd_signaled,      /* signaled */
+    no_satisfied,             /* satisfied */
     no_signal,                /* signal */
     dir_get_fd,               /* get_fd */
-    default_fd_get_sync,      /* get_sync */
+    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     dir_get_sd,               /* get_sd */
     dir_set_sd,               /* set_sd */
diff --git a/server/device.c b/server/device.c
index 892ec98c44f..d4cdacf7132 100644
--- a/server/device.c
+++ b/server/device.c
@@ -215,13 +215,13 @@ static const struct object_ops device_file_ops =
     sizeof(struct device_file),       /* size */
     &file_type,                       /* type */
     device_file_dump,                 /* dump */
-    NULL,                             /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
-    NULL,                             /* satisfied */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    default_fd_signaled,              /* signaled */
+    no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     device_file_get_fd,               /* get_fd */
-    default_fd_get_sync,              /* get_sync */
+    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
diff --git a/server/fd.c b/server/fd.c
index 5f083a2df13..a38394e1cb4 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -162,7 +162,6 @@ struct fd
 };
 
 static void fd_dump( struct object *obj, int verbose );
-static int fd_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void fd_destroy( struct object *obj );
 
 static const struct object_ops fd_ops =
@@ -170,10 +169,10 @@ static const struct object_ops fd_ops =
     sizeof(struct fd),        /* size */
     &no_type,                 /* type */
     fd_dump,                  /* dump */
-    add_queue,                /* add_queue */
-    remove_queue,             /* remove_queue */
-    fd_signaled,              /* signaled */
-    no_satisfied,             /* satisfied */
+    no_add_queue,             /* add_queue */
+    NULL,                     /* remove_queue */
+    NULL,                     /* signaled */
+    NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
     default_get_sync,         /* get_sync */
@@ -2307,7 +2306,7 @@ void set_fd_signaled( struct fd *fd, int signaled )
 {
     if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return;
     fd->signaled = signaled;
-    if (signaled) wake_up( &fd->obj, 0 );
+    if (signaled) wake_up( fd->user, 0 );
 }
 
 /* check if events are pending and if yes return which one(s) */
@@ -2324,20 +2323,13 @@ int check_fd_events( struct fd *fd, int events )
     return pfd.revents;
 }
 
-static int fd_signaled( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct fd *fd = (struct fd *)obj;
-    assert( obj->ops == &fd_ops );
-    return fd->signaled;
-}
-
-/* default get_sync() routine for objects that poll() on an fd */
-struct object *default_fd_get_sync( struct object *obj )
+/* default signaled() routine for objects that poll() on an fd */
+int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct fd *fd = get_obj_fd( obj );
-    struct object *sync = get_obj_sync( &fd->obj );
+    int ret = fd->signaled;
     release_object( fd );
-    return sync;
+    return ret;
 }
 
 /* default get_full_name() routine for objects with an fd */
diff --git a/server/file.c b/server/file.c
index 654b082aa40..708f4e10f88 100644
--- a/server/file.c
+++ b/server/file.c
@@ -120,13 +120,13 @@ static const struct object_ops file_ops =
     sizeof(struct file),          /* size */
     &file_type,                   /* type */
     file_dump,                    /* dump */
-    NULL,                         /* add_queue */
-    NULL,                         /* remove_queue */
-    NULL,                         /* signaled */
-    NULL,                         /* satisfied */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    default_fd_signaled,          /* signaled */
+    no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     file_get_fd,                  /* get_fd */
-    default_fd_get_sync,          /* get_sync */
+    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     file_get_sd,                  /* get_sd */
     file_set_sd,                  /* set_sd */
diff --git a/server/file.h b/server/file.h
index 2a3d83f903f..69c0efdb5b5 100644
--- a/server/file.h
+++ b/server/file.h
@@ -108,7 +108,7 @@ extern void set_fd_signaled( struct fd *fd, int signaled );
 extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(free) __WINE_MALLOC;
 extern void get_nt_name( struct fd *fd, struct unicode_str *name );
 
-extern struct object *default_fd_get_sync( struct object *obj );
+extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
 extern WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_t *ret_len );
 extern int default_fd_get_poll_events( struct fd *fd );
 extern void default_poll_event( struct fd *fd, int event );
diff --git a/server/mailslot.c b/server/mailslot.c
index 430566d044d..15b9909caf2 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -79,13 +79,13 @@ static const struct object_ops mailslot_ops =
     sizeof(struct mailslot),   /* size */
     &file_type,                /* type */
     mailslot_dump,             /* dump */
-    NULL,                      /* add_queue */
-    NULL,                      /* remove_queue */
-    NULL,                      /* signaled */
-    NULL,                      /* satisfied */
+    add_queue,                 /* add_queue */
+    remove_queue,              /* remove_queue */
+    default_fd_signaled,       /* signaled */
+    no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     mailslot_get_fd,           /* get_fd */
-    default_fd_get_sync,       /* get_sync */
+    default_get_sync,          /* get_sync */
     mailslot_map_access,       /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -238,13 +238,13 @@ static const struct object_ops mailslot_device_file_ops =
     sizeof(struct mailslot_device_file),    /* size */
     &file_type,                             /* type */
     mailslot_device_file_dump,              /* dump */
-    NULL,                                   /* add_queue */
-    NULL,                                   /* remove_queue */
-    NULL,                                   /* signaled */
-    NULL,                                   /* satisfied */
+    add_queue,                              /* add_queue */
+    remove_queue,                           /* remove_queue */
+    default_fd_signaled,                    /* signaled */
+    no_satisfied,                           /* satisfied */
     no_signal,                              /* signal */
     mailslot_device_file_get_fd,            /* get_fd */
-    default_fd_get_sync,                    /* get_sync */
+    default_get_sync,                       /* get_sync */
     default_map_access,                     /* map_access */
     default_get_sd,                         /* get_sd */
     default_set_sd,                         /* set_sd */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index e67b25bac5d..d83428233f4 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -165,13 +165,13 @@ static const struct object_ops pipe_server_ops =
     sizeof(struct pipe_server),   /* size */
     &file_type,                   /* type */
     pipe_server_dump,             /* dump */
-    NULL,                         /* add_queue */
-    NULL,                         /* remove_queue */
-    NULL,                         /* signaled */
-    NULL,                         /* satisfied */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    default_fd_signaled,          /* signaled */
+    no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     pipe_end_get_fd,              /* get_fd */
-    default_fd_get_sync,          /* get_sync */
+    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     pipe_end_get_sd,              /* get_sd */
     pipe_end_set_sd,              /* set_sd */
@@ -210,13 +210,13 @@ static const struct object_ops pipe_client_ops =
     sizeof(struct pipe_end),      /* size */
     &file_type,                   /* type */
     pipe_client_dump,             /* dump */
-    NULL,                         /* add_queue */
-    NULL,                         /* remove_queue */
-    NULL,                         /* signaled */
-    NULL,                         /* satisfied */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    default_fd_signaled,          /* signaled */
+    no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     pipe_end_get_fd,              /* get_fd */
-    default_fd_get_sync,          /* get_sync */
+    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     pipe_end_get_sd,              /* get_sd */
     pipe_end_set_sd,              /* set_sd */
@@ -291,13 +291,13 @@ static const struct object_ops named_pipe_device_file_ops =
     sizeof(struct named_pipe_device_file),   /* size */
     &file_type,                              /* type */
     named_pipe_device_file_dump,             /* dump */
-    NULL,                                    /* add_queue */
-    NULL,                                    /* remove_queue */
-    NULL,                                    /* signaled */
-    NULL,                                    /* satisfied */
+    add_queue,                               /* add_queue */
+    remove_queue,                            /* remove_queue */
+    default_fd_signaled,                     /* signaled */
+    no_satisfied,                            /* satisfied */
     no_signal,                               /* signal */
     named_pipe_device_file_get_fd,           /* get_fd */
-    default_fd_get_sync,                     /* get_sync */
+    default_get_sync,                        /* get_sync */
     default_map_access,                      /* map_access */
     default_get_sd,                          /* get_sd */
     default_set_sd,                          /* set_sd */
@@ -342,13 +342,13 @@ static const struct object_ops named_pipe_dir_ops =
     sizeof(struct named_pipe_device_file),   /* size */
     &file_type,                              /* type */
     named_pipe_dir_dump,                     /* dump */
-    NULL,                                    /* add_queue */
-    NULL,                                    /* remove_queue */
-    NULL,                                    /* signaled */
-    NULL,                                    /* satisfied */
+    add_queue,                               /* add_queue */
+    remove_queue,                            /* remove_queue */
+    default_fd_signaled,                     /* signaled */
+    no_satisfied,                            /* satisfied */
     no_signal,                               /* signal */
     named_pipe_dir_get_fd,                   /* get_fd */
-    default_fd_get_sync,                     /* get_sync */
+    default_get_sync,                        /* get_sync */
     default_map_access,                      /* map_access */
     default_get_sd,                          /* get_sd */
     default_set_sd,                          /* set_sd */
diff --git a/server/serial.c b/server/serial.c
index 66cb4aabfbc..fc0939e402b 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -88,13 +88,13 @@ static const struct object_ops serial_ops =
     sizeof(struct serial),        /* size */
     &file_type,                   /* type */
     serial_dump,                  /* dump */
-    NULL,                         /* add_queue */
-    NULL,                         /* remove_queue */
-    NULL,                         /* signaled */
-    NULL,                         /* satisfied */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    default_fd_signaled,          /* signaled */
+    no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     serial_get_fd,                /* get_fd */
-    default_fd_get_sync,          /* get_sync */
+    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/sock.c b/server/sock.c
index 191160562f6..15337fbe2df 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -488,13 +488,13 @@ static const struct object_ops sock_ops =
     sizeof(struct sock),          /* size */
     &file_type,                   /* type */
     sock_dump,                    /* dump */
-    NULL,                         /* add_queue */
-    NULL,                         /* remove_queue */
-    NULL,                         /* signaled */
-    NULL,                         /* satisfied */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    default_fd_signaled,          /* signaled */
+    no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     sock_get_fd,                  /* get_fd */
-    default_fd_get_sync,          /* get_sync */
+    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
-- 
2.50.1


From 6d357dcbf16d2d203fbf239643944143e2f0cf5c Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:38 +0300
Subject: [PATCH 28/57] Revert "server: Add an operation to retrieve an object
 sync."

This reverts commit acde7e3bdcdd5c5f44748dc0b9db624a8cbdf2bc.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/async.c      |  2 --
 server/atom.c       |  1 -
 server/change.c     |  1 -
 server/clipboard.c  |  1 -
 server/completion.c |  2 --
 server/console.c    |  7 -------
 server/debugger.c   |  2 --
 server/device.c     |  4 ----
 server/directory.c  |  2 --
 server/event.c      |  2 --
 server/fd.c         |  4 ----
 server/file.c       |  1 -
 server/handle.c     |  1 -
 server/hook.c       |  1 -
 server/mailslot.c   |  4 ----
 server/mapping.c    |  3 ---
 server/mutex.c      |  1 -
 server/named_pipe.c |  6 ------
 server/object.c     |  7 -------
 server/object.h     |  4 ----
 server/process.c    |  3 ---
 server/queue.c      |  2 --
 server/registry.c   |  1 -
 server/request.c    |  1 -
 server/semaphore.c  |  1 -
 server/serial.c     |  1 -
 server/signal.c     |  1 -
 server/sock.c       |  3 ---
 server/symlink.c    |  1 -
 server/thread.c     | 45 ++++++---------------------------------------
 server/timer.c      |  1 -
 server/token.c      |  1 -
 server/window.c     |  1 -
 server/winstation.c |  2 --
 34 files changed, 6 insertions(+), 114 deletions(-)

diff --git a/server/async.c b/server/async.c
index 4068f744567..62459b18419 100644
--- a/server/async.c
+++ b/server/async.c
@@ -81,7 +81,6 @@ static const struct object_ops async_ops =
     async_satisfied,           /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -703,7 +702,6 @@ static const struct object_ops iosb_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
diff --git a/server/atom.c b/server/atom.c
index f3b0d1abffb..a333c54d006 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -81,7 +81,6 @@ static const struct object_ops atom_table_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/change.c b/server/change.c
index eaa21732cbb..200dd4b4e9e 100644
--- a/server/change.c
+++ b/server/change.c
@@ -115,7 +115,6 @@ static const struct object_ops dir_ops =
     no_satisfied,             /* satisfied */
     no_signal,                /* signal */
     dir_get_fd,               /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     dir_get_sd,               /* get_sd */
     dir_set_sd,               /* set_sd */
diff --git a/server/clipboard.c b/server/clipboard.c
index 59a50354b48..91f159bc7c9 100644
--- a/server/clipboard.c
+++ b/server/clipboard.c
@@ -79,7 +79,6 @@ static const struct object_ops clipboard_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/completion.c b/server/completion.c
index fd623b36d5a..99680ae0680 100644
--- a/server/completion.c
+++ b/server/completion.c
@@ -95,7 +95,6 @@ static const struct object_ops completion_wait_ops =
     completion_wait_satisfied,      /* satisfied */
     no_signal,                      /* signal */
     no_get_fd,                      /* get_fd */
-    default_get_sync,               /* get_sync */
     default_map_access,             /* map_access */
     default_get_sd,                 /* get_sd */
     default_set_sd,                 /* set_sd */
@@ -170,7 +169,6 @@ static const struct object_ops completion_ops =
     no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
diff --git a/server/console.c b/server/console.c
index d3c5317728e..25b8fea0c6c 100644
--- a/server/console.c
+++ b/server/console.c
@@ -87,7 +87,6 @@ static const struct object_ops console_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_get_fd,                   /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -165,7 +164,6 @@ static const struct object_ops console_server_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_server_get_fd,            /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -235,7 +233,6 @@ static const struct object_ops screen_buffer_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     screen_buffer_get_fd,             /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -285,7 +282,6 @@ static const struct object_ops console_device_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -325,7 +321,6 @@ static const struct object_ops console_input_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_input_get_fd,             /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -385,7 +380,6 @@ static const struct object_ops console_output_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_output_get_fd,            /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -444,7 +438,6 @@ static const struct object_ops console_connection_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     console_connection_get_fd,        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
diff --git a/server/debugger.c b/server/debugger.c
index 43d01fbf246..39a740e07e5 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -89,7 +89,6 @@ static const struct object_ops debug_event_ops =
     no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -118,7 +117,6 @@ static const struct object_ops debug_obj_ops =
     no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
diff --git a/server/device.c b/server/device.c
index d4cdacf7132..2e3c5eb5bff 100644
--- a/server/device.c
+++ b/server/device.c
@@ -69,7 +69,6 @@ static const struct object_ops irp_call_ops =
     NULL,                             /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -110,7 +109,6 @@ static const struct object_ops device_manager_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -168,7 +166,6 @@ static const struct object_ops device_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -221,7 +218,6 @@ static const struct object_ops device_file_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     device_file_get_fd,               /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
diff --git a/server/directory.c b/server/directory.c
index c56c216d6d5..7253388d7e1 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -72,7 +72,6 @@ static const struct object_ops object_type_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
@@ -123,7 +122,6 @@ static const struct object_ops directory_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/event.c b/server/event.c
index 8d4a78d988a..ad7c09acc99 100644
--- a/server/event.c
+++ b/server/event.c
@@ -75,7 +75,6 @@ static const struct object_ops event_ops =
     event_satisfied,           /* satisfied */
     event_signal,              /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -123,7 +122,6 @@ static const struct object_ops keyed_event_ops =
     no_satisfied,                /* satisfied */
     no_signal,                   /* signal */
     no_get_fd,                   /* get_fd */
-    default_get_sync,            /* get_sync */
     default_map_access,          /* map_access */
     default_get_sd,              /* get_sd */
     default_set_sd,              /* set_sd */
diff --git a/server/fd.c b/server/fd.c
index a38394e1cb4..085d2f6e368 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -175,7 +175,6 @@ static const struct object_ops fd_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
@@ -217,7 +216,6 @@ static const struct object_ops device_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
@@ -258,7 +256,6 @@ static const struct object_ops inode_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
@@ -301,7 +298,6 @@ static const struct object_ops file_lock_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
diff --git a/server/file.c b/server/file.c
index 708f4e10f88..dc4fb0c0ea5 100644
--- a/server/file.c
+++ b/server/file.c
@@ -126,7 +126,6 @@ static const struct object_ops file_ops =
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     file_get_fd,                  /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     file_get_sd,                  /* get_sd */
     file_set_sd,                  /* set_sd */
diff --git a/server/handle.c b/server/handle.c
index ddcf03accb2..8a90fdc090c 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -129,7 +129,6 @@ static const struct object_ops handle_table_ops =
     NULL,                            /* satisfied */
     no_signal,                       /* signal */
     no_get_fd,                       /* get_fd */
-    default_get_sync,                /* get_sync */
     default_map_access,              /* map_access */
     default_get_sd,                  /* get_sd */
     default_set_sd,                  /* set_sd */
diff --git a/server/hook.c b/server/hook.c
index 7ba1f3ea9bf..4c55c565968 100644
--- a/server/hook.c
+++ b/server/hook.c
@@ -84,7 +84,6 @@ static const struct object_ops hook_table_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/mailslot.c b/server/mailslot.c
index 15b9909caf2..420e3d67345 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -85,7 +85,6 @@ static const struct object_ops mailslot_ops =
     no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     mailslot_get_fd,           /* get_fd */
-    default_get_sync,          /* get_sync */
     mailslot_map_access,       /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -147,7 +146,6 @@ static const struct object_ops mail_writer_ops =
     NULL,                       /* satisfied */
     no_signal,                  /* signal */
     mail_writer_get_fd,         /* get_fd */
-    default_get_sync,           /* get_sync */
     mail_writer_map_access,     /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -213,7 +211,6 @@ static const struct object_ops mailslot_device_ops =
     no_satisfied,                   /* satisfied */
     no_signal,                      /* signal */
     no_get_fd,                      /* get_fd */
-    default_get_sync,               /* get_sync */
     default_map_access,             /* map_access */
     default_get_sd,                 /* get_sd */
     default_set_sd,                 /* set_sd */
@@ -244,7 +241,6 @@ static const struct object_ops mailslot_device_file_ops =
     no_satisfied,                           /* satisfied */
     no_signal,                              /* signal */
     mailslot_device_file_get_fd,            /* get_fd */
-    default_get_sync,                       /* get_sync */
     default_map_access,                     /* map_access */
     default_get_sd,                         /* get_sd */
     default_set_sd,                         /* set_sd */
diff --git a/server/mapping.c b/server/mapping.c
index c3f57b6394c..7edadcbbeda 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -70,7 +70,6 @@ static const struct object_ops ranges_ops =
     NULL,                      /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -107,7 +106,6 @@ static const struct object_ops shared_map_ops =
     NULL,                      /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -181,7 +179,6 @@ static const struct object_ops mapping_ops =
     NULL,                        /* satisfied */
     no_signal,                   /* signal */
     mapping_get_fd,              /* get_fd */
-    default_get_sync,            /* get_sync */
     default_map_access,          /* map_access */
     default_get_sd,              /* get_sd */
     default_set_sd,              /* set_sd */
diff --git a/server/mutex.c b/server/mutex.c
index 4737b6f711b..af0efe72132 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -76,7 +76,6 @@ static const struct object_ops mutex_ops =
     mutex_satisfied,           /* satisfied */
     mutex_signal,              /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index d83428233f4..f1263013bf1 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -122,7 +122,6 @@ static const struct object_ops named_pipe_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     named_pipe_map_access,        /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
@@ -171,7 +170,6 @@ static const struct object_ops pipe_server_ops =
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     pipe_end_get_fd,              /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     pipe_end_get_sd,              /* get_sd */
     pipe_end_set_sd,              /* set_sd */
@@ -216,7 +214,6 @@ static const struct object_ops pipe_client_ops =
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     pipe_end_get_fd,              /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     pipe_end_get_sd,              /* get_sd */
     pipe_end_set_sd,              /* set_sd */
@@ -265,7 +262,6 @@ static const struct object_ops named_pipe_device_ops =
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
-    default_get_sync,                 /* get_sync */
     default_map_access,               /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -297,7 +293,6 @@ static const struct object_ops named_pipe_device_file_ops =
     no_satisfied,                            /* satisfied */
     no_signal,                               /* signal */
     named_pipe_device_file_get_fd,           /* get_fd */
-    default_get_sync,                        /* get_sync */
     default_map_access,                      /* map_access */
     default_get_sd,                          /* get_sd */
     default_set_sd,                          /* set_sd */
@@ -348,7 +343,6 @@ static const struct object_ops named_pipe_dir_ops =
     no_satisfied,                            /* satisfied */
     no_signal,                               /* signal */
     named_pipe_dir_get_fd,                   /* get_fd */
-    default_get_sync,                        /* get_sync */
     default_map_access,                      /* map_access */
     default_get_sd,                          /* get_sd */
     default_set_sd,                          /* set_sd */
diff --git a/server/object.c b/server/object.c
index 9371ca0ef4c..1ff8ede0efc 100644
--- a/server/object.c
+++ b/server/object.c
@@ -112,7 +112,6 @@ static const struct object_ops apc_reserve_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -137,7 +136,6 @@ static const struct object_ops completion_reserve_ops =
     no_satisfied,              /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -643,11 +641,6 @@ struct fd *no_get_fd( struct object *obj )
     return NULL;
 }
 
-struct object *default_get_sync( struct object *obj )
-{
-    return grab_object( obj );
-}
-
 unsigned int default_map_access( struct object *obj, unsigned int access )
 {
     return map_access( access, &obj->ops->type->mapping );
diff --git a/server/object.h b/server/object.h
index 2ac54876ddf..f9f4a5f7462 100644
--- a/server/object.h
+++ b/server/object.h
@@ -84,8 +84,6 @@ struct object_ops
     int  (*signal)(struct object *, unsigned int);
     /* return an fd object that can be used to read/write from the object */
     struct fd *(*get_fd)(struct object *);
-    /* return a sync that can be used to wait/signal the object */
-    struct object *(*get_sync)(struct object *);
     /* map access rights to the specific rights for this object */
     unsigned int (*map_access)(struct object *, unsigned int);
     /* returns the security descriptor of the object */
@@ -172,8 +170,6 @@ extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
 extern void no_satisfied( struct object *obj, struct wait_queue_entry *entry );
 extern int no_signal( struct object *obj, unsigned int access );
 extern struct fd *no_get_fd( struct object *obj );
-extern struct object *default_get_sync( struct object *obj );
-static inline struct object *get_obj_sync( struct object *obj ) { return obj->ops->get_sync( obj ); }
 extern unsigned int default_map_access( struct object *obj, unsigned int access );
 extern struct security_descriptor *default_get_sd( struct object *obj );
 extern int default_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info );
diff --git a/server/process.c b/server/process.c
index f90e725ca93..5561461dc95 100644
--- a/server/process.c
+++ b/server/process.c
@@ -109,7 +109,6 @@ static const struct object_ops process_ops =
     no_satisfied,                /* satisfied */
     no_signal,                   /* signal */
     no_get_fd,                   /* get_fd */
-    default_get_sync,            /* get_sync */
     process_map_access,          /* map_access */
     process_get_sd,              /* get_sd */
     default_set_sd,              /* set_sd */
@@ -161,7 +160,6 @@ static const struct object_ops startup_info_ops =
     no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
@@ -223,7 +221,6 @@ static const struct object_ops job_ops =
     no_satisfied,                  /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
diff --git a/server/queue.c b/server/queue.c
index 4b8fdf677fd..f57ea874ee5 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -169,7 +169,6 @@ static const struct object_ops msg_queue_ops =
     msg_queue_satisfied,       /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
@@ -207,7 +206,6 @@ static const struct object_ops thread_input_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/registry.c b/server/registry.c
index b59bd63f9c6..082cc462e21 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -183,7 +183,6 @@ static const struct object_ops key_ops =
     NULL,                    /* satisfied */
     no_signal,               /* signal */
     no_get_fd,               /* get_fd */
-    default_get_sync,        /* get_sync */
     key_map_access,          /* map_access */
     key_get_sd,              /* get_sd */
     default_set_sd,          /* set_sd */
diff --git a/server/request.c b/server/request.c
index 835ea30cec3..2254315b79e 100644
--- a/server/request.c
+++ b/server/request.c
@@ -92,7 +92,6 @@ static const struct object_ops master_socket_ops =
     NULL,                          /* satisfied */
     no_signal,                     /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
diff --git a/server/semaphore.c b/server/semaphore.c
index 304a821bcec..53b42a886df 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -73,7 +73,6 @@ static const struct object_ops semaphore_ops =
     semaphore_satisfied,           /* satisfied */
     semaphore_signal,              /* signal */
     no_get_fd,                     /* get_fd */
-    default_get_sync,              /* get_sync */
     default_map_access,            /* map_access */
     default_get_sd,                /* get_sd */
     default_set_sd,                /* set_sd */
diff --git a/server/serial.c b/server/serial.c
index fc0939e402b..209f2e9174e 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -94,7 +94,6 @@ static const struct object_ops serial_ops =
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     serial_get_fd,                /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/signal.c b/server/signal.c
index 078951af6e4..19b76d44c16 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -65,7 +65,6 @@ static const struct object_ops handler_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
diff --git a/server/sock.c b/server/sock.c
index 15337fbe2df..1c22af5e1db 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -494,7 +494,6 @@ static const struct object_ops sock_ops =
     no_satisfied,                 /* satisfied */
     no_signal,                    /* signal */
     sock_get_fd,                  /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
@@ -3897,7 +3896,6 @@ static const struct object_ops ifchange_ops =
     no_satisfied,            /* satisfied */
     no_signal,               /* signal */
     ifchange_get_fd,         /* get_fd */
-    default_get_sync,        /* get_sync */
     default_map_access,      /* map_access */
     default_get_sd,          /* get_sd */
     default_set_sd,          /* set_sd */
@@ -4119,7 +4117,6 @@ static const struct object_ops socket_device_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
diff --git a/server/symlink.c b/server/symlink.c
index 238dcfad1c7..55638a502bd 100644
--- a/server/symlink.c
+++ b/server/symlink.c
@@ -74,7 +74,6 @@ static const struct object_ops symlink_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
diff --git a/server/thread.c b/server/thread.c
index 033f7a1e801..f3528711b99 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -110,7 +110,6 @@ static const struct object_ops thread_apc_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -153,7 +152,6 @@ static const struct object_ops context_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     default_map_access,         /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -203,7 +201,6 @@ static const struct object_ops thread_ops =
     no_satisfied,               /* satisfied */
     no_signal,                  /* signal */
     no_get_fd,                  /* get_fd */
-    default_get_sync,           /* get_sync */
     thread_map_access,          /* map_access */
     default_get_sd,             /* get_sd */
     default_set_sd,             /* set_sd */
@@ -966,36 +963,6 @@ void set_wait_status( struct wait_queue_entry *entry, int status )
     entry->wait->status = status;
 }
 
-static void object_sync_satisfied( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct object *sync = get_obj_sync( obj );
-    sync->ops->satisfied( sync, entry );
-    release_object( sync );
-}
-
-static void object_sync_remove_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct object *sync = get_obj_sync( obj );
-    sync->ops->remove_queue( sync, entry );
-    release_object( sync );
-}
-
-static int object_sync_add_queue( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct object *sync = get_obj_sync( obj );
-    int ret = sync->ops->add_queue( sync, entry );
-    release_object( sync );
-    return ret;
-}
-
-static int object_sync_signaled( struct object *obj, struct wait_queue_entry *entry )
-{
-    struct object *sync = get_obj_sync( obj );
-    int ret = sync->ops->signaled( sync, entry );
-    release_object( sync );
-    return ret;
-}
-
 /* finish waiting */
 static unsigned int end_wait( struct thread *thread, unsigned int status )
 {
@@ -1012,19 +979,19 @@ static unsigned int end_wait( struct thread *thread, unsigned int status )
         if (wait->select == SELECT_WAIT_ALL)
         {
             for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
-                object_sync_satisfied( entry->obj, entry );
+                entry->obj->ops->satisfied( entry->obj, entry );
         }
         else
         {
             entry = wait->queues + status;
-            object_sync_satisfied( entry->obj, entry );
+            entry->obj->ops->satisfied( entry->obj, entry );
         }
         status = wait->status;
         if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0;
     }
     for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
     {
-        object_sync_remove_queue( entry->obj, entry );
+        entry->obj->ops->remove_queue( entry->obj, entry );
         release_object( entry->obj );
         entry->obj = NULL;
     }
@@ -1057,7 +1024,7 @@ static int wait_on( const union select_op *select_op, unsigned int count, struct
     {
         struct object *obj = objects[i];
         entry->wait = wait;
-        if (!object_sync_add_queue( obj, entry ))
+        if (!obj->ops->add_queue( obj, entry ))
         {
             wait->count = i;
             end_wait( current, get_error() );
@@ -1112,13 +1079,13 @@ static int check_wait( struct thread *thread )
         /* Note: we must check them all anyway, as some objects may
          * want to do something when signaled, even if others are not */
         for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
-            not_ok |= !object_sync_signaled( entry->obj, entry );
+            not_ok |= !entry->obj->ops->signaled( entry->obj, entry );
         if (!not_ok) return STATUS_WAIT_0;
     }
     else
     {
         for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
-            if (object_sync_signaled( entry->obj, entry )) return i;
+            if (entry->obj->ops->signaled( entry->obj, entry )) return i;
     }
 
     if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
diff --git a/server/timer.c b/server/timer.c
index f85fa66ed47..bfd74de5d4b 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -79,7 +79,6 @@ static const struct object_ops timer_ops =
     timer_satisfied,           /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     default_set_sd,            /* set_sd */
diff --git a/server/token.c b/server/token.c
index 5ce7298211e..3cdb9e5be5f 100644
--- a/server/token.c
+++ b/server/token.c
@@ -148,7 +148,6 @@ static const struct object_ops token_ops =
     NULL,                      /* satisfied */
     no_signal,                 /* signal */
     no_get_fd,                 /* get_fd */
-    default_get_sync,          /* get_sync */
     default_map_access,        /* map_access */
     default_get_sd,            /* get_sd */
     token_set_sd,              /* set_sd */
diff --git a/server/window.c b/server/window.c
index 0729534ad6c..1cad3989f6d 100644
--- a/server/window.c
+++ b/server/window.c
@@ -111,7 +111,6 @@ static const struct object_ops window_ops =
     NULL,                     /* satisfied */
     no_signal,                /* signal */
     no_get_fd,                /* get_fd */
-    default_get_sync,         /* get_sync */
     default_map_access,       /* map_access */
     default_get_sd,           /* get_sd */
     default_set_sd,           /* set_sd */
diff --git a/server/winstation.c b/server/winstation.c
index bb5596f9a03..b3746090ccf 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -79,7 +79,6 @@ static const struct object_ops winstation_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
@@ -120,7 +119,6 @@ static const struct object_ops desktop_ops =
     NULL,                         /* satisfied */
     no_signal,                    /* signal */
     no_get_fd,                    /* get_fd */
-    default_get_sync,             /* get_sync */
     default_map_access,           /* map_access */
     default_get_sd,               /* get_sd */
     default_set_sd,               /* set_sd */
-- 
2.50.1


From 9c69c7fb6d77966d59e6efdaf953f0908961c21d Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 16:03:42 +0300
Subject: [PATCH 29/57] Revert "server: Move object grab/release out of
 (add|remove)_queue."

This reverts commit 465d29d35f8b75bff6856f9bee8535804ed6ced5.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/thread.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index f3528711b99..b580220c02a 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -928,6 +928,8 @@ int resume_thread( struct thread *thread )
 /* add a thread to an object wait queue; return 1 if OK, 0 on error */
 int add_queue( struct object *obj, struct wait_queue_entry *entry )
 {
+    grab_object( obj );
+    entry->obj = obj;
     list_add_tail( &obj->wait_queue, &entry->entry );
     return 1;
 }
@@ -936,6 +938,7 @@ int add_queue( struct object *obj, struct wait_queue_entry *entry )
 void remove_queue( struct object *obj, struct wait_queue_entry *entry )
 {
     list_remove( &entry->entry );
+    release_object( obj );
 }
 
 struct thread *get_wait_queue_thread( struct wait_queue_entry *entry )
@@ -990,11 +993,7 @@ static unsigned int end_wait( struct thread *thread, unsigned int status )
         if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0;
     }
     for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
-    {
         entry->obj->ops->remove_queue( entry->obj, entry );
-        release_object( entry->obj );
-        entry->obj = NULL;
-    }
     if (wait->user) remove_timeout_user( wait->user );
     free( wait );
     return status;
@@ -1031,7 +1030,6 @@ static int wait_on( const union select_op *select_op, unsigned int count, struct
             return 0;
         }
 
-        entry->obj = grab_object( obj );
         if (obj == (struct object *)current->queue) idle = 1;
     }
 
-- 
2.50.1


From 6d59cd4ab0f3bf852a4680fdf3a25b3c29740716 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 10 Feb 2025 16:18:15 -0600
Subject: [PATCH 30/57] ntdll: Add stub functions for in-process
 synchronization.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/sync.c | 114 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 117915beb19..1c36532f13b 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -301,6 +301,59 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at
 }
 
 
+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
+                             BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
+                                        BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
 /******************************************************************************
  *              NtCreateSemaphore (NTDLL.@)
  */
@@ -375,6 +428,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
 
     if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
 
+    if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED)
+    {
+        if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION);
+        return ret;
+    }
+
     SERVER_START_REQ( query_semaphore )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -397,6 +456,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
 {
     unsigned int ret;
 
+    TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous );
+
+    if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     SERVER_START_REQ( release_semaphore )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -473,6 +537,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
 {
     unsigned int ret;
 
+    TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+
+    if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     SERVER_START_REQ( event_op )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -492,6 +561,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
 {
     unsigned int ret;
 
+    TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+
+    if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     SERVER_START_REQ( event_op )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -521,6 +595,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
 {
     unsigned int ret;
 
+    TRACE( "handle %p, prev_state %p\n", handle, prev_state );
+
+    if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     SERVER_START_REQ( event_op )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -552,6 +631,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class,
 
     if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
 
+    if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED)
+    {
+        if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION);
+        return ret;
+    }
+
     SERVER_START_REQ( query_event )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -627,6 +712,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
 {
     unsigned int ret;
 
+    TRACE( "handle %p, prev_count %p\n", handle, prev_count );
+
+    if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     SERVER_START_REQ( release_mutex )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -657,6 +747,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class,
 
     if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
 
+    if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED)
+    {
+        if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION);
+        return ret;
+    }
+
     SERVER_START_REQ( query_mutex )
     {
         req->handle = wine_server_obj_handle( handle );
@@ -1572,11 +1668,25 @@ NTSTATUS WINAPI NtQueryTimer( HANDLE handle, TIMER_INFORMATION_CLASS class,
 NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
                                           BOOLEAN alertable, const LARGE_INTEGER *timeout )
 {
+    unsigned int ret;
     union select_op select_op;
     UINT i, flags = SELECT_INTERRUPTIBLE;
 
     if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
 
+    if (TRACE_ON(sync))
+    {
+        TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] );
+        for (i = 1; i < count; i++) TRACE( ", %p", handles[i] );
+        TRACE( "}, timeout %s\n", debugstr_timeout(timeout) );
+    }
+
+    if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED)
+    {
+        TRACE( "-> %#x\n", ret );
+        return ret;
+    }
+
     if (alertable) flags |= SELECT_ALERTABLE;
     select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
     for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
@@ -1601,9 +1711,13 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
 {
     union select_op select_op;
     UINT flags = SELECT_INTERRUPTIBLE;
+    NTSTATUS ret;
 
     if (!signal) return STATUS_INVALID_HANDLE;
 
+    if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED)
+        return ret;
+
     if (alertable) flags |= SELECT_ALERTABLE;
     select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT;
     select_op.signal_and_wait.wait = wine_server_obj_handle( wait );
-- 
2.50.1


From 2372e42973d4ee00398f432b6209809e34cf5b0b Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 10 Feb 2025 16:44:49 -0600
Subject: [PATCH 31/57] ntdll: Retrieve and cache an ntsync device in wait
 calls.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 configure                      |   6 ++
 configure.ac                   |   1 +
 dlls/ntdll/unix/server.c       |   8 +--
 dlls/ntdll/unix/sync.c         | 107 +++++++++++++++++++++++++++++++++
 dlls/ntdll/unix/unix_private.h |   3 +
 include/config.h.in            |   3 +
 include/wine/server_protocol.h |  15 +++++
 server/Makefile.in             |   1 +
 server/inproc_sync.c           |  72 ++++++++++++++++++++++
 server/protocol.def            |   5 ++
 server/request_handlers.h      |   3 +
 server/request_trace.h         |   7 +++
 12 files changed, 227 insertions(+), 4 deletions(-)
 create mode 100644 server/inproc_sync.c

diff --git a/configure b/configure
index 248be30dd8f..6d16fef3608 100755
--- a/configure
+++ b/configure
@@ -10001,6 +10001,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes
 then :
   printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h
 
+fi
+ac_fn_c_check_header_compile "$LINENO" "linux/ntsync.h" "ac_cv_header_linux_ntsync_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_ntsync_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_LINUX_NTSYNC_H 1" >>confdefs.h
+
 fi
 ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default"
 if test "x$ac_cv_header_linux_param_h" = xyes
diff --git a/configure.ac b/configure.ac
index 5c142c721fd..48b073935d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -682,6 +682,7 @@ AC_CHECK_HEADERS(\
 	linux/input.h \
 	linux/ioctl.h \
 	linux/major.h \
+	linux/ntsync.h \
 	linux/param.h \
 	linux/seccomp.h \
 	linux/serial.h \
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 1aa0d5c0b8d..8d8f286b3fc 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -124,7 +124,7 @@ sigset_t server_block_set;  /* signals to block during server calls */
 static int fd_socket = -1;  /* socket to exchange file descriptors with the server */
 static int initial_cwd = -1;
 static pid_t server_pid;
-static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /* atomically exchange a 64-bit value */
 static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
@@ -981,7 +981,7 @@ void wine_server_send_fd( int fd )
  *
  * Receive a file descriptor passed from the server.
  */
-static int receive_fd( obj_handle_t *handle )
+int wine_server_receive_fd( obj_handle_t *handle )
 {
     struct iovec vec;
     struct msghdr msghdr;
@@ -1176,7 +1176,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
                 if (type) *type = reply->type;
                 if (options) *options = reply->options;
                 access = reply->access;
-                if ((fd = receive_fd( &fd_handle )) != -1)
+                if ((fd = wine_server_receive_fd( &fd_handle )) != -1)
                 {
                     assert( wine_server_ptr_handle(fd_handle) == handle );
                     *needs_close = (!reply->cacheable ||
@@ -1652,7 +1652,7 @@ size_t server_init_process(void)
     pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
 
     /* receive the first thread request fd on the main socket */
-    ntdll_get_thread_data()->request_fd = receive_fd( &version );
+    ntdll_get_thread_data()->request_fd = wine_server_receive_fd( &version );
 
 #ifdef SO_PASSCRED
     /* now that we hopefully received the server_pid, disable SO_PASSCRED */
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 1c36532f13b..e7b9cac6575 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -57,6 +57,9 @@
 #ifdef HAVE_KQUEUE
 # include <sys/event.h>
 #endif
+#ifdef HAVE_LINUX_NTSYNC_H
+# include <linux/ntsync.h>
+#endif
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -301,6 +304,44 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at
 }
 
 
+#ifdef NTSYNC_IOC_EVENT_READ
+
+static int get_linux_sync_device(void)
+{
+    static LONG device = -2;
+
+    if (device == -2)
+    {
+        obj_handle_t handle;
+        sigset_t sigset;
+        NTSTATUS ret;
+        int fd = -1;
+
+        /* We need to use fd_cache_mutex here to protect against races with
+         * other threads trying to receive fds for the fd cache,
+         * and we need to use an uninterrupted section to prevent reentrancy. */
+        server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+        if (device == -2)
+        {
+            SERVER_START_REQ( get_linux_sync_device )
+            {
+                if (!(ret = wine_server_call( req )))
+                {
+                    fd = wine_server_receive_fd( &handle );
+                    assert( !handle );
+                }
+            }
+            SERVER_END_REQ;
+
+            device = fd;
+        }
+
+        server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+    }
+    return device;
+}
+
 static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count )
 {
     return STATUS_NOT_IMPLEMENTED;
@@ -344,15 +385,81 @@ static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *inf
 static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
                              BOOLEAN alertable, const LARGE_INTEGER *timeout )
 {
+    int device;
+
+    if ((device = get_linux_sync_device()) < 0)
+        return STATUS_NOT_IMPLEMENTED;
+
     return STATUS_NOT_IMPLEMENTED;
 }
 
 static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
                                         BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    int device;
+
+    if ((device = get_linux_sync_device()) < 0)
+        return STATUS_NOT_IMPLEMENTED;
+
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+#else
+
+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info )
 {
     return STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
+                             BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
+                                        BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+#endif
+
 
 /******************************************************************************
  *              NtCreateSemaphore (NTDLL.@)
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 11d8221bdff..b14a6e52d62 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -222,6 +222,8 @@ extern NTSTATUS load_start_exe( UNICODE_STRING *nt_name, void **module );
 extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata );
 extern void start_server( BOOL debug );
 
+extern pthread_mutex_t fd_cache_mutex;
+
 extern unsigned int server_call_unlocked( void *req_ptr );
 extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
 extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
@@ -234,6 +236,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const union apc_ca
 extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
                                int *needs_close, enum server_fd_type *type, unsigned int *options );
 extern void wine_server_send_fd( int fd );
+extern int wine_server_receive_fd( obj_handle_t *handle );
 extern void process_exit_wrapper( int status ) DECLSPEC_NORETURN;
 extern size_t server_init_process(void);
 extern void server_init_process_done(void);
diff --git a/include/config.h.in b/include/config.h.in
index 376d2835ec4..cf05cc62998 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -198,6 +198,9 @@
 /* Define to 1 if you have the <linux/major.h> header file. */
 #undef HAVE_LINUX_MAJOR_H
 
+/* Define to 1 if you have the <linux/ntsync.h> header file. */
+#undef HAVE_LINUX_NTSYNC_H
+
 /* Define to 1 if you have the <linux/param.h> header file. */
 #undef HAVE_LINUX_PARAM_H
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 751297f9720..93d5267fdb1 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -5977,6 +5977,18 @@ struct set_keyboard_repeat_reply
 };
 
 
+
+struct get_linux_sync_device_request
+{
+    struct request_header __header;
+    char __pad_12[4];
+};
+struct get_linux_sync_device_reply
+{
+    struct reply_header __header;
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -6276,6 +6288,7 @@ enum request
     REQ_get_next_process,
     REQ_get_next_thread,
     REQ_set_keyboard_repeat,
+    REQ_get_linux_sync_device,
     REQ_NB_REQUESTS
 };
 
@@ -6580,6 +6593,7 @@ union generic_request
     struct get_next_process_request get_next_process_request;
     struct get_next_thread_request get_next_thread_request;
     struct set_keyboard_repeat_request set_keyboard_repeat_request;
+    struct get_linux_sync_device_request get_linux_sync_device_request;
 };
 union generic_reply
 {
@@ -6882,6 +6896,7 @@ union generic_reply
     struct get_next_process_reply get_next_process_reply;
     struct get_next_thread_reply get_next_thread_reply;
     struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
+    struct get_linux_sync_device_reply get_linux_sync_device_reply;
 };
 
 #define SERVER_PROTOCOL_VERSION 885
diff --git a/server/Makefile.in b/server/Makefile.in
index 6e4e68d6ebf..57250fd0332 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -16,6 +16,7 @@ SOURCES = \
 	file.c \
 	handle.c \
 	hook.c \
+	inproc_sync.c \
 	mach.c \
 	mailslot.c \
 	main.c \
diff --git a/server/inproc_sync.c b/server/inproc_sync.c
new file mode 100644
index 00000000000..de07f674bda
--- /dev/null
+++ b/server/inproc_sync.c
@@ -0,0 +1,72 @@
+/*
+ * In-process synchronization primitives
+ *
+ * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "winternl.h"
+
+#include "file.h"
+#include "handle.h"
+#include "request.h"
+#include "thread.h"
+
+#ifdef HAVE_LINUX_NTSYNC_H
+# include <linux/ntsync.h>
+#endif
+
+#ifdef NTSYNC_IOC_EVENT_READ
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static int get_linux_device(void)
+{
+    static int fd = -2;
+
+    if (fd == -2)
+        fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY );
+
+    return fd;
+}
+
+#endif
+
+
+DECL_HANDLER(get_linux_sync_device)
+{
+#ifdef NTSYNC_IOC_EVENT_READ
+    int fd;
+
+    if ((fd = get_linux_device()) >= 0)
+        send_client_fd( current->process, fd, 0 );
+    else
+        set_error( STATUS_NOT_IMPLEMENTED );
+#else
+    set_error( STATUS_NOT_IMPLEMENTED );
+#endif
+}
diff --git a/server/protocol.def b/server/protocol.def
index 0ca4c0551c4..e84de4368d5 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4143,3 +4143,8 @@ struct handle_info
 @REPLY
     int enable;                /* previous state of auto-repeat enable */
 @END
+
+
+/* Obtain a fd for the ntsync device */
+@REQ(get_linux_sync_device)
+@END
diff --git a/server/request_handlers.h b/server/request_handlers.h
index c28f98a5c3f..dfed7904738 100644
--- a/server/request_handlers.h
+++ b/server/request_handlers.h
@@ -304,6 +304,7 @@ DECL_HANDLER(resume_process);
 DECL_HANDLER(get_next_process);
 DECL_HANDLER(get_next_thread);
 DECL_HANDLER(set_keyboard_repeat);
+DECL_HANDLER(get_linux_sync_device);
 
 typedef void (*req_handler)( const void *req, void *reply );
 static const req_handler req_handlers[REQ_NB_REQUESTS] =
@@ -605,6 +606,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_next_process,
     (req_handler)req_get_next_thread,
     (req_handler)req_set_keyboard_repeat,
+    (req_handler)req_get_linux_sync_device,
 };
 
 C_ASSERT( sizeof(abstime_t) == 8 );
@@ -2302,3 +2304,4 @@ C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 );
 C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
 C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 );
 C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 );
+C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 );
diff --git a/server/request_trace.h b/server/request_trace.h
index ecb3cf6f26a..6fd490ca68e 100644
--- a/server/request_trace.h
+++ b/server/request_trace.h
@@ -3399,6 +3399,10 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep
     fprintf( stderr, " enable=%d", req->enable );
 }
 
+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req )
+{
+}
+
 typedef void (*dump_func)( const void *req );
 
 static const dump_func req_dumpers[REQ_NB_REQUESTS] =
@@ -3700,6 +3704,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_next_process_request,
     (dump_func)dump_get_next_thread_request,
     (dump_func)dump_set_keyboard_repeat_request,
+    (dump_func)dump_get_linux_sync_device_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
@@ -4001,6 +4006,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_next_process_reply,
     (dump_func)dump_get_next_thread_reply,
     (dump_func)dump_set_keyboard_repeat_reply,
+    NULL,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
@@ -4302,6 +4308,7 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "get_next_process",
     "get_next_thread",
     "set_keyboard_repeat",
+    "get_linux_sync_device",
 };
 
 static const struct
-- 
2.50.1


From c3de93b3a7b71de8a61c8b5a7784a2b54f5c90f6 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 14:31:06 -0600
Subject: [PATCH 32/57] server: Add an object operation to retrieve an
 in-process synchronization object.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 include/wine/server_protocol.h | 12 ++++++++++++
 server/async.c                 |  2 ++
 server/atom.c                  |  1 +
 server/change.c                |  1 +
 server/clipboard.c             |  1 +
 server/completion.c            |  2 ++
 server/console.c               |  7 +++++++
 server/debugger.c              |  2 ++
 server/device.c                |  4 ++++
 server/directory.c             |  2 ++
 server/event.c                 |  2 ++
 server/fd.c                    |  4 ++++
 server/file.c                  |  1 +
 server/handle.c                |  1 +
 server/hook.c                  |  1 +
 server/mailslot.c              |  4 ++++
 server/mapping.c               |  3 +++
 server/mutex.c                 |  1 +
 server/named_pipe.c            |  6 ++++++
 server/object.c                |  7 +++++++
 server/object.h                |  7 +++++++
 server/process.c               |  3 +++
 server/protocol.def            | 12 ++++++++++++
 server/queue.c                 |  2 ++
 server/registry.c              |  1 +
 server/request.c               |  1 +
 server/semaphore.c             |  1 +
 server/serial.c                |  1 +
 server/signal.c                |  1 +
 server/sock.c                  |  3 +++
 server/symlink.c               |  1 +
 server/thread.c                |  3 +++
 server/timer.c                 |  1 +
 server/token.c                 |  1 +
 server/window.c                |  1 +
 server/winstation.c            |  2 ++
 36 files changed, 105 insertions(+)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 93d5267fdb1..f7a6a42c405 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -5976,6 +5976,18 @@ struct set_keyboard_repeat_reply
     char __pad_12[4];
 };
 
+enum inproc_sync_type
+{
+    INPROC_SYNC_UNKNOWN,
+    INPROC_SYNC_AUTO_EVENT,
+    INPROC_SYNC_MANUAL_EVENT,
+    INPROC_SYNC_SEMAPHORE,
+    INPROC_SYNC_MUTEX,
+    INPROC_SYNC_AUTO_SERVER,
+    INPROC_SYNC_MANUAL_SERVER,
+    INPROC_SYNC_QUEUE,
+};
+
 
 
 struct get_linux_sync_device_request
diff --git a/server/async.c b/server/async.c
index 62459b18419..f68b4b60006 100644
--- a/server/async.c
+++ b/server/async.c
@@ -90,6 +90,7 @@ static const struct object_ops async_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     async_destroy              /* destroy */
 };
@@ -711,6 +712,7 @@ static const struct object_ops iosb_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     iosb_destroy              /* destroy */
 };
diff --git a/server/atom.c b/server/atom.c
index a333c54d006..7f7a9bc81b7 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -90,6 +90,7 @@ static const struct object_ops atom_table_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     atom_table_destroy            /* destroy */
 };
diff --git a/server/change.c b/server/change.c
index 200dd4b4e9e..f65b865d138 100644
--- a/server/change.c
+++ b/server/change.c
@@ -124,6 +124,7 @@ static const struct object_ops dir_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     dir_close_handle,         /* close_handle */
     dir_destroy               /* destroy */
 };
diff --git a/server/clipboard.c b/server/clipboard.c
index 91f159bc7c9..a2258ae869d 100644
--- a/server/clipboard.c
+++ b/server/clipboard.c
@@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     clipboard_destroy             /* destroy */
 };
diff --git a/server/completion.c b/server/completion.c
index 99680ae0680..ac598e85229 100644
--- a/server/completion.c
+++ b/server/completion.c
@@ -104,6 +104,7 @@ static const struct object_ops completion_wait_ops =
     NULL,                           /* unlink_name */
     no_open_file,                   /* open_file */
     no_kernel_obj_list,             /* get_kernel_obj_list */
+    no_get_inproc_sync,             /* get_inproc_sync */
     no_close_handle,                /* close_handle */
     completion_wait_destroy         /* destroy */
 };
@@ -178,6 +179,7 @@ static const struct object_ops completion_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     completion_close_handle,   /* close_handle */
     completion_destroy         /* destroy */
 };
diff --git a/server/console.c b/server/console.c
index 25b8fea0c6c..7070314ed8d 100644
--- a/server/console.c
+++ b/server/console.c
@@ -96,6 +96,7 @@ static const struct object_ops console_ops =
     NULL,                             /* unlink_name */
     console_open_file,                /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_destroy                   /* destroy */
 };
@@ -173,6 +174,7 @@ static const struct object_ops console_server_ops =
     NULL,                             /* unlink_name */
     console_server_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_server_destroy            /* destroy */
 };
@@ -242,6 +244,7 @@ static const struct object_ops screen_buffer_ops =
     NULL,                             /* unlink_name */
     screen_buffer_open_file,          /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     screen_buffer_destroy             /* destroy */
 };
@@ -291,6 +294,7 @@ static const struct object_ops console_device_ops =
     default_unlink_name,              /* unlink_name */
     console_device_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     no_destroy                        /* destroy */
 };
@@ -330,6 +334,7 @@ static const struct object_ops console_input_ops =
     default_unlink_name,              /* unlink_name */
     console_input_open_file,          /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_input_destroy             /* destroy */
 };
@@ -389,6 +394,7 @@ static const struct object_ops console_output_ops =
     default_unlink_name,              /* unlink_name */
     console_output_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_output_destroy            /* destroy */
 };
@@ -447,6 +453,7 @@ static const struct object_ops console_connection_ops =
     default_unlink_name,              /* unlink_name */
     console_connection_open_file,     /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     console_connection_close_handle,  /* close_handle */
     console_connection_destroy        /* destroy */
 };
diff --git a/server/debugger.c b/server/debugger.c
index 39a740e07e5..cab5f95eefd 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -98,6 +98,7 @@ static const struct object_ops debug_event_ops =
     NULL,                          /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     debug_event_destroy            /* destroy */
 };
@@ -126,6 +127,7 @@ static const struct object_ops debug_obj_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     debug_obj_destroy              /* destroy */
 };
diff --git a/server/device.c b/server/device.c
index 2e3c5eb5bff..1f9ceffd8d0 100644
--- a/server/device.c
+++ b/server/device.c
@@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops =
     NULL,                             /* unlink_name */
     no_open_file,                     /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     irp_call_destroy                  /* destroy */
 };
@@ -118,6 +119,7 @@ static const struct object_ops device_manager_ops =
     NULL,                             /* unlink_name */
     no_open_file,                     /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     device_manager_destroy            /* destroy */
 };
@@ -175,6 +177,7 @@ static const struct object_ops device_ops =
     default_unlink_name,              /* unlink_name */
     device_open_file,                 /* open_file */
     device_get_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     device_destroy                    /* destroy */
 };
@@ -227,6 +230,7 @@ static const struct object_ops device_file_ops =
     NULL,                             /* unlink_name */
     no_open_file,                     /* open_file */
     device_file_get_kernel_obj_list,  /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     device_file_close_handle,         /* close_handle */
     device_file_destroy               /* destroy */
 };
diff --git a/server/directory.c b/server/directory.c
index 7253388d7e1..c2830ffef3d 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -81,6 +81,7 @@ static const struct object_ops object_type_ops =
     default_unlink_name,          /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     no_destroy                    /* destroy */
 };
@@ -131,6 +132,7 @@ static const struct object_ops directory_ops =
     default_unlink_name,          /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     directory_destroy             /* destroy */
 };
diff --git a/server/event.c b/server/event.c
index ad7c09acc99..c19cfa5ba3e 100644
--- a/server/event.c
+++ b/server/event.c
@@ -84,6 +84,7 @@ static const struct object_ops event_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     event_get_kernel_obj_list, /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     no_destroy                 /* destroy */
 };
@@ -131,6 +132,7 @@ static const struct object_ops keyed_event_ops =
     default_unlink_name,         /* unlink_name */
     no_open_file,                /* open_file */
     no_kernel_obj_list,          /* get_kernel_obj_list */
+    no_get_inproc_sync,          /* get_inproc_sync */
     no_close_handle,             /* close_handle */
     no_destroy                   /* destroy */
 };
diff --git a/server/fd.c b/server/fd.c
index 085d2f6e368..c6a0e366aca 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -184,6 +184,7 @@ static const struct object_ops fd_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     fd_destroy                /* destroy */
 };
@@ -225,6 +226,7 @@ static const struct object_ops device_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     device_destroy            /* destroy */
 };
@@ -265,6 +267,7 @@ static const struct object_ops inode_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     inode_destroy             /* destroy */
 };
@@ -307,6 +310,7 @@ static const struct object_ops file_lock_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     no_destroy                  /* destroy */
 };
diff --git a/server/file.c b/server/file.c
index dc4fb0c0ea5..a35da0eb1b3 100644
--- a/server/file.c
+++ b/server/file.c
@@ -135,6 +135,7 @@ static const struct object_ops file_ops =
     NULL,                         /* unlink_name */
     file_open_file,               /* open_file */
     file_get_kernel_obj_list,     /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     file_destroy                  /* destroy */
 };
diff --git a/server/handle.c b/server/handle.c
index 8a90fdc090c..b8e2d3423c0 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops =
     NULL,                            /* unlink_name */
     no_open_file,                    /* open_file */
     no_kernel_obj_list,              /* get_kernel_obj_list */
+    no_get_inproc_sync,              /* get_inproc_sync */
     no_close_handle,                 /* close_handle */
     handle_table_destroy             /* destroy */
 };
diff --git a/server/hook.c b/server/hook.c
index 4c55c565968..fcb3dbcfbea 100644
--- a/server/hook.c
+++ b/server/hook.c
@@ -93,6 +93,7 @@ static const struct object_ops hook_table_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     hook_table_destroy            /* destroy */
 };
diff --git a/server/mailslot.c b/server/mailslot.c
index 420e3d67345..edee2534e6e 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -94,6 +94,7 @@ static const struct object_ops mailslot_ops =
     default_unlink_name,       /* unlink_name */
     mailslot_open_file,        /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     mailslot_destroy           /* destroy */
 };
@@ -155,6 +156,7 @@ static const struct object_ops mail_writer_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     mail_writer_destroy         /* destroy */
 };
@@ -220,6 +222,7 @@ static const struct object_ops mailslot_device_ops =
     default_unlink_name,            /* unlink_name */
     mailslot_device_open_file,      /* open_file */
     no_kernel_obj_list,             /* get_kernel_obj_list */
+    no_get_inproc_sync,             /* get_inproc_sync */
     no_close_handle,                /* close_handle */
     mailslot_device_destroy         /* destroy */
 };
@@ -250,6 +253,7 @@ static const struct object_ops mailslot_device_file_ops =
     NULL,                                   /* unlink_name */
     no_open_file,                           /* open_file */
     no_kernel_obj_list,                     /* get_kernel_obj_list */
+    no_get_inproc_sync,                     /* get_inproc_sync */
     no_close_handle,                        /* close_handle */
     mailslot_device_file_destroy            /* destroy */
 };
diff --git a/server/mapping.c b/server/mapping.c
index 7edadcbbeda..5cd62e2fb77 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -79,6 +79,7 @@ static const struct object_ops ranges_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     ranges_destroy             /* destroy */
 };
@@ -115,6 +116,7 @@ static const struct object_ops shared_map_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     shared_map_destroy         /* destroy */
 };
@@ -188,6 +190,7 @@ static const struct object_ops mapping_ops =
     default_unlink_name,         /* unlink_name */
     no_open_file,                /* open_file */
     no_kernel_obj_list,          /* get_kernel_obj_list */
+    no_get_inproc_sync,          /* get_inproc_sync */
     no_close_handle,             /* close_handle */
     mapping_destroy              /* destroy */
 };
diff --git a/server/mutex.c b/server/mutex.c
index af0efe72132..4218423ebac 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -85,6 +85,7 @@ static const struct object_ops mutex_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     mutex_destroy              /* destroy */
 };
diff --git a/server/named_pipe.c b/server/named_pipe.c
index f1263013bf1..8713c2a8360 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops =
     default_unlink_name,          /* unlink_name */
     named_pipe_open_file,         /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     named_pipe_destroy            /* destroy */
 };
@@ -179,6 +180,7 @@ static const struct object_ops pipe_server_ops =
     NULL,                         /* unlink_name */
     pipe_server_open_file,        /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     async_close_obj_handle,       /* close_handle */
     pipe_server_destroy           /* destroy */
 };
@@ -223,6 +225,7 @@ static const struct object_ops pipe_client_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     async_close_obj_handle,       /* close_handle */
     pipe_end_destroy              /* destroy */
 };
@@ -271,6 +274,7 @@ static const struct object_ops named_pipe_device_ops =
     default_unlink_name,              /* unlink_name */
     named_pipe_device_open_file,      /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
+    no_get_inproc_sync,               /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     named_pipe_device_destroy         /* destroy */
 };
@@ -302,6 +306,7 @@ static const struct object_ops named_pipe_device_file_ops =
     NULL,                                    /* unlink_name */
     no_open_file,                            /* open_file */
     no_kernel_obj_list,                      /* get_kernel_obj_list */
+    no_get_inproc_sync,                      /* get_inproc_sync */
     no_close_handle,                         /* close_handle */
     named_pipe_device_file_destroy           /* destroy */
 };
@@ -352,6 +357,7 @@ static const struct object_ops named_pipe_dir_ops =
     NULL,                                    /* unlink_name */
     named_pipe_dir_open_file,                /* open_file */
     no_kernel_obj_list,                      /* get_kernel_obj_list */
+    no_get_inproc_sync,                      /* get_inproc_sync */
     no_close_handle,                         /* close_handle */
     named_pipe_dir_destroy                   /* destroy */
 };
diff --git a/server/object.c b/server/object.c
index 1ff8ede0efc..cdc7ed5353b 100644
--- a/server/object.c
+++ b/server/object.c
@@ -121,6 +121,7 @@ static const struct object_ops apc_reserve_ops =
     default_unlink_name,        /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     no_destroy                  /* destroy */
 };
@@ -145,6 +146,7 @@ static const struct object_ops completion_reserve_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     no_destroy                 /* destroy */
 };
@@ -641,6 +643,11 @@ struct fd *no_get_fd( struct object *obj )
     return NULL;
 }
 
+int no_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    return -1;
+}
+
 unsigned int default_map_access( struct object *obj, unsigned int access )
 {
     return map_access( access, &obj->ops->type->mapping );
diff --git a/server/object.h b/server/object.h
index f9f4a5f7462..07f4bb67d6b 100644
--- a/server/object.h
+++ b/server/object.h
@@ -42,6 +42,7 @@ struct async;
 struct async_queue;
 struct winstation;
 struct object_type;
+struct inproc_sync;
 
 
 struct unicode_str
@@ -103,6 +104,8 @@ struct object_ops
                                 unsigned int options);
     /* return list of kernel objects */
     struct list *(*get_kernel_obj_list)(struct object *);
+    /* get a client-waitable in-process synchronization fd for this object */
+    int (*get_inproc_sync)(struct object *, enum inproc_sync_type *type);
     /* close a handle to this object */
     int (*close_handle)(struct object *,struct process *,obj_handle_t);
     /* destroy on refcount == 0 */
@@ -234,6 +237,10 @@ extern void reset_event( struct event *event );
 
 extern void abandon_mutexes( struct thread *thread );
 
+/* in-process synchronization functions */
+
+extern int no_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
+
 /* serial functions */
 
 int get_serial_async_timeout(struct object *obj, int type, int count);
diff --git a/server/process.c b/server/process.c
index 5561461dc95..d5f3c1963cb 100644
--- a/server/process.c
+++ b/server/process.c
@@ -118,6 +118,7 @@ static const struct object_ops process_ops =
     NULL,                        /* unlink_name */
     no_open_file,                /* open_file */
     process_get_kernel_obj_list, /* get_kernel_obj_list */
+    no_get_inproc_sync,          /* get_inproc_sync */
     no_close_handle,             /* close_handle */
     process_destroy              /* destroy */
 };
@@ -169,6 +170,7 @@ static const struct object_ops startup_info_ops =
     NULL,                          /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     startup_info_destroy           /* destroy */
 };
@@ -230,6 +232,7 @@ static const struct object_ops job_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     job_close_handle,              /* close_handle */
     job_destroy                    /* destroy */
 };
diff --git a/server/protocol.def b/server/protocol.def
index e84de4368d5..1ed8960d303 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4144,6 +4144,18 @@ struct handle_info
     int enable;                /* previous state of auto-repeat enable */
 @END
 
+enum inproc_sync_type
+{
+    INPROC_SYNC_UNKNOWN,
+    INPROC_SYNC_AUTO_EVENT,
+    INPROC_SYNC_MANUAL_EVENT,
+    INPROC_SYNC_SEMAPHORE,
+    INPROC_SYNC_MUTEX,
+    INPROC_SYNC_AUTO_SERVER,
+    INPROC_SYNC_MANUAL_SERVER,
+    INPROC_SYNC_QUEUE,
+};
+
 
 /* Obtain a fd for the ntsync device */
 @REQ(get_linux_sync_device)
diff --git a/server/queue.c b/server/queue.c
index f57ea874ee5..23fb453aedb 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -178,6 +178,7 @@ static const struct object_ops msg_queue_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     msg_queue_destroy          /* destroy */
 };
@@ -215,6 +216,7 @@ static const struct object_ops thread_input_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     thread_input_destroy          /* destroy */
 };
diff --git a/server/registry.c b/server/registry.c
index 082cc462e21..d28a7793257 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -192,6 +192,7 @@ static const struct object_ops key_ops =
     key_unlink_name,         /* unlink_name */
     no_open_file,            /* open_file */
     no_kernel_obj_list,      /* get_kernel_obj_list */
+    no_get_inproc_sync,      /* get_inproc_sync */
     key_close_handle,        /* close_handle */
     key_destroy              /* destroy */
 };
diff --git a/server/request.c b/server/request.c
index 2254315b79e..24a4f779e68 100644
--- a/server/request.c
+++ b/server/request.c
@@ -101,6 +101,7 @@ static const struct object_ops master_socket_ops =
     NULL,                          /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     master_socket_destroy          /* destroy */
 };
diff --git a/server/semaphore.c b/server/semaphore.c
index 53b42a886df..094741bf36d 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -82,6 +82,7 @@ static const struct object_ops semaphore_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
+    no_get_inproc_sync,            /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     no_destroy                     /* destroy */
 };
diff --git a/server/serial.c b/server/serial.c
index 209f2e9174e..df242058a43 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -103,6 +103,7 @@ static const struct object_ops serial_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     serial_destroy                /* destroy */
 };
diff --git a/server/signal.c b/server/signal.c
index 19b76d44c16..85d16baa98c 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -74,6 +74,7 @@ static const struct object_ops handler_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     handler_destroy           /* destroy */
 };
diff --git a/server/sock.c b/server/sock.c
index 1c22af5e1db..a4353c9963a 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -503,6 +503,7 @@ static const struct object_ops sock_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     sock_close_handle,            /* close_handle */
     sock_destroy                  /* destroy */
 };
@@ -3905,6 +3906,7 @@ static const struct object_ops ifchange_ops =
     NULL,                    /* unlink_name */
     no_open_file,            /* open_file */
     no_kernel_obj_list,      /* get_kernel_obj_list */
+    no_get_inproc_sync,      /* get_inproc_sync */
     no_close_handle,         /* close_handle */
     ifchange_destroy         /* destroy */
 };
@@ -4126,6 +4128,7 @@ static const struct object_ops socket_device_ops =
     default_unlink_name,        /* unlink_name */
     socket_device_open_file,    /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     no_destroy                  /* destroy */
 };
diff --git a/server/symlink.c b/server/symlink.c
index 55638a502bd..5f8db81eec9 100644
--- a/server/symlink.c
+++ b/server/symlink.c
@@ -83,6 +83,7 @@ static const struct object_ops symlink_ops =
     default_unlink_name,          /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     symlink_destroy               /* destroy */
 };
diff --git a/server/thread.c b/server/thread.c
index b580220c02a..b0bd041d7ba 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -119,6 +119,7 @@ static const struct object_ops thread_apc_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     thread_apc_destroy          /* destroy */
 };
@@ -161,6 +162,7 @@ static const struct object_ops context_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     no_destroy                  /* destroy */
 };
@@ -210,6 +212,7 @@ static const struct object_ops thread_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     thread_get_kernel_obj_list, /* get_kernel_obj_list */
+    no_get_inproc_sync,         /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     destroy_thread              /* destroy */
 };
diff --git a/server/timer.c b/server/timer.c
index bfd74de5d4b..0fb36338959 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -88,6 +88,7 @@ static const struct object_ops timer_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     timer_destroy              /* destroy */
 };
diff --git a/server/token.c b/server/token.c
index 3cdb9e5be5f..87cfde364be 100644
--- a/server/token.c
+++ b/server/token.c
@@ -157,6 +157,7 @@ static const struct object_ops token_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
+    no_get_inproc_sync,        /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     token_destroy              /* destroy */
 };
diff --git a/server/window.c b/server/window.c
index 1cad3989f6d..5978022866f 100644
--- a/server/window.c
+++ b/server/window.c
@@ -120,6 +120,7 @@ static const struct object_ops window_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
+    no_get_inproc_sync,       /* get_inproc_sync */
     no_close_handle,          /* close_handle */
     window_destroy            /* destroy */
 };
diff --git a/server/winstation.c b/server/winstation.c
index b3746090ccf..4b8a4972971 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -88,6 +88,7 @@ static const struct object_ops winstation_ops =
     default_unlink_name,          /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     winstation_close_handle,      /* close_handle */
     winstation_destroy            /* destroy */
 };
@@ -128,6 +129,7 @@ static const struct object_ops desktop_ops =
     default_unlink_name,          /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
+    no_get_inproc_sync,           /* get_inproc_sync */
     desktop_close_handle,         /* close_handle */
     desktop_destroy               /* destroy */
 };
-- 
2.50.1


From 12dac72205f3beb885210e8087b63e6c44c139e8 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 13 Mar 2025 14:09:42 -0500
Subject: [PATCH 33/57] server: Create in-process synchronization objects for
 events.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/event.c       | 65 ++++++++++++++++++++++++++++++++++----------
 server/inproc_sync.c | 59 ++++++++++++++++++++++++++++++++++++++++
 server/object.h      |  4 +++
 3 files changed, 113 insertions(+), 15 deletions(-)

diff --git a/server/event.c b/server/event.c
index c19cfa5ba3e..6f1b0bec022 100644
--- a/server/event.c
+++ b/server/event.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -55,7 +56,11 @@ struct event
     struct object  obj;             /* object header */
     struct list    kernel_object;   /* list of kernel object pointers */
     int            manual_reset;    /* is it a manual reset event? */
-    int            signaled;        /* event has been signaled */
+    union
+    {
+        int        signaled;        /* event has been signaled */
+        int        inproc_sync;     /* in-process synchronization object */
+    } u;
 };
 
 static void event_dump( struct object *obj, int verbose );
@@ -63,6 +68,8 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static int event_signal( struct object *obj, unsigned int access);
 static struct list *event_get_kernel_obj_list( struct object *obj );
+static int event_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
+static void event_destroy( struct object *obj );
 
 static const struct object_ops event_ops =
 {
@@ -84,9 +91,9 @@ static const struct object_ops event_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     event_get_kernel_obj_list, /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    event_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,           /* close_handle */
-    no_destroy                 /* destroy */
+    event_destroy              /* destroy */
 };
 
 
@@ -151,7 +158,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
             /* initialize it if it didn't already exist */
             list_init( &event->kernel_object );
             event->manual_reset = manual_reset;
-            event->signaled     = initial_state;
+            if (use_inproc_sync())
+                event->u.inproc_sync = create_inproc_event( event->manual_reset, initial_state );
+            else
+                event->u.signaled = initial_state;
         }
     }
     return event;
@@ -164,22 +174,32 @@ struct event *get_event_obj( struct process *process, obj_handle_t handle, unsig
 
 static void pulse_event( struct event *event )
 {
-    event->signaled = 1;
+    event->u.signaled = 1;
     /* wake up all waiters if manual reset, a single one otherwise */
     wake_up( &event->obj, !event->manual_reset );
-    event->signaled = 0;
+    event->u.signaled = 0;
 }
 
 void set_event( struct event *event )
 {
-    event->signaled = 1;
-    /* wake up all waiters if manual reset, a single one otherwise */
-    wake_up( &event->obj, !event->manual_reset );
+    if (use_inproc_sync())
+    {
+        set_inproc_event( event->u.inproc_sync );
+    }
+    else
+    {
+        event->u.signaled = 1;
+        /* wake up all waiters if manual reset, a single one otherwise */
+        wake_up( &event->obj, !event->manual_reset );
+    }
 }
 
 void reset_event( struct event *event )
 {
-    event->signaled = 0;
+    if (use_inproc_sync())
+        reset_inproc_event( event->u.inproc_sync );
+    else
+        event->u.signaled = 0;
 }
 
 static void event_dump( struct object *obj, int verbose )
@@ -187,14 +207,14 @@ static void event_dump( struct object *obj, int verbose )
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
     fprintf( stderr, "Event manual=%d signaled=%d\n",
-             event->manual_reset, event->signaled );
+             event->manual_reset, event->u.signaled );
 }
 
 static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
-    return event->signaled;
+    return event->u.signaled;
 }
 
 static void event_satisfied( struct object *obj, struct wait_queue_entry *entry )
@@ -202,7 +222,7 @@ static void event_satisfied( struct object *obj, struct wait_queue_entry *entry
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
     /* Reset if it's an auto-reset event */
-    if (!event->manual_reset) event->signaled = 0;
+    if (!event->manual_reset) event->u.signaled = 0;
 }
 
 static int event_signal( struct object *obj, unsigned int access )
@@ -225,6 +245,21 @@ static struct list *event_get_kernel_obj_list( struct object *obj )
     return &event->kernel_object;
 }
 
+static int event_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct event *event = (struct event *)obj;
+
+    *type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT;
+    return event->u.inproc_sync;
+}
+
+static void event_destroy( struct object *obj )
+{
+    struct event *event = (struct event *)obj;
+
+    if (use_inproc_sync()) close( event->u.inproc_sync );
+}
+
 struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
                                         unsigned int attr, const struct security_descriptor *sd )
 {
@@ -318,7 +353,7 @@ DECL_HANDLER(event_op)
     struct event *event;
 
     if (!(event = get_event_obj( current->process, req->handle, EVENT_MODIFY_STATE ))) return;
-    reply->state = event->signaled;
+    reply->state = event->u.signaled;
     switch(req->op)
     {
     case PULSE_EVENT:
@@ -345,7 +380,7 @@ DECL_HANDLER(query_event)
     if (!(event = get_event_obj( current->process, req->handle, EVENT_QUERY_STATE ))) return;
 
     reply->manual_reset = event->manual_reset;
-    reply->state = event->signaled;
+    reply->state = event->u.signaled;
 
     release_object( event );
 }
diff --git a/server/inproc_sync.c b/server/inproc_sync.c
index de07f674bda..da148496285 100644
--- a/server/inproc_sync.c
+++ b/server/inproc_sync.c
@@ -54,6 +54,65 @@ static int get_linux_device(void)
     return fd;
 }
 
+int use_inproc_sync(void)
+{
+    return 0;
+}
+
+int create_inproc_event( int manual_reset, int signaled )
+{
+    struct ntsync_event_args args;
+    int device;
+
+    if ((device = get_linux_device()) < 0) return -1;
+
+    args.signaled = signaled;
+    args.manual = manual_reset;
+    return ioctl( device, NTSYNC_IOC_CREATE_EVENT, &args );
+}
+
+void set_inproc_event( int event )
+{
+    __u32 count;
+
+    if (!use_inproc_sync()) return;
+
+    if (debug_level) fprintf( stderr, "set_inproc_event %d\n", event );
+
+    ioctl( event, NTSYNC_IOC_EVENT_SET, &count );
+}
+
+void reset_inproc_event( int event )
+{
+    __u32 count;
+
+    if (!use_inproc_sync()) return;
+
+    if (debug_level) fprintf( stderr, "reset_inproc_event %d\n", event );
+
+    ioctl( event, NTSYNC_IOC_EVENT_RESET, &count );
+}
+
+#else
+
+int use_inproc_sync(void)
+{
+    return 0;
+}
+
+int create_inproc_event( int manual_reset, int signaled )
+{
+    return -1;
+}
+
+void set_inproc_event( int event )
+{
+}
+
+void reset_inproc_event( int event )
+{
+}
+
 #endif
 
 
diff --git a/server/object.h b/server/object.h
index 07f4bb67d6b..ba99feb1a05 100644
--- a/server/object.h
+++ b/server/object.h
@@ -239,7 +239,11 @@ extern void abandon_mutexes( struct thread *thread );
 
 /* in-process synchronization functions */
 
+extern int use_inproc_sync(void);
+extern int create_inproc_event( int manual_reset, int signaled );
 extern int no_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
+extern void set_inproc_event( int event );
+extern void reset_inproc_event( int event );
 
 /* serial functions */
 
-- 
2.50.1


From 97b9c292e99baba88eb401ed25b695e67bf5aa6c Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 13 Mar 2025 14:32:22 -0500
Subject: [PATCH 34/57] server: Create in-process synchronization objects for
 semaphores.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/inproc_sync.c | 17 ++++++++++++
 server/object.h      |  1 +
 server/semaphore.c   | 66 ++++++++++++++++++++++++++++++++------------
 3 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/server/inproc_sync.c b/server/inproc_sync.c
index da148496285..f2aee9ece3f 100644
--- a/server/inproc_sync.c
+++ b/server/inproc_sync.c
@@ -71,6 +71,18 @@ int create_inproc_event( int manual_reset, int signaled )
     return ioctl( device, NTSYNC_IOC_CREATE_EVENT, &args );
 }
 
+int create_inproc_semaphore( unsigned int count, unsigned int max )
+{
+    struct ntsync_sem_args args;
+    int device;
+
+    if ((device = get_linux_device()) < 0) return -1;
+
+    args.count = count;
+    args.max = max;
+    return ioctl( device, NTSYNC_IOC_CREATE_SEM, &args );
+}
+
 void set_inproc_event( int event )
 {
     __u32 count;
@@ -105,6 +117,11 @@ int create_inproc_event( int manual_reset, int signaled )
     return -1;
 }
 
+int create_inproc_semaphore( unsigned int count, unsigned int max )
+{
+    return -1;
+}
+
 void set_inproc_event( int event )
 {
 }
diff --git a/server/object.h b/server/object.h
index ba99feb1a05..eea8705912d 100644
--- a/server/object.h
+++ b/server/object.h
@@ -241,6 +241,7 @@ extern void abandon_mutexes( struct thread *thread );
 
 extern int use_inproc_sync(void);
 extern int create_inproc_event( int manual_reset, int signaled );
+extern int create_inproc_semaphore( unsigned int count, unsigned int max );
 extern int no_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 extern void set_inproc_event( int event );
 extern void reset_inproc_event( int event );
diff --git a/server/semaphore.c b/server/semaphore.c
index 094741bf36d..f3b8179f5fe 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -53,14 +54,23 @@ struct type_descr semaphore_type =
 struct semaphore
 {
     struct object  obj;    /* object header */
-    unsigned int   count;  /* current count */
-    unsigned int   max;    /* maximum possible count */
+    union
+    {
+        struct
+        {
+            unsigned int count;  /* current count */
+            unsigned int max;    /* maximum possible count */
+        } s;
+        int inproc_sync;         /* in-process synchronization object */
+    } u;
 };
 
 static void semaphore_dump( struct object *obj, int verbose );
 static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static int semaphore_signal( struct object *obj, unsigned int access );
+static int semaphore_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
+static void semaphore_destroy( struct object *obj );
 
 static const struct object_ops semaphore_ops =
 {
@@ -82,9 +92,9 @@ static const struct object_ops semaphore_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
-    no_get_inproc_sync,            /* get_inproc_sync */
+    semaphore_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,               /* close_handle */
-    no_destroy                     /* destroy */
+    semaphore_destroy              /* destroy */
 };
 
 
@@ -104,8 +114,15 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            sem->count = initial;
-            sem->max   = max;
+            if (use_inproc_sync())
+            {
+                sem->u.inproc_sync = create_inproc_semaphore( initial, max );
+            }
+            else
+            {
+                sem->u.s.count = initial;
+                sem->u.s.max   = max;
+            }
         }
     }
     return sem;
@@ -114,20 +131,20 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni
 static int release_semaphore( struct semaphore *sem, unsigned int count,
                               unsigned int *prev )
 {
-    if (prev) *prev = sem->count;
-    if (sem->count + count < sem->count || sem->count + count > sem->max)
+    if (prev) *prev = sem->u.s.count;
+    if (sem->u.s.count + count < sem->u.s.count || sem->u.s.count + count > sem->u.s.max)
     {
         set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
         return 0;
     }
-    else if (sem->count)
+    else if (sem->u.s.count)
     {
         /* there cannot be any thread to wake up if the count is != 0 */
-        sem->count += count;
+        sem->u.s.count += count;
     }
     else
     {
-        sem->count = count;
+        sem->u.s.count = count;
         wake_up( &sem->obj, count );
     }
     return 1;
@@ -137,22 +154,22 @@ static void semaphore_dump( struct object *obj, int verbose )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
-    fprintf( stderr, "Semaphore count=%d max=%d\n", sem->count, sem->max );
+    fprintf( stderr, "Semaphore count=%d max=%d\n", sem->u.s.count, sem->u.s.max );
 }
 
 static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
-    return (sem->count > 0);
+    return (sem->u.s.count > 0);
 }
 
 static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
-    assert( sem->count );
-    sem->count--;
+    assert( sem->u.s.count );
+    sem->u.s.count--;
 }
 
 static int semaphore_signal( struct object *obj, unsigned int access )
@@ -168,6 +185,21 @@ static int semaphore_signal( struct object *obj, unsigned int access )
     return release_semaphore( sem, 1, NULL );
 }
 
+static int semaphore_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct semaphore *semaphore = (struct semaphore *)obj;
+
+    *type = INPROC_SYNC_SEMAPHORE;
+    return semaphore->u.inproc_sync;
+}
+
+static void semaphore_destroy( struct object *obj )
+{
+    struct semaphore *semaphore = (struct semaphore *)obj;
+
+    if (use_inproc_sync()) close( semaphore->u.inproc_sync );
+}
+
 /* create a semaphore */
 DECL_HANDLER(create_semaphore)
 {
@@ -222,8 +254,8 @@ DECL_HANDLER(query_semaphore)
     if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle,
                                                    SEMAPHORE_QUERY_STATE, &semaphore_ops )))
     {
-        reply->current = sem->count;
-        reply->max = sem->max;
+        reply->current = sem->u.s.count;
+        reply->max = sem->u.s.max;
         release_object( sem );
     }
 }
-- 
2.50.1


From 0b20d8142ae14745dff57d88d986b931e6f61de9 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 13 Mar 2025 14:49:49 -0500
Subject: [PATCH 35/57] server: Create in-process synchronization objects for
 mutexes.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/inproc_sync.c |  26 ++++++++++
 server/mutex.c       | 115 +++++++++++++++++++++++++++++--------------
 server/object.h      |   2 +
 3 files changed, 107 insertions(+), 36 deletions(-)

diff --git a/server/inproc_sync.c b/server/inproc_sync.c
index f2aee9ece3f..6471364c4de 100644
--- a/server/inproc_sync.c
+++ b/server/inproc_sync.c
@@ -83,6 +83,18 @@ int create_inproc_semaphore( unsigned int count, unsigned int max )
     return ioctl( device, NTSYNC_IOC_CREATE_SEM, &args );
 }
 
+int create_inproc_mutex( thread_id_t owner, unsigned int count )
+{
+    struct ntsync_mutex_args args;
+    int device;
+
+    if ((device = get_linux_device()) < 0) return -1;
+
+    args.owner = owner;
+    args.count = count;
+    return ioctl( device, NTSYNC_IOC_CREATE_MUTEX, &args );
+}
+
 void set_inproc_event( int event )
 {
     __u32 count;
@@ -105,6 +117,11 @@ void reset_inproc_event( int event )
     ioctl( event, NTSYNC_IOC_EVENT_RESET, &count );
 }
 
+void abandon_inproc_mutex( thread_id_t tid, int mutex )
+{
+    ioctl( mutex, NTSYNC_IOC_MUTEX_KILL, &tid );
+}
+
 #else
 
 int use_inproc_sync(void)
@@ -122,6 +139,11 @@ int create_inproc_semaphore( unsigned int count, unsigned int max )
     return -1;
 }
 
+int create_inproc_mutex( thread_id_t owner, unsigned int count )
+{
+    return -1;
+}
+
 void set_inproc_event( int event )
 {
 }
@@ -130,6 +152,10 @@ void reset_inproc_event( int event )
 {
 }
 
+void abandon_inproc_mutex( thread_id_t tid, int mutex )
+{
+}
+
 #endif
 
 
diff --git a/server/mutex.c b/server/mutex.c
index 4218423ebac..671e1a77e36 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -38,6 +39,8 @@
 
 static const WCHAR mutex_name[] = {'M','u','t','a','n','t'};
 
+static struct list inproc_mutexes = LIST_INIT(inproc_mutexes);
+
 struct type_descr mutex_type =
 {
     { mutex_name, sizeof(mutex_name) },   /* name */
@@ -53,10 +56,21 @@ struct type_descr mutex_type =
 struct mutex
 {
     struct object  obj;             /* object header */
-    struct thread *owner;           /* mutex owner */
-    unsigned int   count;           /* recursion count */
-    int            abandoned;       /* has it been abandoned? */
-    struct list    entry;           /* entry in owner thread mutex list */
+    union
+    {
+        struct
+        {
+            struct thread *owner;   /* mutex owner */
+            unsigned int count;     /* recursion count */
+            int abandoned;          /* has it been abandoned? */
+            struct list entry;      /* entry in owner thread mutex list */
+        } server;
+        struct
+        {
+            int inproc_sync;        /* in-process synchronization object */
+            struct list entry;      /* entry in inproc_mutexes list */
+        } inproc;
+    } u;
 };
 
 static void mutex_dump( struct object *obj, int verbose );
@@ -64,6 +78,7 @@ static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static void mutex_destroy( struct object *obj );
 static int mutex_signal( struct object *obj, unsigned int access );
+static int mutex_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 
 static const struct object_ops mutex_ops =
 {
@@ -85,7 +100,7 @@ static const struct object_ops mutex_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    mutex_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     mutex_destroy              /* destroy */
 };
@@ -94,23 +109,23 @@ static const struct object_ops mutex_ops =
 /* grab a mutex for a given thread */
 static void do_grab( struct mutex *mutex, struct thread *thread )
 {
-    assert( !mutex->count || (mutex->owner == thread) );
+    assert( !mutex->u.server.count || (mutex->u.server.owner == thread) );
 
-    if (!mutex->count++)  /* FIXME: avoid wrap-around */
+    if (!mutex->u.server.count++)  /* FIXME: avoid wrap-around */
     {
-        assert( !mutex->owner );
-        mutex->owner = thread;
-        list_add_head( &thread->mutex_list, &mutex->entry );
+        assert( !mutex->u.server.owner );
+        mutex->u.server.owner = thread;
+        list_add_head( &thread->mutex_list, &mutex->u.server.entry );
     }
 }
 
 /* release a mutex once the recursion count is 0 */
 static void do_release( struct mutex *mutex )
 {
-    assert( !mutex->count );
+    assert( !mutex->u.server.count );
     /* remove the mutex from the thread list of owned mutexes */
-    list_remove( &mutex->entry );
-    mutex->owner = NULL;
+    list_remove( &mutex->u.server.entry );
+    mutex->u.server.owner = NULL;
     wake_up( &mutex->obj, 0 );
 }
 
@@ -124,10 +139,18 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            mutex->count = 0;
-            mutex->owner = NULL;
-            mutex->abandoned = 0;
-            if (owned) do_grab( mutex, current );
+            if (use_inproc_sync())
+            {
+                mutex->u.inproc.inproc_sync = create_inproc_mutex( owned ? current->id : 0, owned ? 1 : 0 );
+                list_add_tail( &inproc_mutexes, &mutex->u.inproc.entry );
+            }
+            else
+            {
+                mutex->u.server.count = 0;
+                mutex->u.server.owner = NULL;
+                mutex->u.server.abandoned = 0;
+                if (owned) do_grab( mutex, current );
+            }
         }
     }
     return mutex;
@@ -135,30 +158,34 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str
 
 void abandon_mutexes( struct thread *thread )
 {
+    struct mutex *mutex;
     struct list *ptr;
 
     while ((ptr = list_head( &thread->mutex_list )) != NULL)
     {
-        struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry );
-        assert( mutex->owner == thread );
-        mutex->count = 0;
-        mutex->abandoned = 1;
+        mutex = LIST_ENTRY( ptr, struct mutex, u.server.entry );
+        assert( mutex->u.server.owner == thread );
+        mutex->u.server.count = 0;
+        mutex->u.server.abandoned = 1;
         do_release( mutex );
     }
+
+    LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, u.inproc.entry)
+        abandon_inproc_mutex( thread->id, mutex->u.inproc.inproc_sync );
 }
 
 static void mutex_dump( struct object *obj, int verbose )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
+    fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->u.server.count, mutex->u.server.owner );
 }
 
 static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
-    return (!mutex->count || (mutex->owner == get_wait_queue_thread( entry )));
+    return (!mutex->u.server.count || (mutex->u.server.owner == get_wait_queue_thread( entry )));
 }
 
 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry )
@@ -167,8 +194,8 @@ static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry
     assert( obj->ops == &mutex_ops );
 
     do_grab( mutex, get_wait_queue_thread( entry ));
-    if (mutex->abandoned) make_wait_abandoned( entry );
-    mutex->abandoned = 0;
+    if (mutex->u.server.abandoned) make_wait_abandoned( entry );
+    mutex->u.server.abandoned = 0;
 }
 
 static int mutex_signal( struct object *obj, unsigned int access )
@@ -181,23 +208,39 @@ static int mutex_signal( struct object *obj, unsigned int access )
         set_error( STATUS_ACCESS_DENIED );
         return 0;
     }
-    if (!mutex->count || (mutex->owner != current))
+    if (!mutex->u.server.count || (mutex->u.server.owner != current))
     {
         set_error( STATUS_MUTANT_NOT_OWNED );
         return 0;
     }
-    if (!--mutex->count) do_release( mutex );
+    if (!--mutex->u.server.count) do_release( mutex );
     return 1;
 }
 
+static int mutex_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct mutex *mutex = (struct mutex *)obj;
+
+    *type = INPROC_SYNC_MUTEX;
+    return mutex->u.inproc.inproc_sync;
+}
+
 static void mutex_destroy( struct object *obj )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
 
-    if (!mutex->count) return;
-    mutex->count = 0;
-    do_release( mutex );
+    if (use_inproc_sync())
+    {
+        close( mutex->u.inproc.inproc_sync );
+        list_remove( &mutex->u.inproc.entry );
+    }
+    else
+    {
+        if (!mutex->u.server.count) return;
+        mutex->u.server.count = 0;
+        do_release( mutex );
+    }
 }
 
 /* create a mutex */
@@ -241,11 +284,11 @@ DECL_HANDLER(release_mutex)
     if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle,
                                                  0, &mutex_ops )))
     {
-        if (!mutex->count || (mutex->owner != current)) set_error( STATUS_MUTANT_NOT_OWNED );
+        if (!mutex->u.server.count || (mutex->u.server.owner != current)) set_error( STATUS_MUTANT_NOT_OWNED );
         else
         {
-            reply->prev_count = mutex->count;
-            if (!--mutex->count) do_release( mutex );
+            reply->prev_count = mutex->u.server.count;
+            if (!--mutex->u.server.count) do_release( mutex );
         }
         release_object( mutex );
     }
@@ -259,9 +302,9 @@ DECL_HANDLER(query_mutex)
     if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle,
                                                  MUTANT_QUERY_STATE, &mutex_ops )))
     {
-        reply->count = mutex->count;
-        reply->owned = (mutex->owner == current);
-        reply->abandoned = mutex->abandoned;
+        reply->count = mutex->u.server.count;
+        reply->owned = (mutex->u.server.owner == current);
+        reply->abandoned = mutex->u.server.abandoned;
 
         release_object( mutex );
     }
diff --git a/server/object.h b/server/object.h
index eea8705912d..d956b1d45ad 100644
--- a/server/object.h
+++ b/server/object.h
@@ -241,10 +241,12 @@ extern void abandon_mutexes( struct thread *thread );
 
 extern int use_inproc_sync(void);
 extern int create_inproc_event( int manual_reset, int signaled );
+extern int create_inproc_mutex( thread_id_t owner, unsigned int count );
 extern int create_inproc_semaphore( unsigned int count, unsigned int max );
 extern int no_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 extern void set_inproc_event( int event );
 extern void reset_inproc_event( int event );
+extern void abandon_inproc_mutex( thread_id_t tid, int mutex );
 
 /* serial functions */
 
-- 
2.50.1


From 18d25058bf729c589fee11cc5e695dd5cffb3ac8 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 11 Mar 2021 20:32:58 -0600
Subject: [PATCH 36/57] server: Create in-process synchronization objects for
 completion ports.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/completion.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/server/completion.c b/server/completion.c
index ac598e85229..11e39c93a99 100644
--- a/server/completion.c
+++ b/server/completion.c
@@ -25,6 +25,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -77,6 +78,7 @@ struct completion
     struct list    wait_queue;
     unsigned int   depth;
     int            closed;
+    int            inproc_sync;
 };
 
 static void completion_wait_dump( struct object*, int );
@@ -157,6 +159,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent
 static void completion_dump( struct object*, int );
 static int completion_signaled( struct object *obj, struct wait_queue_entry *entry );
 static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
+static int completion_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void completion_destroy( struct object * );
 
 static const struct object_ops completion_ops =
@@ -179,7 +182,7 @@ static const struct object_ops completion_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    completion_get_inproc_sync,/* get_inproc_sync */
     completion_close_handle,   /* close_handle */
     completion_destroy         /* destroy */
 };
@@ -193,6 +196,7 @@ static void completion_destroy( struct object *obj)
     {
         free( tmp );
     }
+    if (use_inproc_sync()) close( completion->inproc_sync );
 }
 
 static void completion_dump( struct object *obj, int verbose )
@@ -230,6 +234,7 @@ static int completion_close_handle( struct object *obj, struct process *process,
     }
     completion->closed = 1;
     wake_up( obj, 0 );
+    set_inproc_event( completion->inproc_sync );
     return 1;
 }
 
@@ -263,6 +268,14 @@ static struct completion_wait *create_completion_wait( struct thread *thread )
     return wait;
 }
 
+static int completion_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct completion *completion = (struct completion *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return completion->inproc_sync;
+}
+
 static struct completion *create_completion( struct object *root, const struct unicode_str *name,
                                              unsigned int attr, unsigned int concurrent,
                                              const struct security_descriptor *sd )
@@ -277,6 +290,7 @@ static struct completion *create_completion( struct object *root, const struct u
             list_init( &completion->wait_queue );
             completion->depth = 0;
             completion->closed = 0;
+            completion->inproc_sync = create_inproc_event( TRUE, FALSE );
         }
     }
 
@@ -309,7 +323,11 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_
         wake_up( &wait->obj, 1 );
         if (list_empty( &completion->queue )) return;
     }
-    if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 );
+    if (!list_empty( &completion->queue ))
+    {
+        wake_up( &completion->obj, 0 );
+        set_inproc_event( completion->inproc_sync );
+    }
 }
 
 /* create a completion */
@@ -410,6 +428,8 @@ DECL_HANDLER(remove_completion)
         reply->information = msg->information;
         free( msg );
         reply->wait_handle = 0;
+        if (list_empty( &completion->queue ))
+            reset_inproc_event( completion->inproc_sync );
     }
 
     release_object( completion );
-- 
2.50.1


From 15e1790ce28c6300a9af0359325f3accb349fc6c Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 16:43:36 -0500
Subject: [PATCH 37/57] server: Create in-process synchronization objects for
 consoles.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/server/console.c b/server/console.c
index 7070314ed8d..58263d5372b 100644
--- a/server/console.c
+++ b/server/console.c
@@ -54,6 +54,7 @@ struct console
 {
     struct object                obj;           /* object header */
     int                          signaled;      /* is console signaled */
+    int                          inproc_sync;   /* in-process synchronization object */
     struct thread               *renderer;      /* console renderer thread */
     struct screen_buffer        *active;        /* active screen buffer */
     struct console_server       *server;        /* console server object */
@@ -74,6 +75,7 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st
                                            unsigned int attr, struct object *root );
 static struct object *console_open_file( struct object *obj, unsigned int access,
                                          unsigned int sharing, unsigned int options );
+static int console_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
 
 static const struct object_ops console_ops =
@@ -96,7 +98,7 @@ static const struct object_ops console_ops =
     NULL,                             /* unlink_name */
     console_open_file,                /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    console_get_inproc_sync,          /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_destroy                   /* destroy */
 };
@@ -547,6 +549,7 @@ static struct object *create_console(void)
 
     console->renderer      = NULL;
     console->signaled      = 0;
+    console->inproc_sync   = create_inproc_event( TRUE, console->signaled );
     console->active        = NULL;
     console->server        = NULL;
     console->fd            = NULL;
@@ -785,6 +788,7 @@ static void console_destroy( struct object *obj )
     free_async_queue( &console->read_q );
     if (console->fd)
         release_object( console->fd );
+    if (use_inproc_sync()) close( console->inproc_sync );
 }
 
 static struct object *create_console_connection( struct console *console )
@@ -838,6 +842,22 @@ static struct object *console_open_file( struct object *obj, unsigned int access
     return grab_object( obj );
 }
 
+static int console_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct console *console = (struct console *)obj;
+
+    /* cf. console_add_queue() */
+    if (console->server && !console->server->once_input)
+    {
+        console->server->once_input = 1;
+        if (console->server->term_fd == -1)
+            queue_host_ioctl( console->server, IOCTL_CONDRV_PEEK, 0, NULL, NULL );
+    }
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return console->inproc_sync;
+}
+
 static void screen_buffer_dump( struct object *obj, int verbose )
 {
     struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
@@ -1583,11 +1603,16 @@ DECL_HANDLER(get_next_console_request)
 
     if (!server->console->renderer) server->console->renderer = current;
 
-    if (!req->signal) server->console->signaled = 0;
+    if (!req->signal)
+    {
+        server->console->signaled = 0;
+        reset_inproc_event( server->console->inproc_sync );
+    }
     else if (!server->console->signaled)
     {
         server->console->signaled = 1;
         wake_up( &server->console->obj, 0 );
+        set_inproc_event( server->console->inproc_sync );
         LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
             wake_up( &screen_buffer->obj, 0 );
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
-- 
2.50.1


From e96aa03e891664e5e0c544233f844de4ff5d0ee1 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 17:06:29 -0500
Subject: [PATCH 38/57] server: Create in-process synchronization objects for
 console servers.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/server/console.c b/server/console.c
index 58263d5372b..a0b553cece7 100644
--- a/server/console.c
+++ b/server/console.c
@@ -145,6 +145,7 @@ struct console_server
     unsigned int          once_input : 1; /* flag if input thread has already been requested */
     int                   term_fd;        /* UNIX terminal fd */
     struct termios        termios;        /* original termios */
+    int                   inproc_sync;    /* in-process synchronization object */
 };
 
 static void console_server_dump( struct object *obj, int verbose );
@@ -155,6 +156,7 @@ static struct object *console_server_lookup_name( struct object *obj, struct uni
                                                 unsigned int attr, struct object *root );
 static struct object *console_server_open_file( struct object *obj, unsigned int access,
                                                 unsigned int sharing, unsigned int options );
+static int console_server_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 
 static const struct object_ops console_server_ops =
 {
@@ -176,7 +178,7 @@ static const struct object_ops console_server_ops =
     NULL,                             /* unlink_name */
     console_server_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    console_server_get_inproc_sync,   /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_server_destroy            /* destroy */
 };
@@ -596,6 +598,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u
     }
     list_add_tail( &server->queue, &ioctl->entry );
     wake_up( &server->obj, 0 );
+    set_inproc_event( server->inproc_sync );
     if (async) set_error( STATUS_PENDING );
     return 1;
 }
@@ -628,6 +631,7 @@ static void disconnect_console_server( struct console_server *server )
         server->console->server = NULL;
         server->console = NULL;
         wake_up( &server->obj, 0 );
+        set_inproc_event( server->inproc_sync );
     }
 }
 
@@ -919,6 +923,7 @@ static void console_server_destroy( struct object *obj )
     assert( obj->ops == &console_server_ops );
     disconnect_console_server( server );
     if (server->fd) release_object( server->fd );
+    if (use_inproc_sync()) close( server->inproc_sync );
 }
 
 static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name,
@@ -979,6 +984,14 @@ static struct object *console_server_open_file( struct object *obj, unsigned int
     return grab_object( obj );
 }
 
+static int console_server_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct console_server *server = (struct console_server *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return server->inproc_sync;
+}
+
 static struct object *create_console_server( void )
 {
     struct console_server *server;
@@ -988,6 +1001,7 @@ static struct object *create_console_server( void )
     server->busy       = 0;
     server->once_input = 0;
     server->term_fd    = -1;
+    server->inproc_sync = create_inproc_event( TRUE, TRUE );
     list_init( &server->queue );
     list_init( &server->read_queue );
     server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT );
@@ -1642,6 +1656,9 @@ DECL_HANDLER(get_next_console_request)
         list_remove( &ioctl->entry );
     }
 
+    if (list_empty( &server->queue ))
+        reset_inproc_event( server->inproc_sync );
+
     if (ioctl)
     {
         struct async *async = ioctl->async;
@@ -1726,5 +1743,8 @@ DECL_HANDLER(get_next_console_request)
         set_error( STATUS_PENDING );
     }
 
+    if (list_empty( &server->queue ))
+        reset_inproc_event( server->inproc_sync );
+
     release_object( server );
 }
-- 
2.50.1


From 8980f628ec6255e321111bad3966a7ee61722fb0 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 17:14:45 -0500
Subject: [PATCH 39/57] server: Create in-process synchronization objects for
 screen buffers.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/server/console.c b/server/console.c
index a0b553cece7..2fde411ea1b 100644
--- a/server/console.c
+++ b/server/console.c
@@ -219,6 +219,7 @@ struct screen_buffer
     unsigned int          id;            /* buffer id */
     struct fd            *fd;            /* for bare console, attached output fd */
     struct async_queue    ioctl_q;       /* ioctl queue */
+    int                   inproc_sync;   /* in-process synchronization object */
 };
 
 static void screen_buffer_dump( struct object *obj, int verbose );
@@ -227,6 +228,7 @@ static int screen_buffer_signaled( struct object *obj, struct wait_queue_entry *
 static struct fd *screen_buffer_get_fd( struct object *obj );
 static struct object *screen_buffer_open_file( struct object *obj, unsigned int access,
                                                unsigned int sharing, unsigned int options );
+static int screen_buffer_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 
 static const struct object_ops screen_buffer_ops =
 {
@@ -248,7 +250,7 @@ static const struct object_ops screen_buffer_ops =
     NULL,                             /* unlink_name */
     screen_buffer_open_file,          /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    screen_buffer_get_inproc_sync,    /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     screen_buffer_destroy             /* destroy */
 };
@@ -660,6 +662,7 @@ static struct object *create_screen_buffer( struct console *console )
 
     screen_buffer->id    = ++console->last_id;
     screen_buffer->input = console;
+    screen_buffer->inproc_sync = create_inproc_event( TRUE, console->signaled );
     init_async_queue( &screen_buffer->ioctl_q );
     list_add_head( &console->screen_buffers, &screen_buffer->entry );
 
@@ -780,7 +783,10 @@ static void console_destroy( struct object *obj )
     console->active = NULL;
 
     LIST_FOR_EACH_ENTRY( curr, &console->screen_buffers, struct screen_buffer, entry )
+    {
         curr->input = NULL;
+        reset_inproc_event( curr->inproc_sync );
+    }
 
     LIST_FOR_EACH_ENTRY( input, &console->inputs, struct console_input, entry )
         input->console = NULL;
@@ -885,6 +891,7 @@ static void screen_buffer_destroy( struct object *obj )
     }
     free_async_queue( &screen_buffer->ioctl_q );
     if (screen_buffer->fd) release_object( screen_buffer->fd );
+    if (use_inproc_sync()) close( screen_buffer->inproc_sync );
 }
 
 static int screen_buffer_signaled( struct object *obj, struct wait_queue_entry *entry )
@@ -901,6 +908,14 @@ static struct object *screen_buffer_open_file( struct object *obj, unsigned int
     return grab_object( obj );
 }
 
+static int screen_buffer_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return screen_buffer->inproc_sync;
+}
+
 static struct fd *screen_buffer_get_fd( struct object *obj )
 {
     struct screen_buffer *screen_buffer = (struct screen_buffer*)obj;
@@ -1621,6 +1636,8 @@ DECL_HANDLER(get_next_console_request)
     {
         server->console->signaled = 0;
         reset_inproc_event( server->console->inproc_sync );
+        LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
+            reset_inproc_event( screen_buffer->inproc_sync );
     }
     else if (!server->console->signaled)
     {
@@ -1628,7 +1645,10 @@ DECL_HANDLER(get_next_console_request)
         wake_up( &server->console->obj, 0 );
         set_inproc_event( server->console->inproc_sync );
         LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
+        {
             wake_up( &screen_buffer->obj, 0 );
+            set_inproc_event( screen_buffer->inproc_sync );
+        }
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
             wake_up( &input->obj, 0 );
         LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
-- 
2.50.1


From 0a538bb8130a0c8385a25a3c6496b5e53ac49e3e Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 17:30:31 -0500
Subject: [PATCH 40/57] server: Create in-process synchronization objects for
 console inputs.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/server/console.c b/server/console.c
index 2fde411ea1b..7c7b0e6ad53 100644
--- a/server/console.c
+++ b/server/console.c
@@ -311,12 +311,14 @@ struct console_input
     struct fd            *fd;          /* pseudo-fd */
     struct list           entry;       /* entry in console->inputs */
     struct console       *console;     /* associated console at creation time */
+    int                   inproc_sync; /* in-process synchronization object */
 };
 
 static void console_input_dump( struct object *obj, int verbose );
 static int console_input_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct object *console_input_open_file( struct object *obj, unsigned int access,
                                                unsigned int sharing, unsigned int options );
+static int console_input_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static struct fd *console_input_get_fd( struct object *obj );
 static void console_input_destroy( struct object *obj );
 
@@ -340,7 +342,7 @@ static const struct object_ops console_input_ops =
     default_unlink_name,              /* unlink_name */
     console_input_open_file,          /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    console_input_get_inproc_sync,    /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_input_destroy             /* destroy */
 };
@@ -789,7 +791,10 @@ static void console_destroy( struct object *obj )
     }
 
     LIST_FOR_EACH_ENTRY( input, &console->inputs, struct console_input, entry )
+    {
         input->console = NULL;
+        reset_inproc_event( input->inproc_sync );
+    }
 
     LIST_FOR_EACH_ENTRY( output, &console->outputs, struct console_output, entry )
         output->console = NULL;
@@ -1402,6 +1407,7 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
         }
         console_input->console = current->process->console;
         list_add_head( &current->process->console->inputs, &console_input->entry );
+        console_input->inproc_sync = create_inproc_event( TRUE, current->process->console->signaled );
         return &console_input->obj;
     }
 
@@ -1500,6 +1506,14 @@ static struct object *console_input_open_file( struct object *obj, unsigned int
     return grab_object( obj );
 }
 
+static int console_input_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct console_input *console_input = (struct console_input *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return console_input->inproc_sync;
+}
+
 static void console_input_destroy( struct object *obj )
 {
     struct console_input *console_input = (struct console_input *)obj;
@@ -1507,6 +1521,7 @@ static void console_input_destroy( struct object *obj )
     assert( obj->ops == &console_input_ops );
     if (console_input->fd) release_object( console_input->fd );
     if (console_input->console) list_remove( &console_input->entry );
+    if (use_inproc_sync()) close( console_input->inproc_sync );
 }
 
 static void console_input_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
@@ -1638,6 +1653,8 @@ DECL_HANDLER(get_next_console_request)
         reset_inproc_event( server->console->inproc_sync );
         LIST_FOR_EACH_ENTRY( screen_buffer, &server->console->screen_buffers, struct screen_buffer, entry )
             reset_inproc_event( screen_buffer->inproc_sync );
+        LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
+            reset_inproc_event( input->inproc_sync );
     }
     else if (!server->console->signaled)
     {
@@ -1650,7 +1667,10 @@ DECL_HANDLER(get_next_console_request)
             set_inproc_event( screen_buffer->inproc_sync );
         }
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
+        {
             wake_up( &input->obj, 0 );
+            set_inproc_event( input->inproc_sync );
+        }
         LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
             wake_up( &output->obj, 0 );
     }
-- 
2.50.1


From 6c54e77e240761338d3a72be51cc3bbe19fb89c7 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 17:35:15 -0500
Subject: [PATCH 41/57] server: Create in-process synchronization objects for
 console outputs.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/console.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/server/console.c b/server/console.c
index 7c7b0e6ad53..ee8a50aad8d 100644
--- a/server/console.c
+++ b/server/console.c
@@ -373,6 +373,7 @@ struct console_output
     struct fd            *fd;          /* pseudo-fd */
     struct list           entry;       /* entry in console->outputs */
     struct console       *console;     /* associated console at creation time */
+    int                   inproc_sync; /* in-process synchronization object */
 };
 
 static void console_output_dump( struct object *obj, int verbose );
@@ -380,6 +381,7 @@ static int console_output_signaled( struct object *obj, struct wait_queue_entry
 static struct fd *console_output_get_fd( struct object *obj );
 static struct object *console_output_open_file( struct object *obj, unsigned int access,
                                                 unsigned int sharing, unsigned int options );
+static int console_output_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void console_output_destroy( struct object *obj );
 
 static const struct object_ops console_output_ops =
@@ -402,7 +404,7 @@ static const struct object_ops console_output_ops =
     default_unlink_name,              /* unlink_name */
     console_output_open_file,         /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    console_output_get_inproc_sync,   /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     console_output_destroy            /* destroy */
 };
@@ -797,7 +799,10 @@ static void console_destroy( struct object *obj )
     }
 
     LIST_FOR_EACH_ENTRY( output, &console->outputs, struct console_output, entry )
+    {
         output->console = NULL;
+        reset_inproc_event( output->inproc_sync );
+    }
 
     free_async_queue( &console->ioctl_q );
     free_async_queue( &console->read_q );
@@ -1432,6 +1437,7 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
         }
         console_output->console = current->process->console;
         list_add_head( &current->process->console->outputs, &console_output->entry );
+        console_output->inproc_sync = create_inproc_event( TRUE, current->process->console->signaled );
         return &console_output->obj;
     }
 
@@ -1586,6 +1592,14 @@ static struct object *console_output_open_file( struct object *obj, unsigned int
     return grab_object( obj );
 }
 
+static int console_output_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct console_output *console_output = (struct console_output *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return console_output->inproc_sync;
+}
+
 static void console_output_destroy( struct object *obj )
 {
     struct console_output *console_output = (struct console_output *)obj;
@@ -1593,6 +1607,7 @@ static void console_output_destroy( struct object *obj )
     assert( obj->ops == &console_output_ops );
     if (console_output->fd) release_object( console_output->fd );
     if (console_output->console) list_remove( &console_output->entry );
+    if (use_inproc_sync()) close( console_output->inproc_sync );
 }
 
 static void console_output_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
@@ -1655,6 +1670,8 @@ DECL_HANDLER(get_next_console_request)
             reset_inproc_event( screen_buffer->inproc_sync );
         LIST_FOR_EACH_ENTRY( input, &server->console->inputs, struct console_input, entry )
             reset_inproc_event( input->inproc_sync );
+        LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
+            reset_inproc_event( output->inproc_sync );
     }
     else if (!server->console->signaled)
     {
@@ -1672,7 +1689,10 @@ DECL_HANDLER(get_next_console_request)
             set_inproc_event( input->inproc_sync );
         }
         LIST_FOR_EACH_ENTRY( output, &server->console->outputs, struct console_output, entry )
+        {
             wake_up( &output->obj, 0 );
+            set_inproc_event( output->inproc_sync );
+        }
     }
 
     if (req->read)
-- 
2.50.1


From 64ce583ef340943844718b10eb2e2d5e00a2c77c Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:11:03 -0600
Subject: [PATCH 42/57] server: Create in-process synchronization objects for
 debug objects.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/debugger.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/server/debugger.c b/server/debugger.c
index cab5f95eefd..2aaa87ed792 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -71,6 +71,7 @@ struct debug_obj
     struct object        obj;         /* object header */
     struct list          event_queue; /* pending events queue */
     unsigned int         flags;       /* debug flags */
+    int                  inproc_sync; /* in-process synchronization object */
 };
 
 
@@ -105,6 +106,7 @@ static const struct object_ops debug_event_ops =
 
 static void debug_obj_dump( struct object *obj, int verbose );
 static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int debug_obj_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void debug_obj_destroy( struct object *obj );
 
 static const struct object_ops debug_obj_ops =
@@ -127,7 +129,7 @@ static const struct object_ops debug_obj_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
-    no_get_inproc_sync,            /* get_inproc_sync */
+    debug_obj_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,               /* close_handle */
     debug_obj_destroy              /* destroy */
 };
@@ -255,6 +257,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event )
         /* grab reference since debugger could be killed while trying to wake up */
         grab_object( debug_obj );
         wake_up( &debug_obj->obj, 0 );
+        set_inproc_event( debug_obj->inproc_sync );
         release_object( debug_obj );
     }
 }
@@ -267,6 +270,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event
     {
         grab_object( debug_obj );
         wake_up( &debug_obj->obj, 0 );
+        set_inproc_event( debug_obj->inproc_sync );
         release_object( debug_obj );
     }
 }
@@ -332,6 +336,14 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr
     return find_event_to_send( debug_obj ) != NULL;
 }
 
+static int debug_obj_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct debug_obj *debug_obj = (struct debug_obj *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return debug_obj->inproc_sync;
+}
+
 static void debug_obj_destroy( struct object *obj )
 {
     struct list *ptr;
@@ -344,6 +356,8 @@ static void debug_obj_destroy( struct object *obj )
     /* free all pending events */
     while ((ptr = list_head( &debug_obj->event_queue )))
         unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry ));
+
+    if (use_inproc_sync()) close( debug_obj->inproc_sync );
 }
 
 struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access )
@@ -363,6 +377,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni
         {
             debug_obj->flags = flags;
             list_init( &debug_obj->event_queue );
+            debug_obj->inproc_sync = create_inproc_event( TRUE, FALSE );
         }
     }
     return debug_obj;
@@ -571,6 +586,9 @@ DECL_HANDLER(wait_debug_event)
         reply->tid = get_thread_id( event->sender );
         alloc_event_handles( event, current->process );
         set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) ));
+
+        if (!find_event_to_send( debug_obj ))
+            reset_inproc_event( debug_obj->inproc_sync );
     }
     else
     {
-- 
2.50.1


From 99a8416aa0210a633b2a4a204564473f1e6c14e2 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 10 Mar 2021 11:02:42 -0600
Subject: [PATCH 43/57] server: Create in-process synchronization objects for
 device managers.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/device.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/server/device.c b/server/device.c
index 1f9ceffd8d0..3c2bee4c485 100644
--- a/server/device.c
+++ b/server/device.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -93,10 +94,12 @@ struct device_manager
     struct list            requests;       /* list of pending irps across all devices */
     struct irp_call       *current_call;   /* call currently executed on client side */
     struct wine_rb_tree    kernel_objects; /* map of objects that have client side pointer associated */
+    int                    inproc_sync;    /* in-process synchronization object */
 };
 
 static void device_manager_dump( struct object *obj, int verbose );
 static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int device_manager_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void device_manager_destroy( struct object *obj );
 
 static const struct object_ops device_manager_ops =
@@ -119,7 +122,7 @@ static const struct object_ops device_manager_ops =
     NULL,                             /* unlink_name */
     no_open_file,                     /* open_file */
     no_kernel_obj_list,               /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    device_manager_get_inproc_sync,   /* get_inproc_sync */
     no_close_handle,                  /* close_handle */
     device_manager_destroy            /* destroy */
 };
@@ -422,7 +425,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i
     irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL;
     if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry );
     list_add_tail( &manager->requests, &irp->mgr_entry );
-    if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 );  /* first one */
+    if (list_head( &manager->requests ) == &irp->mgr_entry)
+    {
+        /* first one */
+        wake_up( &manager->obj, 0 );
+        set_inproc_event( manager->inproc_sync );
+    }
 }
 
 static struct object *device_open_file( struct object *obj, unsigned int access,
@@ -764,6 +772,9 @@ static void delete_file( struct device_file *file )
         set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 );
     }
 
+    if (list_empty( &file->device->manager->requests ))
+        reset_inproc_event( file->device->manager->inproc_sync );
+
     release_object( file );
 }
 
@@ -795,6 +806,14 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry
     return !list_empty( &manager->requests );
 }
 
+static int device_manager_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct device_manager *manager = (struct device_manager *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return manager->inproc_sync;
+}
+
 static void device_manager_destroy( struct object *obj )
 {
     struct device_manager *manager = (struct device_manager *)obj;
@@ -829,6 +848,8 @@ static void device_manager_destroy( struct object *obj )
         assert( !irp->file && !irp->async );
         release_object( irp );
     }
+
+    if (use_inproc_sync()) close( manager->inproc_sync );
 }
 
 static struct device_manager *create_device_manager(void)
@@ -838,6 +859,7 @@ static struct device_manager *create_device_manager(void)
     if ((manager = alloc_object( &device_manager_ops )))
     {
         manager->current_call = NULL;
+        manager->inproc_sync = create_inproc_event( TRUE, FALSE );
         list_init( &manager->devices );
         list_init( &manager->requests );
         wine_rb_init( &manager->kernel_objects, compare_kernel_object );
@@ -1027,6 +1049,10 @@ DECL_HANDLER(get_next_device_request)
                 }
                 list_remove( &irp->mgr_entry );
                 list_init( &irp->mgr_entry );
+
+                if (list_empty( &manager->requests ))
+                    reset_inproc_event( manager->inproc_sync );
+
                 /* we already own the object if it's only on manager queue */
                 if (irp->file) grab_object( irp );
                 manager->current_call = irp;
-- 
2.50.1


From 7f372da682f0fccda5819a4ad48e7bb83577a2d6 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:13:20 -0600
Subject: [PATCH 44/57] server: Create in-process synchronization objects for
 keyed events.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/event.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/server/event.c b/server/event.c
index 6f1b0bec022..2b93ae2fa76 100644
--- a/server/event.c
+++ b/server/event.c
@@ -114,10 +114,13 @@ struct type_descr keyed_event_type =
 struct keyed_event
 {
     struct object  obj;             /* object header */
+    int inproc_sync;                /* in-process synchronization object */
 };
 
 static void keyed_event_dump( struct object *obj, int verbose );
 static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int keyed_event_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
+static void keyed_event_destroy( struct object *obj );
 
 static const struct object_ops keyed_event_ops =
 {
@@ -139,9 +142,9 @@ static const struct object_ops keyed_event_ops =
     default_unlink_name,         /* unlink_name */
     no_open_file,                /* open_file */
     no_kernel_obj_list,          /* get_kernel_obj_list */
-    no_get_inproc_sync,          /* get_inproc_sync */
+    keyed_event_get_inproc_sync, /* get_inproc_sync */
     no_close_handle,             /* close_handle */
-    no_destroy                   /* destroy */
+    keyed_event_destroy          /* destroy */
 };
 
 
@@ -270,6 +273,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
+            event->inproc_sync = create_inproc_event( TRUE, TRUE );
         }
     }
     return event;
@@ -313,6 +317,21 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en
     return 0;
 }
 
+static int keyed_event_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct keyed_event *event = (struct keyed_event *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return event->inproc_sync;
+}
+
+static void keyed_event_destroy( struct object *obj )
+{
+    struct keyed_event *event = (struct keyed_event *)obj;
+
+    if (use_inproc_sync()) close( event->inproc_sync );
+}
+
 /* create an event */
 DECL_HANDLER(create_event)
 {
-- 
2.50.1


From c4417145ba749dd13d38590d8ee8c0d0dfb29ec5 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:16:53 -0600
Subject: [PATCH 45/57] server: Create in-process synchronization objects for
 processes.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/process.c | 15 ++++++++++++++-
 server/process.h |  1 +
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/server/process.c b/server/process.c
index d5f3c1963cb..960342a1eaa 100644
--- a/server/process.c
+++ b/server/process.c
@@ -95,6 +95,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access
 static struct security_descriptor *process_get_sd( struct object *obj );
 static void process_poll_event( struct fd *fd, int event );
 static struct list *process_get_kernel_obj_list( struct object *obj );
+static int process_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void process_destroy( struct object *obj );
 static void terminate_process( struct process *process, struct thread *skip, int exit_code );
 
@@ -118,7 +119,7 @@ static const struct object_ops process_ops =
     NULL,                        /* unlink_name */
     no_open_file,                /* open_file */
     process_get_kernel_obj_list, /* get_kernel_obj_list */
-    no_get_inproc_sync,          /* get_inproc_sync */
+    process_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,             /* close_handle */
     process_destroy              /* destroy */
 };
@@ -689,6 +690,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
     process->rawinput_device_count = 0;
     process->rawinput_mouse  = NULL;
     process->rawinput_kbd    = NULL;
+    process->inproc_sync     = create_inproc_event( TRUE, FALSE );
     memset( &process->image_info, 0, sizeof(process->image_info) );
     list_init( &process->rawinput_entry );
     list_init( &process->kernel_object );
@@ -789,6 +791,8 @@ static void process_destroy( struct object *obj )
     free( process->rawinput_devices );
     free( process->dir_cache );
     free( process->image );
+
+    if (use_inproc_sync()) close( process->inproc_sync );
 }
 
 /* dump a process on stdout for debugging purposes */
@@ -822,6 +826,14 @@ static struct list *process_get_kernel_obj_list( struct object *obj )
     return &process->kernel_object;
 }
 
+static int process_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct process *process = (struct process *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return process->inproc_sync;
+}
+
 static struct security_descriptor *process_get_sd( struct object *obj )
 {
     static struct security_descriptor *process_default_sd;
@@ -986,6 +998,7 @@ static void process_killed( struct process *process )
     release_job_process( process );
     start_sigkill_timer( process );
     wake_up( &process->obj, 0 );
+    set_inproc_event( process->inproc_sync );
 }
 
 /* add a thread to a process running threads list */
diff --git a/server/process.h b/server/process.h
index dfe8d628538..59ca4ecbabb 100644
--- a/server/process.h
+++ b/server/process.h
@@ -87,6 +87,7 @@ struct process
     struct list          rawinput_entry;  /* entry in the rawinput process list */
     struct list          kernel_object;   /* list of kernel object pointers */
     struct pe_image_info image_info;      /* main exe image info */
+    int                  inproc_sync;     /* in-process synchronization object */
 };
 
 /* process functions */
-- 
2.50.1


From b2f8520e512715b4a9d103b14374e52157b5bab7 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:17:35 -0600
Subject: [PATCH 46/57] server: Create in-process synchronization objects for
 jobs.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/process.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/server/process.c b/server/process.c
index 960342a1eaa..0c2ef8bb20d 100644
--- a/server/process.c
+++ b/server/process.c
@@ -194,6 +194,7 @@ struct type_descr job_type =
 
 static void job_dump( struct object *obj, int verbose );
 static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int job_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static void job_destroy( struct object *obj );
 
@@ -211,6 +212,7 @@ struct job
     struct job *parent;
     struct list parent_job_entry;  /* list entry for parent job */
     struct list child_job_list;    /* list of child jobs */
+    int inproc_sync;               /* in-process synchronization object */
 };
 
 static const struct object_ops job_ops =
@@ -233,7 +235,7 @@ static const struct object_ops job_ops =
     default_unlink_name,           /* unlink_name */
     no_open_file,                  /* open_file */
     no_kernel_obj_list,            /* get_kernel_obj_list */
-    no_get_inproc_sync,            /* get_inproc_sync */
+    job_get_inproc_sync,           /* get_inproc_sync */
     job_close_handle,              /* close_handle */
     job_destroy                    /* destroy */
 };
@@ -258,6 +260,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_
             job->completion_port = NULL;
             job->completion_key = 0;
             job->parent = NULL;
+            job->inproc_sync = create_inproc_event( TRUE, FALSE );
         }
     }
     return job;
@@ -414,6 +417,15 @@ static void terminate_job( struct job *job, int exit_code )
     job->terminating = 0;
     job->signaled = 1;
     wake_up( &job->obj, 0 );
+    set_inproc_event( job->inproc_sync );
+}
+
+static int job_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct job *job = (struct job *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return job->inproc_sync;
 }
 
 static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -444,6 +456,8 @@ static void job_destroy( struct object *obj )
         list_remove( &job->parent_job_entry );
         release_object( job->parent );
     }
+
+    if (use_inproc_sync()) close( job->inproc_sync );
 }
 
 static void job_dump( struct object *obj, int verbose )
-- 
2.50.1


From acb737ad39091c72fab16c1839f1429bec610868 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:24:15 -0600
Subject: [PATCH 47/57] server: Create in-process synchronization objects for
 message queues.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/queue.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/server/queue.c b/server/queue.c
index 23fb453aedb..4717281ea0e 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -135,6 +135,7 @@ struct msg_queue
     int                    keystate_lock;   /* owns an input keystate lock */
     queue_shm_t           *shared;          /* queue in session shared memory */
     unsigned int           ignore_post_msg; /* ignore post messages newer than this unique id */
+    int                    inproc_sync;     /* in-process synchronization object */
 };
 
 struct hotkey
@@ -152,6 +153,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
 static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry );
+static int msg_queue_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void msg_queue_destroy( struct object *obj );
 static void msg_queue_poll_event( struct fd *fd, int event );
 static void thread_input_dump( struct object *obj, int verbose );
@@ -178,7 +180,7 @@ static const struct object_ops msg_queue_ops =
     NULL,                      /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    msg_queue_get_inproc_sync, /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     msg_queue_destroy          /* destroy */
 };
@@ -317,6 +319,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
         queue->last_get_msg    = current_time;
         queue->keystate_lock   = 0;
         queue->ignore_post_msg = 0;
+        queue->inproc_sync     = create_inproc_event( TRUE, FALSE );
         list_init( &queue->send_result );
         list_init( &queue->callback_result );
         list_init( &queue->pending_timers );
@@ -733,7 +736,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
     }
     SHARED_WRITE_END;
 
-    if (is_signaled( queue )) wake_up( &queue->obj, 0 );
+    if (is_signaled( queue ))
+    {
+        wake_up( &queue->obj, 0 );
+        set_inproc_event( queue->inproc_sync );
+    }
 }
 
 /* clear some queue bits */
@@ -753,6 +760,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
         if (queue->keystate_lock) unlock_input_keystate( queue->input );
         queue->keystate_lock = 0;
     }
+    if (!is_signaled( queue ))
+        reset_inproc_event( queue->inproc_sync );
 }
 
 /* check if message is matched by the filter */
@@ -1346,6 +1355,15 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en
         shared->changed_mask = 0;
     }
     SHARED_WRITE_END;
+    reset_inproc_event( queue->inproc_sync );
+}
+
+static int msg_queue_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct msg_queue *queue = (struct msg_queue *)obj;
+
+    *type = INPROC_SYNC_QUEUE;
+    return queue->inproc_sync;
 }
 
 static void msg_queue_destroy( struct object *obj )
@@ -1391,6 +1409,7 @@ static void msg_queue_destroy( struct object *obj )
     if (queue->hooks) release_object( queue->hooks );
     if (queue->fd) release_object( queue->fd );
     if (queue->shared) free_shared_object( queue->shared );
+    if (use_inproc_sync()) close( queue->inproc_sync );
 }
 
 static void msg_queue_poll_event( struct fd *fd, int event )
@@ -1401,6 +1420,7 @@ static void msg_queue_poll_event( struct fd *fd, int event )
     if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
     else set_fd_events( queue->fd, 0 );
     wake_up( &queue->obj, 0 );
+    set_inproc_event( queue->inproc_sync );
 }
 
 static void thread_input_dump( struct object *obj, int verbose )
@@ -3185,7 +3205,15 @@ DECL_HANDLER(set_queue_mask)
                 }
                 SHARED_WRITE_END;
             }
-            else wake_up( &queue->obj, 0 );
+            else
+            {
+                wake_up( &queue->obj, 0 );
+                set_inproc_event( queue->inproc_sync );
+            }
+        }
+        else
+        {
+            reset_inproc_event( queue->inproc_sync );
         }
     }
 }
@@ -3207,6 +3235,9 @@ DECL_HANDLER(get_queue_status)
             shared->changed_bits &= ~req->clear_bits;
         }
         SHARED_WRITE_END;
+
+        if (!is_signaled( queue ))
+            reset_inproc_event( queue->inproc_sync );
     }
     else reply->wake_bits = reply->changed_bits = 0;
 }
@@ -3405,6 +3436,9 @@ DECL_HANDLER(get_message)
     }
     SHARED_WRITE_END;
 
+    if (!is_signaled( queue ))
+        reset_inproc_event( queue->inproc_sync );
+
     /* then check for posted messages */
     if ((filter & QS_POSTMESSAGE) &&
         get_posted_message( queue, queue->ignore_post_msg, get_win, req->get_first, req->get_last, req->flags, reply ))
@@ -3474,6 +3508,7 @@ DECL_HANDLER(get_message)
     }
     SHARED_WRITE_END;
 
+    reset_inproc_event( queue->inproc_sync );
     set_error( STATUS_PENDING );  /* FIXME */
     return;
 
-- 
2.50.1


From a4db0541ebb4e316c6306c8f8e43e8b0446e78e7 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:26:35 -0600
Subject: [PATCH 48/57] server: Create in-process synchronization objects for
 threads.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/thread.c | 14 +++++++++++++-
 server/thread.h |  1 +
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/server/thread.c b/server/thread.c
index b0bd041d7ba..f665bb86c3a 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -190,6 +190,7 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
 static unsigned int thread_map_access( struct object *obj, unsigned int access );
 static void thread_poll_event( struct fd *fd, int event );
 static struct list *thread_get_kernel_obj_list( struct object *obj );
+static int thread_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void destroy_thread( struct object *obj );
 
 static const struct object_ops thread_ops =
@@ -212,7 +213,7 @@ static const struct object_ops thread_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     thread_get_kernel_obj_list, /* get_kernel_obj_list */
-    no_get_inproc_sync,         /* get_inproc_sync */
+    thread_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     destroy_thread              /* destroy */
 };
@@ -421,6 +422,7 @@ static inline void init_thread_structure( struct thread *thread )
     thread->token           = NULL;
     thread->desc            = NULL;
     thread->desc_len        = 0;
+    thread->inproc_sync     = create_inproc_event( TRUE, FALSE );
 
     thread->creation_time = current_time;
     thread->exit_time     = 0;
@@ -578,6 +580,14 @@ static struct list *thread_get_kernel_obj_list( struct object *obj )
     return &thread->kernel_object;
 }
 
+static int thread_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct thread *thread = (struct thread *)obj;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    return thread->inproc_sync;
+}
+
 /* cleanup everything that is no longer needed by a dead thread */
 /* used by destroy_thread and kill_thread */
 static void cleanup_thread( struct thread *thread )
@@ -633,6 +643,7 @@ static void destroy_thread( struct object *obj )
     release_object( thread->process );
     if (thread->id) free_ptid( thread->id );
     if (thread->token) release_object( thread->token );
+    if (use_inproc_sync()) close( thread->inproc_sync );
 }
 
 /* dump a thread on stdout for debugging purposes */
@@ -1519,6 +1530,7 @@ void kill_thread( struct thread *thread, int violent_death )
     kill_console_processes( thread, 0 );
     abandon_mutexes( thread );
     wake_up( &thread->obj, 0 );
+    set_inproc_event( thread->inproc_sync );
     if (violent_death) send_thread_signal( thread, SIGQUIT );
     cleanup_thread( thread );
     remove_process_thread( thread->process, thread );
diff --git a/server/thread.h b/server/thread.h
index 7a4eb983733..980ebd7d17c 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -96,6 +96,7 @@ struct thread
     data_size_t            desc_len;      /* thread description length in bytes */
     WCHAR                 *desc;          /* thread description string */
     struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */
+    int                    inproc_sync;   /* in-process synchronization object */
 };
 
 extern struct thread *current;
-- 
2.50.1


From 1d50c451efa7d8ee1d3904610a845adeb27f9ea2 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:29:38 -0600
Subject: [PATCH 49/57] server: Create in-process synchronization objects for
 timers.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/timer.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/server/timer.c b/server/timer.c
index 0fb36338959..4d159653d63 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -26,6 +26,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <stdarg.h>
+#include <unistd.h>
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -52,20 +53,22 @@ struct type_descr timer_type =
 
 struct timer
 {
-    struct object        obj;       /* object header */
-    int                  manual;    /* manual reset */
-    int                  signaled;  /* current signaled state */
-    unsigned int         period;    /* timer period in ms */
-    abstime_t            when;      /* next expiration */
-    struct timeout_user *timeout;   /* timeout user */
-    struct thread       *thread;    /* thread that set the APC function */
-    client_ptr_t         callback;  /* callback APC function */
-    client_ptr_t         arg;       /* callback argument */
+    struct object        obj;           /* object header */
+    int                  manual;        /* manual reset */
+    int                  signaled;      /* current signaled state */
+    unsigned int         period;        /* timer period in ms */
+    abstime_t            when;          /* next expiration */
+    struct timeout_user *timeout;       /* timeout user */
+    struct thread       *thread;        /* thread that set the APC function */
+    client_ptr_t         callback;      /* callback APC function */
+    client_ptr_t         arg;           /* callback argument */
+    int                  inproc_sync;   /* in-process synchronization object */
 };
 
 static void timer_dump( struct object *obj, int verbose );
 static int timer_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry );
+static int timer_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 static void timer_destroy( struct object *obj );
 
 static const struct object_ops timer_ops =
@@ -88,7 +91,7 @@ static const struct object_ops timer_ops =
     default_unlink_name,       /* unlink_name */
     no_open_file,              /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    timer_get_inproc_sync,     /* get_inproc_sync */
     no_close_handle,           /* close_handle */
     timer_destroy              /* destroy */
 };
@@ -111,6 +114,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str
             timer->period   = 0;
             timer->timeout  = NULL;
             timer->thread   = NULL;
+            timer->inproc_sync = create_inproc_event( manual, FALSE );
         }
     }
     return timer;
@@ -153,6 +157,7 @@ static void timer_callback( void *private )
     /* wake up waiters */
     timer->signaled = 1;
     wake_up( &timer->obj, 0 );
+    set_inproc_event( timer->inproc_sync );
 }
 
 /* cancel a running timer */
@@ -183,6 +188,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period
     {
         period = 0;  /* period doesn't make any sense for a manual timer */
         timer->signaled = 0;
+        reset_inproc_event( timer->inproc_sync );
     }
     timer->when     = (expire <= 0) ? expire - monotonic_time : max( expire, current_time );
     timer->period   = period;
@@ -217,6 +223,14 @@ static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry
     if (!timer->manual) timer->signaled = 0;
 }
 
+static int timer_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct timer *timer = (struct timer *)obj;
+
+    *type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER;
+    return timer->inproc_sync;
+}
+
 static void timer_destroy( struct object *obj )
 {
     struct timer *timer = (struct timer *)obj;
@@ -224,6 +238,7 @@ static void timer_destroy( struct object *obj )
 
     if (timer->timeout) remove_timeout_user( timer->timeout );
     if (timer->thread) release_object( timer->thread );
+    if (use_inproc_sync()) close( timer->inproc_sync );
 }
 
 /* create a timer */
-- 
2.50.1


From 08effd6967085f6433a4689bf177605d1b81b95b Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 17:40:57 -0600
Subject: [PATCH 50/57] server: Create in-process synchronization objects for
 fd-based objects.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 server/change.c     |  2 +-
 server/device.c     |  2 +-
 server/fd.c         | 25 ++++++++++++++++++++++++-
 server/file.c       |  2 +-
 server/file.h       |  1 +
 server/mailslot.c   |  6 +++---
 server/named_pipe.c |  8 ++++----
 server/serial.c     |  2 +-
 server/sock.c       |  2 +-
 9 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/server/change.c b/server/change.c
index f65b865d138..53445dfd360 100644
--- a/server/change.c
+++ b/server/change.c
@@ -124,7 +124,7 @@ static const struct object_ops dir_ops =
     NULL,                     /* unlink_name */
     no_open_file,             /* open_file */
     no_kernel_obj_list,       /* get_kernel_obj_list */
-    no_get_inproc_sync,       /* get_inproc_sync */
+    default_fd_get_inproc_sync, /* get_inproc_sync */
     dir_close_handle,         /* close_handle */
     dir_destroy               /* destroy */
 };
diff --git a/server/device.c b/server/device.c
index 3c2bee4c485..8c5ac281537 100644
--- a/server/device.c
+++ b/server/device.c
@@ -233,7 +233,7 @@ static const struct object_ops device_file_ops =
     NULL,                             /* unlink_name */
     no_open_file,                     /* open_file */
     device_file_get_kernel_obj_list,  /* get_kernel_obj_list */
-    no_get_inproc_sync,               /* get_inproc_sync */
+    default_fd_get_inproc_sync,       /* get_inproc_sync */
     device_file_close_handle,         /* close_handle */
     device_file_destroy               /* destroy */
 };
diff --git a/server/fd.c b/server/fd.c
index c6a0e366aca..793b58c9275 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -159,6 +159,7 @@ struct fd
     struct completion   *completion;  /* completion object attached to this fd */
     apc_param_t          comp_key;    /* completion key to set in completion events */
     unsigned int         comp_flags;  /* completion flags */
+    int                  inproc_sync; /* in-process synchronization object */
 };
 
 static void fd_dump( struct object *obj, int verbose );
@@ -1668,6 +1669,7 @@ static void fd_destroy( struct object *obj )
         if (fd->unix_fd != -1) close( fd->unix_fd );
         free( fd->unix_name );
     }
+    if (use_inproc_sync()) close( fd->inproc_sync );
 }
 
 /* check if the desired access is possible without violating */
@@ -1786,6 +1788,7 @@ static struct fd *alloc_fd_object(void)
     fd->poll_index = -1;
     fd->completion = NULL;
     fd->comp_flags = 0;
+    fd->inproc_sync = create_inproc_event( TRUE, fd->signaled );
     init_async_queue( &fd->read_q );
     init_async_queue( &fd->write_q );
     init_async_queue( &fd->wait_q );
@@ -1826,6 +1829,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     fd->poll_index = -1;
     fd->completion = NULL;
     fd->comp_flags = 0;
+    fd->inproc_sync = create_inproc_event( TRUE, fd->signaled );
     fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
     init_async_queue( &fd->read_q );
     init_async_queue( &fd->write_q );
@@ -2306,7 +2310,15 @@ void set_fd_signaled( struct fd *fd, int signaled )
 {
     if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return;
     fd->signaled = signaled;
-    if (signaled) wake_up( fd->user, 0 );
+    if (signaled)
+    {
+        wake_up( fd->user, 0 );
+        set_inproc_event( fd->inproc_sync );
+    }
+    else
+    {
+        reset_inproc_event( fd->inproc_sync );
+    }
 }
 
 /* check if events are pending and if yes return which one(s) */
@@ -2348,6 +2360,17 @@ WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_
     return ret;
 }
 
+int default_fd_get_inproc_sync( struct object *obj, enum inproc_sync_type *type )
+{
+    struct fd *fd = get_obj_fd( obj );
+    int ret;
+
+    *type = INPROC_SYNC_MANUAL_SERVER;
+    ret = fd->inproc_sync;
+    release_object( fd );
+    return ret;
+}
+
 int default_fd_get_poll_events( struct fd *fd )
 {
     int events = 0;
diff --git a/server/file.c b/server/file.c
index a35da0eb1b3..cc8795f510d 100644
--- a/server/file.c
+++ b/server/file.c
@@ -135,7 +135,7 @@ static const struct object_ops file_ops =
     NULL,                         /* unlink_name */
     file_open_file,               /* open_file */
     file_get_kernel_obj_list,     /* get_kernel_obj_list */
-    no_get_inproc_sync,           /* get_inproc_sync */
+    default_fd_get_inproc_sync,   /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     file_destroy                  /* destroy */
 };
diff --git a/server/file.h b/server/file.h
index 69c0efdb5b5..bfb48b5a598 100644
--- a/server/file.h
+++ b/server/file.h
@@ -110,6 +110,7 @@ extern void get_nt_name( struct fd *fd, struct unicode_str *name );
 
 extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
 extern WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_t *ret_len );
+extern int default_fd_get_inproc_sync( struct object *obj, enum inproc_sync_type *type );
 extern int default_fd_get_poll_events( struct fd *fd );
 extern void default_poll_event( struct fd *fd, int event );
 extern void fd_cancel_async( struct fd *fd, struct async *async );
diff --git a/server/mailslot.c b/server/mailslot.c
index edee2534e6e..bd52815c614 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -94,7 +94,7 @@ static const struct object_ops mailslot_ops =
     default_unlink_name,       /* unlink_name */
     mailslot_open_file,        /* open_file */
     no_kernel_obj_list,        /* get_kernel_obj_list */
-    no_get_inproc_sync,        /* get_inproc_sync */
+    default_fd_get_inproc_sync,/* get_inproc_sync */
     no_close_handle,           /* close_handle */
     mailslot_destroy           /* destroy */
 };
@@ -156,7 +156,7 @@ static const struct object_ops mail_writer_ops =
     NULL,                       /* unlink_name */
     no_open_file,               /* open_file */
     no_kernel_obj_list,         /* get_kernel_obj_list */
-    no_get_inproc_sync,         /* get_inproc_sync */
+    default_fd_get_inproc_sync, /* get_inproc_sync */
     no_close_handle,            /* close_handle */
     mail_writer_destroy         /* destroy */
 };
@@ -253,7 +253,7 @@ static const struct object_ops mailslot_device_file_ops =
     NULL,                                   /* unlink_name */
     no_open_file,                           /* open_file */
     no_kernel_obj_list,                     /* get_kernel_obj_list */
-    no_get_inproc_sync,                     /* get_inproc_sync */
+    default_fd_get_inproc_sync,             /* get_inproc_sync */
     no_close_handle,                        /* close_handle */
     mailslot_device_file_destroy            /* destroy */
 };
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 8713c2a8360..607d3d6e06e 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -180,7 +180,7 @@ static const struct object_ops pipe_server_ops =
     NULL,                         /* unlink_name */
     pipe_server_open_file,        /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
-    no_get_inproc_sync,           /* get_inproc_sync */
+    default_fd_get_inproc_sync,   /* get_inproc_sync */
     async_close_obj_handle,       /* close_handle */
     pipe_server_destroy           /* destroy */
 };
@@ -225,7 +225,7 @@ static const struct object_ops pipe_client_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
-    no_get_inproc_sync,           /* get_inproc_sync */
+    default_fd_get_inproc_sync,   /* get_inproc_sync */
     async_close_obj_handle,       /* close_handle */
     pipe_end_destroy              /* destroy */
 };
@@ -306,7 +306,7 @@ static const struct object_ops named_pipe_device_file_ops =
     NULL,                                    /* unlink_name */
     no_open_file,                            /* open_file */
     no_kernel_obj_list,                      /* get_kernel_obj_list */
-    no_get_inproc_sync,                      /* get_inproc_sync */
+    default_fd_get_inproc_sync,              /* get_inproc_sync */
     no_close_handle,                         /* close_handle */
     named_pipe_device_file_destroy           /* destroy */
 };
@@ -357,7 +357,7 @@ static const struct object_ops named_pipe_dir_ops =
     NULL,                                    /* unlink_name */
     named_pipe_dir_open_file,                /* open_file */
     no_kernel_obj_list,                      /* get_kernel_obj_list */
-    no_get_inproc_sync,                      /* get_inproc_sync */
+    default_fd_get_inproc_sync,              /* get_inproc_sync */
     no_close_handle,                         /* close_handle */
     named_pipe_dir_destroy                   /* destroy */
 };
diff --git a/server/serial.c b/server/serial.c
index df242058a43..93753328d4d 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -103,7 +103,7 @@ static const struct object_ops serial_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
-    no_get_inproc_sync,           /* get_inproc_sync */
+    default_fd_get_inproc_sync,   /* get_inproc_sync */
     no_close_handle,              /* close_handle */
     serial_destroy                /* destroy */
 };
diff --git a/server/sock.c b/server/sock.c
index a4353c9963a..71a65c26b83 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -503,7 +503,7 @@ static const struct object_ops sock_ops =
     NULL,                         /* unlink_name */
     no_open_file,                 /* open_file */
     no_kernel_obj_list,           /* get_kernel_obj_list */
-    no_get_inproc_sync,           /* get_inproc_sync */
+    default_fd_get_inproc_sync,   /* get_inproc_sync */
     sock_close_handle,            /* close_handle */
     sock_destroy                  /* destroy */
 };
-- 
2.50.1


From fde1345b32be77a069d5ad5a4d2d839be446a7d8 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Wed, 19 Mar 2025 19:32:55 -0500
Subject: [PATCH 51/57] server: Add a request to retrieve the in-process
 synchronization object from a handle.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 include/wine/server_protocol.h | 18 +++++++++++++++++-
 server/inproc_sync.c           | 26 ++++++++++++++++++++++++++
 server/protocol.def            |  8 ++++++++
 server/request_handlers.h      |  7 +++++++
 server/request_trace.h         | 14 ++++++++++++++
 5 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index f7a6a42c405..d36e8c2b192 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -6001,6 +6001,19 @@ struct get_linux_sync_device_reply
 };
 
 
+struct get_linux_sync_obj_request
+{
+    struct request_header __header;
+    obj_handle_t handle;
+};
+struct get_linux_sync_obj_reply
+{
+    struct reply_header __header;
+    int type;
+    unsigned int access;
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -6301,6 +6314,7 @@ enum request
     REQ_get_next_thread,
     REQ_set_keyboard_repeat,
     REQ_get_linux_sync_device,
+    REQ_get_linux_sync_obj,
     REQ_NB_REQUESTS
 };
 
@@ -6606,6 +6620,7 @@ union generic_request
     struct get_next_thread_request get_next_thread_request;
     struct set_keyboard_repeat_request set_keyboard_repeat_request;
     struct get_linux_sync_device_request get_linux_sync_device_request;
+    struct get_linux_sync_obj_request get_linux_sync_obj_request;
 };
 union generic_reply
 {
@@ -6909,8 +6924,9 @@ union generic_reply
     struct get_next_thread_reply get_next_thread_reply;
     struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
     struct get_linux_sync_device_reply get_linux_sync_device_reply;
+    struct get_linux_sync_obj_reply get_linux_sync_obj_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 885
+#define SERVER_PROTOCOL_VERSION 886
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/inproc_sync.c b/server/inproc_sync.c
index 6471364c4de..c6f79081b6f 100644
--- a/server/inproc_sync.c
+++ b/server/inproc_sync.c
@@ -172,3 +172,29 @@ DECL_HANDLER(get_linux_sync_device)
     set_error( STATUS_NOT_IMPLEMENTED );
 #endif
 }
+
+DECL_HANDLER(get_linux_sync_obj)
+{
+#ifdef NTSYNC_IOC_EVENT_READ
+    struct object *obj;
+    int fd;
+
+    if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
+    {
+        enum inproc_sync_type type;
+
+        if ((fd = obj->ops->get_inproc_sync( obj, &type )) >= 0)
+        {
+            reply->type = type;
+            reply->access = get_handle_access( current->process, req->handle );
+            send_client_fd( current->process, fd, req->handle );
+        }
+        else
+            set_error( STATUS_NOT_IMPLEMENTED );
+
+        release_object( obj );
+    }
+#else
+    set_error( STATUS_NOT_IMPLEMENTED );
+#endif
+}
diff --git a/server/protocol.def b/server/protocol.def
index 1ed8960d303..8571ec62a54 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4160,3 +4160,11 @@ enum inproc_sync_type
 /* Obtain a fd for the ntsync device */
 @REQ(get_linux_sync_device)
 @END
+
+/* Get the in-process synchronization fd associated with the waitable handle */
+@REQ(get_linux_sync_obj)
+    obj_handle_t handle;        /* handle to the object */
+@REPLY
+    int type;                   /* object type */
+    unsigned int access;        /* handle access rights */
+@END
diff --git a/server/request_handlers.h b/server/request_handlers.h
index dfed7904738..11ef472c579 100644
--- a/server/request_handlers.h
+++ b/server/request_handlers.h
@@ -305,6 +305,7 @@ DECL_HANDLER(get_next_process);
 DECL_HANDLER(get_next_thread);
 DECL_HANDLER(set_keyboard_repeat);
 DECL_HANDLER(get_linux_sync_device);
+DECL_HANDLER(get_linux_sync_obj);
 
 typedef void (*req_handler)( const void *req, void *reply );
 static const req_handler req_handlers[REQ_NB_REQUESTS] =
@@ -607,6 +608,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_next_thread,
     (req_handler)req_set_keyboard_repeat,
     (req_handler)req_get_linux_sync_device,
+    (req_handler)req_get_linux_sync_obj,
 };
 
 C_ASSERT( sizeof(abstime_t) == 8 );
@@ -2305,3 +2307,8 @@ C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
 C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 );
 C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 );
 C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 );
+C_ASSERT( offsetof(struct get_linux_sync_obj_request, handle) == 12 );
+C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 );
+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 8 );
+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 12 );
+C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 16 );
diff --git a/server/request_trace.h b/server/request_trace.h
index 6fd490ca68e..92c94ce616f 100644
--- a/server/request_trace.h
+++ b/server/request_trace.h
@@ -3403,6 +3403,17 @@ static void dump_get_linux_sync_device_request( const struct get_linux_sync_devi
 {
 }
 
+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req )
+{
+    fprintf( stderr, " handle=%04x", req->handle );
+}
+
+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req )
+{
+    fprintf( stderr, " type=%d", req->type );
+    fprintf( stderr, ", access=%08x", req->access );
+}
+
 typedef void (*dump_func)( const void *req );
 
 static const dump_func req_dumpers[REQ_NB_REQUESTS] =
@@ -3705,6 +3716,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_next_thread_request,
     (dump_func)dump_set_keyboard_repeat_request,
     (dump_func)dump_get_linux_sync_device_request,
+    (dump_func)dump_get_linux_sync_obj_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
@@ -4007,6 +4019,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_next_thread_reply,
     (dump_func)dump_set_keyboard_repeat_reply,
     NULL,
+    (dump_func)dump_get_linux_sync_obj_reply,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
@@ -4309,6 +4322,7 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "get_next_thread",
     "set_keyboard_repeat",
     "get_linux_sync_device",
+    "get_linux_sync_obj",
 };
 
 static const struct
-- 
2.50.1


From d8427b4e45c91b13876c5548f10c308bc028b200 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Tue, 9 Mar 2021 11:32:25 -0600
Subject: [PATCH 52/57] server: Introduce select_inproc_queue and
 unselect_inproc_queue requests.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 include/wine/server_protocol.h | 32 +++++++++++++++++++++++-
 server/protocol.def            | 11 +++++++++
 server/queue.c                 | 45 ++++++++++++++++++++++++++++++++++
 server/request_handlers.h      |  7 ++++++
 server/request_trace.h         | 15 ++++++++++++
 5 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index d36e8c2b192..9b906a650c7 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -6014,6 +6014,30 @@ struct get_linux_sync_obj_reply
 };
 
 
+
+struct select_inproc_queue_request
+{
+    struct request_header __header;
+    char __pad_12[4];
+};
+struct select_inproc_queue_reply
+{
+    struct reply_header __header;
+};
+
+
+
+struct unselect_inproc_queue_request
+{
+    struct request_header __header;
+    int          signaled;
+};
+struct unselect_inproc_queue_reply
+{
+    struct reply_header __header;
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -6315,6 +6339,8 @@ enum request
     REQ_set_keyboard_repeat,
     REQ_get_linux_sync_device,
     REQ_get_linux_sync_obj,
+    REQ_select_inproc_queue,
+    REQ_unselect_inproc_queue,
     REQ_NB_REQUESTS
 };
 
@@ -6621,6 +6647,8 @@ union generic_request
     struct set_keyboard_repeat_request set_keyboard_repeat_request;
     struct get_linux_sync_device_request get_linux_sync_device_request;
     struct get_linux_sync_obj_request get_linux_sync_obj_request;
+    struct select_inproc_queue_request select_inproc_queue_request;
+    struct unselect_inproc_queue_request unselect_inproc_queue_request;
 };
 union generic_reply
 {
@@ -6925,8 +6953,10 @@ union generic_reply
     struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
     struct get_linux_sync_device_reply get_linux_sync_device_reply;
     struct get_linux_sync_obj_reply get_linux_sync_obj_reply;
+    struct select_inproc_queue_reply select_inproc_queue_reply;
+    struct unselect_inproc_queue_reply unselect_inproc_queue_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 886
+#define SERVER_PROTOCOL_VERSION 887
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 8571ec62a54..f3e2226a3ba 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4168,3 +4168,14 @@ enum inproc_sync_type
     int type;                   /* object type */
     unsigned int access;        /* handle access rights */
 @END
+
+
+/* Begin a client-side wait on a message queue */
+@REQ(select_inproc_queue)
+@END
+
+
+/* End a client-side wait on a message queue */
+@REQ(unselect_inproc_queue)
+    int          signaled;        /* was the queue signaled? */
+@END
diff --git a/server/queue.c b/server/queue.c
index 4717281ea0e..708d0eca899 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -136,6 +136,7 @@ struct msg_queue
     queue_shm_t           *shared;          /* queue in session shared memory */
     unsigned int           ignore_post_msg; /* ignore post messages newer than this unique id */
     int                    inproc_sync;     /* in-process synchronization object */
+    int                    in_inproc_wait;  /* are we in a client-side wait? */
 };
 
 struct hotkey
@@ -320,6 +321,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
         queue->keystate_lock   = 0;
         queue->ignore_post_msg = 0;
         queue->inproc_sync     = create_inproc_event( TRUE, FALSE );
+        queue->in_inproc_wait  = 0;
         list_init( &queue->send_result );
         list_init( &queue->callback_result );
         list_init( &queue->pending_timers );
@@ -1290,6 +1292,10 @@ static int is_queue_hung( struct msg_queue *queue )
         if (get_wait_queue_thread(entry)->queue == queue)
             return 0;  /* thread is waiting on queue -> not hung */
     }
+
+    if (queue->in_inproc_wait)
+        return 0;  /* thread is waiting on queue in absentia -> not hung */
+
     return 1;
 }
 
@@ -4312,3 +4318,42 @@ DECL_HANDLER(set_keyboard_repeat)
 
     release_object( desktop );
 }
+
+DECL_HANDLER(select_inproc_queue)
+{
+    struct msg_queue *queue = current->queue;
+
+    if (queue->in_inproc_wait)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+    }
+    else
+    {
+        check_thread_queue_idle( current );
+
+        if (queue->fd)
+            set_fd_events( queue->fd, POLLIN );
+
+        queue->in_inproc_wait = 1;
+    }
+}
+
+DECL_HANDLER(unselect_inproc_queue)
+{
+    struct msg_queue *queue = current->queue;
+
+    if (!queue->in_inproc_wait)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+    }
+    else
+    {
+        if (queue->fd)
+            set_fd_events( queue->fd, 0 );
+
+        if (req->signaled)
+            msg_queue_satisfied( &queue->obj, NULL );
+
+        queue->in_inproc_wait = 0;
+    }
+}
diff --git a/server/request_handlers.h b/server/request_handlers.h
index 11ef472c579..3a9717eb8df 100644
--- a/server/request_handlers.h
+++ b/server/request_handlers.h
@@ -306,6 +306,8 @@ DECL_HANDLER(get_next_thread);
 DECL_HANDLER(set_keyboard_repeat);
 DECL_HANDLER(get_linux_sync_device);
 DECL_HANDLER(get_linux_sync_obj);
+DECL_HANDLER(select_inproc_queue);
+DECL_HANDLER(unselect_inproc_queue);
 
 typedef void (*req_handler)( const void *req, void *reply );
 static const req_handler req_handlers[REQ_NB_REQUESTS] =
@@ -609,6 +611,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_set_keyboard_repeat,
     (req_handler)req_get_linux_sync_device,
     (req_handler)req_get_linux_sync_obj,
+    (req_handler)req_select_inproc_queue,
+    (req_handler)req_unselect_inproc_queue,
 };
 
 C_ASSERT( sizeof(abstime_t) == 8 );
@@ -2312,3 +2316,6 @@ C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 );
 C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 8 );
 C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 12 );
 C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 16 );
+C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 );
+C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 );
+C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 );
diff --git a/server/request_trace.h b/server/request_trace.h
index 92c94ce616f..d341cf13227 100644
--- a/server/request_trace.h
+++ b/server/request_trace.h
@@ -3414,6 +3414,15 @@ static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply
     fprintf( stderr, ", access=%08x", req->access );
 }
 
+static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req )
+{
+}
+
+static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req )
+{
+    fprintf( stderr, " signaled=%d", req->signaled );
+}
+
 typedef void (*dump_func)( const void *req );
 
 static const dump_func req_dumpers[REQ_NB_REQUESTS] =
@@ -3717,6 +3726,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_set_keyboard_repeat_request,
     (dump_func)dump_get_linux_sync_device_request,
     (dump_func)dump_get_linux_sync_obj_request,
+    (dump_func)dump_select_inproc_queue_request,
+    (dump_func)dump_unselect_inproc_queue_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
@@ -4020,6 +4031,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_set_keyboard_repeat_reply,
     NULL,
     (dump_func)dump_get_linux_sync_obj_reply,
+    NULL,
+    NULL,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
@@ -4323,6 +4336,8 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "set_keyboard_repeat",
     "get_linux_sync_device",
     "get_linux_sync_obj",
+    "select_inproc_queue",
+    "unselect_inproc_queue",
 };
 
 static const struct
-- 
2.50.1


From 96345f975362cbfc87d5e01b7f0eb1198c0c93c6 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 21 Apr 2022 16:11:14 -0500
Subject: [PATCH 53/57] server: Allow creating an event object for client-side
 user APC signaling.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 include/wine/server_protocol.h | 19 ++++++++++++++++++-
 server/protocol.def            |  7 +++++++
 server/request_handlers.h      |  5 +++++
 server/request_trace.h         | 12 ++++++++++++
 server/thread.c                | 21 +++++++++++++++++++++
 server/thread.h                |  1 +
 6 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 9b906a650c7..5d4a733134b 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -6038,6 +6038,20 @@ struct unselect_inproc_queue_reply
 };
 
 
+
+struct get_inproc_alert_event_request
+{
+    struct request_header __header;
+    char __pad_12[4];
+};
+struct get_inproc_alert_event_reply
+{
+    struct reply_header __header;
+    obj_handle_t handle;
+    char __pad_12[4];
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -6341,6 +6355,7 @@ enum request
     REQ_get_linux_sync_obj,
     REQ_select_inproc_queue,
     REQ_unselect_inproc_queue,
+    REQ_get_inproc_alert_event,
     REQ_NB_REQUESTS
 };
 
@@ -6649,6 +6664,7 @@ union generic_request
     struct get_linux_sync_obj_request get_linux_sync_obj_request;
     struct select_inproc_queue_request select_inproc_queue_request;
     struct unselect_inproc_queue_request unselect_inproc_queue_request;
+    struct get_inproc_alert_event_request get_inproc_alert_event_request;
 };
 union generic_reply
 {
@@ -6955,8 +6971,9 @@ union generic_reply
     struct get_linux_sync_obj_reply get_linux_sync_obj_reply;
     struct select_inproc_queue_reply select_inproc_queue_reply;
     struct unselect_inproc_queue_reply unselect_inproc_queue_reply;
+    struct get_inproc_alert_event_reply get_inproc_alert_event_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 887
+#define SERVER_PROTOCOL_VERSION 888
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index f3e2226a3ba..9b84b964ec9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4179,3 +4179,10 @@ enum inproc_sync_type
 @REQ(unselect_inproc_queue)
     int          signaled;        /* was the queue signaled? */
 @END
+
+
+/* Get an event handle to be used for thread alerts with in-process synchronization */
+@REQ(get_inproc_alert_event)
+@REPLY
+    obj_handle_t handle;          /* handle to the event */
+@END
diff --git a/server/request_handlers.h b/server/request_handlers.h
index 3a9717eb8df..026c2cb2893 100644
--- a/server/request_handlers.h
+++ b/server/request_handlers.h
@@ -308,6 +308,7 @@ DECL_HANDLER(get_linux_sync_device);
 DECL_HANDLER(get_linux_sync_obj);
 DECL_HANDLER(select_inproc_queue);
 DECL_HANDLER(unselect_inproc_queue);
+DECL_HANDLER(get_inproc_alert_event);
 
 typedef void (*req_handler)( const void *req, void *reply );
 static const req_handler req_handlers[REQ_NB_REQUESTS] =
@@ -613,6 +614,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_linux_sync_obj,
     (req_handler)req_select_inproc_queue,
     (req_handler)req_unselect_inproc_queue,
+    (req_handler)req_get_inproc_alert_event,
 };
 
 C_ASSERT( sizeof(abstime_t) == 8 );
@@ -2319,3 +2321,6 @@ C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 16 );
 C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 );
 C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 );
 C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 );
+C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 );
+C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 );
+C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 );
diff --git a/server/request_trace.h b/server/request_trace.h
index d341cf13227..e7bb89c6c72 100644
--- a/server/request_trace.h
+++ b/server/request_trace.h
@@ -3423,6 +3423,15 @@ static void dump_unselect_inproc_queue_request( const struct unselect_inproc_que
     fprintf( stderr, " signaled=%d", req->signaled );
 }
 
+static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req )
+{
+}
+
+static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req )
+{
+    fprintf( stderr, " handle=%04x", req->handle );
+}
+
 typedef void (*dump_func)( const void *req );
 
 static const dump_func req_dumpers[REQ_NB_REQUESTS] =
@@ -3728,6 +3737,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_linux_sync_obj_request,
     (dump_func)dump_select_inproc_queue_request,
     (dump_func)dump_unselect_inproc_queue_request,
+    (dump_func)dump_get_inproc_alert_event_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
@@ -4033,6 +4043,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] =
     (dump_func)dump_get_linux_sync_obj_reply,
     NULL,
     NULL,
+    (dump_func)dump_get_inproc_alert_event_reply,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
@@ -4338,6 +4349,7 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "get_linux_sync_obj",
     "select_inproc_queue",
     "unselect_inproc_queue",
+    "get_inproc_alert_event",
 };
 
 static const struct
diff --git a/server/thread.c b/server/thread.c
index f665bb86c3a..e8f0c40421c 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -423,6 +423,7 @@ static inline void init_thread_structure( struct thread *thread )
     thread->desc            = NULL;
     thread->desc_len        = 0;
     thread->inproc_sync     = create_inproc_event( TRUE, FALSE );
+    thread->inproc_alert_event = NULL;
 
     thread->creation_time = current_time;
     thread->exit_time     = 0;
@@ -644,6 +645,7 @@ static void destroy_thread( struct object *obj )
     if (thread->id) free_ptid( thread->id );
     if (thread->token) release_object( thread->token );
     if (use_inproc_sync()) close( thread->inproc_sync );
+    if (thread->inproc_alert_event) release_object( thread->inproc_alert_event );
 }
 
 /* dump a thread on stdout for debugging purposes */
@@ -1387,8 +1389,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
     grab_object( apc );
     list_add_tail( queue, &apc->entry );
     if (!list_prev( queue, &apc->entry ))  /* first one */
+    {
         wake_thread( thread );
 
+        if (apc->call.type == APC_USER && thread->inproc_alert_event)
+            set_event( thread->inproc_alert_event );
+    }
+
     return 1;
 }
 
@@ -1419,6 +1426,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty
         apc->executed = 1;
         wake_up( &apc->obj, 0 );
         release_object( apc );
+        if (list_empty( &thread->user_apc ) && thread->inproc_alert_event)
+            reset_event( thread->inproc_alert_event );
         return;
     }
 }
@@ -1433,6 +1442,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system
     {
         apc = LIST_ENTRY( ptr, struct thread_apc, entry );
         list_remove( ptr );
+
+        if (list_empty( &thread->user_apc ) && thread->inproc_alert_event)
+            reset_event( thread->inproc_alert_event );
     }
     return apc;
 }
@@ -2301,3 +2313,12 @@ DECL_HANDLER(get_next_thread)
     set_error( STATUS_NO_MORE_ENTRIES );
     release_object( process );
 }
+
+DECL_HANDLER(get_inproc_alert_event)
+{
+    if (!current->inproc_alert_event)
+        current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( &current->user_apc ), NULL );
+
+    if (current->inproc_alert_event)
+        reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 );
+}
diff --git a/server/thread.h b/server/thread.h
index 980ebd7d17c..bd31c58466c 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -97,6 +97,7 @@ struct thread
     WCHAR                 *desc;          /* thread description string */
     struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */
     int                    inproc_sync;   /* in-process synchronization object */
+    struct event          *inproc_alert_event; /* in-process synchronization alert event */
 };
 
 extern struct thread *current;
-- 
2.50.1


From 0c8462d7f2b470d3c17574083637f11144539839 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Mon, 8 Mar 2021 18:07:23 -0600
Subject: [PATCH 54/57] ntdll: Introduce a helper to wait on an internal server
 handle.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/file.c         |  2 +-
 dlls/ntdll/unix/process.c      |  2 +-
 dlls/ntdll/unix/server.c       | 17 ++++++++++++++++-
 dlls/ntdll/unix/sync.c         |  4 ++--
 dlls/ntdll/unix/thread.c       |  2 +-
 dlls/ntdll/unix/unix_private.h |  3 ++-
 6 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 2e6331b23a2..414a0ad10cf 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -7708,7 +7708,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void
         }
         if (handle)
         {
-            NtWaitForSingleObject( handle, FALSE, NULL );
+            server_wait_for_object( handle, FALSE, NULL );
             NtClose( handle );
         }
         else  /* Unix lock conflict, sleep a bit and retry */
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c
index fdb81845a7e..1a6b07667ef 100644
--- a/dlls/ntdll/unix/process.c
+++ b/dlls/ntdll/unix/process.c
@@ -879,7 +879,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
 
     /* wait for the new process info to be ready */
 
-    NtWaitForSingleObject( process_info, FALSE, NULL );
+    server_wait_for_object( process_info, FALSE, NULL );
     SERVER_START_REQ( get_new_process_info )
     {
         req->info = wine_server_obj_handle( process_info );
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 8d8f286b3fc..25c095537d5 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -838,6 +838,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI
 }
 
 
+/* helper function to perform a server-side wait on an internal handle without
+ * using the fast synchronization path */
+unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout )
+{
+    union select_op select_op;
+    UINT flags = SELECT_INTERRUPTIBLE;
+
+    if (alertable) flags |= SELECT_ALERTABLE;
+
+    select_op.wait.op = SELECT_WAIT;
+    select_op.wait.handles[0] = wine_server_obj_handle( handle );
+    return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout );
+}
+
+
 /***********************************************************************
  *              NtContinue  (NTDLL.@)
  */
@@ -914,7 +929,7 @@ unsigned int server_queue_process_apc( HANDLE process, const union apc_call *cal
         }
         else
         {
-            NtWaitForSingleObject( handle, FALSE, NULL );
+            server_wait_for_object( handle, FALSE, NULL );
 
             SERVER_START_REQ( get_apc_result )
             {
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index e7b9cac6575..39c6fd4acba 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -2280,7 +2280,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR *
     }
     SERVER_END_REQ;
     if (status != STATUS_PENDING) return status;
-    if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout );
+    if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout );
     else                               status = STATUS_TIMEOUT;
     if (status != WAIT_OBJECT_0) return status;
 
@@ -2344,7 +2344,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM
         assert( status == STATUS_USER_APC );
         goto done;
     }
-    if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout );
+    if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout );
     else                               status = STATUS_TIMEOUT;
     if (status != WAIT_OBJECT_0) goto done;
 
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index 6c1ea2d0a00..ab08dc57413 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -1832,7 +1832,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma
 
     if (ret == STATUS_PENDING)
     {
-        NtWaitForSingleObject( context_handle, FALSE, NULL );
+        server_wait_for_object( context_handle, FALSE, NULL );
 
         SERVER_START_REQ( get_thread_context )
         {
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index b14a6e52d62..22bb0978803 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -231,6 +231,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t
                                    timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc );
 extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags,
                                  const LARGE_INTEGER *timeout );
+extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout );
 extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call,
                                               union apc_result *result );
 extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
@@ -471,7 +472,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio
 
 static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable )
 {
-    return NtWaitForSingleObject( handle, alertable, NULL );
+    return server_wait_for_object( handle, alertable, NULL );
 }
 
 static inline BOOL in_wow64_call(void)
-- 
2.50.1


From 4dae5db2516caf93135c9013db901b2975eb61db Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Tue, 6 Apr 2021 15:37:02 -0500
Subject: [PATCH 55/57] ntdll: Use in-process synchronization objects.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/sync.c         | 575 ++++++++++++++++++++++++++++++++-
 dlls/ntdll/unix/unix_private.h |   2 +
 dlls/ntdll/unix/virtual.c      |   1 +
 server/inproc_sync.c           |   2 +-
 4 files changed, 568 insertions(+), 12 deletions(-)

diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 39c6fd4acba..8d26564de4b 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -30,9 +30,11 @@
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <signal.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 #ifdef HAVE_SYS_SYSCALL_H
 #include <sys/syscall.h>
@@ -48,6 +50,7 @@
 #endif
 #include <string.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -342,66 +345,616 @@ static int get_linux_sync_device(void)
     return device;
 }
 
+/* It's possible for synchronization primitives to remain alive even after being
+ * closed, because a thread is still waiting on them. It's rare in practice, and
+ * documented as being undefined behaviour by Microsoft, but it works, and some
+ * applications rely on it. This means we need to refcount handles, and defer
+ * deleting them on the server side until the refcount reaches zero. We do this
+ * by having each client process hold a handle to the in-process synchronization
+ * object, as well as a private refcount. When the client refcount reaches zero,
+ * it closes the handle; when all handles are closed, the server deletes the
+ * in-process synchronization object.
+ *
+ * We want lookup of objects from the cache to be very fast; ideally, it should
+ * be lock-free. We achieve this by using atomic modifications to "refcount",
+ * and guaranteeing that all other fields are valid and correct *as long as*
+ * refcount is nonzero, and we store the entire structure in memory which will
+ * never be freed.
+ *
+ * This means that acquiring the object can't use a simple atomic increment; it
+ * has to use a compare-and-swap loop to ensure that it doesn't try to increment
+ * an object with a zero refcount. That's still leagues better than a real lock,
+ * though, and release can be a single atomic decrement.
+ *
+ * It also means that threads modifying the cache need to take a lock, to
+ * prevent other threads from writing to it concurrently.
+ *
+ * It's possible for an object currently in use (by a waiter) to be closed and
+ * the same handle immediately reallocated to a different object. This should be
+ * a very rare situation, and in that case we simply don't cache the handle.
+ */
+struct inproc_sync_cache_entry
+{
+    LONG refcount;
+    int fd;
+    unsigned int access;
+    unsigned short type; /* enum inproc_sync_type, stored as short to save space */
+    unsigned short closed;
+};
+
+
+static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache )
+{
+    /* save the fd now; as soon as the refcount hits 0 we cannot
+     * access the cache anymore */
+    int fd = cache->fd;
+    LONG refcount = InterlockedDecrement( &cache->refcount );
+
+    assert( refcount >= 0 );
+
+    if (!refcount)
+        close( fd );
+}
+
+
+static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b )
+{
+    if (a == b) return TRUE;
+    if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE;
+    if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE;
+    return FALSE;
+}
+
+
+/* returns a pointer to a cache entry; if the object could not be cached,
+ * returns "stack_cache" instead, which should be allocated on stack */
+static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type,
+                                     ACCESS_MASK desired_access,
+                                     struct inproc_sync_cache_entry *stack_cache,
+                                     struct inproc_sync_cache_entry **ret_cache )
+{
+    struct inproc_sync_cache_entry *cache = stack_cache;
+    sigset_t sigset;
+    NTSTATUS ret;
+
+    /* We don't need the device right now, but if we can't access it, that
+     * means ntsync isn't available. Fail fast in that case. */
+    if (get_linux_sync_device() < 0)
+        return STATUS_NOT_IMPLEMENTED;
+
+    *ret_cache = stack_cache;
+
+    /* We need to use fd_cache_mutex here to protect against races with
+     * other threads trying to receive fds for the fd cache,
+     * and we need to use an uninterrupted section to prevent reentrancy. */
+    server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+    SERVER_START_REQ( get_linux_sync_obj )
+    {
+        req->handle = wine_server_obj_handle( handle );
+        if (!(ret = wine_server_call( req )))
+        {
+            obj_handle_t fd_handle;
+            cache->fd = wine_server_receive_fd( &fd_handle );
+            assert( wine_server_ptr_handle(fd_handle) == handle );
+            cache->access = reply->access;
+            cache->type = reply->type;
+            cache->refcount = 1;
+            cache->closed = FALSE;
+        }
+    }
+    SERVER_END_REQ;
+
+    server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+    if (ret) return ret;
+
+    if (desired_type && !inproc_sync_types_match( cache->type, desired_type ))
+    {
+        release_inproc_sync_obj( cache );
+        return STATUS_OBJECT_TYPE_MISMATCH;
+    }
+
+    if ((cache->access & desired_access) != desired_access)
+    {
+        release_inproc_sync_obj( cache );
+        return STATUS_ACCESS_DENIED;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count )
+{
+    NTSTATUS ret;
+
+    ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count );
+    if (ret < 0)
+    {
+        if (errno == EOVERFLOW)
+            return STATUS_SEMAPHORE_LIMIT_EXCEEDED;
+        else
+            return errno_to_status( errno );
+    }
+    if (prev_count) *prev_count = count;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE,
+                                    SEMAPHORE_MODIFY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_release_semaphore_obj( cache->fd, count, prev_count );
+
+    release_inproc_sync_obj( cache );
+    return ret;
 }
 
+
+static NTSTATUS linux_query_semaphore_obj( int obj, SEMAPHORE_BASIC_INFORMATION *info )
+{
+    struct ntsync_sem_args args = {0};
+    NTSTATUS ret;
+
+    ret = ioctl( obj, NTSYNC_IOC_SEM_READ, &args );
+    if (ret < 0)
+        return errno_to_status( errno );
+    info->CurrentCount = args.count;
+    info->MaximumCount = args.max;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE,
+                                    SEMAPHORE_QUERY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_query_semaphore_obj( cache->fd, info );
+
+    release_inproc_sync_obj( cache );
+    return ret;
+}
+
+
+static NTSTATUS linux_set_event_obj( int obj, LONG *prev_state )
+{
+    NTSTATUS ret;
+    __u32 prev;
+
+    ret = ioctl( obj, NTSYNC_IOC_EVENT_SET, &prev );
+    if (ret < 0)
+        return errno_to_status( errno );
+    if (prev_state) *prev_state = prev;
+    return STATUS_SUCCESS;
 }
 
+
 static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT,
+                                    EVENT_MODIFY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_set_event_obj( cache->fd, prev_state );
+
+    release_inproc_sync_obj( cache );
+    return ret;
 }
 
+
+static NTSTATUS linux_reset_event_obj( int obj, LONG *prev_state )
+{
+    NTSTATUS ret;
+    __u32 prev;
+
+    ret = ioctl( obj, NTSYNC_IOC_EVENT_RESET, &prev );
+    if (ret < 0)
+        return errno_to_status( errno );
+    if (prev_state) *prev_state = prev;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT,
+                                    EVENT_MODIFY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_reset_event_obj( cache->fd, prev_state );
+
+    release_inproc_sync_obj( cache );
+    return ret;
+}
+
+
+static NTSTATUS linux_pulse_event_obj( int obj, LONG *prev_state )
+{
+    NTSTATUS ret;
+    __u32 prev;
+
+    ret = ioctl( obj, NTSYNC_IOC_EVENT_PULSE, &prev );
+    if (ret < 0)
+        return errno_to_status( errno );
+    if (prev_state) *prev_state = prev;
+    return STATUS_SUCCESS;
 }
 
+
 static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT,
+                                    EVENT_MODIFY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_pulse_event_obj( cache->fd, prev_state );
+
+    release_inproc_sync_obj( cache );
+    return ret;
 }
 
+
+static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info )
+{
+    struct ntsync_event_args args = {0};
+    NTSTATUS ret;
+
+    ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args );
+    if (ret < 0)
+        return errno_to_status( errno );
+    info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent;
+    info->EventState = args.signaled;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT,
+                                    EVENT_QUERY_STATE, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_query_event_obj( cache->fd, cache->type, info );
+
+    release_inproc_sync_obj( cache );
+    return ret;
 }
 
+
+static NTSTATUS linux_release_mutex_obj( int obj, LONG *prev_count )
+{
+    struct ntsync_mutex_args args = {0};
+    NTSTATUS ret;
+
+    args.owner = GetCurrentThreadId();
+    ret = ioctl( obj, NTSYNC_IOC_MUTEX_UNLOCK, &args );
+
+    if (ret < 0)
+    {
+        if (errno == EOVERFLOW)
+            return STATUS_MUTANT_LIMIT_EXCEEDED;
+        else if (errno == EPERM)
+            return STATUS_MUTANT_NOT_OWNED;
+        else
+            return errno_to_status( errno );
+    }
+    if (prev_count) *prev_count = 1 - args.count;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_release_mutex_obj( cache->fd, prev_count );
+
+    release_inproc_sync_obj( cache );
+    return ret;
 }
 
+
+static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info )
+{
+    struct ntsync_mutex_args args = {0};
+    NTSTATUS ret;
+
+    ret = ioctl( obj, NTSYNC_IOC_MUTEX_READ, &args );
+
+    if (ret < 0)
+    {
+        if (errno == EOWNERDEAD)
+        {
+            info->AbandonedState = TRUE;
+            info->OwnedByCaller = FALSE;
+            info->CurrentCount = 1;
+            return STATUS_SUCCESS;
+        }
+        else
+            return errno_to_status( errno );
+    }
+    info->AbandonedState = FALSE;
+    info->OwnedByCaller = (args.owner == GetCurrentThreadId());
+    info->CurrentCount = 1 - args.count;
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    NTSTATUS ret;
+
+    if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE,
+                                    &stack_cache, &cache )))
+        return ret;
+
+    ret = linux_query_mutex_obj( cache->fd, info );
+
+    release_inproc_sync_obj( cache );
+    return ret;
+}
+
+static void select_queue(void)
+{
+    SERVER_START_REQ( select_inproc_queue )
+    {
+        wine_server_call( req );
+    }
+    SERVER_END_REQ;
+}
+
+static void unselect_queue( BOOL signaled )
+{
+    SERVER_START_REQ( unselect_inproc_queue )
+    {
+        req->signaled = signaled;
+        wine_server_call( req );
+    }
+    SERVER_END_REQ;
+}
+
+static int get_inproc_alert_obj(void)
+{
+    struct ntdll_thread_data *data = ntdll_get_thread_data();
+    struct inproc_sync_cache_entry stack_cache, *cache;
+    HANDLE alert_handle;
+    unsigned int ret;
+
+    if (data->linux_alert_obj == -1)
+    {
+        SERVER_START_REQ( get_inproc_alert_event )
+        {
+            if ((ret = wine_server_call( req )))
+                ERR( "failed to get inproc alert event, status %#x\n", ret );
+            alert_handle = wine_server_ptr_handle( reply->handle );
+        }
+        SERVER_END_REQ;
+
+        if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache )))
+            ERR( "failed to get inproc alert obj, status %#x\n", ret );
+        data->linux_alert_obj = cache->fd;
+        /* Set the fd to -1 so release_inproc_sync_obj() won't close it.
+         * Manhandling the cache entry here is fine since we're the only thread
+         * that can access our own alert event. */
+        cache->fd = -1;
+        release_inproc_sync_obj( cache );
+        NtClose( alert_handle );
+    }
+
+    return data->linux_alert_obj;
+}
+
+static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs,
+                                 BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+    struct ntsync_wait_args args = {0};
+    unsigned long request;
+    struct timespec now;
+    int ret;
+
+    if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE)
+    {
+        args.timeout = ~(__u64)0;
+    }
+    else if (timeout->QuadPart <= 0)
+    {
+        clock_gettime( CLOCK_MONOTONIC, &now );
+        args.timeout = (now.tv_sec * NSECPERSEC) + now.tv_nsec + (-timeout->QuadPart * 100);
+    }
+    else
+    {
+        args.timeout = (timeout->QuadPart * 100) - (SECS_1601_TO_1970 * NSECPERSEC);
+        args.flags |= NTSYNC_WAIT_REALTIME;
+    }
+
+    args.objs = (uintptr_t)objs;
+    args.count = count;
+    args.owner = GetCurrentThreadId();
+    args.index = ~0u;
+
+    if (alertable)
+        args.alert = get_inproc_alert_obj();
+
+    if (wait_any || count == 1)
+        request = NTSYNC_IOC_WAIT_ANY;
+    else
+        request = NTSYNC_IOC_WAIT_ALL;
+
+    do
+    {
+        ret = ioctl( device, request, &args );
+    } while (ret < 0 && errno == EINTR);
+
+    if (!ret)
+    {
+        if (args.index == count)
+        {
+            static const LARGE_INTEGER timeout;
+
+            ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &timeout );
+            assert( ret == STATUS_USER_APC );
+            return ret;
+        }
+
+        return wait_any ? args.index : 0;
+    }
+    else if (errno == EOWNERDEAD)
+        return STATUS_ABANDONED + (wait_any ? args.index : 0);
+    else if (errno == ETIMEDOUT)
+        return STATUS_TIMEOUT;
+    else
+        return errno_to_status( errno );
 }
 
 static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
                              BOOLEAN alertable, const LARGE_INTEGER *timeout )
 {
-    int device;
+    struct inproc_sync_cache_entry stack_cache[64], *cache[64];
+    int device, objs[64];
+    HANDLE queue = NULL;
+    NTSTATUS ret;
+    DWORD i, j;
 
     if ((device = get_linux_sync_device()) < 0)
         return STATUS_NOT_IMPLEMENTED;
 
-    return STATUS_NOT_IMPLEMENTED;
+    for (i = 0; i < count; ++i)
+    {
+        if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] )))
+        {
+            for (j = 0; j < i; ++j)
+                release_inproc_sync_obj( cache[j] );
+            return ret;
+        }
+        if (cache[i]->type == INPROC_SYNC_QUEUE)
+            queue = handles[i];
+
+        objs[i] = cache[i]->fd;
+    }
+
+    if (queue) select_queue();
+
+    ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout );
+
+    if (queue) unselect_queue( handles[ret] == queue );
+
+    for (i = 0; i < count; ++i)
+        release_inproc_sync_obj( cache[i] );
+
+    return ret;
 }
 
 static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
                                         BOOLEAN alertable, const LARGE_INTEGER *timeout )
 {
+    struct inproc_sync_cache_entry signal_stack_cache, *signal_cache;
+    struct inproc_sync_cache_entry wait_stack_cache, *wait_cache;
+    HANDLE queue = NULL;
+    NTSTATUS ret;
     int device;
 
     if ((device = get_linux_sync_device()) < 0)
         return STATUS_NOT_IMPLEMENTED;
 
-    return STATUS_NOT_IMPLEMENTED;
+    if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache )))
+        return ret;
+
+    switch (signal_cache->type)
+    {
+        case INPROC_SYNC_SEMAPHORE:
+            if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE))
+            {
+                release_inproc_sync_obj( signal_cache );
+                return STATUS_ACCESS_DENIED;
+            }
+            break;
+
+        case INPROC_SYNC_AUTO_EVENT:
+        case INPROC_SYNC_MANUAL_EVENT:
+            if (!(signal_cache->access & EVENT_MODIFY_STATE))
+            {
+                release_inproc_sync_obj( signal_cache );
+                return STATUS_ACCESS_DENIED;
+            }
+            break;
+
+        case INPROC_SYNC_MUTEX:
+            break;
+
+        default:
+            /* can't be signaled */
+            release_inproc_sync_obj( signal_cache );
+            return STATUS_OBJECT_TYPE_MISMATCH;
+    }
+
+    if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache )))
+    {
+        release_inproc_sync_obj( signal_cache );
+        return ret;
+    }
+
+    if (wait_cache->type == INPROC_SYNC_QUEUE)
+        queue = wait;
+
+    switch (signal_cache->type)
+    {
+        case INPROC_SYNC_SEMAPHORE:
+            ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL );
+            break;
+
+        case INPROC_SYNC_AUTO_EVENT:
+        case INPROC_SYNC_MANUAL_EVENT:
+            ret = linux_set_event_obj( signal_cache->fd, NULL );
+            break;
+
+        case INPROC_SYNC_MUTEX:
+            ret = linux_release_mutex_obj( signal_cache->fd, NULL );
+            break;
+
+        default:
+            assert( 0 );
+            break;
+    }
+
+    if (!ret)
+    {
+        if (queue) select_queue();
+        ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout );
+        if (queue) unselect_queue( !ret );
+    }
+
+    release_inproc_sync_obj( signal_cache );
+    release_inproc_sync_obj( wait_cache );
+    return ret;
 }
 
 #else
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 22bb0978803..84667d989dd 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -115,6 +115,7 @@ struct ntdll_thread_data
     PRTL_THREAD_START_ROUTINE start;         /* thread entry point */
     void                     *param;         /* thread entry point parameter */
     void                     *jmp_buf;       /* setjmp buffer for exception handling */
+    int                       linux_alert_obj; /* fd for the linux in-process alert event */
 };
 
 C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) );
@@ -401,6 +402,7 @@ extern void call_raise_user_exception_dispatcher(void);
 #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */
 
 #define TICKSPERSEC 10000000
+#define NSECPERSEC 1000000000
 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)86400)
 
 static inline ULONGLONG ticks_from_time_t( time_t time )
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index d796783dbf4..a3a1eed08fd 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4036,6 +4036,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
     thread_data->reply_fd   = -1;
     thread_data->wait_fd[0] = -1;
     thread_data->wait_fd[1] = -1;
+    thread_data->linux_alert_obj = -1;
     list_add_head( &teb_list, &thread_data->entry );
     return teb;
 }
diff --git a/server/inproc_sync.c b/server/inproc_sync.c
index c6f79081b6f..f3c6a37fc8c 100644
--- a/server/inproc_sync.c
+++ b/server/inproc_sync.c
@@ -56,7 +56,7 @@ static int get_linux_device(void)
 
 int use_inproc_sync(void)
 {
-    return 0;
+    return get_linux_device() >= 0;
 }
 
 int create_inproc_event( int manual_reset, int signaled )
-- 
2.50.1


From 7ad496ca5460837c87fa43d9bc415d20d031f352 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Tue, 20 Apr 2021 17:55:59 -0500
Subject: [PATCH 56/57] ntdll: Use server_wait_for_object() when waiting on
 only the queue object.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/sync.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 8d26564de4b..080d4654c76 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -861,6 +861,17 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an
         objs[i] = cache[i]->fd;
     }
 
+    /* It's common to wait on the message queue alone. Some applications wait
+     * on it in fast paths, with a zero timeout. Since we take two server calls
+     * instead of one when going through inproc_wait(), and since we only need
+     * to go through that path if we're waiting on other objects, just delegate
+     * to the server if we're only waiting on the message queue. */
+    if (count == 1 && queue)
+    {
+        release_inproc_sync_obj( cache[0] );
+        return server_wait_for_object( handles[0], alertable, timeout );
+    }
+
     if (queue) select_queue();
 
     ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout );
-- 
2.50.1


From e43f8ac52e99831b4ee1d2aeea72f5fa4cd1cd84 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Fri, 12 Mar 2021 15:04:17 -0600
Subject: [PATCH 57/57] ntdll: Cache in-process synchronization objects.

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/ntdll/unix/server.c       |   9 ++
 dlls/ntdll/unix/sync.c         | 190 +++++++++++++++++++++++++++++++--
 dlls/ntdll/unix/unix_private.h |   2 +
 3 files changed, 192 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 25c095537d5..a99d2784fb8 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -1883,12 +1883,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
         return result.dup_handle.status;
     }
 
+    /* hold fd_cache_mutex to prevent the fd from being added again between the
+     * call to remove_fd_from_cache and close_handle */
     server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
 
     /* always remove the cached fd; if the server request fails we'll just
      * retrieve it again */
     if (options & DUPLICATE_CLOSE_SOURCE)
+    {
         fd = remove_fd_from_cache( source );
+        close_inproc_sync_obj( source );
+    }
 
     SERVER_START_REQ( dup_handle )
     {
@@ -1954,12 +1959,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
     if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0)
         return STATUS_SUCCESS;
 
+    /* hold fd_cache_mutex to prevent the fd from being added again between the
+     * call to remove_fd_from_cache and close_handle */
     server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
 
     /* always remove the cached fd; if the server request fails we'll just
      * retrieve it again */
     fd = remove_fd_from_cache( handle );
 
+    close_inproc_sync_obj( handle );
+
     SERVER_START_REQ( close_handle )
     {
         req->handle = wine_server_obj_handle( handle );
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 080d4654c76..428ffb33c8e 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -355,6 +355,12 @@ static int get_linux_sync_device(void)
  * it closes the handle; when all handles are closed, the server deletes the
  * in-process synchronization object.
  *
+ * We also need this for signal-and-wait. The signal and wait operations aren't
+ * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE
+ * for the wait—we need to either do both operations or neither. That means we
+ * need to grab references to both objects, and prevent them from being
+ * destroyed before we're done with them.
+ *
  * We want lookup of objects from the cache to be very fast; ideally, it should
  * be lock-free. We achieve this by using atomic modifications to "refcount",
  * and guaranteeing that all other fields are valid and correct *as long as*
@@ -397,6 +403,117 @@ static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache )
 }
 
 
+#define INPROC_SYNC_CACHE_BLOCK_SIZE  (65536 / sizeof(struct inproc_sync_cache_entry))
+#define INPROC_SYNC_CACHE_ENTRIES     128
+
+static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES];
+static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE];
+
+static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry )
+{
+    unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1;
+    *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE;
+    return idx % INPROC_SYNC_CACHE_BLOCK_SIZE;
+}
+
+
+static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd,
+                                                              enum inproc_sync_type type, unsigned int access )
+{
+    unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry );
+    struct inproc_sync_cache_entry *cache;
+    int refcount;
+
+    /* don't cache pseudo-handles; waiting on them is pointless anyway */
+    if ((ULONG)(ULONG_PTR)handle > 0xfffffffa)
+        return FALSE;
+
+    if (entry >= INPROC_SYNC_CACHE_ENTRIES)
+    {
+        FIXME( "too many allocated handles, not caching %p\n", handle );
+        return NULL;
+    }
+
+    if (!inproc_sync_cache[entry])  /* do we need to allocate a new block of entries? */
+    {
+        if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block;
+        else
+        {
+            static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry);
+            void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE );
+            if (ptr == MAP_FAILED) return NULL;
+            if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL ))
+                munmap( ptr, size ); /* someone beat us to it */
+        }
+    }
+
+    cache = &inproc_sync_cache[entry][idx];
+
+    if (InterlockedCompareExchange( &cache->refcount, 0, 0 ))
+    {
+        /* The handle is currently being used for another object (i.e. it was
+         * closed and then reused, but some thread is waiting on the old handle
+         * or otherwise simultaneously using the old object). We can't cache
+         * this object until the old one is completely destroyed. */
+        return NULL;
+    }
+
+    cache->fd = fd;
+    cache->type = type;
+    cache->access = access;
+    cache->closed = FALSE;
+    /* Make sure we set the other members before the refcount; this store needs
+     * release semantics [paired with the load in get_cached_inproc_sync_obj()].
+     * Set the refcount to 2 (one for the handle, one for the caller). */
+    refcount = InterlockedExchange( &cache->refcount, 2 );
+    assert( !refcount );
+
+    return cache;
+}
+
+
+/* returns the previous value */
+static inline LONG interlocked_inc_if_nonzero( LONG *dest )
+{
+    LONG val, tmp;
+    for (val = *dest;; val = tmp)
+    {
+        if (!val || (tmp = InterlockedCompareExchange( dest, val + 1, val )) == val)
+            break;
+    }
+    return val;
+}
+
+
+static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle )
+{
+    unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry );
+    struct inproc_sync_cache_entry *cache;
+
+    if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry])
+        return NULL;
+
+    cache = &inproc_sync_cache[entry][idx];
+
+    /* this load needs acquire semantics [paired with the store in
+     * cache_inproc_sync_obj()] */
+    if (!interlocked_inc_if_nonzero( &cache->refcount ))
+        return NULL;
+
+    if (cache->closed)
+    {
+        /* The object is still being used, but "handle" has been closed. The
+         * handle value might have been reused for another object in the
+         * meantime, in which case we have to report that valid object, so
+         * force the caller to check the server. */
+        release_inproc_sync_obj( cache );
+        return NULL;
+    }
+
+    return cache;
+}
+
+
 static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b )
 {
     if (a == b) return TRUE;
@@ -413,41 +530,77 @@ static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desire
                                      struct inproc_sync_cache_entry *stack_cache,
                                      struct inproc_sync_cache_entry **ret_cache )
 {
-    struct inproc_sync_cache_entry *cache = stack_cache;
+    struct inproc_sync_cache_entry *cache;
+    obj_handle_t inproc_sync_handle;
+    enum inproc_sync_type type;
+    unsigned int access;
     sigset_t sigset;
     NTSTATUS ret;
+    int fd;
 
     /* We don't need the device right now, but if we can't access it, that
      * means ntsync isn't available. Fail fast in that case. */
     if (get_linux_sync_device() < 0)
         return STATUS_NOT_IMPLEMENTED;
 
-    *ret_cache = stack_cache;
+    /* try to find it in the cache already */
+    if ((cache = get_cached_inproc_sync_obj( handle )))
+    {
+        *ret_cache = cache;
+        return STATUS_SUCCESS;
+    }
 
     /* We need to use fd_cache_mutex here to protect against races with
      * other threads trying to receive fds for the fd cache,
-     * and we need to use an uninterrupted section to prevent reentrancy. */
+     * and we need to use an uninterrupted section to prevent reentrancy.
+     * We also need fd_cache_mutex to protect against the same race with
+     * NtClose, that is, to prevent the object from being cached again between
+     * close_inproc_sync_obj() and close_handle. */
     server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
 
+    if ((cache = get_cached_inproc_sync_obj( handle )))
+    {
+        server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+        *ret_cache = cache;
+        return STATUS_SUCCESS;
+    }
+
+    /* try to retrieve it from the server */
     SERVER_START_REQ( get_linux_sync_obj )
     {
         req->handle = wine_server_obj_handle( handle );
         if (!(ret = wine_server_call( req )))
         {
             obj_handle_t fd_handle;
-            cache->fd = wine_server_receive_fd( &fd_handle );
+            fd = wine_server_receive_fd( &fd_handle );
             assert( wine_server_ptr_handle(fd_handle) == handle );
-            cache->access = reply->access;
-            cache->type = reply->type;
-            cache->refcount = 1;
-            cache->closed = FALSE;
+            access = reply->access;
+            type = reply->type;
         }
     }
     SERVER_END_REQ;
 
+    if (ret)
+    {
+        server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+        return ret;
+    }
+
+    cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access );
+
     server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
 
-    if (ret) return ret;
+    if (!cache)
+    {
+        cache = stack_cache;
+        cache->fd = fd;
+        cache->type = type;
+        cache->access = access;
+        cache->closed = FALSE;
+        cache->refcount = 1;
+    }
+
+    *ret_cache = cache;
 
     if (desired_type && !inproc_sync_types_match( cache->type, desired_type ))
     {
@@ -465,6 +618,21 @@ static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desire
 }
 
 
+/* caller must hold fd_cache_mutex */
+void close_inproc_sync_obj( HANDLE handle )
+{
+    struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle );
+
+    if (cache)
+    {
+        cache->closed = TRUE;
+        /* once for the reference we just grabbed, and once for the handle */
+        release_inproc_sync_obj( cache );
+        release_inproc_sync_obj( cache );
+    }
+}
+
+
 static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count )
 {
     NTSTATUS ret;
@@ -970,6 +1138,10 @@ static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
 
 #else
 
+void close_inproc_sync_obj( HANDLE handle )
+{
+}
+
 static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count )
 {
     return STATUS_NOT_IMPLEMENTED;
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 84667d989dd..0db2d50e439 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -396,6 +396,8 @@ extern void dbg_init(void);
 
 extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2,
                                           ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status );
+extern void close_inproc_sync_obj( HANDLE handle );
+
 extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context );
 extern void call_raise_user_exception_dispatcher(void);
 
-- 
2.50.1

07070100B6933E000081A4000003E8000003E80000000168AA560300000C61000001030000000200000000000000000000003100000000patches/Add-workarounds-for-game-launchers.patchFrom ebc9e0914f293952405e622e440a05a253b1b038 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Sat, 19 Jul 2025 17:20:25 +0300
Subject: [PATCH] Add workarounds for game launchers

Based on Proton patch from Paul Gofman <pgofman@codeweavers.com>

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/kernelbase/process.c | 57 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c
index b75963fef1d..9b78606f1cc 100644
--- a/dlls/kernelbase/process.c
+++ b/dlls/kernelbase/process.c
@@ -502,6 +502,38 @@ done:
     return ret;
 }
 
+static const WCHAR *hack_append_command_line( const WCHAR *cmd )
+{
+    static const struct
+    {
+        const WCHAR *exe_name;
+        const WCHAR *append;
+    }
+    options[] =
+    {
+        {L"UplayWebCore.exe", L" --use-gl=swiftshader"},
+        {L"Paradox Launcher.exe", L" --use-gl=swiftshader --in-process-gpu"},
+        {L"\\EpicOnlineServicesUIHelper", L" --use-gl=desktop"},
+        {L"Battle.net.exe", L" --in-process-gpu"},
+        {L"RSI Launcher.exe", L" --in-process-gpu"},
+        {L"EADesktop.exe", L" --in-process-gpu"},
+        {L"launcher_epic.exe", L" --in-process-gpu"},
+    };
+    unsigned int i;
+
+    if (!cmd) return NULL;
+
+    for (i = 0; i < ARRAY_SIZE(options); ++i)
+    {
+        if (wcsstr( cmd, options[i].exe_name ))
+        {
+            FIXME( "HACK: appending %s to command line.\n", debugstr_w(options[i].append) );
+            return options[i].append;
+        }
+    }
+    return NULL;
+}
+
 /**********************************************************************
  *           CreateProcessInternalW   (kernelbase.@)
  */
@@ -518,6 +550,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR
     RTL_USER_PROCESS_PARAMETERS *params = NULL;
     RTL_USER_PROCESS_INFORMATION rtl_info;
     HANDLE parent = 0, debug = 0;
+    const WCHAR *append;
     ULONG nt_flags = 0;
     USHORT machine = 0;
     NTSTATUS status;
@@ -539,7 +572,29 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR
     }
     else
     {
-        if (!(tidy_cmdline = get_file_name( cmd_line, name, ARRAY_SIZE(name) ))) return FALSE;
+        WCHAR *cmdline_new = NULL;
+
+        if ((append = hack_append_command_line( cmd_line )))
+        {
+            cmdline_new = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(WCHAR)
+                                           * (lstrlenW(cmd_line) + lstrlenW(append) + 1) );
+            lstrcpyW(cmdline_new, cmd_line);
+            lstrcatW(cmdline_new, append);
+        }
+
+        tidy_cmdline = get_file_name( cmdline_new ? cmdline_new : cmd_line, name, ARRAY_SIZE(name) );
+
+        if (!tidy_cmdline)
+        {
+            HeapFree( GetProcessHeap(), 0, cmdline_new );
+            return FALSE;
+        }
+
+        if (cmdline_new)
+        {
+            if (cmdline_new == tidy_cmdline) cmd_line = NULL;
+            else HeapFree( GetProcessHeap(), 0, cmdline_new );
+        }
         app_name = name;
     }
 
-- 
2.50.1

07070100B6933F000081A4000003E8000003E80000000168AA560300000C82000001030000000200000000000000000000004800000000patches/0001-HACK-wine.inf-Add-native-builtin-overrides-for-msvcr.patchFrom ac40f35bbdead99900d16d9b3e3ea1337443f7ac Mon Sep 17 00:00:00 2001
From: Andrew Eikum <aeikum@codeweavers.com>
Date: Fri, 7 Feb 2025 22:22:59 +0300
Subject: [PATCH 1/5] HACK: wine.inf: Add native,builtin overrides for msvcrt
 DLLs

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 loader/wine.inf.in | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index e6ff05570f0..04612cd2522 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -2874,6 +2874,37 @@ HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Shanghai-EnableGame",0x1
 HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Solitaire-EnableGame",0x10001,0x00000001
 HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-SpiderSolitaire-EnableGame",0x10001,0x00000001
 HKLM,Software\Wine\LicenseInformation,"Shell-PremiumInBoxGames-Chess-EnableGame",0x10001,0x00000001
+;;Likely want *80 and *90 too, but those require removing Wine's manifest files.
+HKCU,Software\Wine\DllOverrides,"atl100",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp100",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcr100",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcomp100",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"atl110",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp110",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcr110",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcomp110",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"atl120",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp120",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcr120",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcomp120",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-conio-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-heap-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-locale-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-math-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-runtime-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-stdio-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"api-ms-win-crt-time-l1-1-0",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"atl140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"concrt140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp140_1",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp140_codecvt_ids",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcp140_2",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"msvcr140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"ucrtbase",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcomp140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcruntime140",0x2,"native,builtin"
+HKCU,Software\Wine\DllOverrides,"vcruntime140_1",0x2,"native,builtin"
 
 [ColorFiles]
 srgb color space profile.icm,"@%11%\mscms.dll,-1"
-- 
2.48.1

07070100B69340000081A4000003E8000003E80000000168AA560300001932000001030000000200000000000000000000004300000000patches/ntdll-loader-add-support-for-overriding-IMAGE_FILE_L.patchFrom 07d32c24cc264e2a746d8e5054159f9aa893edbc Mon Sep 17 00:00:00 2001
From: Steven Noonan <steven@valvesoftware.com>
Date: Wed, 17 Oct 2018 04:13:37 -0700
Subject: [PATCH] ntdll/loader: add support for overriding
 IMAGE_FILE_LARGE_ADDRESS_AWARE

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 dlls/kernel32/heap.c           |  8 +++++++-
 dlls/ntdll/ntdll.spec          |  3 +++
 dlls/ntdll/signal_arm64ec.c    |  1 +
 dlls/ntdll/unix/unix_private.h |  2 ++
 dlls/ntdll/unix/virtual.c      | 22 ++++++++++++++++++++--
 dlls/wow64/system.c            |  6 ++++++
 6 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c
index 1ec2f5cce0d..10f6895478e 100644
--- a/dlls/kernel32/heap.c
+++ b/dlls/kernel32/heap.c
@@ -42,6 +42,8 @@
 WINE_DEFAULT_DEBUG_CHANNEL(globalmem);
 
 
+extern BOOL WINAPI __wine_needs_override_large_address_aware(void);
+
 /***********************************************************************
  *           HeapCreate   (KERNEL32.@)
  *
@@ -424,6 +426,7 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer )
     OSVERSIONINFOW osver;
 #ifndef _WIN64
     IMAGE_NT_HEADERS *nt = RtlImageNtHeader( GetModuleHandleW(0) );
+    static int force_large_address_aware = -1;
 #endif
 
     /* Because GlobalMemoryStatus is identical to GlobalMemoryStatusEX save
@@ -450,6 +453,8 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer )
     lpBuffer->dwAvailVirtual = memstatus.ullAvailVirtual;
 
 #ifndef _WIN64
+    if (force_large_address_aware == -1)
+        force_large_address_aware = __wine_needs_override_large_address_aware();
     if ( osver.dwMajorVersion >= 5 || osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
     {
         lpBuffer->dwTotalPhys = min( memstatus.ullTotalPhys, MAXDWORD );
@@ -463,7 +468,8 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer )
 
     /* values are limited to 2Gb unless the app has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag */
     /* page file sizes are not limited (Adobe Illustrator 8 depends on this) */
-    if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE))
+    if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) &&
+        !force_large_address_aware)
     {
         if (lpBuffer->dwTotalPhys > MAXLONG) lpBuffer->dwTotalPhys = MAXLONG;
         if (lpBuffer->dwAvailPhys > MAXLONG) lpBuffer->dwAvailPhys = MAXLONG;
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 7c2e494e4ad..7dff2b6a0eb 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1757,3 +1757,6 @@
 @ cdecl wine_get_version()
 @ cdecl wine_get_build_id()
 @ cdecl wine_get_host_version(ptr ptr)
+
+# Filesystem
+@ stdcall -syscall __wine_needs_override_large_address_aware()
diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c
index 0f4b55b60c4..001da1327a7 100644
--- a/dlls/ntdll/signal_arm64ec.c
+++ b/dlls/ntdll/signal_arm64ec.c
@@ -596,6 +596,7 @@ DEFINE_SYSCALL(NtWriteFileGather, (HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
 DEFINE_SYSCALL(NtWriteRequestData, (HANDLE handle, LPC_MESSAGE *request, ULONG id, void *buffer, ULONG len, ULONG *retlen))
 DEFINE_SYSCALL(NtWriteVirtualMemory, (HANDLE process, void *addr, const void *buffer, SIZE_T size, SIZE_T *bytes_written))
 DEFINE_SYSCALL(NtYieldExecution, (void))
+DEFINE_SYSCALL_(BOOL, __wine_needs_override_large_address_aware, (void))
 
 NTSTATUS SYSCALL_API NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR zero_bits,
                                               SIZE_T *size_ptr, ULONG type, ULONG protect )
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index fa38f4b87ca..e2f3a5d1e44 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -590,4 +590,6 @@ static inline NTSTATUS map_section( HANDLE mapping, void **ptr, SIZE_T *size, UL
                                0, NULL, size, ViewShare, 0, protect );
 }
 
+BOOL WINAPI __wine_needs_override_large_address_aware(void);
+
 #endif /* __NTDLL_UNIX_PRIVATE_H */
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index e733e3ffdd6..5fb33757d36 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4890,6 +4890,24 @@ static void virtual_release_address_space(void)
 
 #endif  /* _WIN64 */
 
+BOOL WINAPI __wine_needs_override_large_address_aware(void)
+{
+    static int needs_override = -1;
+
+    if (needs_override == -1)
+    {
+        const char *str = getenv( "WINE_LARGE_ADDRESS_AWARE" );
+
+        needs_override = (str ? atoi(str) == 1 : 0);
+    }
+    return needs_override;
+}
+
+static BOOL is_large_address_aware(void)
+{
+    return (main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
+           || __wine_needs_override_large_address_aware();
+}
 
 /***********************************************************************
  *           virtual_set_large_address_space
@@ -4901,7 +4919,7 @@ void virtual_set_large_address_space(void)
     if (is_win64)
     {
         if (is_wow64())
-            user_space_wow_limit = ((main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) ? limit_4g : limit_2g) - 1;
+            user_space_wow_limit = (is_large_address_aware() ? limit_4g : limit_2g) - 1;
 #ifndef __APPLE__  /* don't free the zerofill section on macOS */
         else if ((main_image_info.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) &&
                  (main_image_info.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE))
@@ -4910,7 +4928,7 @@ void virtual_set_large_address_space(void)
     }
     else
     {
-        if (!(main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) return;
+        if (!is_large_address_aware()) return;
         free_reserved_memory( (char *)0x80000000, address_space_limit );
     }
     user_space_limit = working_set_limit = address_space_limit;
diff --git a/dlls/wow64/system.c b/dlls/wow64/system.c
index fd10a0585ce..933a594f29b 100644
--- a/dlls/wow64/system.c
+++ b/dlls/wow64/system.c
@@ -857,3 +857,9 @@ NTSTATUS WINAPI wow64_NtWow64GetNativeSystemInformation( UINT *args )
         return STATUS_INVALID_INFO_CLASS;
     }
 }
+
+BOOL WINAPI __wine_needs_override_large_address_aware(void);
+NTSTATUS WINAPI wow64___wine_needs_override_large_address_aware( UINT * args )
+{
+    return __wine_needs_override_large_address_aware();
+}
-- 
2.50.1

07070100B69341000081A4000003E8000003E80000000168AA560300002491000001030000000200000000000000000000002A00000000patches/winecfg-Add-tweaks-tab-page.patchFrom 67d81111cbbbcc799da7097b5a9222d4e8ac4107 Mon Sep 17 00:00:00 2001
From: Vasiliy Stelmachenok <ventureo@cachyos.org>
Date: Fri, 21 Mar 2025 14:04:59 +0300
Subject: [PATCH] winecfg: Add tweaks tab page

As of now, it currently allows you to:

- Enable ALSA driver for audio output
- Enable Wayland graphics driver
- Enable video decoding via FFmpeg (winedmo)
- Enable display mode emulation for X11

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 programs/winecfg/Makefile.in |   1 +
 programs/winecfg/main.c      |  12 +++-
 programs/winecfg/resource.h  |   8 +++
 programs/winecfg/tweaks.c    | 123 +++++++++++++++++++++++++++++++++++
 programs/winecfg/winecfg.h   |   1 +
 programs/winecfg/winecfg.rc  |  13 ++++
 6 files changed, 157 insertions(+), 1 deletion(-)
 create mode 100644 programs/winecfg/tweaks.c

diff --git a/programs/winecfg/Makefile.in b/programs/winecfg/Makefile.in
index 1105a99e177..a51505902d1 100644
--- a/programs/winecfg/Makefile.in
+++ b/programs/winecfg/Makefile.in
@@ -14,6 +14,7 @@ SOURCES = \
 	logo.svg \
 	main.c \
 	staging.c \
+	tweaks.c \
 	theme.c \
 	winecfg.c \
 	winecfg.man.in \
diff --git a/programs/winecfg/main.c b/programs/winecfg/main.c
index b733b11be5e..48739f44997 100644
--- a/programs/winecfg/main.c
+++ b/programs/winecfg/main.c
@@ -58,7 +58,7 @@ PropSheetCallback (HWND hWnd, UINT uMsg, LPARAM lParam)
     return 0;
 }
 
-#define NUM_PROPERTY_PAGES 9
+#define NUM_PROPERTY_PAGES 10
 
 static INT_PTR
 doPropertySheet (HINSTANCE hInstance, HWND hOwner)
@@ -149,6 +149,16 @@ doPropertySheet (HINSTANCE hInstance, HWND hOwner)
     psp[pg].lParam = 0;
     pg++;
 
+    psp[pg].dwSize = sizeof (PROPSHEETPAGEW);
+    psp[pg].dwFlags = PSP_USETITLE;
+    psp[pg].hInstance = hInstance;
+    psp[pg].pszTemplate = MAKEINTRESOURCEW (IDD_TWEAKS);
+    psp[pg].pszIcon = NULL;
+    psp[pg].pfnDlgProc = TweaksDlgProc;
+    psp[pg].pszTitle =  load_string (IDS_TAB_TWEAKS);
+    psp[pg].lParam = 0;
+    pg++;
+
     psp[pg].dwSize = sizeof (PROPSHEETPAGEW);
     psp[pg].dwFlags = PSP_USETITLE;
     psp[pg].hInstance = hInstance;
diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
index 803a0fc150e..16851e7adb8 100644
--- a/programs/winecfg/resource.h
+++ b/programs/winecfg/resource.h
@@ -47,6 +47,7 @@
 #define IDS_WINECFG_TITLE_APP           18   /* App specific title */
 #define IDS_TAB_STAGING                 19
 #define IDS_TAB_INPUT                   20
+#define IDS_TAB_TWEAKS                  21
 #define IDI_WINECFG                     100
 #define IDI_LOGO                        102
 #define IDD_ABOUTCFG                    107
@@ -58,6 +59,7 @@
 #define IDD_DESKTOP_INTEGRATION         115
 #define IDD_STAGING                     116
 #define IDD_INPUT_CONFIG                117
+#define IDD_TWEAKS                      118
 #define IDC_WINVER                      1012
 #define IDC_DESKTOP_WIDTH               1023
 #define IDC_DESKTOP_HEIGHT              1024
@@ -223,6 +225,12 @@
 #define IDC_ENABLE_HIDEWINE             9004
 #define IDC_ENABLE_GTK3                 9005
 
+/* Tweaks tab */
+#define IDC_ENABLE_ALSA                 10001
+#define IDC_ENABLE_WAYLAND              10002
+#define IDC_ENABLE_FSHACK               10003
+#define IDC_ENABLE_FFMPEG               10004
+
 /* About tab */
 #define IDC_ABT_OWNER                8432
 #define IDC_ABT_ORG                  8433
diff --git a/programs/winecfg/tweaks.c b/programs/winecfg/tweaks.c
new file mode 100644
index 00000000000..6e7e45d4205
--- /dev/null
+++ b/programs/winecfg/tweaks.c
@@ -0,0 +1,123 @@
+#define COBJMACROS
+
+#include <windows.h>
+
+#include "resource.h"
+#include "winecfg.h"
+
+/*
+ * ALSA
+ */
+static BOOL alsa_get(void)
+{
+    BOOL ret;
+    WCHAR *value = get_reg_key(config_key, keypath(L"Drivers"), L"Audio", NULL);
+    ret = (value && !wcsicmp(value, L"alsa"));
+    free(value);
+    return ret;
+}
+static void alsa_set(BOOL status)
+{
+    set_reg_key(config_key, keypath(L"Drivers"), L"Audio", status ? L"alsa" : NULL);
+}
+
+/*
+ * Wayland
+ */
+static BOOL wayland_get(void)
+{
+    BOOL ret;
+    WCHAR *value = get_reg_key(config_key, keypath(L"Drivers"), L"Graphics", NULL);
+    ret = (value && !wcsicmp(value, L"wayland"));
+    free(value);
+    return ret;
+}
+static void wayland_set(BOOL status)
+{
+    set_reg_key(config_key, keypath(L"Drivers"), L"Graphics", status ? L"wayland" : NULL);
+}
+
+/*
+ * FS Hack
+ */
+static BOOL fshack_get(void)
+{
+    BOOL ret;
+    WCHAR *value = get_reg_key(config_key, keypath(L"X11 Driver"), L"EmulateModeset", NULL);
+    ret = (value && !wcsicmp(value, L"Y"));
+    free(value);
+    return ret;
+}
+static void fshack_set(BOOL status)
+{
+    set_reg_key(config_key, keypath(L"X11 Driver"), L"EmulateModeset", status ? L"Y" : NULL);
+}
+
+/*
+ * FFmpeg
+ */
+static BOOL ffmpeg_get(void)
+{
+    BOOL ret;
+    WCHAR *value = get_reg_key(config_key, keypath(L"MediaFoundation"), L"DisableGstByteStreamHandler", NULL);
+    ret = (value && !wcsicmp(value, L"Y"));
+    free(value);
+    return ret;
+}
+static void ffmpeg_set(BOOL status)
+{
+    set_reg_key(config_key, keypath(L"MediaFoundation"), L"DisableGstByteStreamHandler", status ? L"Y" : NULL);
+}
+
+static void load_staging_settings(HWND dialog)
+{
+    CheckDlgButton(dialog, IDC_ENABLE_ALSA, alsa_get() ? BST_CHECKED : BST_UNCHECKED);
+    CheckDlgButton(dialog, IDC_ENABLE_WAYLAND, wayland_get() ? BST_CHECKED : BST_UNCHECKED);
+    CheckDlgButton(dialog, IDC_ENABLE_FSHACK, fshack_get() ? BST_CHECKED : BST_UNCHECKED);
+    CheckDlgButton(dialog, IDC_ENABLE_FFMPEG, ffmpeg_get() ? BST_CHECKED : BST_UNCHECKED);
+}
+
+INT_PTR CALLBACK TweaksDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    switch (uMsg)
+    {
+    case WM_INITDIALOG:
+        break;
+
+    case WM_NOTIFY:
+        if (((LPNMHDR)lParam)->code == PSN_SETACTIVE)
+            load_staging_settings(hDlg);
+        break;
+
+    case WM_SHOWWINDOW:
+        set_window_title(hDlg);
+        break;
+
+    case WM_DESTROY:
+        break;
+
+    case WM_COMMAND:
+        if (HIWORD(wParam) != BN_CLICKED) break;
+        switch (LOWORD(wParam))
+        {
+        case IDC_ENABLE_ALSA:
+            alsa_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_ALSA) == BST_CHECKED);
+            SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+            return TRUE;
+        case IDC_ENABLE_WAYLAND:
+            wayland_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_WAYLAND) == BST_CHECKED);
+            SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+            return TRUE;
+        case IDC_ENABLE_FSHACK:
+            fshack_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_FSHACK) == BST_CHECKED);
+            SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+            return TRUE;
+        case IDC_ENABLE_FFMPEG:
+            ffmpeg_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_FFMPEG) == BST_CHECKED);
+            SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+            return TRUE;
+        }
+        break;
+    }
+    return FALSE;
+}
diff --git a/programs/winecfg/winecfg.h b/programs/winecfg/winecfg.h
index b83234470c1..d5ed6cf9f5c 100644
--- a/programs/winecfg/winecfg.h
+++ b/programs/winecfg/winecfg.h
@@ -89,6 +89,7 @@ INT_PTR CALLBACK LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM l
 INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK ThemeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK StagingDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK TweaksDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK InputDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc
index 4370d9b360c..aea7a3a5d07 100644
--- a/programs/winecfg/winecfg.rc
+++ b/programs/winecfg/winecfg.rc
@@ -39,6 +39,7 @@ BEGIN
     IDS_TAB_DESKTOP_INTEGRATION "Desktop Integration"
     IDS_TAB_AUDIO           "Audio"
     IDS_TAB_STAGING         "Staging"
+    IDS_TAB_TWEAKS          "Tweaks"
     IDS_TAB_ABOUT           "About"
     IDS_TAB_INPUT           "Input"
     IDS_WINECFG_TITLE       "Wine configuration"
@@ -337,6 +338,18 @@ BEGIN
     CONTROL     "Enable &GTK3 Theming",IDC_ENABLE_GTK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,100,230,8
 END
 
+IDD_TWEAKS DIALOG  0, 0, 260, 220
+STYLE WS_CHILD | WS_DISABLED
+FONT 8, "MS Shell Dlg"
+BEGIN
+    GROUPBOX    "Tweaks",IDC_STATIC,8,4,244,210
+    LTEXT       "The following settings are experimental and may break stuff!\nMake sure to reset them again in case of a problem.",IDC_STATIC,16,16,230,16
+    CONTROL     "Enable &ALSA sound driver",IDC_ENABLE_ALSA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,40,230,8
+    CONTROL     "Enable &Wayland graphics driver",IDC_ENABLE_WAYLAND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,55,230,8
+    CONTROL     "Enable X11 display mode virtualization",IDC_ENABLE_FSHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,70,230,8
+    CONTROL     "Enable video decoding via FFmpeg",IDC_ENABLE_FFMPEG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,85,230,8
+END
+
 IDD_INPUT_CONFIG DIALOG  0, 0, 260, 220
 STYLE WS_CHILD | WS_DISABLED
 FONT 8, "MS Shell Dlg"
-- 
2.49.0

07070100B69342000081A4000003E8000003E80000000168AA560300000810000001030000000200000000000000000000004800000000patches/0001-HACK-ws2_32-Block-first-internet-connection-for-some.patchFrom d0eee8a7ec74f370df43f342a8b2977f99e7cb40 Mon Sep 17 00:00:00 2001
From: NelloKudo <marshnelloosu@gmail.com>
Date: Thu, 14 Aug 2025 14:18:26 +0200
Subject: [PATCH] HACK: ws2_32: Block first internet connection for some games

Fixes launch issues/high CPU usage, can be disabled in-case of
various issues with WINE_DISABLE_DISCONNECT=1.
---
 dlls/ws2_32/socket.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d4223e93bd1..3030d8df6bb 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1262,6 +1262,25 @@ int WINAPI closesocket( SOCKET s )
     return 0;
 }
 
+static BOOL is_mhy(void)
+{
+    static volatile char cache = -1;
+    BOOL ret = cache;
+    if (ret == -1)
+    {
+        const WCHAR *p, *name = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
+        if ((p = wcsrchr(name, '/')))
+            name = p + 1;
+        if ((p = wcsrchr(name, '\\')))
+            name = p + 1;
+        ret = (!wcsicmp(name, L"GenshinImpact.exe") ||
+               !wcsicmp(name, L"StarRail.exe") ||
+               !wcsicmp(name, L"YuanShen.exe") ||
+               !wcsicmp(name, L"ZenlessZoneZero.exe"));
+        cache = ret;
+    }
+    return ret;
+}
 
 /***********************************************************************
  *      connect   (ws2_32.4)
@@ -1272,6 +1291,18 @@ int WINAPI connect( SOCKET s, const struct sockaddr *addr, int len )
     IO_STATUS_BLOCK io;
     HANDLE sync_event;
     NTSTATUS status;
+    static int count = 0;
+    const char* env = getenv("WINE_DISABLE_DISCONNECT");
+
+    // HACK: Block first connection for mhy games
+    // can be disabled with WINE_DISABLE_DISCONNECT=1
+    if (!count && !(env && atoi(env) == 1) && is_mhy())
+    {
+        FIXME("Toggle detected, disabling first connection..\n");
+        count = 1;
+        WSASetLastError(WSAECONNREFUSED);
+        return SOCKET_ERROR;
+    }
 
     TRACE( "socket %#Ix, addr %s, len %d\n", s, debugstr_sockaddr(addr), len );
 
-- 
2.50.1

07070100B69343000081A4000003E8000003E80000000168AA560300000618000001030000000200000000000000000000003800000000patches/0002-wine.inf-Set-a-valid-Win10-ProductId.patchFrom b664a786b1b7a5b00e9dbc30c40d537a57fde145 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Fri, 7 Feb 2025 22:25:55 +0300
Subject: [PATCH 2/5] wine.inf: Set a valid Win10 ProductId

Signed-off-by: Vasiliy Stelmachenok <ventureo@cachyos.org>
---
 loader/wine.inf.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 04612cd2522..27df37619d0 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -369,7 +369,7 @@ HKCU,%CurrentVersion%\Run,,16
 HKCU,%CurrentVersionNT%\Winlogon,,16
 HKLM,%CurrentVersion%,"CommonFilesDir",,"%16427%"
 HKLM,%CurrentVersion%,"FirstInstallDateTime",1,21,81,7c,23
-HKLM,%CurrentVersion%,"ProductId",,"12345-oem-0000001-54321"
+HKLM,%CurrentVersion%,"ProductId",,"00330-50000-00000-AAOEM"
 HKLM,%CurrentVersion%,"ProgramFilesDir",,"%16422%"
 HKLM,%CurrentVersion%,"ProgramFilesPath",0x20000,"%%ProgramFiles%%"
 HKLM,%CurrentVersion%,"RegisteredOrganization",2,""
@@ -395,7 +395,7 @@ HKLM,%CurrentVersion%\Shell Extensions\Approved,,16
 HKLM,%CurrentVersion%\Time Zones,"SymbolicLinkValue",0x60000,"\Registry\Machine\%CurrentVersionNT%\Time Zones"
 HKLM,%CurrentVersion%\Uninstall,,16
 HKLM,%CurrentVersionNT%,"InstallDate",0x10003,1273299354
-HKLM,%CurrentVersionNT%,"ProductId",,"12345-oem-0000001-54321"
+HKLM,%CurrentVersionNT%,"ProductId",,"00330-50000-00000-AAOEM"
 HKLM,%CurrentVersionNT%,"RegisteredOrganization",2,""
 HKLM,%CurrentVersionNT%,"RegisteredOwner",2,""
 HKLM,%CurrentVersionNT%,"SystemRoot",,"%10%"
-- 
2.48.1

07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!
openSUSE Build Service is sponsored by