<pre style='margin:0'>
Perry E. Metzger (pmetzger) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/facffaf1632ee83f99eaac61abe3793b9eb7adef">https://github.com/macports/macports-ports/commit/facffaf1632ee83f99eaac61abe3793b9eb7adef</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new facffaf1632 wine-devel,wine-staging: update to 9.15
</span>facffaf1632 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit facffaf1632ee83f99eaac61abe3793b9eb7adef
</span>Author: Dean M Greer <38226388+Gcenx@users.noreply.github.com>
AuthorDate: Mon Aug 12 15:18:05 2024 -0400

<span style='display:block; white-space:pre;color:#404040;'>    wine-devel,wine-staging: update to 9.15
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Co-Authored-By: marzent <44967463+marzent@users.noreply.github.com>
</span>---
 emulators/wine-devel/Portfile                      |   22 +-
 .../{1001-msync.diff => 1001-devel-msync.diff}     | 1260 +++++++++-----------
 .../{1001-msync.diff => 1001-staging-msync.diff}   |  190 +--
 3 files changed, 711 insertions(+), 761 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/emulators/wine-devel/Portfile b/emulators/wine-devel/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index d101bff2f75..9e5df0c1352 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/emulators/wine-devel/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/emulators/wine-devel/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -7,7 +7,7 @@ PortGroup                   muniversal 1.1
</span> 
 # Keep the wine-stable, wine-devel and wine-crossover portfiles as similar as possible.
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-github.setup                wine-mirror wine 9.14 wine-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+github.setup                wine-mirror wine 9.15 wine-
</span> github.tarball_from         archive
 name                        wine-devel
 conflicts                   wine-stable wine-staging wine-crossover
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -37,9 +37,9 @@ long_description \
</span> 
 checksums \
     ${distname}${extract.suffix} \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    rmd160  84db00576e723c3e0b929e4f07e29d2784205729 \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    sha256  2a66b02b1ba8b59aa31dd3c7e0f5a369f36bf4c1494b1dd292976a0ae263b90c \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    size    49637864
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    rmd160  34f72b65f5f98d07ec09b2f2e8b2a461c2abc51c \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    sha256  735c34c446fe00439d22f42eca9dec91acc0aed3b5164260fc726e03ad8bc60e \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    size    49668690
</span> 
 depends_build \
     port:bison \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -129,6 +129,10 @@ compiler.blacklist-append   {*gcc*} {clang < 800} {macports-clang-3.*}
</span> # https://gitlab.winehq.org/wine/wine/-/merge_requests/5935#note_74758
 macosx_deployment_target    10.15
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+if {${subport} eq "wine-devel"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    patchfiles-append       1001-devel-msync.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> subport wine-staging {
     conflicts               wine-stable wine-devel wine-crossover
     set staging_version     ${version}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -140,18 +144,18 @@ subport wine-staging {
</span> 
     checksums-append \
         ${wine_staging_distfile} \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        rmd160  a4333fa62df0f57921410ef0e5281b54f7396e5c \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        sha256  0a7c9ca9f8d137657417495d5445793f89e5681965a6381d7cfafd998d019557 \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        size    9452219
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        rmd160  220db5f902d65b29a704d3f5f53b090b5cb7ad83 \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        sha256  1534258ee6cd8cb853c650193644ea4a08357b5c9ca1345fe3efb798a3acf70e \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        size    9516589
</span> 
     depends_patch-append    port:autoconf
 
     # Applying staging after other patchfiles to avoid problems
     post-patch {
         system -W ${worksrcpath} \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            "${workpath}/wine-staging-${staging_version}/staging/patchinstall.py --all -W winemac.drv-no-flicker-patch -W ntdll-Syscall_Emulation"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            "${workpath}/wine-staging-${staging_version}/staging/patchinstall.py --all -W ntdll-Syscall_Emulation -W winemac.drv-no-flicker-patch"
</span>         system -W ${worksrcpath} \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            "patch -p1 < ${filespath}/1001-msync.diff"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            "patch -p1 < ${filespath}/1001-staging-msync.diff"
</span>     }
 }
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/emulators/wine-devel/files/1001-msync.diff b/emulators/wine-devel/files/1001-devel-msync.diff
</span>similarity index 83%
copy from emulators/wine-devel/files/1001-msync.diff
copy to emulators/wine-devel/files/1001-devel-msync.diff
<span style='display:block; white-space:pre;color:#808080;'>index d9457b5f342..628c5220230 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/emulators/wine-devel/files/1001-msync.diff
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/emulators/wine-devel/files/1001-devel-msync.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,100 +1,41 @@
</span> diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 78b3fdf94aa..061c730bf63 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 37bd6c86e31..89ee0286daa 100644
</span> --- a/dlls/ntdll/Makefile.in
 +++ b/dlls/ntdll/Makefile.in
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -50,6 +50,7 @@ SOURCES = \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -49,6 +49,7 @@ SOURCES = \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   unix/debug.c \
</span>   unix/env.c \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        unix/esync.c \
</span>   unix/file.c \
 +      unix/msync.c \
        unix/loader.c \
        unix/loadorder.c \
        unix/process.c \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index 85d3db0cb8c..b63a386ee96 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- a/dlls/ntdll/unix/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ b/dlls/ntdll/unix/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -51,6 +51,7 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "unix_private.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#include "msync.h"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- WINE_DEFAULT_DEBUG_CHANNEL(esync);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -60,13 +61,16 @@ int do_esync(void)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     static int do_esync_cached = -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync_cached == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")) && !do_msync();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return do_esync_cached;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     static int once;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (!once++)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        FIXME("eventfd not supported on this platform.\n");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (getenv("WINEESYNC") && atoi(getenv("WINEESYNC")) && !do_msync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            FIXME("eventfd not supported on this platform.\n");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -571,6 +575,9 @@ NTSTATUS esync_reset_event( HANDLE handle )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if ((ret = get_object( handle, &obj ))) return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     event = obj->shm;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (obj->type != ESYNC_MANUAL_EVENT && obj->type != ESYNC_AUTO_EVENT)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return STATUS_OBJECT_TYPE_MISMATCH;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (obj->type == ESYNC_MANUAL_EVENT)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         /* Acquire the spinlock. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -861,7 +868,7 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (count && objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         msgwait = TRUE;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (has_esync && has_server)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -890,7 +897,7 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--    if (wait_any || count == 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (wait_any || count <= 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         /* Try to check objects now, so we can obviate poll() at least. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         for (i = 0; i < count; i++)
</span> diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ae7e2e8e6ec..a7175b35ae6 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 92f2e2eb3a3..bc9af9d34a8 100644
</span> --- a/dlls/ntdll/unix/loader.c
 +++ b/dlls/ntdll/unix/loader.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -89,6 +89,7 @@ extern char **environ;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -90,6 +90,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "winioctl.h"
</span>  #include "winternl.h"
  #include "unix_private.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  #include "wine/list.h"
  #include "ntsyscalls.h"
  #include "wine/debug.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1896,6 +1897,7 @@ static void start_main_thread(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1858,6 +1859,7 @@ static void start_main_thread(void)
</span>      signal_alloc_thread( teb );
      dbg_init();
      startup_info_size = server_init_process();
 +    msync_init();
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     esync_init();
</span>      virtual_map_user_shared_data();
      init_cpu_info();
<span style='display:block; white-space:pre;background:#e0ffe0;'>+     init_files();
</span> diff --git a/dlls/ntdll/unix/msync.c b/dlls/ntdll/unix/msync.c
 new file mode 100644
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 00000000000..90e785f6df2
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 00000000000..2eef30dd0f2
</span> --- /dev/null
 +++ b/dlls/ntdll/unix/msync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,1661 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -0,0 +1,1689 @@
</span> +/*
 + * mach semaphore-based synchronization objects
 + *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -412,7 +353,7 @@ index 00000000000..90e785f6df2
</span> +
 +static const mach_msg_bits_t msgh_bits_send = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static inline void server_register_wait( semaphore_t sem, unsigned int msgh_id,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static inline mach_msg_return_t server_register_wait( semaphore_t sem, unsigned int msgh_id,
</span> +                                         struct msync **wait_objs, const int count )
 +{
 +    int i, is_mutex;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -444,10 +385,11 @@ index 00000000000..90e785f6df2
</span> +
 +    if (mr != MACH_MSG_SUCCESS)
 +        ERR("Failed to send server register wait: %#x\n", mr);
<span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return mr;
</span> +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static inline void server_remove_wait( semaphore_t sem, unsigned int msgh_id,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                       struct msync **wait_objs, const int count )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static inline void server_remove_wait( unsigned int msgh_id, struct msync **wait_objs, const int count )
</span> +{
 +    int i;
 +    mach_msg_return_t mr;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -504,19 +446,19 @@ index 00000000000..90e785f6df2
</span> +}
 +
 +static inline NTSTATUS msync_wait_single( struct msync *wait_obj,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                          ULONGLONG *end )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                          ULONGLONG *end, int tid )
</span> +{
 +    int ret, val = 0;
 +    void *addr = wait_obj->shm;
 +    ULONGLONG ns_timeleft = 0;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    do 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    do
</span> +    {
 +        if (wait_obj->type == MSYNC_MUTEX)
 +        {
 +            val = __atomic_load_n( (int *)addr, __ATOMIC_ACQUIRE );
 +            if (!val || val == ~0)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                val = GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                val = tid;
</span> +        }
 +
 +        if (__atomic_load_n( (int *)addr, __ATOMIC_ACQUIRE ) != val)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -577,27 +519,51 @@ index 00000000000..90e785f6df2
</span> +}
 +
 +static NTSTATUS msync_wait_multiple( struct msync **wait_objs,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                     int count, ULONGLONG *end )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                     int count, ULONGLONG *end, int tid )
</span> +{
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    int tid;
</span> +    semaphore_t *sem;
 +    kern_return_t kr;
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    mach_msg_return_t mr;
</span> +    unsigned int msgh_id;
 +    __thread static struct msync *objs[MAXIMUM_WAIT_OBJECTS + 1];
 +
 +    count = resize_wait_objs( wait_objs, objs, count );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (count == 1 && __ulock_wait2) return msync_wait_single( objs[0], end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (count == 1 && __ulock_wait2) return msync_wait_single( objs[0], end, tid );
</span> +    if (!count) return destroyed_wait( end );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tid = GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span> +    if (check_shm_contention( objs, count, tid ))
 +        return STATUS_PENDING;
 +
 +    sem = semaphore_pool_alloc();
 +    msgh_id = (tid << 8) | count;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    mr = server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (mr != MACH_MSG_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        /* The os failed to send the mach message, which is either because
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * we lost the wineserver process or the semaphore from semaphore_pool_alloc
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * is not valid...
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * To avoid pooling in a dead port, recreate it here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * Worst case, this will behave effectively like a spinlock. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        semaphore_destroy( mach_task_self(), *sem) ;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        kr = semaphore_create( mach_task_self(), sem, SYNC_POLICY_FIFO, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (kr != KERN_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            ERR("Cannot create semaphore: %#x %s\n", kr, mach_error_string(kr));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            semaphore_pool_free( sem );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            return STATUS_PENDING;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        mr = server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (mr != MACH_MSG_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            semaphore_pool_free( sem );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            return STATUS_PENDING;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span> +
 +    do
 +    {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -613,7 +579,7 @@ index 00000000000..90e785f6df2
</span> +    if (is_destroyed( objs, count ))
 +        return destroyed_wait( end );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    server_remove_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    server_remove_wait( msgh_id, objs, count );
</span> +
 +    switch (kr) {
 +        case KERN_SUCCESS:
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1220,7 +1186,7 @@ index 00000000000..90e785f6df2
</span> +    return STATUS_SUCCESS;
 +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static NTSTATUS do_single_wait( struct msync *obj, ULONGLONG *end, BOOLEAN alertable )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static NTSTATUS do_single_wait( struct msync *obj, ULONGLONG *end, BOOLEAN alertable, int tid )
</span> +{
 +    NTSTATUS status;
 +    struct msync *wait_objs[2];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1241,14 +1207,14 @@ index 00000000000..90e785f6df2
</span> +
 +        wait_objs[1] = &apc_obj;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = msync_wait_multiple( wait_objs, 2, end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        status = msync_wait_multiple( wait_objs, 2, end, tid );
</span> +
 +        if (__atomic_load_n( apc_addr, __ATOMIC_SEQ_CST ))
 +            return STATUS_USER_APC;
 +    }
 +    else
 +    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = msync_wait_multiple( wait_objs, 1, end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        status = msync_wait_multiple( wait_objs, 1, end, tid );
</span> +    }
 +    return status;
 +}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1258,6 +1224,7 @@ index 00000000000..90e785f6df2
</span> +{
 +    static const LARGE_INTEGER zero = {0};
 +
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    __thread static int current_tid = 0;
</span> +    __thread static struct msync *objs[MAXIMUM_WAIT_OBJECTS + 1];
 +    struct msync apc_obj;
 +    int has_msync = 0, has_server = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1268,6 +1235,8 @@ index 00000000000..90e785f6df2
</span> +    ULONGLONG end;
 +    int i, ret;
 +
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    current_tid = current_tid ? current_tid : GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    /* Grab the APC idx if we don't already have it. */
 +    if (alertable && !ntdll_get_thread_data()->msync_apc_addr)
 +    {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1386,7 +1355,7 @@ index 00000000000..90e785f6df2
</span> +                        struct mutex *mutex = obj->shm;
 +                        int tid;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        if (mutex->tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        if (mutex->tid == current_tid)
</span> +                        {
 +                            TRACE("Woken up by handle %p [%d].\n", handles[i], i);
 +                            mutex->count++;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1394,13 +1363,13 @@ index 00000000000..90e785f6df2
</span> +                        }
 +
 +                        tid = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        if (__atomic_compare_exchange_n(&mutex->tid, &tid, GetCurrentThreadId(), 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        if (__atomic_compare_exchange_n(&mutex->tid, &tid, current_tid, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span> +                        {
 +                            TRACE("Woken up by handle %p [%d].\n", handles[i], i);
 +                            mutex->count = 1;
 +                            return i;
 +                        }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        else if (tid == ~0 && __atomic_compare_exchange_n(&mutex->tid, &tid, GetCurrentThreadId(), 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        else if (tid == ~0 && __atomic_compare_exchange_n(&mutex->tid, &tid, current_tid, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span> +                        {
 +                            TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i);
 +                            mutex->count = 1;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1463,7 +1432,7 @@ index 00000000000..90e785f6df2
</span> +                return STATUS_TIMEOUT;
 +            }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+            ret = msync_wait_multiple( objs, waitcount, timeout ? &end : NULL );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            ret = msync_wait_multiple( objs, waitcount, timeout ? &end : NULL, current_tid );
</span> +
 +            if (ret == STATUS_TIMEOUT)
 +            {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1514,12 +1483,12 @@ index 00000000000..90e785f6df2
</span> +                {
 +                    struct mutex *mutex = obj->shm;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (mutex->tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (mutex->tid == current_tid)
</span> +                        continue;
 +
 +                    while (__atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST ))
 +                    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        status = do_single_wait( obj, timeout ? &end : NULL, alertable );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        status = do_single_wait( obj, timeout ? &end : NULL, alertable, current_tid );
</span> +                        if (status != STATUS_PENDING)
 +                            break;
 +                    }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1531,7 +1500,7 @@ index 00000000000..90e785f6df2
</span> +
 +                    while (!__atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST ))
 +                    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        status = do_single_wait( obj, timeout ? &end : NULL, alertable );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        status = do_single_wait( obj, timeout ? &end : NULL, alertable, current_tid );
</span> +                        if (status != STATUS_PENDING)
 +                            break;
 +                    }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1557,7 +1526,7 @@ index 00000000000..90e785f6df2
</span> +                    struct mutex *mutex = obj->shm;
 +                    int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (tid && tid != ~0 && tid != GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (tid && tid != ~0 && tid != current_tid)
</span> +                        goto tryagain;
 +                }
 +                else if (obj)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1580,11 +1549,11 @@ index 00000000000..90e785f6df2
</span> +                {
 +                    struct mutex *mutex = obj->shm;
 +                    int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (tid == current_tid)
</span> +                        break;
 +                    if (tid && tid != ~0)
 +                        goto tooslow;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (__sync_val_compare_and_swap( &mutex->tid, tid, GetCurrentThreadId() ) != tid)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (__sync_val_compare_and_swap( &mutex->tid, tid, current_tid ) != tid)
</span> +                        goto tooslow;
 +                    if (tid == ~0)
 +                        abandoned = TRUE;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1813,189 +1782,184 @@ index 00000000000..3e6eb2c8b1e
</span> +extern NTSTATUS msync_signal_and_wait( HANDLE signal, HANDLE wait,
 +    BOOLEAN alertable, const LARGE_INTEGER *timeout );
 diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 77aa995326c..f45db2f3090 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f3ffd99c3fc..aac6c8aedb7 100644
</span> --- a/dlls/ntdll/unix/server.c
 +++ b/dlls/ntdll/unix/server.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -84,6 +84,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -79,6 +79,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "wine/server.h"
</span>  #include "wine/debug.h"
  #include "unix_private.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  #include "ddk/wdm.h"
  
  WINE_DEFAULT_DEBUG_CHANNEL(server);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1882,6 +1883,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1830,6 +1831,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
</span>       * retrieve it again */
      fd = remove_fd_from_cache( handle );
  
 +    if (do_msync())
 +        msync_close( handle );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_close( handle );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( close_handle )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span> diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a52327841d2..4d4644f9c8c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 21e66f01875..7ebc8cdd77c 100644
</span> --- a/dlls/ntdll/unix/sync.c
 +++ b/dlls/ntdll/unix/sync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -67,6 +67,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -66,6 +66,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "wine/server.h"
</span>  #include "wine/debug.h"
  #include "unix_private.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  WINE_DEFAULT_DEBUG_CHANNEL(sync);
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -120,7 +121,7 @@ static inline int futex_wait( const LONG *addr, int val, struct timespec *timeou
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             long tv_nsec;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         } timeout32 = { timeout->tv_sec, timeout->tv_nsec };
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE, val, &timeout32, 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE| futex_private, val, &timeout32, 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE, val, timeout, 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -320,6 +321,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -319,6 +320,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
</span>      if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
      if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
  
 +    if (do_msync())
 +        return msync_create_semaphore( handle, access, attr, initial, max );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_create_semaphore( handle, access, attr, initial, max );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -348,6 +352,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( create_semaphore )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->access  = access;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -343,6 +347,10 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     unsigned int ret;
</span>  
      *handle = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        return msync_open_semaphore( handle, access, attr );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_open_semaphore( handle, access, attr );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if ((ret = validate_open_object_attributes( attr ))) return ret;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -387,6 +394,9 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( open_semaphore )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -379,6 +387,9 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
</span>  
      if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
  
 +    if (do_msync())
 +        return msync_query_semaphore( handle, info, ret_len );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_query_semaphore( handle, info, ret_len );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -412,6 +422,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( query_semaphore )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -401,6 +412,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
</span>  {
      unsigned int ret;
  
 +    if (do_msync())
 +        return msync_release_semaphore( handle, count, previous );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_release_semaphore( handle, count, previous );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( release_semaphore )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -427,6 +441,10 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -442,6 +455,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_
</span>      *handle = 0;
      if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        return msync_create_event( handle, access, attr, type, state );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_create_event( handle, access, attr, type, state );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -473,6 +489,9 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( create_event )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -455,6 +473,9 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT
</span>      *handle = 0;
      if ((ret = validate_open_object_attributes( attr ))) return ret;
  
 +    if (do_msync())
 +        return msync_open_event( handle, access, attr );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_open_event( handle, access, attr );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -499,6 +518,9 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* This comment is a dummy to make sure this patch applies in the right place. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( open_event )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->access     = access;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -477,6 +498,9 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span>      unsigned int ret;
  
 +    if (do_msync())
 +        return msync_set_event( handle, prev_state );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_set_event( handle );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -522,6 +544,9 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* This comment is a dummy to make sure this patch applies in the right place. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( event_op )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -496,6 +520,10 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span>      unsigned int ret;
  
 +    if (do_msync())
 +        return msync_reset_event( handle, prev_state );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_reset_event( handle );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -555,6 +580,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( event_op )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -525,6 +553,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
</span>  {
      unsigned int ret;
  
 +    if (do_msync())
 +        return msync_pulse_event( handle, prev_state );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_pulse_event( handle );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -589,6 +617,9 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( event_op )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -556,6 +587,9 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class,
</span>  
      if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
  
 +    if (do_msync())
 +        return msync_query_event( handle, info, ret_len );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_query_event( handle, info, ret_len );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -619,6 +650,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( query_event )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -582,6 +616,10 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct object_attributes *objattr;
</span>  
      *handle = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        return msync_create_mutex( handle, access, attr, owned );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_create_mutex( handle, access, attr, owned );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -649,6 +683,9 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( create_mutex )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -609,6 +647,9 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A
</span>      *handle = 0;
      if ((ret = validate_open_object_attributes( attr ))) return ret;
  
 +    if (do_msync())
 +        return msync_open_mutex( handle, access, attr );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_open_mutex( handle, access, attr );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -674,6 +711,9 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( open_mutex )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->access  = access;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -631,6 +672,9 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
</span>  {
      unsigned int ret;
  
 +    if (do_msync())
 +        return msync_release_mutex( handle, prev_count );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_release_mutex( handle, prev_count );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -707,6 +747,9 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( release_mutex )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -661,6 +705,9 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class,
</span>  
      if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
  
 +    if (do_msync())
 +        return msync_query_mutex( handle, info, ret_len );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_query_mutex( handle, info, ret_len );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1630,6 +1673,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SERVER_START_REQ( query_mutex )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         req->handle = wine_server_obj_handle( handle );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1581,6 +1628,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
</span>  
      if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2006,20 +1970,20 @@ index a52327841d2..4d4644f9c8c 100644
</span> +            return ret;
 +    }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         NTSTATUS ret = esync_wait_objects( count, handles, wait_any, alertable, timeout );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1662,6 +1712,9 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (alertable) flags |= SELECT_ALERTABLE;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1606,6 +1660,9 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
</span>      select_op_t select_op;
      UINT flags = SELECT_INTERRUPTIBLE;
  
 +    if (do_msync())
 +        return msync_signal_and_wait( signal, wait, alertable, timeout );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return esync_signal_and_wait( signal, wait, alertable, timeout );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (!signal) return STATUS_INVALID_HANDLE;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1705,7 +1758,24 @@ NTSTATUS WINAPI NtYieldExecution(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (alertable) flags |= SELECT_ALERTABLE;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1646,7 +1703,17 @@ NTSTATUS WINAPI NtYieldExecution(void)
</span>  NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
  {
      /* if alertable, we need to query the server */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2033,50 +1997,43 @@ index a52327841d2..4d4644f9c8c 100644
</span> +                return ret;
 +        }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+        if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            NTSTATUS ret = esync_wait_objects( 0, NULL, TRUE, TRUE, timeout );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+            if (ret != STATUS_NOT_IMPLEMENTED)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span> +        return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
 +    }
  
      if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE)  /* sleep forever */
      {
 diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 791b7b88c62..dc194eb09ac 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index ee5630e76f1..84f0bef8bda 100644
</span> --- a/dlls/ntdll/unix/unix_private.h
 +++ b/dlls/ntdll/unix/unix_private.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -104,6 +104,8 @@ struct ntdll_thread_data
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -103,6 +103,8 @@ struct ntdll_thread_data
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span>      void              *cpu_data[16];  /* reserved for CPU-specific data */
      void              *kernel_stack;  /* stack for thread startup and kernel syscalls */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                esync_apc_fd;  /* fd to wait on for user APCs */
</span> +    int               *msync_apc_addr;
 +    unsigned int       msync_apc_idx;
      int                request_fd;    /* fd for sending server requests */
      int                reply_fd;      /* fd for receiving server replies */
      int                wait_fd[2];    /* fd for sleeping server requests */
 diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index efccfac76d0..8247b82852d 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 0fedfe0fb1d..ff770ecbdb4 100644
</span> --- a/dlls/ntdll/unix/virtual.c
 +++ b/dlls/ntdll/unix/virtual.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3737,6 +3737,8 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3653,6 +3653,8 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
</span>      teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
      thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     thread_data->esync_apc_fd = -1;
</span> +    thread_data->msync_apc_addr = NULL;
 +    thread_data->msync_apc_idx = 0;
      thread_data->request_fd = -1;
      thread_data->reply_fd   = -1;
      thread_data->wait_fd[0] = -1;
 diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index d3399268d00..c38120548ab 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 74bf0f0c839..fd84ee0d1a9 100644
</span> --- a/include/wine/server_protocol.h
 +++ b/include/wine/server_protocol.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -5828,6 +5828,92 @@ struct get_esync_apc_fd_reply
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct reply_header __header;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -5722,6 +5722,92 @@ struct set_keyboard_repeat_reply
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     char __pad_12[4];
</span>  };
  
 +enum msync_type
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2168,10 +2125,10 @@ index d3399268d00..c38120548ab 100644
</span>  
  enum request
  {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6123,6 +6209,11 @@ enum request
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     REQ_esync_msgwait,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6011,6 +6097,11 @@ enum request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     REQ_resume_process,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     REQ_get_next_thread,
</span>      REQ_set_keyboard_repeat,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     REQ_get_esync_apc_fd,
</span> +    REQ_create_msync,
 +    REQ_open_msync,
 +    REQ_get_msync_idx,
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2180,10 +2137,10 @@ index d3399268d00..c38120548ab 100644
</span>      REQ_NB_REQUESTS
  };
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6422,6 +6513,11 @@ union generic_request
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct esync_msgwait_request esync_msgwait_request;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6304,6 +6395,11 @@ union generic_request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct resume_process_request resume_process_request;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct get_next_thread_request get_next_thread_request;
</span>      struct set_keyboard_repeat_request set_keyboard_repeat_request;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct get_esync_apc_fd_request get_esync_apc_fd_request;
</span> +    struct create_msync_request create_msync_request;
 +    struct open_msync_request open_msync_request;
 +    struct get_msync_idx_request get_msync_idx_request;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2192,10 +2149,10 @@ index d3399268d00..c38120548ab 100644
</span>  };
  union generic_reply
  {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6719,11 +6815,16 @@ union generic_reply
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct esync_msgwait_reply esync_msgwait_reply;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6595,11 +6691,16 @@ union generic_reply
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct resume_process_reply resume_process_reply;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct get_next_thread_reply get_next_thread_reply;
</span>      struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct get_esync_apc_fd_reply get_esync_apc_fd_reply;
</span> +    struct create_msync_reply create_msync_reply;
 +    struct open_msync_reply open_msync_reply;
 +    struct get_msync_idx_reply get_msync_idx_reply;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2206,15 +2163,15 @@ index d3399268d00..c38120548ab 100644
</span>  /* ### protocol_version begin ### */
  
 -#define SERVER_PROTOCOL_VERSION 837
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+#define SERVER_PROTOCOL_VERSION 838
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define SERVER_PROTOCOL_VERSION 841
</span>  
  /* ### protocol_version end ### */
  
 diff --git a/server/Makefile.in b/server/Makefile.in
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 87103cb2002..85b7b8f6693 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 7e571ac2ba6..dabe3fe83a8 100644
</span> --- a/server/Makefile.in
 +++ b/server/Makefile.in
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -15,6 +15,7 @@ SOURCES = \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -14,6 +14,7 @@ SOURCES = \
</span>   event.c \
        fd.c \
        file.c \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2223,180 +2180,176 @@ index 87103cb2002..85b7b8f6693 100644
</span>   hook.c \
        mach.c \
 diff --git a/server/async.c b/server/async.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index b0f9fe42ad1..b7270394579 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 3c9b9588c6e..b53e2e5d15e 100644
</span> --- a/server/async.c
 +++ b/server/async.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -78,6 +78,7 @@ static const struct object_ops async_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -77,6 +77,7 @@ static const struct object_ops async_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      async_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      async_satisfied,           /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -688,6 +689,7 @@ static const struct object_ops iosb_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -686,6 +687,7 @@ static const struct object_ops iosb_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
 diff --git a/server/atom.c b/server/atom.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index d9824de8eac..d99f10d6f19 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index ff0799f5880..7d53bd5e3bb 100644
</span> --- a/server/atom.c
 +++ b/server/atom.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -80,6 +80,7 @@ static const struct object_ops atom_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -79,6 +79,7 @@ static const struct object_ops atom_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
 diff --git a/server/change.c b/server/change.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 17a29c02867..84d4b25252b 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f773ccf8831..798a7e9c841 100644
</span> --- a/server/change.c
 +++ b/server/change.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -113,6 +113,7 @@ static const struct object_ops dir_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -112,6 +112,7 @@ static const struct object_ops dir_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                /* add_queue */
</span>      remove_queue,             /* remove_queue */
      default_fd_signaled,      /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     default_fd_get_esync_fd,  /* get_esync_fd */
</span> +    default_fd_get_msync_idx, /* get_msync_idx */
      no_satisfied,             /* satisfied */
      no_signal,                /* signal */
      dir_get_fd,               /* get_fd */
 diff --git a/server/clipboard.c b/server/clipboard.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 8b265f2dcea..e7149f20488 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 8118a467dd8..927edb99a03 100644
</span> --- a/server/clipboard.c
 +++ b/server/clipboard.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -77,6 +77,7 @@ static const struct object_ops clipboard_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -76,6 +76,7 @@ static const struct object_ops clipboard_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
 diff --git a/server/completion.c b/server/completion.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 3d4be86a212..d761d372314 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 6933195e72d..6be3bc7da85 100644
</span> --- a/server/completion.c
 +++ b/server/completion.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -76,6 +76,7 @@ static const struct object_ops completion_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -75,6 +75,7 @@ static const struct object_ops completion_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      completion_signaled,       /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      no_satisfied,              /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
 diff --git a/server/console.c b/server/console.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index dbd4a97459c..2b023546907 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index b64283baf4a..3b552346871 100644
</span> --- a/server/console.c
 +++ b/server/console.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -42,6 +42,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -41,6 +41,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "wincon.h"
</span>  #include "winternl.h"
  #include "wine/condrv.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  struct screen_buffer;
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -83,6 +84,7 @@ static const struct object_ops console_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -81,6 +82,7 @@ static const struct object_ops console_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     console_add_queue,                /* add_queue */
</span>      remove_queue,                     /* remove_queue */
      console_signaled,                 /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      console_get_fd,                   /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -142,12 +144,14 @@ struct console_server
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                   term_fd;     /* UNIX terminal fd */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct termios        termios;     /* original termios */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                   esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -139,11 +141,13 @@ struct console_server
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     unsigned int          once_input : 1; /* flag if input thread has already been requested */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     int                   term_fd;        /* UNIX terminal fd */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct termios        termios;        /* original termios */
</span> +    unsigned int          msync_idx;
  };
  
  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 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int console_server_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int console_server_get_msync_idx( struct object *obj, enum msync_type *type );
  static struct fd *console_server_get_fd( struct object *obj );
  static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name,
                                                  unsigned int attr, struct object *root );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -163,6 +167,7 @@ static const struct object_ops console_server_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -158,6 +162,7 @@ static const struct object_ops console_server_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                        /* add_queue */
</span>      remove_queue,                     /* remove_queue */
      console_server_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     console_server_get_esync_fd,      /* get_esync_fd */
</span> +    console_server_get_msync_idx,     /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      console_server_get_fd,            /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -233,6 +238,7 @@ static const struct object_ops screen_buffer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -227,6 +232,7 @@ static const struct object_ops screen_buffer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     screen_buffer_add_queue,          /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      NULL,                             /* satisfied */
      no_signal,                        /* signal */
      screen_buffer_get_fd,             /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -283,6 +289,7 @@ static const struct object_ops console_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -276,6 +282,7 @@ static const struct object_ops console_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                     /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      no_get_fd,                        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -321,6 +328,7 @@ static const struct object_ops console_input_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -313,6 +320,7 @@ static const struct object_ops console_input_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     console_input_add_queue,          /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      console_input_get_fd,             /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -379,6 +387,7 @@ static const struct object_ops console_output_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -370,6 +378,7 @@ static const struct object_ops console_output_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     console_output_add_queue,         /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      console_output_get_fd,            /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -438,6 +447,7 @@ static const struct object_ops console_connection_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -428,6 +437,7 @@ static const struct object_ops console_connection_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                     /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      console_connection_get_fd,        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -600,8 +610,13 @@ static void disconnect_console_server( struct console_server *server )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -590,6 +600,10 @@ static void disconnect_console_server( struct console_server *server )
</span>          list_remove( &call->entry );
          console_host_ioctl_terminate( call, STATUS_CANCELLED );
      }
 +
 +    if (do_msync())
 +        msync_clear_shm( server->msync_idx );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( server->esync_fd );
</span> +
      while (!list_empty( &server->read_queue ))
      {
          struct console_host_ioctl *call = LIST_ENTRY( list_head( &server->read_queue ), struct console_host_ioctl, entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -885,6 +900,7 @@ static void console_server_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -872,6 +886,7 @@ static void console_server_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     assert( obj->ops == &console_server_ops );
</span>      disconnect_console_server( server );
      if (server->fd) release_object( server->fd );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync()) close( server->esync_fd );
</span> +    if (do_msync()) msync_destroy_semaphore( server->msync_idx );
  }
  
  static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -933,6 +949,13 @@ static int console_server_get_esync_fd( struct object *obj, enum esync_type *typ
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return server->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -913,6 +928,13 @@ static int console_server_signaled( struct object *obj, struct wait_queue_entry
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return !server->console || !list_empty( &server->queue );
</span>  }
  
 +static unsigned int console_server_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2409,17 +2362,17 @@ index dbd4a97459c..2b023546907 100644
</span>  static struct fd *console_server_get_fd( struct object* obj )
  {
      struct console_server *server = (struct console_server*)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -966,6 +989,9 @@ static struct object *create_console_server( void )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -945,6 +967,9 @@ static struct object *create_console_server( void )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span>      allow_fd_caching(server->fd);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     server->esync_fd = -1;
</span>  
 +    if (do_msync())
 +        server->msync_idx = msync_alloc_shm( 0, 0 );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         server->esync_fd = esync_create_fd( 0, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return &server->obj;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1581,6 +1607,10 @@ DECL_HANDLER(get_next_console_request)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1557,6 +1582,10 @@ DECL_HANDLER(get_next_console_request)
</span>          /* set result of previous ioctl */
          ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry );
          list_remove( &ioctl->entry );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2427,110 +2380,108 @@ index dbd4a97459c..2b023546907 100644
</span> +        if (do_msync() && list_empty( &server->queue ))
 +            msync_clear_shm( server->msync_idx );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync() && list_empty( &server->queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_clear( server->esync_fd );
</span>      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1668,6 +1698,10 @@ DECL_HANDLER(get_next_console_request)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (ioctl)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1643,5 +1672,9 @@ DECL_HANDLER(get_next_console_request)
</span>          set_error( STATUS_PENDING );
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span> +    if (do_msync() && list_empty( &server->queue ))
 +        msync_clear_shm( server->msync_idx );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && list_empty( &server->queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( server->esync_fd );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     release_object( server );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> diff --git a/server/debugger.c b/server/debugger.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ca04d4c71ce..946dc7b04b5 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index c59a0abea77..273a75840e5 100644
</span> --- a/server/debugger.c
 +++ b/server/debugger.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -87,6 +87,7 @@ static const struct object_ops debug_event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -86,6 +86,7 @@ static const struct object_ops debug_event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                     /* add_queue */
</span>      remove_queue,                  /* remove_queue */
      debug_event_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      no_satisfied,                  /* satisfied */
      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -116,6 +117,7 @@ static const struct object_ops debug_obj_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -114,6 +115,7 @@ static const struct object_ops debug_obj_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                     /* add_queue */
</span>      remove_queue,                  /* remove_queue */
      debug_obj_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      no_satisfied,                  /* satisfied */
      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
 diff --git a/server/device.c b/server/device.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index c45d0102a56..93e22bbd78a 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 436dac6bfe9..225f8b9890d 100644
</span> --- a/server/device.c
 +++ b/server/device.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -39,6 +39,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -38,6 +38,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "handle.h"
</span>  #include "request.h"
  #include "process.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  /* IRP object */
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -68,6 +69,7 @@ static const struct object_ops irp_call_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -66,6 +67,7 @@ static const struct object_ops irp_call_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                     /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      NULL,                             /* satisfied */
      no_signal,                        /* signal */
      no_get_fd,                        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -95,11 +97,13 @@ struct device_manager
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -92,10 +94,12 @@ struct device_manager
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct list            requests;       /* list of pending irps across all devices */
</span>      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 */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                    esync_fd;       /* esync file descriptor */
</span> +    unsigned int           msync_idx;
  };
  
  static void device_manager_dump( struct object *obj, int verbose );
  static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int device_manager_get_msync_idx( struct object *obj, enum msync_type *type );
  static void device_manager_destroy( struct object *obj );
  
  static const struct object_ops device_manager_ops =
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -111,6 +115,7 @@ static const struct object_ops device_manager_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -106,6 +110,7 @@ static const struct object_ops device_manager_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                        /* add_queue */
</span>      remove_queue,                     /* remove_queue */
      device_manager_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     device_manager_get_esync_fd,      /* get_esync_fd */
</span> +    device_manager_get_msync_idx,     /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      no_get_fd,                        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -169,6 +174,7 @@ static const struct object_ops device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -163,6 +168,7 @@ static const struct object_ops device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                     /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      no_get_fd,                        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -222,6 +228,7 @@ static const struct object_ops device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -215,6 +221,7 @@ static const struct object_ops device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                        /* add_queue */
</span>      remove_queue,                     /* remove_queue */
      default_fd_signaled,              /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      device_file_get_fd,               /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -754,6 +761,9 @@ static void delete_file( struct device_file *file )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -747,6 +754,9 @@ static void delete_file( struct device_file *file )
</span>      /* terminate all pending requests */
      LIST_FOR_EACH_ENTRY_SAFE( irp, next, &file->requests, struct irp_call, dev_entry )
      {
 +        if (do_msync() && file->device->manager && list_empty( &file->device->manager->requests ))
 +            msync_clear( &file->device->manager->obj );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync() && file->device->manager && list_empty( &file->device->manager->requests ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_clear( file->device->manager->esync_fd );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -799,6 +809,13 @@ static int device_manager_get_esync_fd( struct object *obj, enum esync_type *typ
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return manager->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         list_remove( &irp->mgr_entry );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -782,6 +792,13 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return !list_empty( &manager->requests );
</span>  }
  
 +static unsigned int device_manager_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2543,142 +2494,120 @@ index c45d0102a56..93e22bbd78a 100644
</span>  static void device_manager_destroy( struct object *obj )
  {
      struct device_manager *manager = (struct device_manager *)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -834,6 +851,9 @@ static void device_manager_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -816,6 +833,9 @@ static void device_manager_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         assert( !irp->file && !irp->async );
</span>          release_object( irp );
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        msync_destroy_semaphore( manager->msync_idx );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         close( manager->esync_fd );
</span>  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -849,6 +869,9 @@ static struct device_manager *create_device_manager(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static struct device_manager *create_device_manager(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -828,6 +848,9 @@ static struct device_manager *create_device_manager(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         list_init( &manager->devices );
</span>          list_init( &manager->requests );
          wine_rb_init( &manager->kernel_objects, compare_kernel_object );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +        if (do_msync())
 +            manager->msync_idx = msync_alloc_shm( 0, 0 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             manager->esync_fd = esync_create_fd( 0, 0 );
</span>      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1041,6 +1064,9 @@ DECL_HANDLER(get_next_device_request)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return manager;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1017,6 +1040,9 @@ DECL_HANDLER(get_next_device_request)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 /* we already own the object if it's only on manager queue */
</span>                  if (irp->file) grab_object( irp );
                  manager->current_call = irp;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +                if (do_msync() && list_empty( &manager->requests ))
 +                    msync_clear( &manager->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                 if (do_esync() && list_empty( &manager->requests ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                     esync_clear( manager->esync_fd );
</span>              }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+             else close_handle( current->process, reply->next );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         }
</span> diff --git a/server/directory.c b/server/directory.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 1c44ded4606..962daee2045 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index b3f055dfd01..753d8904b6b 100644
</span> --- a/server/directory.c
 +++ b/server/directory.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -70,6 +70,7 @@ static const struct object_ops object_type_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -69,6 +69,7 @@ static const struct object_ops object_type_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -121,6 +122,7 @@ static const struct object_ops directory_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -119,6 +120,7 @@ static const struct object_ops directory_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-diff --git a/server/esync.c b/server/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-index e193f61b3a7..06e17c01874 100644
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>---- a/server/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+++ b/server/esync.c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -49,7 +49,7 @@ int do_esync(void)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     static int do_esync_cached = -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync_cached == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")) && !do_msync();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return do_esync_cached;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -128,6 +128,7 @@ const struct object_ops esync_ops =
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* remove_queue */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* signaled */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     esync_get_esync_fd,        /* get_esync_fd */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    NULL,                      /* get_msync_idx */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* satisfied */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     no_signal,                 /* signal */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     no_get_fd,                 /* get_fd */
</span> diff --git a/server/event.c b/server/event.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index f4ca3e48c6f..2770d83e6d6 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f1b79b1b35e..0162b78a5be 100644
</span> --- a/server/event.c
 +++ b/server/event.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -36,6 +36,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -35,6 +35,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "thread.h"
</span>  #include "request.h"
  #include "security.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  static const WCHAR event_name[] = {'E','v','e','n','t'};
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -58,12 +59,14 @@ struct event
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -56,11 +57,13 @@ struct event
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct list    kernel_object;   /* list of kernel object pointers */
</span>      int            manual_reset;    /* is it a manual reset event? */
      int            signaled;        /* event has been signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int            esync_fd;        /* esync file descriptor */
</span> +    unsigned int   msync_idx;
  };
  
  static void event_dump( struct object *obj, int verbose );
  static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
  static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int event_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int event_get_msync_idx( struct object *obj, enum msync_type *type );
  static int event_signal( struct object *obj, unsigned int access);
  static struct list *event_get_kernel_obj_list( struct object *obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static void event_destroy( struct object *obj );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -77,6 +80,7 @@ static const struct object_ops event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -72,6 +75,7 @@ static const struct object_ops event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      event_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     event_get_esync_fd,        /* get_esync_fd */
</span> +    event_get_msync_idx,       /* get_msync_idx */
      event_satisfied,           /* satisfied */
      event_signal,              /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -125,6 +129,7 @@ static const struct object_ops keyed_event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -119,6 +123,7 @@ static const struct object_ops keyed_event_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                   /* add_queue */
</span>      remove_queue,                /* remove_queue */
      keyed_event_signaled,        /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                        /* get_esync_fd */
</span> +    NULL,                        /* get_msync_idx */
      no_satisfied,                /* satisfied */
      no_signal,                   /* signal */
      no_get_fd,                   /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -157,6 +162,9 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -150,6 +155,9 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             list_init( &event->kernel_object );
</span>              event->manual_reset = manual_reset;
              event->signaled     = initial_state;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +            if (do_msync())
 +                event->msync_idx = msync_alloc_shm( initial_state, 0 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                 event->esync_fd = esync_create_fd( initial_state, 0 );
</span>          }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -167,6 +175,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return event;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -157,6 +165,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span>  struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access )
  {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct object *obj;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    struct object *obj;
</span> +    if (do_msync() && (obj = get_handle_obj( process, handle, access, &msync_ops)))
 +        return (struct event *)obj; /* even though it's not an event */
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && (obj = get_handle_obj( process, handle, access, &esync_ops)))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return (struct event *)obj; /* even though it's not an event */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return (struct event *)get_handle_obj( process, handle, access, &event_ops );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -179,10 +191,19 @@ static void pulse_event( struct event *event )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -166,10 +178,19 @@ static void pulse_event( struct event *event )
</span>      /* wake up all waiters if manual reset, a single one otherwise */
      wake_up( &event->obj, !event->manual_reset );
      event->signaled = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2695,10 +2624,10 @@ index f4ca3e48c6f..2770d83e6d6 100644
</span> +        return;
 +    }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && event->obj.ops == &esync_ops)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_set_event( (struct esync *)event );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -196,6 +217,12 @@ void set_event( struct event *event )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     event->signaled = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* wake up all waiters if manual reset, a single one otherwise */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     wake_up( &event->obj, !event->manual_reset );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -177,7 +198,16 @@ void set_event( struct event *event )
</span>  
  void reset_event( struct event *event )
  {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2708,21 +2637,15 @@ index f4ca3e48c6f..2770d83e6d6 100644
</span> +        return;
 +    }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && event->obj.ops == &esync_ops)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_reset_event( (struct esync *)event );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -203,6 +230,9 @@ void reset_event( struct event *event )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span>      event->signaled = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        msync_clear( &event->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( event->esync_fd );
</span>  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -229,6 +259,13 @@ static int event_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return event->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void event_dump( struct object *obj, int verbose )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -195,6 +225,13 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return event->signaled;
</span>  }
  
 +static unsigned int event_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2735,89 +2658,93 @@ index f4ca3e48c6f..2770d83e6d6 100644
</span>  static void event_satisfied( struct object *obj, struct wait_queue_entry *entry )
  {
      struct event *event = (struct event *)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -261,6 +298,9 @@ static void event_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     struct event *event = (struct event *)obj;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -223,6 +260,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return &event->kernel_object;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#e0ffe0;'>++static void event_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    struct event *event = (struct event *)obj;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        msync_destroy_semaphore( event->msync_idx );
<span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span> +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         close( event->esync_fd );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                         unsigned int attr, const struct security_descriptor *sd )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span> diff --git a/server/fd.c b/server/fd.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index b90999aae3c..17132109b8e 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f28937466fc..17bde66453a 100644
</span> --- a/server/fd.c
 +++ b/server/fd.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -98,6 +98,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -96,6 +96,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "handle.h"
</span>  #include "process.h"
  #include "request.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  #include "winternl.h"
  #include "winioctl.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -163,6 +164,7 @@ struct fd
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -156,6 +157,7 @@ struct fd
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct completion   *completion;  /* completion object attached to this fd */
</span>      apc_param_t          comp_key;    /* completion key to set in completion events */
      unsigned int         comp_flags;  /* completion flags */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                  esync_fd;    /* esync file descriptor */
</span> +    unsigned int         msync_idx;   /* msync shm index */
  };
  
  static void fd_dump( struct object *obj, int verbose );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -177,6 +179,7 @@ static const struct object_ops fd_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -169,6 +171,7 @@ static const struct object_ops fd_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -219,6 +222,7 @@ static const struct object_ops device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -210,6 +213,7 @@ static const struct object_ops device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -260,6 +264,7 @@ static const struct object_ops inode_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -250,6 +254,7 @@ static const struct object_ops inode_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -303,6 +308,7 @@ static const struct object_ops file_lock_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -292,6 +297,7 @@ static const struct object_ops file_lock_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                  /* add_queue */
</span>      remove_queue,               /* remove_queue */
      file_lock_signaled,         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                       /* get_esync_fd */
</span> +    NULL,                       /* get_msync_idx */
      no_satisfied,               /* satisfied */
      no_signal,                  /* signal */
      no_get_fd,                  /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1652,6 +1658,9 @@ static void fd_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1565,6 +1571,9 @@ static void fd_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         if (fd->unix_fd != -1) close( fd->unix_fd );
</span>          free( fd->unix_name );
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        msync_destroy_semaphore( fd->msync_idx );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         close( fd->esync_fd );
</span>  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1773,6 +1782,7 @@ static struct fd *alloc_fd_object(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* check if the desired access is possible without violating */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1683,12 +1692,16 @@ static struct fd *alloc_fd_object(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     fd->poll_index = -1;
</span>      fd->completion = NULL;
      fd->comp_flags = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     fd->esync_fd   = -1;
</span> +    fd->msync_idx  = 0;
      init_async_queue( &fd->read_q );
      init_async_queue( &fd->write_q );
      init_async_queue( &fd->wait_q );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1782,6 +1792,9 @@ static struct fd *alloc_fd_object(void)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         fd->esync_fd = esync_create_fd( 1, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     list_init( &fd->inode_entry );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     list_init( &fd->locks );
</span>  
 +    if (do_msync())
 +        fd->msync_idx = msync_alloc_shm( 1, 0 );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2825,37 +2752,33 @@ index b90999aae3c..17132109b8e 100644
</span>      if ((fd->poll_index = add_poll_user( fd )) == -1)
      {
          release_object( fd );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1818,14 +1831,19 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1724,11 +1737,15 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     fd->completion = NULL;
</span>      fd->comp_flags = 0;
      fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     fd->esync_fd   = -1;
</span> +    fd->msync_idx  = 0;
      init_async_queue( &fd->read_q );
      init_async_queue( &fd->write_q );
      init_async_queue( &fd->wait_q );
      list_init( &fd->inode_entry );
      list_init( &fd->locks );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync())
 +        fd->msync_idx = msync_alloc_shm( 0, 0 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         fd->esync_fd = esync_create_fd( 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span>      return fd;
  }
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2284,6 +2302,9 @@ void set_fd_signaled( struct fd *fd, int signaled )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2140,6 +2157,9 @@ void set_fd_signaled( struct fd *fd, int signaled )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return;
</span>      fd->signaled = signaled;
      if (signaled) wake_up( fd->user, 0 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync() && !signaled)
 +        msync_clear( fd->user );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && !signaled)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( fd->esync_fd );
</span>  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2320,6 +2341,15 @@ int default_fd_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* check if events are pending and if yes return which one(s) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2165,6 +2185,15 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry )
</span>      return ret;
  }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2872,151 +2795,148 @@ index b90999aae3c..17132109b8e 100644
</span>  {
      int events = 0;
 diff --git a/server/file.c b/server/file.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 828a21c08c6..017c89bf025 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 76c687833c9..8f51635c38a 100644
</span> --- a/server/file.c
 +++ b/server/file.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -124,6 +124,7 @@ static const struct object_ops file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -94,6 +94,7 @@ static const struct object_ops file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                    /* add_queue */
</span>      remove_queue,                 /* remove_queue */
      default_fd_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      file_get_fd,                  /* get_fd */
 diff --git a/server/file.h b/server/file.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0a81d7c4a3d..2654cb15ed7 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 006b5a8e324..12e71541ec0 100644
</span> --- a/server/file.h
 +++ b/server/file.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -109,6 +109,7 @@ extern void get_nt_name( struct fd *fd, struct unicode_str *name );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -108,6 +108,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ extern void get_nt_name( struct fd *fd, struct unicode_str *name );
</span>  
  extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +extern unsigned int default_fd_get_msync_idx( struct object *obj, enum msync_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/handle.c b/server/handle.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 7fc24d12a34..0d3e1f74655 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index ef243e06e0b..48ab37b314b 100644
</span> --- a/server/handle.c
 +++ b/server/handle.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -127,6 +127,7 @@ static const struct object_ops handle_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -126,6 +126,7 @@ static const struct object_ops handle_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                    /* add_queue */
</span>      NULL,                            /* remove_queue */
      NULL,                            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                            /* get_esync_fd */
</span> +    NULL,                            /* get_msync_idx */
      NULL,                            /* satisfied */
      no_signal,                       /* signal */
      no_get_fd,                       /* get_fd */
 diff --git a/server/hook.c b/server/hook.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ab4d0e9dd31..0bbdcc5aa88 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index c2d2823cd61..dfb210b9de6 100644
</span> --- a/server/hook.c
 +++ b/server/hook.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -82,6 +82,7 @@ static const struct object_ops hook_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -81,6 +81,7 @@ static const struct object_ops hook_table_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
 diff --git a/server/mailslot.c b/server/mailslot.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 4cf9b73f784..d04fc2f4edc 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 7defbccdb44..f7b8bca210d 100644
</span> --- a/server/mailslot.c
 +++ b/server/mailslot.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -75,6 +75,7 @@ static const struct object_ops mailslot_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -81,6 +81,7 @@ static const struct object_ops mailslot_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      default_fd_signaled,       /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      no_satisfied,              /* satisfied */
      no_signal,                 /* signal */
      mailslot_get_fd,           /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -135,6 +136,7 @@ static const struct object_ops mail_writer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -142,6 +143,7 @@ static const struct object_ops mail_writer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,               /* add_queue */
</span>      NULL,                       /* remove_queue */
      NULL,                       /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                       /* get_esync_fd */
</span> +    NULL,                       /* get_msync_idx */
      NULL,                       /* satisfied */
      no_signal,                  /* signal */
      mail_writer_get_fd,         /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -199,6 +201,7 @@ static const struct object_ops mailslot_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -207,6 +209,7 @@ static const struct object_ops mailslot_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                   /* add_queue */
</span>      NULL,                           /* remove_queue */
      NULL,                           /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                           /* get_esync_fd */
</span> +    NULL,                           /* get_msync_idx */
      no_satisfied,                   /* satisfied */
      no_signal,                      /* signal */
      no_get_fd,                      /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -230,6 +233,7 @@ static const struct object_ops mailslot_device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -237,6 +240,7 @@ static const struct object_ops mailslot_device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                              /* add_queue */
</span>      remove_queue,                           /* remove_queue */
      default_fd_signaled,                    /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                                   /* get_esync_fd */
</span> +    NULL,                                   /* get_msync_idx */
      no_satisfied,                           /* satisfied */
      no_signal,                              /* signal */
      mailslot_device_file_get_fd,            /* get_fd */
 diff --git a/server/main.c b/server/main.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 5062d0999fa..d5a8c05cb86 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 1248b92f24d..cedc5776a95 100644
</span> --- a/server/main.c
 +++ b/server/main.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -35,6 +35,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -34,6 +34,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "thread.h"
</span>  #include "request.h"
  #include "unicode.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  /* command-line options */
  int debug_level = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -230,9 +231,15 @@ int main( int argc, char *argv[] )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -229,6 +230,12 @@ int main( int argc, char *argv[] )
</span>      sock_init();
      open_master_socket();
  
 +    if (do_msync())
 +        msync_init();
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_init();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (!do_msync() && !do_esync())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (!do_msync())
</span> +        fprintf( stderr, "wineserver: using server-side synchronization.\n" );
 +
      if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
      set_current_time();
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     init_scheduler();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     init_signals();
</span> diff --git a/server/mapping.c b/server/mapping.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index bdb9ee5d840..597416130f1 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 8a34760b10e..81b8e48caaf 100644
</span> --- a/server/mapping.c
 +++ b/server/mapping.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -68,6 +68,7 @@ static const struct object_ops ranges_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -67,6 +67,7 @@ static const struct object_ops ranges_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,              /* add_queue */
</span>      NULL,                      /* remove_queue */
      NULL,                      /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      NULL,                      /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -105,6 +106,7 @@ static const struct object_ops shared_map_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -103,6 +104,7 @@ static const struct object_ops shared_map_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,              /* add_queue */
</span>      NULL,                      /* remove_queue */
      NULL,                      /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      NULL,                      /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -179,6 +181,7 @@ static const struct object_ops mapping_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -176,6 +178,7 @@ static const struct object_ops mapping_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                /* add_queue */
</span>      NULL,                        /* remove_queue */
      NULL,                        /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                        /* get_esync_fd */
</span> +    NULL,                        /* get_msync_idx */
      NULL,                        /* satisfied */
      no_signal,                   /* signal */
      mapping_get_fd,              /* get_fd */
 diff --git a/server/msync.c b/server/msync.c
 new file mode 100644
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 00000000000..b6e98cbffbe
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 00000000000..58c3542b7fc
</span> --- /dev/null
 +++ b/server/msync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,992 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -0,0 +1,991 @@
</span> +/*
 + * mach semaphore-based synchronization objects
 + *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3626,7 +3546,6 @@ index 00000000000..b6e98cbffbe
</span> +    no_add_queue,              /* add_queue */
 +    NULL,                      /* remove_queue */
 +    NULL,                      /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    NULL,                      /* get_esync_fd */
</span> +    msync_get_msync_idx,       /* get_msync_idx */
 +    NULL,                      /* satisfied */
 +    no_signal,                 /* signal */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4052,146 +3971,146 @@ index 00000000000..000aa48c53d
</span> +extern void msync_reset_event( struct msync *msync );
 +extern void msync_abandon_mutexes( struct thread *thread );
 diff --git a/server/mutex.c b/server/mutex.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 4785a830e92..6a60adee0bd 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index af0efe72132..0f6d013a119 100644
</span> --- a/server/mutex.c
 +++ b/server/mutex.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -74,6 +74,7 @@ static const struct object_ops mutex_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -73,6 +73,7 @@ static const struct object_ops mutex_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      mutex_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      mutex_satisfied,           /* satisfied */
      mutex_signal,              /* signal */
      no_get_fd,                 /* get_fd */
 diff --git a/server/named_pipe.c b/server/named_pipe.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a90ec606226..d8d17fa95f7 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index dd8c14b30a9..bfe60839b6f 100644
</span> --- a/server/named_pipe.c
 +++ b/server/named_pipe.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -120,6 +120,7 @@ static const struct object_ops named_pipe_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -119,6 +119,7 @@ static const struct object_ops named_pipe_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -169,6 +170,7 @@ static const struct object_ops pipe_server_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -167,6 +168,7 @@ static const struct object_ops pipe_server_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                    /* add_queue */
</span>      remove_queue,                 /* remove_queue */
      default_fd_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     default_fd_get_esync_fd,      /* get_esync_fd */
</span> +    default_fd_get_msync_idx,     /* get_msync_idx */
      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      pipe_end_get_fd,              /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -214,6 +216,7 @@ static const struct object_ops pipe_client_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -211,6 +213,7 @@ static const struct object_ops pipe_client_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                    /* add_queue */
</span>      remove_queue,                 /* remove_queue */
      default_fd_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     default_fd_get_esync_fd,      /* get_esync_fd */
</span> +    default_fd_get_msync_idx,     /* get_msync_idx */
      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      pipe_end_get_fd,              /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -262,6 +265,7 @@ static const struct object_ops named_pipe_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -258,6 +261,7 @@ static const struct object_ops named_pipe_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                     /* add_queue */
</span>      NULL,                             /* remove_queue */
      NULL,                             /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                             /* get_esync_fd */
</span> +    NULL,                             /* get_msync_idx */
      no_satisfied,                     /* satisfied */
      no_signal,                        /* signal */
      no_get_fd,                        /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -294,6 +298,7 @@ static const struct object_ops named_pipe_device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -289,6 +293,7 @@ static const struct object_ops named_pipe_device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                               /* add_queue */
</span>      remove_queue,                            /* remove_queue */
      default_fd_signaled,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                                    /* get_esync_fd */
</span> +    NULL,                                    /* get_msync_idx */
      no_satisfied,                            /* satisfied */
      no_signal,                               /* signal */
      named_pipe_device_file_get_fd,           /* get_fd */
 diff --git a/server/object.h b/server/object.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a6e9af93664..a59eb135501 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 2337ee88231..77084b1ee32 100644
</span> --- a/server/object.h
 +++ b/server/object.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -80,6 +80,8 @@ struct object_ops
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -78,6 +78,8 @@ struct object_ops
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     void (*remove_queue)(struct object *,struct wait_queue_entry *);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* is object signaled? */
</span>      int  (*signaled)(struct object *,struct wait_queue_entry *);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     /* return the esync fd for this object */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int (*get_esync_fd)(struct object *, enum esync_type *type);
</span> +    /* return the msync shm idx for this object */
 +    unsigned int (*get_msync_idx)(struct object *, enum msync_type *type);
      /* wait satisfied */
      void (*satisfied)(struct object *,struct wait_queue_entry *);
      /* signal an object */
 diff --git a/server/process.c b/server/process.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ce34f46166a..93bcd822b38 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 155dc050d95..f9b393e59e7 100644
</span> --- a/server/process.c
 +++ b/server/process.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -64,6 +64,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -63,6 +63,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "request.h"
</span>  #include "user.h"
  #include "security.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  /* process object */
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -97,6 +98,7 @@ static void process_poll_event( struct fd *fd, int event );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -95,6 +96,7 @@ static struct security_descriptor *process_get_sd( struct object *obj );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void process_poll_event( struct fd *fd, int event );
</span>  static struct list *process_get_kernel_obj_list( struct object *obj );
  static void process_destroy( struct object *obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int process_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int process_get_msync_idx( struct object *obj, enum msync_type *type );
  static void terminate_process( struct process *process, struct thread *skip, int exit_code );
  
  static const struct object_ops process_ops =
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -108,6 +110,7 @@ static const struct object_ops process_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -105,6 +107,7 @@ static const struct object_ops process_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                   /* add_queue */
</span>      remove_queue,                /* remove_queue */
      process_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     process_get_esync_fd,        /* get_esync_fd */
</span> +    process_get_msync_idx,       /* get_msync_idx */
      no_satisfied,                /* satisfied */
      no_signal,                   /* signal */
      no_get_fd,                   /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -160,6 +163,7 @@ static const struct object_ops startup_info_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -156,6 +159,7 @@ static const struct object_ops startup_info_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                     /* add_queue */
</span>      remove_queue,                  /* remove_queue */
      startup_info_signaled,         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      no_satisfied,                  /* satisfied */
      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -222,6 +226,7 @@ static const struct object_ops job_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -217,6 +221,7 @@ static const struct object_ops job_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                     /* add_queue */
</span>      remove_queue,                  /* remove_queue */
      job_signaled,                  /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      no_satisfied,                  /* satisfied */
      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -691,6 +696,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -685,6 +690,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     process->rawinput_kbd    = NULL;
</span>      memset( &process->image_info, 0, sizeof(process->image_info) );
      list_init( &process->rawinput_entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     process->esync_fd        = -1;
</span> +    process->msync_idx       = 0;
      list_init( &process->kernel_object );
      list_init( &process->thread_list );
      list_init( &process->locks );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -741,6 +747,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -735,6 +741,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
</span>      if (!process->handles || !process->token) goto error;
      process->session_id = token_get_session_id( process->token );
  
 +    if (do_msync())
 +        process->msync_idx = msync_alloc_shm( 0, 0 );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         process->esync_fd = esync_create_fd( 0, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     set_fd_events( process->msg_fd, POLLIN );  /* start listening to events */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return process;
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -793,6 +802,7 @@ static void process_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -783,6 +792,7 @@ static void process_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     free( process->rawinput_devices );
</span>      free( process->dir_cache );
      free( process->image );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync()) close( process->esync_fd );
</span> +    if (do_msync()) msync_destroy_semaphore( process->msync_idx );
  }
  
  /* dump a process on stdout for debugging purposes */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -817,6 +827,13 @@ static int process_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return process->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -800,6 +810,13 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return !process->running_threads;
</span>  }
  
 +static unsigned int process_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4205,24 +4124,24 @@ index ce34f46166a..93bcd822b38 100644
</span>  {
      access = default_map_access( obj, access );
 diff --git a/server/process.h b/server/process.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index bedd8bb4586..24276142a63 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 1e73e9d47dc..217d94aa63a 100644
</span> --- a/server/process.h
 +++ b/server/process.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -87,6 +87,7 @@ struct process
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -86,6 +86,7 @@ struct process
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct list          rawinput_entry;  /* entry in the rawinput process list */
</span>      struct list          kernel_object;   /* list of kernel object pointers */
      pe_image_info_t      image_info;      /* main exe image info */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                  esync_fd;        /* esync file descriptor (signaled on exit) */
</span> +    unsigned int         msync_idx;
  };
  
  /* process functions */
 diff --git a/server/protocol.def b/server/protocol.def
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 1e4171c56ef..7ad9129f5d4 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 2c791cbdd46..9677e55f6ad 100644
</span> --- a/server/protocol.def
 +++ b/server/protocol.def
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -4022,3 +4022,57 @@ enum esync_type
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Retrieve the fd to wait on for user APCs. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- @REQ(get_esync_apc_fd)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3953,3 +3953,57 @@ struct handle_info
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ @REPLY
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     int enable;                /* previous state of auto-repeat enable */
</span>  @END
 +
 +enum msync_type
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4279,62 +4198,62 @@ index 1e4171c56ef..7ad9129f5d4 100644
</span> +    unsigned int shm_idx;
 +@END
 diff --git a/server/queue.c b/server/queue.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 109610b3d31..2c1f8053102 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 0156a4c66f2..ddf88a94581 100644
</span> --- a/server/queue.c
 +++ b/server/queue.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -45,6 +45,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -44,6 +44,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "process.h"
</span>  #include "request.h"
  #include "user.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
  #define WM_NCMOUSELAST  (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -139,6 +140,8 @@ struct msg_queue
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     unsigned int           ignore_post_msg; /* ignore post messages newer than this unique id */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                    esync_fd;        /* esync file descriptor (signalled on message) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                    esync_in_msgwait; /* our thread is currently waiting on us */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -133,6 +134,8 @@ struct msg_queue
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     timeout_t              last_get_msg;    /* time of last get message call */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     int                    keystate_lock;   /* owns an input keystate lock */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     const queue_shm_t     *shared;          /* queue in session shared memory */
</span> +    unsigned int           msync_idx;
 +    int                    msync_in_msgwait; /* our thread is currently waiting on us */
  };
  
  struct hotkey
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -156,6 +159,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -149,6 +152,7 @@ static void msg_queue_dump( struct object *obj, int verbose );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
</span>  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 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int msg_queue_get_msync_idx( struct object *obj, enum msync_type *type );
  static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry );
  static void msg_queue_destroy( struct object *obj );
  static void msg_queue_poll_event( struct fd *fd, int event );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -172,6 +176,7 @@ static const struct object_ops msg_queue_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -164,6 +168,7 @@ static const struct object_ops msg_queue_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     msg_queue_add_queue,       /* add_queue */
</span>      msg_queue_remove_queue,    /* remove_queue */
      msg_queue_signaled,        /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     msg_queue_get_esync_fd,    /* get_esync_fd */
</span> +    msg_queue_get_msync_idx,   /* get_msync_idx */
      msg_queue_satisfied,       /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -210,6 +215,7 @@ static const struct object_ops thread_input_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -201,6 +206,7 @@ static const struct object_ops thread_input_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -324,6 +330,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         queue->ignore_post_msg = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         queue->esync_fd        = -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         queue->esync_in_msgwait = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -312,6 +318,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         queue->hooks           = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         queue->last_get_msg    = current_time;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         queue->keystate_lock   = 0;
</span> +        queue->msync_idx       = 0;
 +        queue->msync_in_msgwait = 0;
          list_init( &queue->send_result );
          list_init( &queue->callback_result );
          list_init( &queue->pending_timers );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -349,6 +357,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             queue->esync_fd = esync_create_fd( 0, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -334,6 +342,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         SHARED_WRITE_END;
</span>  
 +        if (do_msync())
 +            queue->msync_idx = msync_alloc_shm( 0, 0 );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4342,28 +4261,29 @@ index 109610b3d31..2c1f8053102 100644
</span>          thread->queue = queue;
  
          if ((desktop = get_thread_desktop( thread, 0 )))
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -737,6 +748,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -740,6 +751,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         if (queue->keystate_lock) unlock_input_keystate( queue->input );
</span>          queue->keystate_lock = 0;
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync() && !is_signaled( queue ))
 +        msync_clear( &queue->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && !is_signaled( queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( queue->esync_fd );
</span>  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1228,6 +1242,9 @@ static int is_queue_hung( struct msg_queue *queue )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* check if message is matched by the filter */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1219,6 +1233,10 @@ static int is_queue_hung( struct msg_queue *queue )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         if (get_wait_queue_thread(entry)->queue == queue)
</span>              return 0;  /* thread is waiting on queue -> not hung */
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync() && queue->msync_in_msgwait)
 +        return 0;   /* thread is waiting on queue in absentia -> not hung */
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && queue->esync_in_msgwait)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         return 0;   /* thread is waiting on queue in absentia -> not hung */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1292,6 +1309,13 @@ static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return queue->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1273,6 +1291,13 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return ret || is_signaled( queue );
</span>  }
  
 +static unsigned int msg_queue_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4376,46 +4296,49 @@ index 109610b3d31..2c1f8053102 100644
</span>  static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry )
  {
      struct msg_queue *queue = (struct msg_queue *)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1349,6 +1373,8 @@ static void msg_queue_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1329,6 +1354,8 @@ static void msg_queue_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (queue->hooks) release_object( queue->hooks );
</span>      if (queue->fd) release_object( queue->fd );
      if (queue->shared) free_shared_object( queue->shared );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync()) close( queue->esync_fd );
</span> +    if (do_msync())
 +        msync_destroy_semaphore( queue->msync_idx );
  }
  
  static void msg_queue_poll_event( struct fd *fd, int event )
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3121,6 +3147,8 @@ DECL_HANDLER(set_queue_mask)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3106,6 +3133,9 @@ DECL_HANDLER(set_queue_mask)
</span>              }
              else wake_up( &queue->obj, 0 );
          }
<span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +        if (do_msync() && !is_signaled( queue ))
 +            msync_clear( &queue->obj );
<span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync() && !is_signaled( queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_clear( queue->esync_fd );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3145,6 +3173,9 @@ DECL_HANDLER(get_queue_status)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3126,6 +3156,9 @@ DECL_HANDLER(get_queue_status)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             shared->changed_bits &= ~req->clear_bits;
</span>          }
          SHARED_WRITE_END;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +        if (do_msync() && !is_signaled( queue ))
 +            msync_clear( &queue->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync() && !is_signaled( queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_clear( queue->esync_fd );
</span>      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3416,6 +3447,9 @@ DECL_HANDLER(get_message)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     else reply->wake_bits = reply->changed_bits = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3383,6 +3416,11 @@ DECL_HANDLER(get_message)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     SHARED_WRITE_END;
</span>  
      set_error( STATUS_PENDING );  /* FIXME */
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync() && !is_signaled( queue ))
 +        msync_clear( &queue->obj );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && !is_signaled( queue ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( queue->esync_fd );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -4220,6 +4254,23 @@ DECL_HANDLER(esync_msgwait)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -4155,6 +4193,23 @@ DECL_HANDLER(update_rawinput_devices)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span>  }
  
 +DECL_HANDLER(msync_msgwait)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4439,37 +4362,37 @@ index 109610b3d31..2c1f8053102 100644
</span>  {
      struct desktop *desktop;
 diff --git a/server/registry.c b/server/registry.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 1cca1acfe6b..eb54495208c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 804cfcc638b..1b2da63cafb 100644
</span> --- a/server/registry.c
 +++ b/server/registry.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -181,6 +181,7 @@ static const struct object_ops key_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -180,6 +180,7 @@ static const struct object_ops key_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,            /* add_queue */
</span>      NULL,                    /* remove_queue */
      NULL,                    /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                    /* get_esync_fd */
</span> +    NULL,                    /* get_msync_idx */
      NULL,                    /* satisfied */
      no_signal,               /* signal */
      no_get_fd,               /* get_fd */
 diff --git a/server/request.c b/server/request.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 8e7d88a0d4c..3287b16170d 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 2691e0c7cff..84f5032d59f 100644
</span> --- a/server/request.c
 +++ b/server/request.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -91,6 +91,7 @@ static const struct object_ops master_socket_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -90,6 +90,7 @@ static const struct object_ops master_socket_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                  /* add_queue */
</span>      NULL,                          /* remove_queue */
      NULL,                          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      NULL,                          /* satisfied */
      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
 diff --git a/server/request.h b/server/request.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a68983ef6dc..32fd61d7903 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 6158aefdb78..6b876918510 100644
</span> --- a/server/request.h
 +++ b/server/request.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -411,6 +411,11 @@ DECL_HANDLER(get_esync_fd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- DECL_HANDLER(esync_msgwait);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -405,6 +405,11 @@ DECL_HANDLER(suspend_process);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ DECL_HANDLER(resume_process);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ DECL_HANDLER(get_next_thread);
</span>  DECL_HANDLER(set_keyboard_repeat);
<span style='display:block; white-space:pre;background:#ffe0e0;'>- DECL_HANDLER(get_esync_apc_fd);
</span> +DECL_HANDLER(create_msync);
 +DECL_HANDLER(open_msync);
 +DECL_HANDLER(get_msync_idx);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4478,10 +4401,10 @@ index a68983ef6dc..32fd61d7903 100644
</span>  
  #ifdef WANT_REQUEST_HANDLERS
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -709,6 +714,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     (req_handler)req_esync_msgwait,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -697,6 +702,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     (req_handler)req_resume_process,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     (req_handler)req_get_next_thread,
</span>      (req_handler)req_set_keyboard_repeat,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     (req_handler)req_get_esync_apc_fd,
</span> +    (req_handler)req_create_msync,
 +    (req_handler)req_open_msync,
 +    (req_handler)req_get_msync_idx,
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4490,10 +4413,10 @@ index a68983ef6dc..32fd61d7903 100644
</span>  };
  
  C_ASSERT( sizeof(abstime_t) == 8 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2386,6 +2396,34 @@ C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2341,6 +2351,34 @@ C_ASSERT( FIELD_OFFSET(struct set_keyboard_repeat_request, period) == 20 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
</span>  C_ASSERT( FIELD_OFFSET(struct set_keyboard_repeat_reply, enable) == 8 );
  C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 );
</span> +C_ASSERT( FIELD_OFFSET(struct create_msync_request, access) == 12 );
 +C_ASSERT( FIELD_OFFSET(struct create_msync_request, low) == 16 );
 +C_ASSERT( FIELD_OFFSET(struct create_msync_request, high) == 20 );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4526,135 +4449,135 @@ index a68983ef6dc..32fd61d7903 100644
</span>  #endif  /* WANT_REQUEST_HANDLERS */
  
 diff --git a/server/semaphore.c b/server/semaphore.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index e3889f24601..8d3c325c0b3 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 53b42a886df..bbcbc831793 100644
</span> --- a/server/semaphore.c
 +++ b/server/semaphore.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -71,6 +71,7 @@ static const struct object_ops semaphore_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -70,6 +70,7 @@ static const struct object_ops semaphore_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                     /* add_queue */
</span>      remove_queue,                  /* remove_queue */
      semaphore_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                          /* get_esync_fd */
</span> +    NULL,                          /* get_msync_idx */
      semaphore_satisfied,           /* satisfied */
      semaphore_signal,              /* signal */
      no_get_fd,                     /* get_fd */
 diff --git a/server/serial.c b/server/serial.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 0d49a996c2a..9c28c78cf28 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 209f2e9174e..62eafa87408 100644
</span> --- a/server/serial.c
 +++ b/server/serial.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -92,6 +92,7 @@ static const struct object_ops serial_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -91,6 +91,7 @@ static const struct object_ops serial_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                    /* add_queue */
</span>      remove_queue,                 /* remove_queue */
      default_fd_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      serial_get_fd,                /* get_fd */
 diff --git a/server/signal.c b/server/signal.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 55cd6aa037e..e86ad49df8e 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 19b76d44c16..57415604d07 100644
</span> --- a/server/signal.c
 +++ b/server/signal.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -63,6 +63,7 @@ static const struct object_ops handler_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -62,6 +62,7 @@ static const struct object_ops handler_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
 diff --git a/server/sock.c b/server/sock.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 7be912b3b50..af92f134538 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 06ffd1b81f8..e7081476458 100644
</span> --- a/server/sock.c
 +++ b/server/sock.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -454,6 +454,7 @@ static const struct object_ops sock_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -453,6 +453,7 @@ static const struct object_ops sock_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                    /* add_queue */
</span>      remove_queue,                 /* remove_queue */
      default_fd_signaled,          /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      sock_get_fd,                  /* get_fd */
 @@ -3562,6 +3563,7 @@ static const struct object_ops ifchange_ops =
<span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,            /* add_queue */
</span>      NULL,                    /* remove_queue */
      NULL,                    /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                    /* get_esync_fd */
</span> +    NULL,                    /* get_msync_idx */
      no_satisfied,            /* satisfied */
      no_signal,               /* signal */
      ifchange_get_fd,         /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3784,6 +3786,7 @@ static const struct object_ops socket_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3783,6 +3785,7 @@ static const struct object_ops socket_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,               /* add_queue */
</span>      NULL,                       /* remove_queue */
      NULL,                       /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                       /* get_esync_fd */
</span> +    NULL,                       /* get_msync_idx */
      no_satisfied,               /* satisfied */
      no_signal,                  /* signal */
      no_get_fd,                  /* get_fd */
 diff --git a/server/symlink.c b/server/symlink.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index c7f34412317..d40d060492b 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index dd28efd3a75..d6a51f0091d 100644
</span> --- a/server/symlink.c
 +++ b/server/symlink.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -72,6 +72,7 @@ static const struct object_ops symlink_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -71,6 +71,7 @@ static const struct object_ops symlink_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
 diff --git a/server/thread.c b/server/thread.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index dac5c43e3bd..5003898e822 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 6542e1584ab..7026c785a13 100644
</span> --- a/server/thread.c
 +++ b/server/thread.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -51,6 +51,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -50,6 +50,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "request.h"
</span>  #include "user.h"
  #include "security.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  
  /* thread queues */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -98,6 +99,7 @@ static const struct object_ops thread_apc_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -96,6 +97,7 @@ static const struct object_ops thread_apc_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                  /* add_queue */
</span>      remove_queue,               /* remove_queue */
      thread_apc_signaled,        /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                       /* get_esync_fd */
</span> +    NULL,                       /* get_msync_idx */
      no_satisfied,               /* satisfied */
      no_signal,                  /* signal */
      no_get_fd,                  /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -141,6 +143,7 @@ static const struct object_ops context_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -138,6 +140,7 @@ static const struct object_ops context_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                  /* add_queue */
</span>      remove_queue,               /* remove_queue */
      context_signaled,           /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                       /* get_esync_fd */
</span> +    NULL,                       /* get_msync_idx */
      no_satisfied,               /* satisfied */
      no_signal,                  /* signal */
      no_get_fd,                  /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -178,6 +181,7 @@ struct type_descr thread_type =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -174,6 +177,7 @@ struct type_descr thread_type =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span>  static void dump_thread( struct object *obj, int verbose );
  static int thread_signaled( struct object *obj, struct wait_queue_entry *entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int thread_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int thread_get_msync_idx( struct object *obj, enum msync_type *type );
  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 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -192,6 +196,7 @@ static const struct object_ops thread_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -187,6 +191,7 @@ static const struct object_ops thread_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                  /* add_queue */
</span>      remove_queue,               /* remove_queue */
      thread_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     thread_get_esync_fd,        /* get_esync_fd */
</span> +    thread_get_msync_idx,       /* get_msync_idx */
      no_satisfied,               /* satisfied */
      no_signal,                  /* signal */
      no_get_fd,                  /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -233,6 +238,8 @@ static inline void init_thread_structure( struct thread *thread )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -226,6 +231,8 @@ static inline void init_thread_structure( struct thread *thread )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     thread->context         = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     thread->teb             = 0;
</span>      thread->entry_point     = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     thread->esync_fd        = -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     thread->esync_apc_fd    = -1;
</span> +    thread->msync_idx       = 0;
 +    thread->msync_apc_idx   = 0;
      thread->system_regs     = 0;
      thread->queue           = NULL;
      thread->wait            = NULL;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -380,6 +387,12 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -372,6 +379,12 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
</span>          }
      }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4664,13 +4587,13 @@ index dac5c43e3bd..5003898e822 100644
</span> +        thread->msync_apc_idx = msync_alloc_shm( 0, 0 );
 +    }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         thread->esync_fd = esync_create_fd( 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -468,6 +481,12 @@ static void destroy_thread( struct object *obj )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         close( thread->esync_fd );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_process_thread( thread->process, thread );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return thread;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -450,6 +463,12 @@ static void destroy_thread( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     release_object( thread->process );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (thread->id) free_ptid( thread->id );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (thread->token) release_object( thread->token );
</span> +
 +    if (do_msync())
 +    {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4680,8 +4603,8 @@ index dac5c43e3bd..5003898e822 100644
</span>  }
  
  /* dump a thread on stdout for debugging purposes */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -493,6 +512,13 @@ static int thread_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return thread->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -468,6 +487,13 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return (mythread->state == TERMINATED);
</span>  }
  
 +static unsigned int thread_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4694,7 +4617,7 @@ index dac5c43e3bd..5003898e822 100644
</span>  static unsigned int thread_map_access( struct object *obj, unsigned int access )
  {
      access = default_map_access( obj, access );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -545,6 +571,7 @@ static struct thread_apc *create_apc( struct object *owner, const apc_call_t *ca
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -520,6 +546,7 @@ static struct thread_apc *create_apc( struct object *owner, const apc_call_t *ca
</span>          apc->result.type = APC_NONE;
          if (owner) grab_object( owner );
      }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4702,114 +4625,117 @@ index dac5c43e3bd..5003898e822 100644
</span>      return apc;
  }
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1091,6 +1118,9 @@ void wake_up( struct object *obj, int max )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1063,6 +1090,9 @@ void wake_up( struct object *obj, int max )
</span>      struct list *ptr;
      int ret;
  
 +    if (do_msync())
 +        msync_wake_up( obj );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_wake_up( obj );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1181,6 +1211,9 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     LIST_FOR_EACH( ptr, &obj->wait_queue )
</span>      {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+         struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1147,8 +1177,12 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     grab_object( apc );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     list_add_tail( queue, &apc->entry );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (!list_prev( queue, &apc->entry ))  /* first one */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {
</span>          wake_thread( thread );
  
 +        if (do_msync() && queue == &thread->user_apc)
 +            msync_signal_all( thread->msync_apc_idx );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync() && queue == &thread->user_apc)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_wake_fd( thread->esync_apc_fd );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1231,6 +1264,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1194,6 +1228,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         apc = LIST_ENTRY( ptr, struct thread_apc, entry );
</span>          list_remove( ptr );
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    if (do_msync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc ))
 +        msync_clear_shm( thread->msync_apc_idx );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc ))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_clear( thread->esync_apc_fd );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return apc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span>  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1349,6 +1385,8 @@ void kill_thread( struct thread *thread, int violent_death )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1289,6 +1327,8 @@ void kill_thread( struct thread *thread, int violent_death )
</span>      }
      kill_console_processes( thread, 0 );
      abandon_mutexes( thread );
 +    if (do_msync())
 +        msync_abandon_mutexes( thread );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         esync_abandon_mutexes( thread );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (violent_death)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     wake_up( &thread->obj, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     if (violent_death) send_thread_signal( thread, SIGQUIT );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     cleanup_thread( thread );
</span> diff --git a/server/thread.h b/server/thread.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 10e9e28b432..26b41745261 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 766ed78a72f..d9116df1cba 100644
</span> --- a/server/thread.h
 +++ b/server/thread.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -57,6 +57,8 @@ struct thread
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -55,6 +55,8 @@ struct thread
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct process        *process;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     thread_id_t            id;            /* thread id */
</span>      struct list            mutex_list;    /* list of currently owned mutexes */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                    esync_fd;      /* esync file descriptor (signalled on exit) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                    esync_apc_fd;  /* esync apc fd (signalled when APCs are present) */
</span> +    unsigned int           msync_idx;
 +    unsigned int           msync_apc_idx;
      unsigned int           system_regs;   /* which system regs have been set */
      struct msg_queue      *queue;         /* message queue */
      struct thread_wait    *wait;          /* current wait condition if sleeping */
 diff --git a/server/timer.c b/server/timer.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 36645a2a8d2..d57a5536eb3 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 96dc9d00ca1..75756b27c66 100644
</span> --- a/server/timer.c
 +++ b/server/timer.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -36,6 +36,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -35,6 +35,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "file.h"
</span>  #include "handle.h"
  #include "request.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #include "esync.h"
</span> +#include "msync.h"
  
  static const WCHAR timer_name[] = {'T','i','m','e','r'};
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -63,11 +64,13 @@ struct timer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -61,10 +62,12 @@ struct timer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     struct thread       *thread;    /* thread that set the APC function */
</span>      client_ptr_t         callback;  /* callback APC function */
      client_ptr_t         arg;       /* callback argument */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     int                  esync_fd;  /* esync file descriptor */
</span> +    unsigned int         msync_idx; /* msync shm index */
  };
  
  static void timer_dump( struct object *obj, int verbose );
  static int timer_signaled( struct object *obj, struct wait_queue_entry *entry );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- static int timer_get_esync_fd( struct object *obj, enum esync_type *type );
</span> +static unsigned int timer_get_msync_idx( struct object *obj, enum msync_type *type );
  static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry );
  static void timer_destroy( struct object *obj );
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -80,6 +83,7 @@ static const struct object_ops timer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -76,6 +79,7 @@ static const struct object_ops timer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     add_queue,                 /* add_queue */
</span>      remove_queue,              /* remove_queue */
      timer_signaled,            /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     timer_get_esync_fd,        /* get_esync_fd */
</span> +    timer_get_msync_idx,       /* get_msync_idx */
      timer_satisfied,           /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -116,6 +120,9 @@ static struct timer *create_timer( struct object *root, const struct unicode_str
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -110,6 +114,9 @@ static struct timer *create_timer( struct object *root, const struct unicode_str
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             timer->period   = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             timer->timeout  = NULL;
</span>              timer->thread   = NULL;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-             timer->esync_fd = -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span> +            if (do_msync())
 +                timer->msync_idx = msync_alloc_shm( 0, 0 );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-             if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                 timer->esync_fd = esync_create_fd( 0, 0 );
</span>          }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -190,6 +197,9 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return timer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -181,6 +188,9 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span>          period = 0;  /* period doesn't make any sense for a manual timer */
          timer->signaled = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +        if (do_msync())
 +            msync_clear( &timer->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         if (do_esync())
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             esync_clear( timer->esync_fd );
</span>      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -226,6 +236,13 @@ static int timer_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return timer->esync_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     timer->when     = (expire <= 0) ? expire - monotonic_time : max( expire, current_time );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     timer->period   = period;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -208,6 +218,13 @@ static int timer_signaled( struct object *obj, struct wait_queue_entry *entry )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     return timer->signaled;
</span>  }
  
 +static unsigned int timer_get_msync_idx( struct object *obj, enum msync_type *type )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4822,33 +4748,33 @@ index 36645a2a8d2..d57a5536eb3 100644
</span>  static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry )
  {
      struct timer *timer = (struct timer *)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -241,6 +258,8 @@ static void timer_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -222,6 +239,8 @@ static void timer_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span>      if (timer->timeout) remove_timeout_user( timer->timeout );
      if (timer->thread) release_object( timer->thread );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     if (do_esync()) close( timer->esync_fd );
</span> +    if (do_msync())
 +        msync_destroy_semaphore( timer->msync_idx );
  }
  
  /* create a timer */
 diff --git a/server/token.c b/server/token.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index e40ba10f9aa..1101c7224b9 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index da7f0bb7ff2..1394d06750a 100644
</span> --- a/server/token.c
 +++ b/server/token.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -146,6 +146,7 @@ static const struct object_ops token_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -145,6 +145,7 @@ static const struct object_ops token_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,              /* add_queue */
</span>      NULL,                      /* remove_queue */
      NULL,                      /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                      /* get_esync_fd */
</span> +    NULL,                      /* get_msync_idx */
      NULL,                      /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
 diff --git a/server/trace.c b/server/trace.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 89e9c0b3aa1..f692e86a878 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 96dc5781d4c..345b622d22b 100644
</span> --- a/server/trace.c
 +++ b/server/trace.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -4712,6 +4712,63 @@ static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -4641,6 +4641,63 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     fprintf( stderr, " enable=%d", req->enable );
</span>  }
  
 +static void dump_create_msync_request( const struct create_msync_request *req )
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4911,10 +4837,10 @@ index 89e9c0b3aa1..f692e86a878 100644
</span>  static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
      (dump_func)dump_new_process_request,
      (dump_func)dump_get_new_process_info_request,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -5005,6 +5062,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     (dump_func)dump_esync_msgwait_request,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -4928,6 +4985,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     (dump_func)dump_resume_process_request,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     (dump_func)dump_get_next_thread_request,
</span>      (dump_func)dump_set_keyboard_repeat_request,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     (dump_func)dump_get_esync_apc_fd_request,
</span> +    (dump_func)dump_create_msync_request,
 +    (dump_func)dump_open_msync_request,
 +    (dump_func)dump_get_msync_idx_request,
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4923,10 +4849,10 @@ index 89e9c0b3aa1..f692e86a878 100644
</span>  };
  
  static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -5300,6 +5362,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -5217,6 +5279,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
</span>      NULL,
<span style='display:block; white-space:pre;background:#e0ffe0;'>+     (dump_func)dump_get_next_thread_reply,
</span>      (dump_func)dump_set_keyboard_repeat_reply,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,
</span> +    (dump_func)dump_create_msync_reply,
 +    (dump_func)dump_open_msync_reply,
 +    (dump_func)dump_get_msync_idx_reply,
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4935,10 +4861,10 @@ index 89e9c0b3aa1..f692e86a878 100644
</span>  };
  
  static const char * const req_names[REQ_NB_REQUESTS] = {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -5595,6 +5662,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     "esync_msgwait",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -5506,6 +5573,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     "resume_process",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     "get_next_thread",
</span>      "set_keyboard_repeat",
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     "get_esync_apc_fd",
</span> +    "create_msync",
 +    "open_msync",
 +    "get_msync_idx",
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4948,33 +4874,33 @@ index 89e9c0b3aa1..f692e86a878 100644
</span>  
  static const struct
 diff --git a/server/window.c b/server/window.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 13318b75fe2..85ee8d8f9b2 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 564c69bf18d..e605324a865 100644
</span> --- a/server/window.c
 +++ b/server/window.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -107,6 +107,7 @@ static const struct object_ops window_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -106,6 +106,7 @@ static const struct object_ops window_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,             /* add_queue */
</span>      NULL,                     /* remove_queue */
      NULL,                     /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                     /* get_esync_fd */
</span> +    NULL,                     /* get_msync_idx */
      NULL,                     /* satisfied */
      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
 diff --git a/server/winstation.c b/server/winstation.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 5cd235c528e..c1dfbc85272 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 76a23b197a4..da1fecf30da 100644
</span> --- a/server/winstation.c
 +++ b/server/winstation.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -77,6 +77,7 @@ static const struct object_ops winstation_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -76,6 +76,7 @@ static const struct object_ops winstation_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -118,6 +119,7 @@ static const struct object_ops desktop_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -116,6 +117,7 @@ static const struct object_ops desktop_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     no_add_queue,                 /* add_queue */
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-     NULL,                         /* get_esync_fd */
</span> +    NULL,                         /* get_msync_idx */
      NULL,                         /* satisfied */
      no_signal,                    /* signal */
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/emulators/wine-devel/files/1001-msync.diff b/emulators/wine-devel/files/1001-staging-msync.diff
</span>similarity index 97%
rename from emulators/wine-devel/files/1001-msync.diff
rename to emulators/wine-devel/files/1001-staging-msync.diff
<span style='display:block; white-space:pre;color:#808080;'>index d9457b5f342..d3c89c80a5a 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/emulators/wine-devel/files/1001-msync.diff
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/emulators/wine-devel/files/1001-staging-msync.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -11,7 +11,7 @@ index 78b3fdf94aa..061c730bf63 100644
</span>   unix/loadorder.c \
        unix/process.c \
 diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 85d3db0cb8c..b63a386ee96 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f4748e405ef..2e116a56f4b 100644
</span> --- a/dlls/ntdll/unix/esync.c
 +++ b/dlls/ntdll/unix/esync.c
 @@ -51,6 +51,7 @@
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -70,10 +70,10 @@ index 85d3db0cb8c..b63a386ee96 100644
</span>          /* Try to check objects now, so we can obviate poll() at least. */
          for (i = 0; i < count; i++)
 diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index ae7e2e8e6ec..a7175b35ae6 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index d8f289054d4..67485a863f5 100644
</span> --- a/dlls/ntdll/unix/loader.c
 +++ b/dlls/ntdll/unix/loader.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -89,6 +89,7 @@ extern char **environ;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -91,6 +91,7 @@
</span>  #include "winternl.h"
  #include "unix_private.h"
  #include "esync.h"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -81,7 +81,7 @@ index ae7e2e8e6ec..a7175b35ae6 100644
</span>  #include "wine/list.h"
  #include "ntsyscalls.h"
  #include "wine/debug.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1896,6 +1897,7 @@ static void start_main_thread(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1859,6 +1860,7 @@ static void start_main_thread(void)
</span>      signal_alloc_thread( teb );
      dbg_init();
      startup_info_size = server_init_process();
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -91,10 +91,10 @@ index ae7e2e8e6ec..a7175b35ae6 100644
</span>      init_cpu_info();
 diff --git a/dlls/ntdll/unix/msync.c b/dlls/ntdll/unix/msync.c
 new file mode 100644
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 00000000000..90e785f6df2
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 00000000000..2eef30dd0f2
</span> --- /dev/null
 +++ b/dlls/ntdll/unix/msync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -0,0 +1,1661 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -0,0 +1,1689 @@
</span> +/*
 + * mach semaphore-based synchronization objects
 + *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -412,7 +412,7 @@ index 00000000000..90e785f6df2
</span> +
 +static const mach_msg_bits_t msgh_bits_send = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static inline void server_register_wait( semaphore_t sem, unsigned int msgh_id,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static inline mach_msg_return_t server_register_wait( semaphore_t sem, unsigned int msgh_id,
</span> +                                         struct msync **wait_objs, const int count )
 +{
 +    int i, is_mutex;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -444,10 +444,11 @@ index 00000000000..90e785f6df2
</span> +
 +    if (mr != MACH_MSG_SUCCESS)
 +        ERR("Failed to send server register wait: %#x\n", mr);
<span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return mr;
</span> +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static inline void server_remove_wait( semaphore_t sem, unsigned int msgh_id,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                       struct msync **wait_objs, const int count )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static inline void server_remove_wait( unsigned int msgh_id, struct msync **wait_objs, const int count )
</span> +{
 +    int i;
 +    mach_msg_return_t mr;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -504,19 +505,19 @@ index 00000000000..90e785f6df2
</span> +}
 +
 +static inline NTSTATUS msync_wait_single( struct msync *wait_obj,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                          ULONGLONG *end )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                          ULONGLONG *end, int tid )
</span> +{
 +    int ret, val = 0;
 +    void *addr = wait_obj->shm;
 +    ULONGLONG ns_timeleft = 0;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    do 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    do
</span> +    {
 +        if (wait_obj->type == MSYNC_MUTEX)
 +        {
 +            val = __atomic_load_n( (int *)addr, __ATOMIC_ACQUIRE );
 +            if (!val || val == ~0)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                val = GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                val = tid;
</span> +        }
 +
 +        if (__atomic_load_n( (int *)addr, __ATOMIC_ACQUIRE ) != val)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -577,27 +578,51 @@ index 00000000000..90e785f6df2
</span> +}
 +
 +static NTSTATUS msync_wait_multiple( struct msync **wait_objs,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                                     int count, ULONGLONG *end )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                                     int count, ULONGLONG *end, int tid )
</span> +{
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    int tid;
</span> +    semaphore_t *sem;
 +    kern_return_t kr;
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    mach_msg_return_t mr;
</span> +    unsigned int msgh_id;
 +    __thread static struct msync *objs[MAXIMUM_WAIT_OBJECTS + 1];
 +
 +    count = resize_wait_objs( wait_objs, objs, count );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    if (count == 1 && __ulock_wait2) return msync_wait_single( objs[0], end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (count == 1 && __ulock_wait2) return msync_wait_single( objs[0], end, tid );
</span> +    if (!count) return destroyed_wait( end );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    tid = GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+
</span> +    if (check_shm_contention( objs, count, tid ))
 +        return STATUS_PENDING;
 +
 +    sem = semaphore_pool_alloc();
 +    msgh_id = (tid << 8) | count;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    mr = server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (mr != MACH_MSG_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        /* The os failed to send the mach message, which is either because
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * we lost the wineserver process or the semaphore from semaphore_pool_alloc
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * is not valid...
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * To avoid pooling in a dead port, recreate it here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++         * Worst case, this will behave effectively like a spinlock. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        semaphore_destroy( mach_task_self(), *sem) ;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        kr = semaphore_create( mach_task_self(), sem, SYNC_POLICY_FIFO, 0 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (kr != KERN_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            ERR("Cannot create semaphore: %#x %s\n", kr, mach_error_string(kr));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            semaphore_pool_free( sem );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            return STATUS_PENDING;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        mr = server_register_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (mr != MACH_MSG_SUCCESS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            semaphore_pool_free( sem );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            return STATUS_PENDING;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span> +
 +    do
 +    {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -613,7 +638,7 @@ index 00000000000..90e785f6df2
</span> +    if (is_destroyed( objs, count ))
 +        return destroyed_wait( end );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+    server_remove_wait( *sem, msgh_id, objs, count );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    server_remove_wait( msgh_id, objs, count );
</span> +
 +    switch (kr) {
 +        case KERN_SUCCESS:
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1220,7 +1245,7 @@ index 00000000000..90e785f6df2
</span> +    return STATUS_SUCCESS;
 +}
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+static NTSTATUS do_single_wait( struct msync *obj, ULONGLONG *end, BOOLEAN alertable )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static NTSTATUS do_single_wait( struct msync *obj, ULONGLONG *end, BOOLEAN alertable, int tid )
</span> +{
 +    NTSTATUS status;
 +    struct msync *wait_objs[2];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1241,14 +1266,14 @@ index 00000000000..90e785f6df2
</span> +
 +        wait_objs[1] = &apc_obj;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = msync_wait_multiple( wait_objs, 2, end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        status = msync_wait_multiple( wait_objs, 2, end, tid );
</span> +
 +        if (__atomic_load_n( apc_addr, __ATOMIC_SEQ_CST ))
 +            return STATUS_USER_APC;
 +    }
 +    else
 +    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+        status = msync_wait_multiple( wait_objs, 1, end );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        status = msync_wait_multiple( wait_objs, 1, end, tid );
</span> +    }
 +    return status;
 +}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1258,6 +1283,7 @@ index 00000000000..90e785f6df2
</span> +{
 +    static const LARGE_INTEGER zero = {0};
 +
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    __thread static int current_tid = 0;
</span> +    __thread static struct msync *objs[MAXIMUM_WAIT_OBJECTS + 1];
 +    struct msync apc_obj;
 +    int has_msync = 0, has_server = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1268,6 +1294,8 @@ index 00000000000..90e785f6df2
</span> +    ULONGLONG end;
 +    int i, ret;
 +
<span style='display:block; white-space:pre;background:#e0ffe0;'>++    current_tid = current_tid ? current_tid : GetCurrentThreadId();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span> +    /* Grab the APC idx if we don't already have it. */
 +    if (alertable && !ntdll_get_thread_data()->msync_apc_addr)
 +    {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1386,7 +1414,7 @@ index 00000000000..90e785f6df2
</span> +                        struct mutex *mutex = obj->shm;
 +                        int tid;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        if (mutex->tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        if (mutex->tid == current_tid)
</span> +                        {
 +                            TRACE("Woken up by handle %p [%d].\n", handles[i], i);
 +                            mutex->count++;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1394,13 +1422,13 @@ index 00000000000..90e785f6df2
</span> +                        }
 +
 +                        tid = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        if (__atomic_compare_exchange_n(&mutex->tid, &tid, GetCurrentThreadId(), 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        if (__atomic_compare_exchange_n(&mutex->tid, &tid, current_tid, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span> +                        {
 +                            TRACE("Woken up by handle %p [%d].\n", handles[i], i);
 +                            mutex->count = 1;
 +                            return i;
 +                        }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        else if (tid == ~0 && __atomic_compare_exchange_n(&mutex->tid, &tid, GetCurrentThreadId(), 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        else if (tid == ~0 && __atomic_compare_exchange_n(&mutex->tid, &tid, current_tid, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
</span> +                        {
 +                            TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i);
 +                            mutex->count = 1;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1463,7 +1491,7 @@ index 00000000000..90e785f6df2
</span> +                return STATUS_TIMEOUT;
 +            }
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+            ret = msync_wait_multiple( objs, waitcount, timeout ? &end : NULL );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            ret = msync_wait_multiple( objs, waitcount, timeout ? &end : NULL, current_tid );
</span> +
 +            if (ret == STATUS_TIMEOUT)
 +            {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1514,12 +1542,12 @@ index 00000000000..90e785f6df2
</span> +                {
 +                    struct mutex *mutex = obj->shm;
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (mutex->tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (mutex->tid == current_tid)
</span> +                        continue;
 +
 +                    while (__atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST ))
 +                    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        status = do_single_wait( obj, timeout ? &end : NULL, alertable );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        status = do_single_wait( obj, timeout ? &end : NULL, alertable, current_tid );
</span> +                        if (status != STATUS_PENDING)
 +                            break;
 +                    }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1531,7 +1559,7 @@ index 00000000000..90e785f6df2
</span> +
 +                    while (!__atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST ))
 +                    {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                        status = do_single_wait( obj, timeout ? &end : NULL, alertable );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                        status = do_single_wait( obj, timeout ? &end : NULL, alertable, current_tid );
</span> +                        if (status != STATUS_PENDING)
 +                            break;
 +                    }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1557,7 +1585,7 @@ index 00000000000..90e785f6df2
</span> +                    struct mutex *mutex = obj->shm;
 +                    int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST );
 +
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (tid && tid != ~0 && tid != GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (tid && tid != ~0 && tid != current_tid)
</span> +                        goto tryagain;
 +                }
 +                else if (obj)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1580,11 +1608,11 @@ index 00000000000..90e785f6df2
</span> +                {
 +                    struct mutex *mutex = obj->shm;
 +                    int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (tid == GetCurrentThreadId())
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (tid == current_tid)
</span> +                        break;
 +                    if (tid && tid != ~0)
 +                        goto tooslow;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-+                    if (__sync_val_compare_and_swap( &mutex->tid, tid, GetCurrentThreadId() ) != tid)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    if (__sync_val_compare_and_swap( &mutex->tid, tid, current_tid ) != tid)
</span> +                        goto tooslow;
 +                    if (tid == ~0)
 +                        abandoned = TRUE;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1835,7 +1863,7 @@ index 77aa995326c..f45db2f3090 100644
</span>          esync_close( handle );
  
 diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a52327841d2..4d4644f9c8c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index a52327841d2..3e3d2ea1fb4 100644
</span> --- a/dlls/ntdll/unix/sync.c
 +++ b/dlls/ntdll/unix/sync.c
 @@ -67,6 +67,7 @@
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1846,15 +1874,6 @@ index a52327841d2..4d4644f9c8c 100644
</span>  
  WINE_DEFAULT_DEBUG_CHANNEL(sync);
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -120,7 +121,7 @@ static inline int futex_wait( const LONG *addr, int val, struct timespec *timeou
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             long tv_nsec;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-         } timeout32 = { timeout->tv_sec, timeout->tv_nsec };
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--        return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE, val, &timeout32, 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+        return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE| futex_private, val, &timeout32, 0, 0 );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #endif
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     return syscall( __NR_futex, addr, FUTEX_WAIT_PRIVATE, val, timeout, 0, 0 );
</span> @@ -320,6 +321,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
      if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
      if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2046,7 +2065,7 @@ index a52327841d2..4d4644f9c8c 100644
</span>      if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE)  /* sleep forever */
      {
 diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 791b7b88c62..dc194eb09ac 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 0f92988d9d5..8f62d380cc4 100644
</span> --- a/dlls/ntdll/unix/unix_private.h
 +++ b/dlls/ntdll/unix/unix_private.h
 @@ -104,6 +104,8 @@ struct ntdll_thread_data
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2059,10 +2078,10 @@ index 791b7b88c62..dc194eb09ac 100644
</span>      int                reply_fd;      /* fd for receiving server replies */
      int                wait_fd[2];    /* fd for sleeping server requests */
 diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index efccfac76d0..8247b82852d 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 75088a2036d..8f55f14ca66 100644
</span> --- a/dlls/ntdll/unix/virtual.c
 +++ b/dlls/ntdll/unix/virtual.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3737,6 +3737,8 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3700,6 +3700,8 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
</span>      teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
      thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
      thread_data->esync_apc_fd = -1;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2072,10 +2091,10 @@ index efccfac76d0..8247b82852d 100644
</span>      thread_data->reply_fd   = -1;
      thread_data->wait_fd[0] = -1;
 diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index d3399268d00..c38120548ab 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 44f18710766..e6610d3cab5 100644
</span> --- a/include/wine/server_protocol.h
 +++ b/include/wine/server_protocol.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -5828,6 +5828,92 @@ struct get_esync_apc_fd_reply
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -5830,6 +5830,92 @@ struct get_esync_apc_fd_reply
</span>      struct reply_header __header;
  };
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2168,7 +2187,7 @@ index d3399268d00..c38120548ab 100644
</span>  
  enum request
  {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6123,6 +6209,11 @@ enum request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6125,6 +6211,11 @@ enum request
</span>      REQ_esync_msgwait,
      REQ_set_keyboard_repeat,
      REQ_get_esync_apc_fd,
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2180,7 +2199,7 @@ index d3399268d00..c38120548ab 100644
</span>      REQ_NB_REQUESTS
  };
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6422,6 +6513,11 @@ union generic_request
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6424,6 +6515,11 @@ union generic_request
</span>      struct esync_msgwait_request esync_msgwait_request;
      struct set_keyboard_repeat_request set_keyboard_repeat_request;
      struct get_esync_apc_fd_request get_esync_apc_fd_request;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2192,7 +2211,7 @@ index d3399268d00..c38120548ab 100644
</span>  };
  union generic_reply
  {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -6719,11 +6815,16 @@ union generic_reply
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6721,11 +6817,16 @@ union generic_reply
</span>      struct esync_msgwait_reply esync_msgwait_reply;
      struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
      struct get_esync_apc_fd_reply get_esync_apc_fd_reply;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2205,8 +2224,8 @@ index d3399268d00..c38120548ab 100644
</span>  
  /* ### protocol_version begin ### */
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>--#define SERVER_PROTOCOL_VERSION 837
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-+#define SERVER_PROTOCOL_VERSION 838
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define SERVER_PROTOCOL_VERSION 838
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define SERVER_PROTOCOL_VERSION 839
</span>  
  /* ### protocol_version end ### */
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2223,7 +2242,7 @@ index 87103cb2002..85b7b8f6693 100644
</span>   hook.c \
        mach.c \
 diff --git a/server/async.c b/server/async.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index b0f9fe42ad1..b7270394579 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index bea720b1f19..2dff610f4bd 100644
</span> --- a/server/async.c
 +++ b/server/async.c
 @@ -78,6 +78,7 @@ static const struct object_ops async_ops =
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2920,10 +2939,10 @@ index ab4d0e9dd31..0bbdcc5aa88 100644
</span>      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
 diff --git a/server/mailslot.c b/server/mailslot.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 4cf9b73f784..d04fc2f4edc 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index a8258328364..6301cdf06c1 100644
</span> --- a/server/mailslot.c
 +++ b/server/mailslot.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -75,6 +75,7 @@ static const struct object_ops mailslot_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -82,6 +82,7 @@ static const struct object_ops mailslot_ops =
</span>      remove_queue,              /* remove_queue */
      default_fd_signaled,       /* signaled */
      NULL,                      /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2931,7 +2950,7 @@ index 4cf9b73f784..d04fc2f4edc 100644
</span>      no_satisfied,              /* satisfied */
      no_signal,                 /* signal */
      mailslot_get_fd,           /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -135,6 +136,7 @@ static const struct object_ops mail_writer_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -144,6 +145,7 @@ static const struct object_ops mail_writer_ops =
</span>      NULL,                       /* remove_queue */
      NULL,                       /* signaled */
      NULL,                       /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2939,7 +2958,7 @@ index 4cf9b73f784..d04fc2f4edc 100644
</span>      NULL,                       /* satisfied */
      no_signal,                  /* signal */
      mail_writer_get_fd,         /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -199,6 +201,7 @@ static const struct object_ops mailslot_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -210,6 +212,7 @@ static const struct object_ops mailslot_device_ops =
</span>      NULL,                           /* remove_queue */
      NULL,                           /* signaled */
      NULL,                           /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2947,7 +2966,7 @@ index 4cf9b73f784..d04fc2f4edc 100644
</span>      no_satisfied,                   /* satisfied */
      no_signal,                      /* signal */
      no_get_fd,                      /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -230,6 +233,7 @@ static const struct object_ops mailslot_device_file_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -241,6 +244,7 @@ static const struct object_ops mailslot_device_file_ops =
</span>      remove_queue,                           /* remove_queue */
      default_fd_signaled,                    /* signaled */
      NULL,                                   /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4064,7 +4083,7 @@ index 4785a830e92..6a60adee0bd 100644
</span>      mutex_signal,              /* signal */
      no_get_fd,                 /* get_fd */
 diff --git a/server/named_pipe.c b/server/named_pipe.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a90ec606226..d8d17fa95f7 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 8ba8126563a..6396ea532b0 100644
</span> --- a/server/named_pipe.c
 +++ b/server/named_pipe.c
 @@ -120,6 +120,7 @@ static const struct object_ops named_pipe_ops =
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4217,10 +4236,10 @@ index bedd8bb4586..24276142a63 100644
</span>  
  /* process functions */
 diff --git a/server/protocol.def b/server/protocol.def
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 1e4171c56ef..7ad9129f5d4 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 47c76c17c5b..5475a51639d 100644
</span> --- a/server/protocol.def
 +++ b/server/protocol.def
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -4022,3 +4022,57 @@ enum esync_type
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -4023,3 +4023,57 @@ enum esync_type
</span>  /* Retrieve the fd to wait on for user APCs. */
  @REQ(get_esync_apc_fd)
  @END
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4279,7 +4298,7 @@ index 1e4171c56ef..7ad9129f5d4 100644
</span> +    unsigned int shm_idx;
 +@END
 diff --git a/server/queue.c b/server/queue.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 109610b3d31..2c1f8053102 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index ef4283e27df..c6dd91f8d4a 100644
</span> --- a/server/queue.c
 +++ b/server/queue.c
 @@ -45,6 +45,7 @@
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4290,7 +4309,7 @@ index 109610b3d31..2c1f8053102 100644
</span>  
  #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
  #define WM_NCMOUSELAST  (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -139,6 +140,8 @@ struct msg_queue
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -137,6 +138,8 @@ struct msg_queue
</span>      unsigned int           ignore_post_msg; /* ignore post messages newer than this unique id */
      int                    esync_fd;        /* esync file descriptor (signalled on message) */
      int                    esync_in_msgwait; /* our thread is currently waiting on us */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4299,7 +4318,7 @@ index 109610b3d31..2c1f8053102 100644
</span>  };
  
  struct hotkey
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -156,6 +159,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -154,6 +157,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
</span>  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 int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4307,7 +4326,7 @@ index 109610b3d31..2c1f8053102 100644
</span>  static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry );
  static void msg_queue_destroy( struct object *obj );
  static void msg_queue_poll_event( struct fd *fd, int event );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -172,6 +176,7 @@ static const struct object_ops msg_queue_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -170,6 +174,7 @@ static const struct object_ops msg_queue_ops =
</span>      msg_queue_remove_queue,    /* remove_queue */
      msg_queue_signaled,        /* signaled */
      msg_queue_get_esync_fd,    /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4315,7 +4334,7 @@ index 109610b3d31..2c1f8053102 100644
</span>      msg_queue_satisfied,       /* satisfied */
      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -210,6 +215,7 @@ static const struct object_ops thread_input_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -208,6 +213,7 @@ static const struct object_ops thread_input_ops =
</span>      NULL,                         /* remove_queue */
      NULL,                         /* signaled */
      NULL,                         /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4323,7 +4342,7 @@ index 109610b3d31..2c1f8053102 100644
</span>      NULL,                         /* satisfied */
      no_signal,                    /* signal */
      no_get_fd,                    /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -324,6 +330,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -322,6 +328,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span>          queue->ignore_post_msg = 0;
          queue->esync_fd        = -1;
          queue->esync_in_msgwait = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4332,7 +4351,7 @@ index 109610b3d31..2c1f8053102 100644
</span>          list_init( &queue->send_result );
          list_init( &queue->callback_result );
          list_init( &queue->pending_timers );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -349,6 +357,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -347,6 +355,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
</span>          if (do_esync())
              queue->esync_fd = esync_create_fd( 0, 0 );
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4342,7 +4361,7 @@ index 109610b3d31..2c1f8053102 100644
</span>          thread->queue = queue;
  
          if ((desktop = get_thread_desktop( thread, 0 )))
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -737,6 +748,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -754,6 +765,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
</span>          queue->keystate_lock = 0;
      }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4352,7 +4371,7 @@ index 109610b3d31..2c1f8053102 100644
</span>      if (do_esync() && !is_signaled( queue ))
          esync_clear( queue->esync_fd );
  }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1228,6 +1242,9 @@ static int is_queue_hung( struct msg_queue *queue )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1245,6 +1259,9 @@ static int is_queue_hung( struct msg_queue *queue )
</span>              return 0;  /* thread is waiting on queue -> not hung */
      }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4362,7 +4381,7 @@ index 109610b3d31..2c1f8053102 100644
</span>      if (do_esync() && queue->esync_in_msgwait)
          return 0;   /* thread is waiting on queue in absentia -> not hung */
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1292,6 +1309,13 @@ static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1309,6 +1326,13 @@ static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type )
</span>      return queue->esync_fd;
  }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4376,7 +4395,7 @@ index 109610b3d31..2c1f8053102 100644
</span>  static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry )
  {
      struct msg_queue *queue = (struct msg_queue *)obj;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -1349,6 +1373,8 @@ static void msg_queue_destroy( struct object *obj )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1366,6 +1390,8 @@ static void msg_queue_destroy( struct object *obj )
</span>      if (queue->fd) release_object( queue->fd );
      if (queue->shared) free_shared_object( queue->shared );
      if (do_esync()) close( queue->esync_fd );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4385,16 +4404,17 @@ index 109610b3d31..2c1f8053102 100644
</span>  }
  
  static void msg_queue_poll_event( struct fd *fd, int event )
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3121,6 +3147,8 @@ DECL_HANDLER(set_queue_mask)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-             }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3152,6 +3178,9 @@ DECL_HANDLER(set_queue_mask)
</span>              else wake_up( &queue->obj, 0 );
          }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span> +        if (do_msync() && !is_signaled( queue ))
 +            msync_clear( &queue->obj );
<span style='display:block; white-space:pre;background:#ffe0e0;'>- 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span>          if (do_esync() && !is_signaled( queue ))
              esync_clear( queue->esync_fd );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3145,6 +3173,9 @@ DECL_HANDLER(get_queue_status)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3175,6 +3204,9 @@ DECL_HANDLER(get_queue_status)
</span>          }
          SHARED_WRITE_END;
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4404,7 +4424,7 @@ index 109610b3d31..2c1f8053102 100644
</span>          if (do_esync() && !is_signaled( queue ))
              esync_clear( queue->esync_fd );
      }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3416,6 +3447,9 @@ DECL_HANDLER(get_message)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3446,6 +3478,9 @@ DECL_HANDLER(get_message)
</span>  
      set_error( STATUS_PENDING );  /* FIXME */
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4414,7 +4434,7 @@ index 109610b3d31..2c1f8053102 100644
</span>      if (do_esync() && !is_signaled( queue ))
          esync_clear( queue->esync_fd );
  
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -4220,6 +4254,23 @@ DECL_HANDLER(esync_msgwait)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -4248,6 +4283,23 @@ DECL_HANDLER(esync_msgwait)
</span>          set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 );
  }
  
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4463,7 +4483,7 @@ index 8e7d88a0d4c..3287b16170d 100644
</span>      no_signal,                     /* signal */
      no_get_fd,                     /* get_fd */
 diff --git a/server/request.h b/server/request.h
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index a68983ef6dc..32fd61d7903 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index b8a3f24f521..a73b9bdd2f3 100644
</span> --- a/server/request.h
 +++ b/server/request.h
 @@ -411,6 +411,11 @@ DECL_HANDLER(get_esync_fd);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4490,7 +4510,7 @@ index a68983ef6dc..32fd61d7903 100644
</span>  };
  
  C_ASSERT( sizeof(abstime_t) == 8 );
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -2386,6 +2396,34 @@ C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2387,6 +2397,34 @@ C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 );
</span>  C_ASSERT( FIELD_OFFSET(struct set_keyboard_repeat_reply, enable) == 8 );
  C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 );
  C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 );
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4562,7 +4582,7 @@ index 55cd6aa037e..e86ad49df8e 100644
</span>      no_signal,                /* signal */
      no_get_fd,                /* get_fd */
 diff --git a/server/sock.c b/server/sock.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 7be912b3b50..af92f134538 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 3110a125add..3b6fb723548 100644
</span> --- a/server/sock.c
 +++ b/server/sock.c
 @@ -454,6 +454,7 @@ static const struct object_ops sock_ops =
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4573,7 +4593,7 @@ index 7be912b3b50..af92f134538 100644
</span>      no_satisfied,                 /* satisfied */
      no_signal,                    /* signal */
      sock_get_fd,                  /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3562,6 +3563,7 @@ static const struct object_ops ifchange_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3564,6 +3565,7 @@ static const struct object_ops ifchange_ops =
</span>      NULL,                    /* remove_queue */
      NULL,                    /* signaled */
      NULL,                    /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4581,7 +4601,7 @@ index 7be912b3b50..af92f134538 100644
</span>      no_satisfied,            /* satisfied */
      no_signal,               /* signal */
      ifchange_get_fd,         /* get_fd */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-@@ -3784,6 +3786,7 @@ static const struct object_ops socket_device_ops =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3786,6 +3788,7 @@ static const struct object_ops socket_device_ops =
</span>      NULL,                       /* remove_queue */
      NULL,                       /* signaled */
      NULL,                       /* get_esync_fd */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4844,7 +4864,7 @@ index e40ba10f9aa..1101c7224b9 100644
</span>      no_signal,                 /* signal */
      no_get_fd,                 /* get_fd */
 diff --git a/server/trace.c b/server/trace.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 89e9c0b3aa1..f692e86a878 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index fd224685bfb..0d7eac7dc60 100644
</span> --- a/server/trace.c
 +++ b/server/trace.c
 @@ -4712,6 +4712,63 @@ static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4948,7 +4968,7 @@ index 89e9c0b3aa1..f692e86a878 100644
</span>  
  static const struct
 diff --git a/server/window.c b/server/window.c
<span style='display:block; white-space:pre;background:#ffe0e0;'>-index 13318b75fe2..85ee8d8f9b2 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 7e8055bac4a..f91794e278f 100644
</span> --- a/server/window.c
 +++ b/server/window.c
 @@ -107,6 +107,7 @@ static const struct object_ops window_ops =
</pre><pre style='margin:0'>

</pre>