From 975bc35af94f7387798fb491b7cda245ae4423ab Mon Sep 17 00:00:00 2001 From: Kirill Artemev Date: Tue, 24 Dec 2024 00:06:24 +0500 Subject: [PATCH] Revert "ntsync5: Implement ntsync7 support and revert ntsync5 to v6 version (#1345)" (#1346) Now ntsync5 v7 avalable in ntsync-dkms from AUR This reverts commit 41f7e2477bb25179439698fa86613408ba9afed0. --- wine-tkg-git/customization.cfg | 1 - .../wine-tkg-patches/misc/fastsync/fastsync | 18 +- .../misc/fastsync/ntsync5-mainline.patch | 2309 ++--- .../misc/fastsync/ntsync5-protonify.patch | 2309 ++--- .../fastsync/ntsync5-staging-protonify.patch | 1470 ++- .../misc/fastsync/ntsync5-staging.patch | 1533 ++- .../misc/fastsync/ntsync7-mainline.patch | 4447 --------- .../misc/fastsync/ntsync7-protonify.patch | 4447 --------- .../fastsync/ntsync7-staging-protonify.patch | 8376 ----------------- .../misc/fastsync/ntsync7-staging.patch | 8364 ---------------- wine-tkg-git/wine-tkg-scripts/prepare.sh | 4 +- 11 files changed, 3789 insertions(+), 29489 deletions(-) delete mode 100644 wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-mainline.patch delete mode 100644 wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-protonify.patch delete mode 100644 wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging-protonify.patch delete mode 100644 wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging.patch diff --git a/wine-tkg-git/customization.cfg b/wine-tkg-git/customization.cfg index 8db99a648..e8025bf1d 100644 --- a/wine-tkg-git/customization.cfg +++ b/wine-tkg-git/customization.cfg @@ -70,7 +70,6 @@ _use_fastsync="false" # !! (Arch: see the three packages https://aur.archlinux.org/pkgbase/ntsync for both module and header) !! # !! Not compatible with _use_esync, _use_fsync or _use_fastsync options !! # !! Not compatible with Valve trees !! -# Set to ntsync7 when using ntsync5 v7 kernel driver (Available in linux-cachyos 6.12.6) _use_ntsync="false" # esync - Enable with WINEESYNC=1 envvar - Set to true to enable esync support on plain wine or wine-staging <4.6 (it got merged in wine-staging 4.6). The option is ignored on wine-staging 4.6+ diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/fastsync b/wine-tkg-git/wine-tkg-patches/misc/fastsync/fastsync index ec93b1c35..72a4a5e91 100644 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/fastsync +++ b/wine-tkg-git/wine-tkg-patches/misc/fastsync/fastsync @@ -72,7 +72,7 @@ _patchname='fastsync-clock_monotonic-fixup.patch' && _patchmsg="Applied fastsync fix due clock_monotonic" && nonuser_patcher fi - elif [ "$_use_ntsync" = "true" ] || [ "$_use_ntsync" = "ntsync7" ]; then + elif [ "$_use_ntsync" = "true" ]; then # check Linux headers ntsync_header_check=$(echo '#include ' | gcc -H -E -fsyntax-only - 2>&1 | head -n1 | cut -d' ' -f2-) @@ -101,9 +101,7 @@ _patchname='ntsync-config.h.in-alt.patch' && _patchmsg="Using alternative config.h.in patchset for ntsync5" && nonuser_patcher fi if [ "$_protonify" = "true" ]; then - if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ) && [ "$_use_ntsync" = "ntsync7" ]; then - _patchname='ntsync7-staging-protonify.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher - elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then + if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then _patchname='ntsync5-staging-protonify.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor ac1ff67cfda77618ac05c2c8c38dedc991809316 HEAD ); then _patchname='ntsync5-staging-protonify-e24ba584.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher @@ -127,9 +125,7 @@ _patchname='ntsync5-staging-protonify-7eb72b7b.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher fi else - if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ) && [ "$_use_ntsync" = "ntsync7" ]; then - _patchname='ntsync7-staging.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher - elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then + if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then _patchname='ntsync5-staging.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor ac1ff67cfda77618ac05c2c8c38dedc991809316 HEAD ); then _patchname='ntsync5-staging-e24ba584.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher @@ -155,9 +151,7 @@ fi else if [ "$_protonify" = "true" ]; then - if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ) && [ "$_use_ntsync" = "ntsync7" ]; then - _patchname='ntsync7-protonify.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher - elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then + if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then _patchname='ntsync5-protonify.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor ac1ff67cfda77618ac05c2c8c38dedc991809316 HEAD ); then _patchname='ntsync5-protonify-e24ba584.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher @@ -177,9 +171,7 @@ _patchname='ntsync5-protonify-7eb72b7b.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher fi else - if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ) && [ "$_use_ntsync" = "ntsync7" ]; then - _patchname='ntsync7-mainline.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher - elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then + if ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor e24ba5849843bbef2ca038c12b5bb1b5ff0af8be HEAD ); then _patchname='ntsync5-mainline.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher elif ( cd "${srcdir}"/"${_winesrcdir}" && git merge-base --is-ancestor ac1ff67cfda77618ac05c2c8c38dedc991809316 HEAD ); then _patchname='ntsync5-mainline-e24ba584.patch' && _patchmsg="Using ntsync patchset" && nonuser_patcher diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-mainline.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-mainline.patch index b395c4e64..8fb2b81dc 100644 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-mainline.patch +++ b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-mainline.patch @@ -1,8 +1,73 @@ +From 0b446d37ae366bf9921bc7f99f313ffe1a7530b2 Mon Sep 17 00:00:00 2001 +From: Kirill Artemev +Date: Fri, 20 Dec 2024 21:54:47 +0500 +Subject: [PATCH] ntsync7-mainline + +Signed-off-by: Kirill Artemev +--- + configure | 6 + + configure.ac | 1 + + dlls/kernel32/tests/sync.c | 79 +++ + dlls/ntdll/unix/file.c | 2 +- + dlls/ntdll/unix/process.c | 2 +- + dlls/ntdll/unix/server.c | 28 +- + dlls/ntdll/unix/sync.c | 1007 +++++++++++++++++++++++++++++- + dlls/ntdll/unix/thread.c | 2 +- + dlls/ntdll/unix/unix_private.h | 9 +- + dlls/ntdll/unix/virtual.c | 1 + + dlls/webservices/tests/channel.c | 3 + + include/config.h.in | 3 + + include/wine/server_protocol.h | 97 ++- + server/Makefile.in | 1 + + server/async.c | 2 + + server/atom.c | 1 + + server/change.c | 1 + + server/clipboard.c | 1 + + server/completion.c | 25 +- + server/console.c | 85 ++- + server/debugger.c | 23 + + server/device.c | 33 +- + server/directory.c | 2 + + server/event.c | 53 +- + server/fd.c | 31 +- + server/file.c | 1 + + server/file.h | 1 + + server/handle.c | 1 + + server/hook.c | 1 + + server/inproc_sync.c | 437 +++++++++++++ + server/mailslot.c | 4 + + server/mapping.c | 3 + + server/mutex.c | 39 +- + server/named_pipe.c | 6 + + server/object.c | 8 + + server/object.h | 14 + + server/process.c | 34 + + server/process.h | 1 + + server/protocol.def | 47 ++ + server/queue.c | 88 ++- + server/registry.c | 1 + + server/request.c | 1 + + server/request_handlers.h | 25 + + server/request_trace.h | 54 ++ + server/semaphore.c | 24 +- + server/serial.c | 1 + + server/signal.c | 1 + + server/sock.c | 3 + + server/symlink.c | 1 + + server/thread.c | 38 ++ + server/thread.h | 2 + + server/timer.c | 38 +- + server/token.c | 1 + + server/window.c | 1 + + server/winstation.c | 2 + + 55 files changed, 2343 insertions(+), 33 deletions(-) + create mode 100644 server/inproc_sync.c + diff --git a/configure b/configure -index 0468aea..f8142f8 100755 +index beba1346b6a..da17410a661 100755 --- a/configure +++ b/configure -@@ -7979,6 +7979,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes +@@ -7734,6 +7734,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h @@ -16,7 +81,7 @@ index 0468aea..f8142f8 100755 ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" if test "x$ac_cv_header_linux_param_h" = xyes diff --git a/configure.ac b/configure.ac -index 31c2fa2..e064df8 100644 +index 6596f653fb1..c3f925a55a5 100644 --- a/configure.ac +++ b/configure.ac @@ -383,6 +383,7 @@ AC_CHECK_HEADERS(\ @@ -28,10 +93,10 @@ index 31c2fa2..e064df8 100644 linux/serial.h \ linux/types.h \ diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index c06ced4..c5d2713 100644 +index 49420e4519f..2c69073db10 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c -@@ -2871,6 +2871,84 @@ static void test_QueueUserAPC(void) +@@ -2904,6 +2904,84 @@ static void test_QueueUserAPC(void) ok(apc_count == 1, "APC count %u\n", apc_count); } @@ -116,7 +181,7 @@ index c06ced4..c5d2713 100644 START_TEST(sync) { char **argv; -@@ -2941,5 +3019,6 @@ START_TEST(sync) +@@ -2974,5 +3052,6 @@ START_TEST(sync) test_srwlock_example(); test_alertable_wait(); test_apc_deadlock(); @@ -124,10 +189,10 @@ index c06ced4..c5d2713 100644 test_crit_section(); } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index d292d93..17e7266 100644 +index 8bc69557057..755a6e844a4 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6372,7 +6372,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void +@@ -6451,7 +6451,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void } if (handle) { @@ -137,10 +202,10 @@ index d292d93..17e7266 100644 } else /* Unix lock conflict, sleep a bit and retry */ diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index cc2d820..8ee2afe 100644 +index c3a730379a4..db4d096acd1 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c -@@ -922,7 +922,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ +@@ -920,7 +920,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ /* wait for the new process info to be ready */ @@ -150,7 +215,7 @@ index cc2d820..8ee2afe 100644 { req->info = wine_server_obj_handle( process_info ); diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index f3ffd99..6e0ecf9 100644 +index b40e7c2a1d7..3579e4f454d 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */ @@ -162,7 +227,7 @@ index f3ffd99..6e0ecf9 100644 /* atomically exchange a 64-bit value */ static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val ) -@@ -789,6 +789,21 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f +@@ -789,6 +789,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI } @@ -184,7 +249,7 @@ index f3ffd99..6e0ecf9 100644 /*********************************************************************** * NtContinue (NTDLL.@) */ -@@ -850,7 +865,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a +@@ -865,7 +880,7 @@ unsigned int server_queue_process_apc( HANDLE process, const union apc_call *cal } else { @@ -193,7 +258,7 @@ index f3ffd99..6e0ecf9 100644 SERVER_START_REQ( get_apc_result ) { -@@ -1753,12 +1768,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE +@@ -1793,12 +1808,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE return result.dup_handle.status; } @@ -206,12 +271,12 @@ index f3ffd99..6e0ecf9 100644 if (options & DUPLICATE_CLOSE_SOURCE) + { fd = remove_fd_from_cache( source ); -+ close_fast_sync_obj( source ); ++ close_inproc_sync_obj( source ); + } SERVER_START_REQ( dup_handle ) { -@@ -1824,12 +1844,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) +@@ -1864,12 +1884,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) return STATUS_SUCCESS; @@ -223,13 +288,13 @@ index f3ffd99..6e0ecf9 100644 * retrieve it again */ fd = remove_fd_from_cache( handle ); -+ close_fast_sync_obj( handle ); ++ close_inproc_sync_obj( handle ); + SERVER_START_REQ( close_handle ) { req->handle = wine_server_obj_handle( handle ); diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index e070233..6e7fd4e 100644 +index d486b50001d..c3203debc0b 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -30,9 +30,11 @@ @@ -275,7 +340,7 @@ index e070233..6e7fd4e 100644 /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { -@@ -241,6 +249,902 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at +@@ -301,6 +309,901 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at } @@ -283,44 +348,44 @@ index e070233..6e7fd4e 100644 + +static int get_linux_sync_device(void) +{ -+ static LONG fast_sync_fd = -2; ++ static LONG device = -2; + -+ if (fast_sync_fd == -2) ++ if (device == -2) + { -+ HANDLE device; ++ HANDLE handle; + int fd, needs_close; + NTSTATUS ret; + + SERVER_START_REQ( get_linux_sync_device ) + { -+ if (!(ret = wine_server_call( req ))) device = wine_server_ptr_handle( reply->handle ); ++ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + if (!ret) + { -+ if (!server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )) ++ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) + { -+ if (InterlockedCompareExchange( &fast_sync_fd, fd, -2 ) != -2) ++ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) + { + /* someone beat us to it */ + if (needs_close) close( fd ); -+ NtClose( device ); ++ NtClose( handle ); + } + /* otherwise don't close the device */ + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); -+ NtClose( device ); ++ InterlockedCompareExchange( &device, -1, -2 ); ++ NtClose( handle ); + } + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); ++ InterlockedCompareExchange( &device, -1, -2 ); + } + } -+ return fast_sync_fd; ++ return device; +} + +/* It's possible for synchronization primitives to remain alive even after being @@ -328,10 +393,10 @@ index e070233..6e7fd4e 100644 + * documented as being undefined behaviour by Microsoft, but it works, and some + * applications rely on it. This means we need to refcount handles, and defer + * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the fast synchronization ++ * by having each client process hold a handle to the in-process synchronization + * object, as well as a private refcount. When the client refcount reaches zero, + * it closes the handle; when all handles are closed, the server deletes the -+ * fast synchronization object. ++ * in-process synchronization object. + * + * We also need this for signal-and-wait. The signal and wait operations aren't + * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE @@ -357,20 +422,20 @@ index e070233..6e7fd4e 100644 + * the same handle immediately reallocated to a different object. This should be + * a very rare situation, and in that case we simply don't cache the handle. + */ -+struct fast_sync_cache_entry ++struct inproc_sync_cache_entry +{ + LONG refcount; + int fd; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + unsigned int access; + BOOL closed; -+ /* handle to the underlying fast sync object, stored as obj_handle_t to save -+ * space */ ++ /* handle to the underlying in-process sync object, stored as obj_handle_t ++ * to save space */ + obj_handle_t handle; +}; + + -+static void release_fast_sync_obj( struct fast_sync_cache_entry *cache ) ++static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) +{ + /* save the handle and fd now; as soon as the refcount hits 0 we cannot + * access the cache anymore */ @@ -398,52 +463,52 @@ index e070233..6e7fd4e 100644 +} + + -+#define FAST_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct fast_sync_cache_entry)) -+#define FAST_SYNC_CACHE_ENTRIES 128 ++#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) ++#define INPROC_SYNC_CACHE_ENTRIES 128 + -+static struct fast_sync_cache_entry *fast_sync_cache[FAST_SYNC_CACHE_ENTRIES]; -+static struct fast_sync_cache_entry fast_sync_cache_initial_block[FAST_SYNC_CACHE_BLOCK_SIZE]; ++static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; ++static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; + -+static inline unsigned int fast_sync_handle_to_index( HANDLE handle, unsigned int *entry ) ++static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) +{ + unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / FAST_SYNC_CACHE_BLOCK_SIZE; -+ return idx % FAST_SYNC_CACHE_BLOCK_SIZE; ++ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; ++ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; +} + + -+static struct fast_sync_cache_entry *cache_fast_sync_obj( HANDLE handle, obj_handle_t fast_sync, int fd, -+ enum fast_sync_type type, unsigned int access ) ++static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, ++ enum inproc_sync_type type, unsigned int access ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + sigset_t sigset; + int refcount; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES) + { + FIXME( "too many allocated handles, not caching %p\n", handle ); + return NULL; + } + -+ if (!fast_sync_cache[entry]) /* do we need to allocate a new block of entries? */ ++ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ + { -+ if (!entry) fast_sync_cache[0] = fast_sync_cache_initial_block; ++ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; + else + { -+ static const size_t size = FAST_SYNC_CACHE_BLOCK_SIZE * sizeof(struct fast_sync_cache_entry); ++ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); + void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); + if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&fast_sync_cache[entry], ptr, NULL )) ++ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) + munmap( ptr, size ); /* someone beat us to it */ + } + } + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same + * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_fast_sync_obj() and close_handle. */ ++ * being cached again between close_inproc_sync_obj() and close_handle. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) @@ -457,13 +522,13 @@ index e070233..6e7fd4e 100644 + return NULL; + } + -+ cache->handle = fast_sync; ++ cache->handle = inproc_sync; + cache->fd = fd; + cache->type = type; + cache->access = access; + cache->closed = FALSE; + /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_fast_sync_obj()]. ++ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. + * Set the refcount to 2 (one for the handle, one for the caller). */ + refcount = InterlockedExchange( &cache->refcount, 2 ); + assert( !refcount ); @@ -487,18 +552,18 @@ index e070233..6e7fd4e 100644 +} + + -+static struct fast_sync_cache_entry *get_cached_fast_sync_obj( HANDLE handle ) ++static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES || !fast_sync_cache[entry]) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) + return NULL; + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* this load needs acquire semantics [paired with the store in -+ * cache_fast_sync_obj()] */ ++ * cache_inproc_sync_obj()] */ + if (!interlocked_inc_if_nonzero( &cache->refcount )) + return NULL; + @@ -508,7 +573,7 @@ index e070233..6e7fd4e 100644 + * handle value might have been reused for another object in the + * meantime, in which case we have to report that valid object, so + * force the caller to check the server. */ -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return NULL; + } + @@ -516,30 +581,31 @@ index e070233..6e7fd4e 100644 +} + + -+static BOOL fast_sync_types_match( enum fast_sync_type a, enum fast_sync_type b ) ++static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) +{ + if (a == b) return TRUE; -+ if (a == FAST_SYNC_AUTO_EVENT && b == FAST_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == FAST_SYNC_AUTO_EVENT && a == FAST_SYNC_MANUAL_EVENT) return TRUE; ++ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; ++ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; + return FALSE; +} + + +/* returns a pointer to a cache entry; if the object could not be cached, + * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_fast_sync_obj( HANDLE handle, enum fast_sync_type desired_type, ACCESS_MASK desired_access, -+ struct fast_sync_cache_entry *stack_cache, -+ struct fast_sync_cache_entry **ret_cache ) ++static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, ++ ACCESS_MASK desired_access, ++ struct inproc_sync_cache_entry *stack_cache, ++ struct inproc_sync_cache_entry **ret_cache ) +{ -+ struct fast_sync_cache_entry *cache; -+ obj_handle_t fast_sync_handle; -+ enum fast_sync_type type; ++ struct inproc_sync_cache_entry *cache; ++ obj_handle_t inproc_sync_handle; ++ enum inproc_sync_type type; + unsigned int access; + int fd, needs_close; + NTSTATUS ret; + + /* try to find it in the cache already */ -+ if ((cache = get_cached_fast_sync_obj( handle ))) ++ if ((cache = get_cached_inproc_sync_obj( handle ))) + { + *ret_cache = cache; + return STATUS_SUCCESS; @@ -551,7 +617,7 @@ index e070233..6e7fd4e 100644 + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { -+ fast_sync_handle = reply->handle; ++ inproc_sync_handle = reply->handle; + access = reply->access; + type = reply->type; + } @@ -560,15 +626,15 @@ index e070233..6e7fd4e 100644 + + if (ret) return ret; + -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( fast_sync_handle ), ++ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), + 0, &fd, &needs_close, NULL, NULL ))) + return ret; + -+ cache = cache_fast_sync_obj( handle, fast_sync_handle, fd, type, access ); ++ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); + if (!cache) + { + cache = stack_cache; -+ cache->handle = fast_sync_handle; ++ cache->handle = inproc_sync_handle; + cache->fd = fd; + cache->type = type; + cache->access = access; @@ -578,15 +644,15 @@ index e070233..6e7fd4e 100644 + + *ret_cache = cache; + -+ if (desired_type && !fast_sync_types_match( cache->type, desired_type )) ++ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + + if ((cache->access & desired_access) != desired_access) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_ACCESS_DENIED; + } + @@ -595,16 +661,16 @@ index e070233..6e7fd4e 100644 + + +/* caller must hold fd_cache_mutex */ -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ -+ struct fast_sync_cache_entry *cache = get_cached_fast_sync_obj( handle ); ++ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); + + if (cache) + { + cache->closed = TRUE; + /* once for the reference we just grabbed, and once for the handle */ -+ release_fast_sync_obj( cache ); -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + } +} + @@ -613,7 +679,7 @@ index e070233..6e7fd4e 100644 +{ + NTSTATUS ret; + -+ ret = ioctl( obj, NTSYNC_IOC_SEM_POST, &count ); ++ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); + if (ret < 0) + { + if (errno == EOVERFLOW) @@ -626,18 +692,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -656,18 +722,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_semaphore_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -685,18 +751,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_set_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -714,18 +780,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_reset_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -743,23 +809,23 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_pulse_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + + -+static NTSTATUS linux_query_event_obj( int obj, enum fast_sync_type type, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) +{ + struct ntsync_event_args args = {0}; + NTSTATUS ret; @@ -767,24 +833,24 @@ index e070233..6e7fd4e 100644 + ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); + if (ret < 0) + return errno_to_status( errno ); -+ info->EventType = (type == FAST_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; ++ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; + info->EventState = args.signaled; + return STATUS_SUCCESS; +} + + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_event_obj( cache->fd, cache->type, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -811,17 +877,17 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, 0, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) + return ret; + + ret = linux_release_mutex_obj( cache->fd, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -852,71 +918,69 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, ++ &stack_cache, &cache ))) + return ret; + + ret = linux_query_mutex_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + -+static void select_queue( HANDLE queue ) ++static void select_queue(void) +{ -+ SERVER_START_REQ( fast_select_queue ) ++ SERVER_START_REQ( select_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static void unselect_queue( HANDLE queue, BOOL signaled ) ++static void unselect_queue( BOOL signaled ) +{ -+ SERVER_START_REQ( fast_unselect_queue ) ++ SERVER_START_REQ( unselect_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + req->signaled = signaled; + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static int get_fast_alert_obj(void) ++static int get_inproc_alert_obj(void) +{ + struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + HANDLE alert_handle; + unsigned int ret; + -+ if (!data->fast_alert_obj) ++ if (data->linux_alert_obj == -1) + { -+ SERVER_START_REQ( get_fast_alert_event ) ++ SERVER_START_REQ( get_inproc_alert_event ) + { + if ((ret = wine_server_call( req ))) -+ ERR( "failed to get fast alert event, status %#x\n", ret ); ++ ERR( "failed to get inproc alert event, status %#x\n", ret ); + alert_handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + -+ if ((ret = get_fast_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get fast alert obj, status %#x\n", ret ); -+ data->fast_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_fast_sync_obj() won't close it. ++ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) ++ ERR( "failed to get inproc alert obj, status %#x\n", ret ); ++ data->linux_alert_obj = cache->fd; ++ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. + * Manhandling the cache entry here is fine since we're the only thread + * that can access our own alert event. */ + cache->fd = -1; -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + NtClose( alert_handle ); + } + -+ return data->fast_alert_obj; ++ return data->linux_alert_obj; +} + +static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, @@ -948,7 +1012,7 @@ index e070233..6e7fd4e 100644 + args.index = ~0u; + + if (alertable) -+ args.alert = get_fast_alert_obj(); ++ args.alert = get_inproc_alert_obj(); + + if (wait_any || count == 1) + request = NTSYNC_IOC_WAIT_ANY; @@ -981,10 +1045,10 @@ index e070233..6e7fd4e 100644 + return errno_to_status( errno ); +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry stack_cache[64], *cache[64]; ++ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; + int device, objs[64]; + HANDLE queue = NULL; + NTSTATUS ret; @@ -995,13 +1059,13 @@ index e070233..6e7fd4e 100644 + + for (i = 0; i < count; ++i) + { -+ if ((ret = get_fast_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) ++ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) + { + for (j = 0; j < i; ++j) -+ release_fast_sync_obj( cache[j] ); ++ release_inproc_sync_obj( cache[j] ); + return ret; + } -+ if (cache[i]->type == FAST_SYNC_QUEUE) ++ if (cache[i]->type == INPROC_SYNC_QUEUE) + queue = handles[i]; + + objs[i] = cache[i]->fd; @@ -1009,32 +1073,32 @@ index e070233..6e7fd4e 100644 + + /* It's common to wait on the message queue alone. Some applications wait + * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through fast_wait_objs(), and since we only -+ * need to go through that path if we're waiting on other objects, just -+ * delegate to the server if we're only waiting on the message queue. */ ++ * instead of one when going through inproc_wait(), and since we only need ++ * to go through that path if we're waiting on other objects, just delegate ++ * to the server if we're only waiting on the message queue. */ + if (count == 1 && queue) + { -+ release_fast_sync_obj( cache[0] ); ++ release_inproc_sync_obj( cache[0] ); + return server_wait_for_object( handles[0], alertable, timeout ); + } + -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + + ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); + -+ if (queue) unselect_queue( queue, handles[ret] == queue ); ++ if (queue) unselect_queue( handles[ret] == queue ); + + for (i = 0; i < count; ++i) -+ release_fast_sync_obj( cache[i] ); ++ release_inproc_sync_obj( cache[i] ); + + return ret; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct fast_sync_cache_entry wait_stack_cache, *wait_cache; ++ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; ++ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; + HANDLE queue = NULL; + NTSTATUS ret; + int device; @@ -1042,58 +1106,58 @@ index e070233..6e7fd4e 100644 + if ((device = get_linux_sync_device()) < 0) + return STATUS_NOT_IMPLEMENTED; + -+ if ((ret = get_fast_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) ++ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) + return ret; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + if (!(signal_cache->access & EVENT_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + break; + + default: + /* can't be signaled */ -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + -+ if ((ret = get_fast_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) ++ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return ret; + } + -+ if (wait_cache->type == FAST_SYNC_QUEUE) ++ if (wait_cache->type == INPROC_SYNC_QUEUE) + queue = wait; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + ret = linux_set_event_obj( signal_cache->fd, NULL ); + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + ret = linux_release_mutex_obj( signal_cache->fd, NULL ); + break; + @@ -1104,70 +1168,70 @@ index e070233..6e7fd4e 100644 + + if (!ret) + { -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( queue, !ret ); ++ if (queue) unselect_queue( !ret ); + } + -+ release_fast_sync_obj( signal_cache ); -+ release_fast_sync_obj( wait_cache ); ++ release_inproc_sync_obj( signal_cache ); ++ release_inproc_sync_obj( wait_cache ); + return ret; +} + +#else + -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ +} + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} @@ -1178,7 +1242,7 @@ index e070233..6e7fd4e 100644 /****************************************************************************** * NtCreateSemaphore (NTDLL.@) */ -@@ -251,6 +1155,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ +@@ -311,6 +1214,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ data_size_t len; struct object_attributes *objattr; @@ -1188,7 +1252,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -278,6 +1185,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC +@@ -338,6 +1244,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC { unsigned int ret; @@ -1197,11 +1261,11 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -315,6 +1224,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla +@@ -375,6 +1283,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + return ret; @@ -1210,19 +1274,19 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_semaphore ) { req->handle = wine_server_obj_handle( handle ); -@@ -337,6 +1252,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous +@@ -397,6 +1311,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous { unsigned int ret; + TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); + -+ if ((ret = fast_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_semaphore ) { req->handle = wine_server_obj_handle( handle ); -@@ -361,6 +1281,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ +@@ -421,6 +1340,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr; @@ -1232,7 +1296,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -388,6 +1311,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT +@@ -448,6 +1370,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret; @@ -1241,47 +1305,47 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -413,6 +1338,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) +@@ -473,6 +1397,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -432,6 +1362,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) +@@ -492,6 +1421,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -461,6 +1396,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) +@@ -521,6 +1455,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -492,6 +1432,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, +@@ -552,6 +1491,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); + return ret; @@ -1290,7 +1354,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_event ) { req->handle = wine_server_obj_handle( handle ); -@@ -517,6 +1463,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT +@@ -577,6 +1522,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT data_size_t len; struct object_attributes *objattr; @@ -1300,7 +1364,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -542,6 +1491,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A +@@ -602,6 +1550,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A { unsigned int ret; @@ -1309,23 +1373,23 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -567,6 +1518,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) +@@ -627,6 +1577,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) { unsigned int ret; + TRACE( "handle %p, prev_count %p\n", handle, prev_count ); + -+ if ((ret = fast_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_mutex ) { req->handle = wine_server_obj_handle( handle ); -@@ -597,6 +1553,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, +@@ -657,6 +1612,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); + return ret; @@ -1334,7 +1398,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_mutex ) { req->handle = wine_server_obj_handle( handle ); -@@ -1325,6 +2287,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ +@@ -1426,6 +2387,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr; @@ -1344,7 +1408,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1352,6 +2317,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT +@@ -1453,6 +2417,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret; @@ -1353,7 +1417,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -1405,6 +2372,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) +@@ -1506,6 +2472,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) { unsigned int ret; @@ -1362,7 +1426,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( cancel_timer ) { req->handle = wine_server_obj_handle( handle ); -@@ -1473,13 +2442,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO +@@ -1574,13 +2542,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO { union select_op select_op; UINT i, flags = SELECT_INTERRUPTIBLE; @@ -1377,7 +1441,7 @@ index e070233..6e7fd4e 100644 + TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); + } + -+ if ((ret = fast_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + { + TRACE( "-> %#x\n", ret ); + return ret; @@ -1393,7 +1457,7 @@ index e070233..6e7fd4e 100644 } -@@ -1500,9 +2485,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, +@@ -1601,9 +2585,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, { union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1403,13 +1467,13 @@ index e070233..6e7fd4e 100644 if (!signal) return STATUS_INVALID_HANDLE; -+ if ((ret = fast_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + return ret; + if (alertable) flags |= SELECT_ALERTABLE; select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1735,6 +2726,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, +@@ -1836,6 +2826,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, data_size_t len; struct object_attributes *objattr; @@ -1419,7 +1483,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1759,6 +2753,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE +@@ -1860,6 +2853,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE { unsigned int ret; @@ -1428,7 +1492,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -1785,6 +2781,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, +@@ -1886,6 +2881,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1437,7 +1501,7 @@ index e070233..6e7fd4e 100644 if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE; -@@ -1804,6 +2802,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, +@@ -1905,6 +2902,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1446,7 +1510,7 @@ index e070233..6e7fd4e 100644 if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE; -@@ -2019,7 +2019,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * +@@ -2049,7 +3048,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * } SERVER_END_REQ; if (status != STATUS_PENDING) return status; @@ -1455,7 +1519,7 @@ index e070233..6e7fd4e 100644 else status = STATUS_TIMEOUT; if (status != WAIT_OBJECT_0) return status; -@@ -2081,7 +2081,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM +@@ -2111,7 +3110,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM assert( status == STATUS_USER_APC ); goto done; } @@ -1465,10 +1529,10 @@ index e070233..6e7fd4e 100644 if (status != WAIT_OBJECT_0) goto done; diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 3d151e7..68339d7 100644 +index cec6b3cb106..74b4eb9673a 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c -@@ -1798,7 +1798,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma +@@ -1801,7 +1801,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma if (ret == STATUS_PENDING) { @@ -1478,18 +1542,18 @@ index 3d151e7..68339d7 100644 SERVER_START_REQ( get_thread_context ) { diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index b278ab8..2226096 100644 +index f840045f841..8201e2934f3 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -101,6 +101,7 @@ struct ntdll_thread_data +@@ -112,6 +112,7 @@ struct ntdll_thread_data PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ void *jmp_buf; /* setjmp buffer for exception handling */ -+ int fast_alert_obj; /* fd for the fast alert event */ ++ int linux_alert_obj; /* fd for the linux in-process alert event */ }; C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -194,6 +195,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); +@@ -205,6 +206,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); extern void start_server( BOOL debug ); @@ -1498,24 +1562,24 @@ index b278ab8..2226096 100644 extern unsigned int server_call_unlocked( void *req_ptr ); extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -201,6 +204,7 @@ extern unsigned int server_select( const select_op_t *select_op, data_size_t siz - timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, +@@ -212,6 +215,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t + timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc ); + extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags, const LARGE_INTEGER *timeout ); +extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, union apc_result *result ); extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -360,6 +364,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); +@@ -378,6 +382,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); extern void dbg_init(void); -+extern void close_fast_sync_obj( HANDLE handle ); ++extern void close_inproc_sync_obj( HANDLE handle ); + extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ); extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -368,6 +374,7 @@ extern void call_raise_user_exception_dispatcher(void); +@@ -386,6 +392,7 @@ extern void call_raise_user_exception_dispatcher(void); #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ #define TICKSPERSEC 10000000 @@ -1523,7 +1587,7 @@ index b278ab8..2226096 100644 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -426,7 +433,7 @@ static inline async_data_t server_async( HANDLE handle, struct async_fileio *use +@@ -451,7 +458,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) { @@ -1532,8 +1596,20 @@ index b278ab8..2226096 100644 } static inline BOOL in_wow64_call(void) +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index 0c0a12c394d..7567362a542 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -3689,6 +3689,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) + thread_data->reply_fd = -1; + thread_data->wait_fd[0] = -1; + thread_data->wait_fd[1] = -1; ++ thread_data->linux_alert_obj = -1; + list_add_head( &teb_list, &thread_data->entry ); + return teb; + } diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027f..ddcf896 100644 +index c64027fb86d..ddcf8964f23 100644 --- a/dlls/webservices/tests/channel.c +++ b/dlls/webservices/tests/channel.c @@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { @@ -1547,10 +1623,10 @@ index c64027f..ddcf896 100644 { char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; diff --git a/include/config.h.in b/include/config.h.in -index 65743b5..456344b 100644 +index 6033d8674f3..7fb12090dfe 100644 --- a/include/config.h.in +++ b/include/config.h.in -@@ -180,6 +180,9 @@ +@@ -189,6 +189,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_MAJOR_H @@ -1561,22 +1637,22 @@ index 65743b5..456344b 100644 #undef HAVE_LINUX_PARAM_H diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index 48e778c..e809f98 100644 +index f524a3dc8b5..a6c74fa79e0 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h -@@ -5649,6 +5649,88 @@ struct get_next_thread_reply +@@ -5881,6 +5881,86 @@ struct set_keyboard_repeat_reply }; -+enum fast_sync_type ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + @@ -1611,38 +1687,36 @@ index 48e778c..e809f98 100644 + + + -+struct fast_select_queue_request ++struct select_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; ++ char __pad_12[4]; +}; -+struct fast_select_queue_reply ++struct select_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct fast_unselect_queue_request ++struct unselect_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; + int signaled; -+ char __pad_20[4]; +}; -+struct fast_unselect_queue_reply ++struct unselect_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct get_fast_alert_event_request ++struct get_inproc_alert_event_request +{ + struct request_header __header; + char __pad_12[4]; +}; -+struct get_fast_alert_event_reply ++struct get_inproc_alert_event_reply +{ + struct reply_header __header; + obj_handle_t handle; @@ -1653,218 +1727,221 @@ index 48e778c..e809f98 100644 enum request { REQ_new_process, -@@ -5936,7 +6018,12 @@ enum request - REQ_suspend_process, +@@ -6175,6 +6255,11 @@ enum request REQ_resume_process, REQ_get_next_thread, + REQ_set_keyboard_repeat, + REQ_get_linux_sync_device, + REQ_get_linux_sync_obj, -+ REQ_fast_select_queue, -+ REQ_fast_unselect_queue, - REQ_set_keyboard_repeat, -+ REQ_get_fast_alert_event, ++ REQ_select_inproc_queue, ++ REQ_unselect_inproc_queue, ++ REQ_get_inproc_alert_event, REQ_NB_REQUESTS }; -@@ -6228,7 +6315,12 @@ union generic_request - struct suspend_process_request suspend_process_request; +@@ -6474,6 +6559,11 @@ union generic_request struct resume_process_request resume_process_request; struct get_next_thread_request get_next_thread_request; + struct set_keyboard_repeat_request set_keyboard_repeat_request; + struct get_linux_sync_device_request get_linux_sync_device_request; + struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct fast_select_queue_request fast_select_queue_request; -+ struct fast_unselect_queue_request fast_unselect_queue_request; - struct set_keyboard_repeat_request set_keyboard_repeat_request; -+ struct get_fast_alert_event_request get_fast_alert_event_request; ++ struct select_inproc_queue_request select_inproc_queue_request; ++ struct unselect_inproc_queue_request unselect_inproc_queue_request; ++ struct get_inproc_alert_event_request get_inproc_alert_event_request; }; union generic_reply { -@@ -6518,7 +6610,12 @@ union generic_reply - struct suspend_process_reply suspend_process_reply; +@@ -6771,8 +6861,13 @@ union generic_reply struct resume_process_reply resume_process_reply; struct get_next_thread_reply get_next_thread_reply; + struct set_keyboard_repeat_reply set_keyboard_repeat_reply; + struct get_linux_sync_device_reply get_linux_sync_device_reply; + struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct fast_select_queue_reply fast_select_queue_reply; -+ struct fast_unselect_queue_reply fast_unselect_queue_reply; - struct set_keyboard_repeat_reply set_keyboard_repeat_reply; -+ struct get_fast_alert_event_reply get_fast_alert_event_reply; ++ struct select_inproc_queue_reply select_inproc_queue_reply; ++ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; ++ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; }; - /* ### protocol_version begin ### */ +-#define SERVER_PROTOCOL_VERSION 854 ++#define SERVER_PROTOCOL_VERSION 855 + + #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/Makefile.in b/server/Makefile.in -index 7b46b92..d21bd55 100644 +index 7e571ac2ba6..91ec73dabc5 100644 --- a/server/Makefile.in +++ b/server/Makefile.in -@@ -12,6 +12,7 @@ SOURCES = \ - device.c \ - directory.c \ - event.c \ -+ fast_sync.c \ - fd.c \ +@@ -16,6 +16,7 @@ SOURCES = \ file.c \ handle.c \ + hook.c \ ++ inproc_sync.c \ + mach.c \ + mailslot.c \ + main.c \ diff --git a/server/async.c b/server/async.c -index 80129ac..02fb966 100644 +index d2d929c9709..e8b50a72f7e 100644 --- a/server/async.c +++ b/server/async.c -@@ -89,6 +89,7 @@ static const struct object_ops async_ops = +@@ -90,6 +90,7 @@ static const struct object_ops async_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ async_destroy /* destroy */ }; -@@ -698,6 +699,7 @@ static const struct object_ops iosb_ops = +@@ -710,6 +711,7 @@ static const struct object_ops iosb_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ iosb_destroy /* destroy */ }; diff --git a/server/atom.c b/server/atom.c -index ff0799f..ba320c4 100644 +index ff0799f5880..04951e628ba 100644 --- a/server/atom.c +++ b/server/atom.c @@ -91,6 +91,7 @@ static const struct object_ops atom_table_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; diff --git a/server/change.c b/server/change.c -index f773ccf..d902578 100644 +index f42ce066340..92d321c8784 100644 --- a/server/change.c +++ b/server/change.c @@ -124,6 +124,7 @@ static const struct object_ops dir_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; diff --git a/server/clipboard.c b/server/clipboard.c -index 8118a46..de9f84f 100644 +index 91f159bc7c9..a2258ae869d 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ clipboard_destroy /* destroy */ }; diff --git a/server/completion.c b/server/completion.c -index 6933195..5ec6d20 100644 +index 99680ae0680..529ed9d7956 100644 --- a/server/completion.c +++ b/server/completion.c -@@ -77,6 +77,7 @@ +@@ -77,6 +77,7 @@ struct completion struct list wait_queue; unsigned int depth; int closed; -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; }; static void completion_wait_dump( struct object*, int ); -@@ -104,6 +105,7 @@ +@@ -104,6 +105,7 @@ static const struct object_ops completion_wait_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ completion_wait_destroy /* destroy */ }; -@@ -149,12 +151,17 @@ - msg = LIST_ENTRY( msg_entry, struct comp_msg, queue_entry ); - --wait->completion->depth; - list_remove( &msg->queue_entry ); -+ if (list_empty( &wait->completion->queue )) -+ { -+ fast_reset_event( wait->completion->fast_sync ); -+ } - if (wait->msg) free( wait->msg ); - wait->msg = msg; - } - +@@ -156,6 +158,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent static void completion_dump( struct object*, int ); static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *completion_get_fast_sync( struct object *obj ); static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); static void completion_destroy( struct object * ); -@@ -178,6 +185,7 @@ + static const struct object_ops completion_ops = +@@ -178,6 +181,7 @@ static const struct object_ops completion_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_fast_sync, /* get_fast_sync */ ++ completion_get_inproc_sync,/* get_inproc_sync */ completion_close_handle, /* close_handle */ completion_destroy /* destroy */ }; -@@ -191,6 +199,7 @@ +@@ -191,6 +195,7 @@ static void completion_destroy( struct object *obj) { free( tmp ); } -+ if (completion->fast_sync) release_object( completion->fast_sync ); ++ if (completion->inproc_sync) release_object( completion->inproc_sync ); } static void completion_dump( struct object *obj, int verbose ) -@@ -261,6 +270,16 @@ +@@ -228,6 +233,7 @@ static int completion_close_handle( struct object *obj, struct process *process, + } + completion->closed = 1; + wake_up( obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); + return 1; + } + +@@ -261,6 +267,16 @@ static struct completion_wait *create_completion_wait( struct thread *thread ) return wait; } -+static struct fast_sync *completion_get_fast_sync( struct object *obj ) ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) +{ + struct completion *completion = (struct completion *)obj; + -+ if (!completion->fast_sync) -+ completion->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->fast_sync) grab_object( completion->fast_sync ); -+ return completion->fast_sync; ++ if (!completion->inproc_sync) ++ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); ++ if (completion->inproc_sync) grab_object( completion->inproc_sync ); ++ return completion->inproc_sync; +} + static struct completion *create_completion( struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent, const struct security_descriptor *sd ) -@@ -275,6 +294,7 @@ +@@ -275,6 +291,7 @@ static struct completion *create_completion( struct object *root, const struct u list_init( &completion->wait_queue ); completion->depth = 0; completion->closed = 0; -+ completion->fast_sync = NULL; ++ completion->inproc_sync = NULL; } } -@@ -308,6 +328,7 @@ +@@ -307,7 +324,11 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ + wake_up( &wait->obj, 1 ); if (list_empty( &completion->queue )) return; } - if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ fast_set_event( completion->fast_sync ); +- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); ++ if (!list_empty( &completion->queue )) ++ { ++ wake_up( &completion->obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); ++ } } /* create a completion */ -@@ -404,6 +425,8 @@ +@@ -408,6 +429,8 @@ DECL_HANDLER(remove_completion) reply->information = msg->information; free( msg ); reply->wait_handle = 0; + if (list_empty( &completion->queue )) -+ fast_reset_event( completion->fast_sync ); ++ reset_inproc_event( completion->inproc_sync ); } release_object( completion ); diff --git a/server/console.c b/server/console.c -index b64283b..17708df 100644 +index c3e7bf57e92..b4058f2d002 100644 --- a/server/console.c +++ b/server/console.c @@ -61,6 +61,7 @@ struct console struct fd *fd; /* for bare console, attached input fd */ struct async_queue ioctl_q; /* ioctl queue */ struct async_queue read_q; /* read queue */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_dump( struct object *obj, int verbose ); @@ -1872,7 +1949,7 @@ index b64283b..17708df 100644 static struct object *console_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *console_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ); static const struct object_ops console_ops = { @@ -1880,7 +1957,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ console_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_fast_sync, /* get_fast_sync */ ++ console_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_destroy /* destroy */ }; @@ -1888,7 +1965,7 @@ index b64283b..17708df 100644 unsigned int once_input : 1; /* flag if input thread has already been requested */ int term_fd; /* UNIX terminal fd */ struct termios termios; /* original termios */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_server_dump( struct object *obj, int verbose ); @@ -1896,7 +1973,7 @@ index b64283b..17708df 100644 unsigned int attr, struct object *root ); static struct object *console_server_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); static const struct object_ops console_server_ops = { @@ -1904,7 +1981,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ console_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_fast_sync, /* get_fast_sync */ ++ console_server_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_server_destroy /* destroy */ }; @@ -1912,7 +1989,7 @@ index b64283b..17708df 100644 static struct fd *screen_buffer_get_fd( struct object *obj ); static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); static const struct object_ops screen_buffer_ops = { @@ -1920,7 +1997,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ screen_buffer_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_fast_sync, /* get_fast_sync */ ++ screen_buffer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; @@ -1928,7 +2005,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -1936,7 +2013,7 @@ index b64283b..17708df 100644 unsigned int sharing, unsigned int options ); static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); static void console_input_destroy( struct object *obj ); static const struct object_ops console_input_ops = @@ -1944,7 +2021,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_input_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_fast_sync, /* get_fast_sync */ ++ console_input_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -1952,7 +2029,7 @@ index b64283b..17708df 100644 static struct fd *console_output_get_fd( struct object *obj ); static struct object *console_output_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); static void console_output_destroy( struct object *obj ); static const struct object_ops console_output_ops = @@ -1960,7 +2037,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_output_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_fast_sync, /* get_fast_sync */ ++ console_output_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_output_destroy /* destroy */ }; @@ -1968,7 +2045,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_connection_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ console_connection_close_handle, /* close_handle */ console_connection_destroy /* destroy */ }; @@ -1976,7 +2053,7 @@ index b64283b..17708df 100644 console->server = NULL; console->fd = NULL; console->last_id = 0; -+ console->fast_sync = NULL; ++ console->inproc_sync = NULL; init_async_queue( &console->ioctl_q ); init_async_queue( &console->read_q ); @@ -1984,7 +2061,7 @@ index b64283b..17708df 100644 } list_add_tail( &server->queue, &ioctl->entry ); wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); if (async) set_error( STATUS_PENDING ); return 1; } @@ -1992,7 +2069,7 @@ index b64283b..17708df 100644 server->console->server = NULL; server->console = NULL; wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); } } @@ -2001,32 +2078,32 @@ index b64283b..17708df 100644 if (console->fd) release_object( console->fd ); + -+ if (console->fast_sync) release_object( console->fast_sync ); ++ if (console->inproc_sync) release_object( console->inproc_sync ); } static struct object *create_console_connection( struct console *console ) -@@ -811,6 +830,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access +@@ -817,6 +836,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access return grab_object( obj ); } -+static struct fast_sync *console_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ) +{ + struct console *console = (struct console *)obj; + -+ if (!console->fast_sync) -+ console->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->fast_sync) grab_object( console->fast_sync ); -+ return console->fast_sync; ++ if (!console->inproc_sync) ++ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); ++ if (console->inproc_sync) grab_object( console->inproc_sync ); ++ return console->inproc_sync; +} + static void screen_buffer_dump( struct object *obj, int verbose ) { struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -860,6 +889,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) +@@ -866,6 +895,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) return NULL; } -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) +{ + struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; + if (!screen_buffer->input) @@ -2034,81 +2111,81 @@ index b64283b..17708df 100644 + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( &screen_buffer->input->obj ); ++ return console_get_inproc_sync( &screen_buffer->input->obj ); +} + static void console_server_dump( struct object *obj, int verbose ) { assert( obj->ops == &console_server_ops ); -@@ -872,6 +912,7 @@ static void console_server_destroy( struct object *obj ) +@@ -878,6 +918,7 @@ static void console_server_destroy( struct object *obj ) assert( obj->ops == &console_server_ops ); disconnect_console_server( server ); if (server->fd) release_object( server->fd ); -+ if (server->fast_sync) release_object( server->fast_sync ); ++ if (server->inproc_sync) release_object( server->inproc_sync ); } static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -926,6 +967,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int +@@ -938,6 +979,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) +{ + struct console_server *server = (struct console_server *)obj; + int signaled = !server->console || !list_empty( &server->queue ); + -+ if (!server->fast_sync) -+ server->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (server->fast_sync) grab_object( server->fast_sync ); -+ return server->fast_sync; ++ if (!server->inproc_sync) ++ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (server->inproc_sync) grab_object( server->inproc_sync ); ++ return server->inproc_sync; +} + static struct object *create_console_server( void ) { struct console_server *server; -@@ -937,6 +989,7 @@ static struct object *create_console_server( void ) +@@ -949,6 +1001,7 @@ static struct object *create_console_server( void ) server->term_fd = -1; list_init( &server->queue ); list_init( &server->read_queue ); -+ server->fast_sync = NULL; ++ server->inproc_sync = NULL; server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!server->fd) { -@@ -1402,6 +1455,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int +@@ -1414,6 +1467,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_input_destroy( struct object *obj ) { struct console_input *console_input = (struct console_input *)obj; -@@ -1474,6 +1537,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int +@@ -1486,6 +1549,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console || !current->process->console->active) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_output_destroy( struct object *obj ) { struct console_output *console_output = (struct console_output *)obj; -@@ -1531,11 +1604,16 @@ DECL_HANDLER(get_next_console_request) +@@ -1543,11 +1616,16 @@ DECL_HANDLER(get_next_console_request) if (!server->console->renderer) server->console->renderer = current; @@ -2116,43 +2193,43 @@ index b64283b..17708df 100644 + if (!req->signal) + { + server->console->signaled = 0; -+ fast_reset_event( server->console->fast_sync ); ++ reset_inproc_event( server->console->inproc_sync ); + } else if (!server->console->signaled) { server->console->signaled = 1; wake_up( &server->console->obj, 0 ); -+ fast_set_event( server->console->fast_sync ); ++ set_inproc_event( server->console->inproc_sync ); } if (req->read) -@@ -1557,6 +1635,8 @@ DECL_HANDLER(get_next_console_request) +@@ -1569,6 +1647,8 @@ DECL_HANDLER(get_next_console_request) /* set result of previous ioctl */ ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); list_remove( &ioctl->entry ); + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); } if (ioctl) -@@ -1643,5 +1723,8 @@ DECL_HANDLER(get_next_console_request) +@@ -1655,5 +1735,8 @@ DECL_HANDLER(get_next_console_request) set_error( STATUS_PENDING ); } + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); + release_object( server ); } diff --git a/server/debugger.c b/server/debugger.c -index c59a0ab..7975fc4 100644 +index 39a740e07e5..35449172eaa 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -71,6 +71,7 @@ struct debug_obj struct object obj; /* object header */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; @@ -2160,14 +2237,14 @@ index c59a0ab..7975fc4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; static void debug_obj_dump( struct object *obj, int verbose ); static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ); ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); static void debug_obj_destroy( struct object *obj ); static const struct object_ops debug_obj_ops = @@ -2175,7 +2252,7 @@ index c59a0ab..7975fc4 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_fast_sync, /* get_fast_sync */ ++ debug_obj_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_obj_destroy /* destroy */ }; @@ -2183,7 +2260,7 @@ index c59a0ab..7975fc4 100644 /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -2191,7 +2268,7 @@ index c59a0ab..7975fc4 100644 { grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -2199,15 +2276,15 @@ index c59a0ab..7975fc4 100644 return find_event_to_send( debug_obj ) != NULL; } -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ) ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) +{ + struct debug_obj *debug_obj = (struct debug_obj *)obj; + int signaled = find_event_to_send( debug_obj ) != NULL; + -+ if (!debug_obj->fast_sync) -+ debug_obj->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->fast_sync) grab_object( debug_obj->fast_sync ); -+ return debug_obj->fast_sync; ++ if (!debug_obj->inproc_sync) ++ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); ++ return debug_obj->inproc_sync; +} + static void debug_obj_destroy( struct object *obj ) @@ -2218,7 +2295,7 @@ index c59a0ab..7975fc4 100644 while ((ptr = list_head( &debug_obj->event_queue ))) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); + -+ if (debug_obj->fast_sync) release_object( debug_obj->fast_sync ); ++ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); } struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -2226,7 +2303,7 @@ index c59a0ab..7975fc4 100644 { debug_obj->flags = flags; list_init( &debug_obj->event_queue ); -+ debug_obj->fast_sync = NULL; ++ debug_obj->inproc_sync = NULL; } } return debug_obj; @@ -2236,19 +2313,19 @@ index c59a0ab..7975fc4 100644 set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); + + if (!find_event_to_send( debug_obj )) -+ fast_reset_event( debug_obj->fast_sync ); ++ reset_inproc_event( debug_obj->inproc_sync ); } else { diff --git a/server/device.c b/server/device.c -index 436dac6..698fee6 100644 +index cab09700d8c..72410c2da8b 100644 --- a/server/device.c +++ b/server/device.c @@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ irp_call_destroy /* destroy */ }; @@ -2256,12 +2333,12 @@ index 436dac6..698fee6 100644 struct list requests; /* list of pending irps across all devices */ struct irp_call *current_call; /* call currently executed on client side */ struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void device_manager_dump( struct object *obj, int verbose ); static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ); ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); static void device_manager_destroy( struct object *obj ); static const struct object_ops device_manager_ops = @@ -2269,7 +2346,7 @@ index 436dac6..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_fast_sync, /* get_fast_sync */ ++ device_manager_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_manager_destroy /* destroy */ }; @@ -2277,7 +2354,7 @@ index 436dac6..698fee6 100644 default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -2285,11 +2362,11 @@ index 436dac6..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ device_file_close_handle, /* close_handle */ device_file_destroy /* destroy */ }; -@@ -417,7 +423,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i +@@ -418,7 +424,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); list_add_tail( &manager->requests, &irp->mgr_entry ); @@ -2298,75 +2375,75 @@ index 436dac6..698fee6 100644 + { + /* first one */ + wake_up( &manager->obj, 0 ); -+ fast_set_event( manager->fast_sync ); ++ set_inproc_event( manager->inproc_sync ); + } } static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -751,6 +762,9 @@ static void delete_file( struct device_file *file ) +@@ -752,6 +763,9 @@ static void delete_file( struct device_file *file ) set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); } + if (list_empty( &file->device->manager->requests )) -+ fast_reset_event( file->device->manager->fast_sync ); ++ reset_inproc_event( file->device->manager->inproc_sync ); + release_object( file ); } -@@ -782,6 +796,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry +@@ -783,6 +797,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry return !list_empty( &manager->requests ); } -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ) ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) +{ + struct device_manager *manager = (struct device_manager *)obj; + -+ if (!manager->fast_sync) -+ manager->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->fast_sync) grab_object( manager->fast_sync ); -+ return manager->fast_sync; ++ if (!manager->inproc_sync) ++ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); ++ if (manager->inproc_sync) grab_object( manager->inproc_sync ); ++ return manager->inproc_sync; +} + static void device_manager_destroy( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; -@@ -816,6 +840,8 @@ static void device_manager_destroy( struct object *obj ) +@@ -817,6 +841,8 @@ static void device_manager_destroy( struct object *obj ) assert( !irp->file && !irp->async ); release_object( irp ); } + -+ if (manager->fast_sync) release_object( manager->fast_sync ); ++ if (manager->inproc_sync) release_object( manager->inproc_sync ); } static struct device_manager *create_device_manager(void) -@@ -825,6 +851,7 @@ static struct device_manager *create_device_manager(void) +@@ -826,6 +852,7 @@ static struct device_manager *create_device_manager(void) if ((manager = alloc_object( &device_manager_ops ))) { manager->current_call = NULL; -+ manager->fast_sync = NULL; ++ manager->inproc_sync = NULL; list_init( &manager->devices ); list_init( &manager->requests ); wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -@@ -1014,6 +1041,10 @@ DECL_HANDLER(get_next_device_request) +@@ -1015,6 +1042,10 @@ DECL_HANDLER(get_next_device_request) } list_remove( &irp->mgr_entry ); list_init( &irp->mgr_entry ); + + if (list_empty( &manager->requests )) -+ fast_reset_event( manager->fast_sync ); ++ reset_inproc_event( manager->inproc_sync ); + /* we already own the object if it's only on manager queue */ if (irp->file) grab_object( irp ); manager->current_call = irp; diff --git a/server/directory.c b/server/directory.c -index e521a7b..4e7fc5e 100644 +index fd689c561bc..40cb9b95999 100644 --- a/server/directory.c +++ b/server/directory.c @@ -81,6 +81,7 @@ static const struct object_ops object_type_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -2374,19 +2451,19 @@ index e521a7b..4e7fc5e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ }; diff --git a/server/event.c b/server/event.c -index f1b79b1..b750a22 100644 +index ad7c09acc99..4fb44d70039 100644 --- a/server/event.c +++ b/server/event.c @@ -56,6 +56,7 @@ struct event struct list kernel_object; /* list of kernel object pointers */ int manual_reset; /* is it a manual reset event? */ int signaled; /* event has been signaled */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void event_dump( struct object *obj, int verbose ); @@ -2394,7 +2471,7 @@ index f1b79b1..b750a22 100644 static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int event_signal( struct object *obj, unsigned int access); static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ); +static void event_destroy( struct object *obj ); static const struct object_ops event_ops = @@ -2403,7 +2480,7 @@ index f1b79b1..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_fast_sync, /* get_fast_sync */ ++ event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + event_destroy /* destroy */ @@ -2414,12 +2491,12 @@ index f1b79b1..b750a22 100644 struct keyed_event { struct object obj; /* object header */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void keyed_event_dump( struct object *obj, int verbose ); static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); +static void keyed_event_destroy( struct object *obj ); static const struct object_ops keyed_event_ops = @@ -2428,7 +2505,7 @@ index f1b79b1..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_fast_sync, /* get_fast_sync */ ++ keyed_event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + keyed_event_destroy /* destroy */ @@ -2439,7 +2516,7 @@ index f1b79b1..b750a22 100644 list_init( &event->kernel_object ); event->manual_reset = manual_reset; event->signaled = initial_state; -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -2447,13 +2524,13 @@ index f1b79b1..b750a22 100644 event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ wake_up( &event->obj, !event->manual_reset ); -+ fast_set_event( event->fast_sync ); ++ set_inproc_event( event->inproc_sync ); } void reset_event( struct event *event ) { event->signaled = 0; -+ fast_reset_event( event->fast_sync ); ++ reset_inproc_event( event->inproc_sync ); } static void event_dump( struct object *obj, int verbose ) @@ -2461,24 +2538,24 @@ index f1b79b1..b750a22 100644 return &event->kernel_object; } -+static struct fast_sync *event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (!event->fast_sync) ++ if (!event->inproc_sync) + { -+ enum fast_sync_type type = event->manual_reset ? FAST_SYNC_MANUAL_EVENT : FAST_SYNC_AUTO_EVENT; -+ event->fast_sync = fast_create_event( type, event->signaled ); ++ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; ++ event->inproc_sync = create_inproc_event( type, event->signaled ); + } -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void event_destroy( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, @@ -2488,7 +2565,7 @@ index f1b79b1..b750a22 100644 if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -2496,34 +2573,187 @@ index f1b79b1..b750a22 100644 return 0; } -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (!event->fast_sync) -+ event->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, 1 ); -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (!event->inproc_sync) ++ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void keyed_event_destroy( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + /* create an event */ DECL_HANDLER(create_event) { -diff --git a/server/fast_sync.c b/server/fast_sync.c +diff --git a/server/fd.c b/server/fd.c +index ce32e7f8397..77ac22b9655 100644 +--- a/server/fd.c ++++ b/server/fd.c +@@ -154,6 +154,7 @@ struct fd + struct completion *completion; /* completion object attached to this fd */ + apc_param_t comp_key; /* completion key to set in completion events */ + unsigned int comp_flags; /* completion flags */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ + }; + + static void fd_dump( struct object *obj, int verbose ); +@@ -179,6 +180,7 @@ static const struct object_ops fd_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + fd_destroy /* destroy */ + }; +@@ -220,6 +222,7 @@ static const struct object_ops device_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + device_destroy /* destroy */ + }; +@@ -260,6 +263,7 @@ static const struct object_ops inode_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + inode_destroy /* destroy */ + }; +@@ -302,6 +306,7 @@ static const struct object_ops file_lock_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + no_destroy /* destroy */ + }; +@@ -1572,6 +1577,7 @@ static void fd_destroy( struct object *obj ) + if (fd->unix_fd != -1) close( fd->unix_fd ); + free( fd->unix_name ); + } ++ if (fd->inproc_sync) release_object( fd->inproc_sync ); + } + + /* check if the desired access is possible without violating */ +@@ -1690,6 +1696,7 @@ static struct fd *alloc_fd_object(void) + fd->poll_index = -1; + fd->completion = NULL; + fd->comp_flags = 0; ++ fd->inproc_sync = NULL; + init_async_queue( &fd->read_q ); + init_async_queue( &fd->write_q ); + init_async_queue( &fd->wait_q ); +@@ -1730,6 +1737,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use + fd->poll_index = -1; + fd->completion = NULL; + fd->comp_flags = 0; ++ fd->inproc_sync = NULL; + fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; + init_async_queue( &fd->read_q ); + init_async_queue( &fd->write_q ); +@@ -2140,7 +2148,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) + { + if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; + fd->signaled = signaled; +- if (signaled) wake_up( fd->user, 0 ); ++ if (signaled) ++ { ++ wake_up( fd->user, 0 ); ++ set_inproc_event( fd->inproc_sync ); ++ } ++ else ++ { ++ reset_inproc_event( fd->inproc_sync ); ++ } + } + + /* check if events are pending and if yes return which one(s) */ +@@ -2166,6 +2182,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) + return ret; + } + ++struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) ++{ ++ struct fd *fd = get_obj_fd( obj ); ++ struct inproc_sync *ret; ++ ++ if (!fd->inproc_sync) ++ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); ++ ret = fd->inproc_sync; ++ release_object( fd ); ++ if (ret) grab_object( ret ); ++ return ret; ++} ++ + int default_fd_get_poll_events( struct fd *fd ) + { + int events = 0; +diff --git a/server/file.c b/server/file.c +index 8f6566a0077..bab203b1914 100644 +--- a/server/file.c ++++ b/server/file.c +@@ -106,6 +106,7 @@ static const struct object_ops file_ops = + NULL, /* unlink_name */ + file_open_file, /* open_file */ + file_get_kernel_obj_list, /* get_kernel_obj_list */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + file_destroy /* destroy */ + }; +diff --git a/server/file.h b/server/file.h +index 4f5fc7b26f1..882976e9e02 100644 +--- a/server/file.h ++++ b/server/file.h +@@ -109,6 +109,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre + extern void get_nt_name( struct fd *fd, struct unicode_str *name ); + + extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); ++extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); + 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 +index e65831b3b22..29b43789372 100644 +--- a/server/handle.c ++++ b/server/handle.c +@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + handle_table_destroy /* destroy */ + }; +diff --git a/server/hook.c b/server/hook.c +index c2d2823cd61..c45900549fc 100644 +--- a/server/hook.c ++++ b/server/hook.c +@@ -93,6 +93,7 @@ static const struct object_ops hook_table_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + hook_table_destroy /* destroy */ + }; +diff --git a/server/inproc_sync.c b/server/inproc_sync.c new file mode 100644 -index 0000000..fed6eb9 +index 00000000000..6dd50d79bc0 --- /dev/null -+++ b/server/fast_sync.c -@@ -0,0 +1,434 @@ ++++ b/server/inproc_sync.c +@@ -0,0 +1,437 @@ +/* -+ * Fast synchronization primitives ++ * In-process synchronization primitives + * + * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers + * @@ -2577,7 +2807,7 @@ index 0000000..fed6eb9 +static void linux_device_dump( struct object *obj, int verbose ); +static struct fd *linux_device_get_fd( struct object *obj ); +static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ); ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); + +static const struct object_ops linux_device_ops = +{ @@ -2599,16 +2829,16 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_device_destroy /* destroy */ +}; + -+static const struct fd_ops fast_sync_fd_ops = ++static const struct fd_ops inproc_sync_fd_ops = +{ + default_fd_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ -+ fast_sync_get_fd_type, /* get_fd_type */ ++ inproc_sync_get_fd_type, /* get_fd_type */ + no_fd_read, /* read */ + no_fd_write, /* write */ + no_fd_flush, /* flush */ @@ -2624,7 +2854,7 @@ index 0000000..fed6eb9 +{ + struct linux_device *device = (struct linux_device *)obj; + assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "Fast synchronization device fd=%p\n", device->fd ); ++ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); +} + +static struct fd *linux_device_get_fd( struct object *obj ) @@ -2641,7 +2871,7 @@ index 0000000..fed6eb9 + linux_device_object = NULL; +} + -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ) ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) +{ + return FD_TYPE_FILE; +} @@ -2688,7 +2918,7 @@ index 0000000..fed6eb9 + return NULL; + } + -+ if (!(device->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &device->obj, 0 ))) ++ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) + { + release_object( device ); + initialized = 1; @@ -2701,10 +2931,10 @@ index 0000000..fed6eb9 + return device; +} + -+struct fast_sync ++struct inproc_sync +{ + struct object obj; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + struct fd *fd; +}; + @@ -2714,7 +2944,7 @@ index 0000000..fed6eb9 + +static const struct object_ops linux_obj_ops = +{ -+ sizeof(struct fast_sync), /* size */ ++ sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + linux_obj_dump, /* dump */ + no_add_queue, /* add_queue */ @@ -2732,80 +2962,81 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_obj_destroy /* destroy */ +}; + +static void linux_obj_dump( struct object *obj, int verbose ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "Fast synchronization object type=%u fd=%p\n", fast_sync->type, fast_sync->fd ); ++ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); +} + +static void linux_obj_destroy( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ if (fast_sync->fd) release_object( fast_sync->fd ); ++ if (inproc_sync->fd) release_object( inproc_sync->fd ); +} + +static struct fd *linux_obj_get_fd( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( fast_sync->fd ); ++ return (struct fd *)grab_object( inproc_sync->fd ); +} + -+static struct fast_sync *create_fast_sync( enum fast_sync_type type, int unix_fd ) ++static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) +{ -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if (!(fast_sync = alloc_object( &linux_obj_ops ))) ++ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) + { + close( unix_fd ); + return NULL; + } + -+ fast_sync->type = type; ++ inproc_sync->type = type; + -+ if (!(fast_sync->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &fast_sync->obj, 0 ))) ++ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) + { -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + return NULL; + } + -+ return fast_sync; ++ return inproc_sync; +} + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ -+ struct ntsync_event_args args = {0}; ++ struct ntsync_event_args args; + struct linux_device *device; ++ int event; + + if (!(device = get_linux_device())) return NULL; + + args.signaled = signaled; + switch (type) + { -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_AUTO_SERVER: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_AUTO_SERVER: + args.manual = 0; + break; + -+ case FAST_SYNC_MANUAL_EVENT: -+ case FAST_SYNC_MANUAL_SERVER: -+ case FAST_SYNC_QUEUE: ++ case INPROC_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_MANUAL_SERVER: ++ case INPROC_SYNC_QUEUE: + args.manual = 1; + break; + -+ case FAST_SYNC_MUTEX: -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_MUTEX: ++ case INPROC_SYNC_SEMAPHORE: + assert(0); + break; + } -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args ) < 0) ++ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2813,19 +3044,20 @@ index 0000000..fed6eb9 + } + release_object( device ); + -+ return create_fast_sync( type, args.event ); ++ return create_inproc_sync( type, event ); +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ -+ struct ntsync_sem_args args = {0}; ++ struct ntsync_sem_args args; + struct linux_device *device; ++ int semaphore; + + if (!(device = get_linux_device())) return NULL; + + args.count = count; + args.max = max; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args ) < 0) ++ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2834,19 +3066,20 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_SEMAPHORE, args.sem ); ++ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ -+ struct ntsync_mutex_args args = {0}; ++ struct ntsync_mutex_args args; + struct linux_device *device; ++ int mutex; + + if (!(device = get_linux_device())) return NULL; + + args.owner = owner; + args.count = count; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args ) < 0) ++ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2855,65 +3088,65 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_MUTEX, args.mutex ); ++ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); +} + -+void fast_reset_event( struct fast_sync *fast_sync ) ++void reset_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); +} + +#else + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ +} + -+void fast_reset_event( struct fast_sync *obj ) ++void reset_inproc_event( struct inproc_sync *obj ) +{ +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ +} + @@ -2941,14 +3174,14 @@ index 0000000..fed6eb9 + + if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) + { -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if ((fast_sync = obj->ops->get_fast_sync( obj ))) ++ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) + { -+ reply->handle = alloc_handle( current->process, fast_sync, 0, 0 ); -+ reply->type = fast_sync->type; ++ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); ++ reply->type = inproc_sync->type; + reply->access = get_handle_access( current->process, req->handle ); -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + } + release_object( obj ); + } @@ -2956,204 +3189,51 @@ index 0000000..fed6eb9 + set_error( STATUS_NOT_IMPLEMENTED ); +#endif +} -diff --git a/server/fd.c b/server/fd.c -index fc7f7be..00507ec 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -156,6 +156,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -181,6 +182,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -222,6 +224,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -262,6 +265,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -304,6 +308,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1565,6 +1570,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -+ if (fd->fast_sync) release_object( fd->fast_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1683,6 +1689,7 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->fast_sync = NULL; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); - init_async_queue( &fd->wait_q ); -@@ -1723,6 +1730,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->fast_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); -@@ -2139,7 +2147,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ fast_set_event( fd->fast_sync ); -+ } -+ else -+ { -+ fast_reset_event( fd->fast_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2165,6 +2181,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - -+struct fast_sync *default_fd_get_fast_sync( struct object *obj ) -+{ -+ struct fd *fd = get_obj_fd( obj ); -+ struct fast_sync *ret; -+ -+ if (!fd->fast_sync) -+ fd->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->fast_sync; -+ release_object( fd ); -+ if (ret) grab_object( ret ); -+ return ret; -+} -+ - int default_fd_get_poll_events( struct fd *fd ) - { - int events = 0; -diff --git a/server/file.c b/server/file.c -index 76c6878..1191303 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -106,6 +106,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index 7f2d163..2ec50aa 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -108,6 +108,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -+extern struct fast_sync *default_fd_get_fast_sync( struct object *obj ); - 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 -index ef243e0..782889d 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index 5abdf39..5a00699 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -92,6 +92,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; diff --git a/server/mailslot.c b/server/mailslot.c -index 2d8697e..d9807b4 100644 +index b14954ad6c3..701ac35f393 100644 --- a/server/mailslot.c +++ b/server/mailslot.c -@@ -86,6 +86,7 @@ static const struct object_ops mailslot_ops = +@@ -93,6 +93,7 @@ static const struct object_ops mailslot_ops = default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync,/* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; -@@ -145,6 +146,7 @@ static const struct object_ops mail_writer_ops = +@@ -154,6 +155,7 @@ static const struct object_ops mail_writer_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; -@@ -208,6 +210,7 @@ static const struct object_ops mailslot_device_ops = +@@ -219,6 +221,7 @@ static const struct object_ops mailslot_device_ops = default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ }; -@@ -238,6 +241,7 @@ static const struct object_ops mailslot_device_file_ops = +@@ -249,6 +252,7 @@ static const struct object_ops mailslot_device_file_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_file_destroy /* destroy */ }; diff --git a/server/mapping.c b/server/mapping.c -index ff99b45..e1cf700 100644 +index 4bdd7c5080a..7c715a87457 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -79,6 +79,7 @@ static const struct object_ops ranges_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ranges_destroy /* destroy */ }; @@ -3161,7 +3241,7 @@ index ff99b45..e1cf700 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ shared_map_destroy /* destroy */ }; @@ -3169,19 +3249,19 @@ index ff99b45..e1cf700 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; diff --git a/server/mutex.c b/server/mutex.c -index af0efe7..167c236 100644 +index af0efe72132..a4374317760 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -38,6 +38,8 @@ static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; -+static struct list fast_mutexes = LIST_INIT(fast_mutexes); ++static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); + struct type_descr mutex_type = { @@ -3190,8 +3270,8 @@ index af0efe7..167c236 100644 unsigned int count; /* recursion count */ int abandoned; /* has it been abandoned? */ struct list entry; /* entry in owner thread mutex list */ -+ struct list fast_mutexes_entry; /* entry in fast_mutexes list */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void mutex_dump( struct object *obj, int verbose ); @@ -3199,7 +3279,7 @@ index af0efe7..167c236 100644 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void mutex_destroy( struct object *obj ); static int mutex_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ); ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); static const struct object_ops mutex_ops = { @@ -3207,7 +3287,7 @@ index af0efe7..167c236 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_fast_sync, /* get_fast_sync */ ++ mutex_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; @@ -3215,11 +3295,11 @@ index af0efe7..167c236 100644 mutex->owner = NULL; mutex->abandoned = 0; if (owned) do_grab( mutex, current ); -+ mutex->fast_sync = NULL; ++ mutex->inproc_sync = NULL; } } return mutex; -@@ -134,16 +141,22 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str +@@ -134,16 +141,20 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str void abandon_mutexes( struct thread *thread ) { @@ -3236,28 +3316,26 @@ index af0efe7..167c236 100644 do_release( mutex ); } + -+ LIST_FOR_EACH_ENTRY(mutex, &fast_mutexes, struct mutex, fast_mutexes_entry) -+ { -+ fast_abandon_mutex( thread->id, mutex->fast_sync ); -+ } ++ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) ++ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); } static void mutex_dump( struct object *obj, int verbose ) -@@ -189,14 +202,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) +@@ -189,14 +200,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) return 1; } -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ) ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) +{ + struct mutex *mutex = (struct mutex *)obj; + -+ if (!mutex->fast_sync) ++ if (!mutex->inproc_sync) + { -+ mutex->fast_sync = fast_create_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->fast_sync) list_add_tail( &fast_mutexes, &mutex->fast_mutexes_entry ); ++ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); ++ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); + } -+ if (mutex->fast_sync) grab_object( mutex->fast_sync ); -+ return mutex->fast_sync; ++ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); ++ return mutex->inproc_sync; +} + static void mutex_destroy( struct object *obj ) @@ -3273,23 +3351,23 @@ index af0efe7..167c236 100644 + mutex->count = 0; + do_release( mutex ); + } -+ if (mutex->fast_sync) ++ if (mutex->inproc_sync) + { -+ release_object( mutex->fast_sync ); -+ list_remove( &mutex->fast_mutexes_entry ); ++ release_object( mutex->inproc_sync ); ++ list_remove( &mutex->inproc_mutexes_entry ); + } } /* create a mutex */ diff --git a/server/named_pipe.c b/server/named_pipe.c -index f3404a3..6d8cb3e 100644 +index 59a90c36663..04e8f49fb79 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops = default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -3297,7 +3375,7 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ pipe_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -3305,7 +3383,7 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_end_destroy /* destroy */ }; @@ -3313,7 +3391,7 @@ index f3404a3..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ }; @@ -3321,27 +3399,27 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_file_destroy /* destroy */ }; -@@ -357,6 +356,7 @@ +@@ -351,6 +356,7 @@ static const struct object_ops named_pipe_dir_ops = NULL, /* unlink_name */ named_pipe_dir_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_dir_destroy /* destroy */ }; diff --git a/server/object.c b/server/object.c -index 89e541f..6c6568e 100644 +index cd368ef724a..b07bc59bde1 100644 --- a/server/object.c +++ b/server/object.c @@ -120,6 +120,7 @@ static const struct object_ops apc_reserve_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -3349,15 +3427,15 @@ index 89e541f..6c6568e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; -@@ -538,6 +538,12 @@ struct fd *no_get_fd( struct object *obj ) +@@ -639,6 +641,12 @@ struct fd *no_get_fd( struct object *obj ) return NULL; } -+struct fast_sync *no_get_fast_sync( struct object *obj ) ++struct inproc_sync *no_get_inproc_sync( struct object *obj ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; @@ -3367,14 +3445,14 @@ index 89e541f..6c6568e 100644 { return map_access( access, &obj->ops->type->mapping ); diff --git a/server/object.h b/server/object.h -index d4d6653..b1147bc 100644 +index 7555f564a08..b1612623b0f 100644 --- a/server/object.h +++ b/server/object.h @@ -42,6 +42,7 @@ struct async; struct async_queue; struct winstation; struct object_type; -+struct fast_sync; ++struct inproc_sync; struct unicode_str @@ -3382,38 +3460,38 @@ index d4d6653..b1147bc 100644 unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable fast-synchronization handle to this object */ -+ struct fast_sync *(*get_fast_sync)(struct object *); ++ /* get a client-waitable in-process synchronization handle to this object */ ++ struct inproc_sync *(*get_inproc_sync)(struct object *); /* close a handle to this object */ int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ -@@ -219,6 +222,17 @@ extern void reset_event( struct event *event ); +@@ -228,6 +231,17 @@ extern void reset_event( struct event *event ); extern void abandon_mutexes( struct thread *thread ); -+/* fast-synchronization functions */ ++/* in-process synchronization functions */ + -+extern struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ); -+extern struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ); -+extern struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ); -+extern void fast_set_event( struct fast_sync *obj ); -+extern void fast_reset_event( struct fast_sync *obj ); -+extern void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ); ++extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); ++extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); ++extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); ++extern void set_inproc_event( struct inproc_sync *obj ); ++extern void reset_inproc_event( struct inproc_sync *obj ); ++extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); + -+extern struct fast_sync *no_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); + /* serial functions */ int get_serial_async_timeout(struct object *obj, int type, int count); diff --git a/server/process.c b/server/process.c -index f6d1641..1c2cc8b 100644 +index e06350f7311..fed2f95bd30 100644 --- a/server/process.c +++ b/server/process.c @@ -94,6 +94,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access static struct security_descriptor *process_get_sd( struct object *obj ); static void process_poll_event( struct fd *fd, int event ); static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *process_get_fast_sync( struct object *obj ); ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ); static void process_destroy( struct object *obj ); static void terminate_process( struct process *process, struct thread *skip, int exit_code ); @@ -3421,7 +3499,7 @@ index f6d1641..1c2cc8b 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_fast_sync, /* get_fast_sync */ ++ process_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -3429,7 +3507,7 @@ index f6d1641..1c2cc8b 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; @@ -3437,7 +3515,7 @@ index f6d1641..1c2cc8b 100644 static void job_dump( struct object *obj, int verbose ); static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *job_get_fast_sync( struct object *obj ); ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ); static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void job_destroy( struct object *obj ); @@ -3445,7 +3523,7 @@ index f6d1641..1c2cc8b 100644 struct job *parent; struct list parent_job_entry; /* list entry for parent job */ struct list child_job_list; /* list of child jobs */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static const struct object_ops job_ops = @@ -3453,7 +3531,7 @@ index f6d1641..1c2cc8b 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_fast_sync, /* get_fast_sync */ ++ job_get_inproc_sync, /* get_inproc_sync */ job_close_handle, /* close_handle */ job_destroy /* destroy */ }; @@ -3461,7 +3539,7 @@ index f6d1641..1c2cc8b 100644 job->completion_port = NULL; job->completion_key = 0; job->parent = NULL; -+ job->fast_sync = NULL; ++ job->inproc_sync = NULL; } } return job; @@ -3469,17 +3547,17 @@ index f6d1641..1c2cc8b 100644 job->terminating = 0; job->signaled = 1; wake_up( &job->obj, 0 ); -+ fast_set_event( job->fast_sync ); ++ set_inproc_event( job->inproc_sync ); +} + -+static struct fast_sync *job_get_fast_sync( struct object *obj ) ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ) +{ + struct job *job = (struct job *)obj; + -+ if (!job->fast_sync) -+ job->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->fast_sync) grab_object( job->fast_sync ); -+ return job->fast_sync; ++ if (!job->inproc_sync) ++ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); ++ if (job->inproc_sync) grab_object( job->inproc_sync ); ++ return job->inproc_sync; } static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) @@ -3488,94 +3566,94 @@ index f6d1641..1c2cc8b 100644 release_object( job->parent ); } + -+ if (job->fast_sync) release_object( job->fast_sync ); ++ if (job->inproc_sync) release_object( job->inproc_sync ); } static void job_dump( struct object *obj, int verbose ) -@@ -683,6 +703,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla +@@ -684,6 +704,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla process->rawinput_device_count = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; -+ process->fast_sync = NULL; ++ process->inproc_sync = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); list_init( &process->rawinput_entry ); list_init( &process->kernel_object ); -@@ -789,6 +810,8 @@ static void process_destroy( struct object *obj ) +@@ -784,6 +805,8 @@ static void process_destroy( struct object *obj ) free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); + -+ if (process->fast_sync) release_object( process->fast_sync ); ++ if (process->inproc_sync) release_object( process->inproc_sync ); } /* dump a process on stdout for debugging purposes */ -@@ -820,6 +843,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) +@@ -817,6 +840,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) return &process->kernel_object; } -+static struct fast_sync *process_get_fast_sync( struct object *obj ) ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ) +{ + struct process *process = (struct process *)obj; + -+ if (!process->fast_sync) -+ process->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->fast_sync) grab_object( process->fast_sync ); -+ return process->fast_sync; ++ if (!process->inproc_sync) ++ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); ++ if (process->inproc_sync) grab_object( process->inproc_sync ); ++ return process->inproc_sync; +} + static struct security_descriptor *process_get_sd( struct object *obj ) { static struct security_descriptor *process_default_sd; -@@ -984,6 +1017,7 @@ static void process_killed( struct process *process ) +@@ -981,6 +1014,7 @@ static void process_killed( struct process *process ) release_job_process( process ); start_sigkill_timer( process ); wake_up( &process->obj, 0 ); -+ fast_set_event( process->fast_sync ); ++ set_inproc_event( process->inproc_sync ); } /* add a thread to a process running threads list */ diff --git a/server/process.h b/server/process.h -index 1e73e9d..2140427 100644 +index 96814ab7cf8..667e2506672 100644 --- a/server/process.h +++ b/server/process.h @@ -86,6 +86,7 @@ struct process struct list rawinput_entry; /* entry in the rawinput process list */ struct list kernel_object; /* list of kernel object pointers */ struct pe_image_info image_info; /* main exe image info */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; /* process functions */ diff --git a/server/protocol.def b/server/protocol.def -index f6d644d..e477d3b 100644 +index 4b9c4dc8e5c..85ab00ea704 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -3888,13 +3888,61 @@ struct handle_info +@@ -4076,3 +4076,50 @@ struct handle_info @REPLY - obj_handle_t handle; /* next thread handle */ + int enable; /* previous state of auto-repeat enable */ @END + + -+enum fast_sync_type ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + -+/* Obtain a handle to the fast synchronization device object */ ++/* Obtain a handle to the ntsync device object */ +@REQ(get_linux_sync_device) +@REPLY + obj_handle_t handle; /* handle to the device */ +@END + + -+/* Get the fast synchronization object associated with the given handle */ ++/* Get the in-process synchronization object associated with the given handle */ +@REQ(get_linux_sync_obj) + obj_handle_t handle; /* handle to the object */ +@REPLY @@ -3586,79 +3664,68 @@ index f6d644d..e477d3b 100644 + + +/* Begin a client-side wait on a message queue */ -+@REQ(fast_select_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(select_inproc_queue) +@END + + +/* End a client-side wait on a message queue */ -+@REQ(fast_unselect_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(unselect_inproc_queue) + int signaled; /* was the queue signaled? */ +@END - - - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ - int delay; /* auto-repeat delay in ms */ - int period; /* auto-repeat period in ms */ - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END + -+/* Get an event handle to be used for thread alerts with fast synchronization */ -+@REQ(get_fast_alert_event) ++ ++/* Get an event handle to be used for thread alerts with in-process synchronization */ ++@REQ(get_inproc_alert_event) +@REPLY + obj_handle_t handle; /* handle to the event */ +@END diff --git a/server/queue.c b/server/queue.c -index ed099b3..b4a1c53 100644 +index 47870884644..19a5e7aa9b8 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -145,6 +145,8 @@ struct msg_queue +@@ -133,6 +133,8 @@ struct msg_queue timeout_t last_get_msg; /* time of last get message call */ int keystate_lock; /* owns an input keystate lock */ const queue_shm_t *shared; /* queue in session shared memory */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ int in_fast_wait; /* are we in a client-side wait? */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ int in_inproc_wait; /* are we in a client-side wait? */ }; struct hotkey -@@ -162,6 +164,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent +@@ -150,6 +152,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ); static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ); static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ); ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); static void msg_queue_destroy( struct object *obj ); static void msg_queue_poll_event( struct fd *fd, int event ); static void thread_input_dump( struct object *obj, int verbose ); -@@ -188,6 +191,7 @@ static const struct object_ops msg_queue_ops = +@@ -176,6 +179,7 @@ static const struct object_ops msg_queue_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_fast_sync, /* get_fast_sync */ ++ msg_queue_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; -@@ -225,6 +229,7 @@ static const struct object_ops thread_input_ops = +@@ -213,6 +217,7 @@ static const struct object_ops thread_input_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; -@@ -313,6 +318,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ +@@ -312,6 +317,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->hooks = NULL; queue->last_get_msg = current_time; queue->keystate_lock = 0; -+ queue->fast_sync = NULL; -+ queue->in_fast_wait = 0; ++ queue->inproc_sync = NULL; ++ queue->in_inproc_wait = 0; list_init( &queue->send_result ); list_init( &queue->callback_result ); list_init( &queue->pending_timers ); -@@ -599,7 +606,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) +@@ -728,7 +735,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) } SHARED_WRITE_END; @@ -3666,64 +3733,62 @@ index ed099b3..b4a1c53 100644 + if (is_signaled( queue )) + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } } /* clear some queue bits */ -@@ -612,6 +623,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits +@@ -748,6 +759,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits if (queue->keystate_lock) unlock_input_keystate( queue->input ); queue->keystate_lock = 0; } + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } /* check if message is matched by the filter */ -@@ -1091,6 +1104,10 @@ static int is_queue_hung( struct msg_queue *queue ) +@@ -1227,6 +1240,10 @@ static int is_queue_hung( struct msg_queue *queue ) if (get_wait_queue_thread(entry)->queue == queue) return 0; /* thread is waiting on queue -> not hung */ } + -+ if (queue->in_fast_wait) ++ if (queue->in_inproc_wait) + return 0; /* thread is waiting on queue in absentia -> not hung */ + return 1; } -@@ -1151,6 +1168,19 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en +@@ -1292,6 +1309,17 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en shared->changed_mask = 0; } SHARED_WRITE_END; -+ -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); +} + -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ) ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) +{ + struct msg_queue *queue = (struct msg_queue *)obj; -+ const queue_shm_t *queue_shm = queue->shared; + -+ if (!queue->fast_sync) -+ queue->fast_sync = fast_create_event( FAST_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->fast_sync) grab_object( queue->fast_sync ); -+ return queue->fast_sync; ++ if (!queue->inproc_sync) ++ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); ++ if (queue->inproc_sync) grab_object( queue->inproc_sync ); ++ return queue->inproc_sync; } static void msg_queue_destroy( struct object *obj ) -@@ -1190,6 +1218,7 @@ static void msg_queue_destroy( struct object *obj ) +@@ -1337,6 +1365,7 @@ static void msg_queue_destroy( struct object *obj ) if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); -+ if (queue->fast_sync) release_object( queue->fast_sync ); ++ if (queue->inproc_sync) release_object( queue->inproc_sync ); } static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1200,6 +1229,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) +@@ -1347,6 +1376,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); } static void thread_input_dump( struct object *obj, int verbose ) @@ -3735,101 +3800,142 @@ index ed099b3..b4a1c53 100644 + else + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } + } + else + { -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } } } -@@ -2831,6 +2873,9 @@ DECL_HANDLER(get_queue_status) +@@ -3136,6 +3174,9 @@ DECL_HANDLER(get_queue_status) shared->changed_bits &= ~req->clear_bits; } SHARED_WRITE_END; + + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } else reply->wake_bits = reply->changed_bits = 0; } -@@ -3020,6 +3064,9 @@ DECL_HANDLER(get_message) - if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT; - if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; +@@ -3333,6 +3374,9 @@ DECL_HANDLER(get_message) + } + SHARED_WRITE_END; + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); + /* then check for posted messages */ if ((filter & QS_POSTMESSAGE) && get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3073,6 +3120,7 @@ DECL_HANDLER(get_message) +@@ -3392,6 +3436,7 @@ DECL_HANDLER(get_message) } SHARED_WRITE_END; -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); set_error( STATUS_PENDING ); /* FIXME */ } +@@ -4183,3 +4228,42 @@ DECL_HANDLER(set_keyboard_repeat) + + release_object( desktop ); + } ++ ++DECL_HANDLER(select_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ check_thread_queue_idle( current ); ++ ++ if (queue->fd) ++ set_fd_events( queue->fd, POLLIN ); ++ ++ queue->in_inproc_wait = 1; ++ } ++} ++ ++DECL_HANDLER(unselect_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (!queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ if (queue->fd) ++ set_fd_events( queue->fd, 0 ); ++ ++ if (req->signaled) ++ msg_queue_satisfied( &queue->obj, NULL ); ++ ++ queue->in_inproc_wait = 0; ++ } ++} diff --git a/server/registry.c b/server/registry.c -index 804cfcc..f6bb34e 100644 +index 3f02faaaefd..65beb11702d 100644 --- a/server/registry.c +++ b/server/registry.c @@ -192,6 +192,7 @@ static const struct object_ops key_ops = key_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ key_close_handle, /* close_handle */ key_destroy /* destroy */ }; diff --git a/server/request.c b/server/request.c -index 2691e0c..e0585be 100644 +index 2254315b79e..24a4f779e68 100644 --- a/server/request.c +++ b/server/request.c -@@ -102,6 +102,7 @@ static const struct object_ops master_socket_ops = +@@ -101,6 +101,7 @@ static const struct object_ops master_socket_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; diff --git a/server/request_handlers.h b/server/request_handlers.h -index eb6b8f4..1636e98 100644 ---- a/server/request_handlers.h 2024-11-18 18:02:30.072599085 +0500 -+++ b/server/request_handlers.h 2024-11-18 18:14:42.357268807 +0500 -@@ -298,7 +298,12 @@ - DECL_HANDLER(suspend_process); +index fb03e421562..1d88b63dff3 100644 +--- a/server/request_handlers.h ++++ b/server/request_handlers.h +@@ -299,6 +299,11 @@ DECL_HANDLER(suspend_process); DECL_HANDLER(resume_process); DECL_HANDLER(get_next_thread); + DECL_HANDLER(set_keyboard_repeat); +DECL_HANDLER(get_linux_sync_device); +DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(fast_select_queue); -+DECL_HANDLER(fast_unselect_queue); - DECL_HANDLER(set_keyboard_repeat); -+DECL_HANDLER(get_fast_alert_event); ++DECL_HANDLER(select_inproc_queue); ++DECL_HANDLER(unselect_inproc_queue); ++DECL_HANDLER(get_inproc_alert_event); typedef void (*req_handler)( const void *req, void *reply ); static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -599,7 +599,12 @@ - (req_handler)req_suspend_process, +@@ -595,6 +600,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_resume_process, (req_handler)req_get_next_thread, + (req_handler)req_set_keyboard_repeat, + (req_handler)req_get_linux_sync_device, + (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_fast_select_queue, -+ (req_handler)req_fast_unselect_queue, - (req_handler)req_set_keyboard_repeat, -+ (req_handler)req_get_fast_alert_event, ++ (req_handler)req_select_inproc_queue, ++ (req_handler)req_unselect_inproc_queue, ++ (req_handler)req_get_inproc_alert_event, }; C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,9 +2276,26 @@ - C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); - C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); - C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); +@@ -2268,3 +2278,18 @@ C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); +C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); +C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); @@ -3839,36 +3945,114 @@ index eb6b8f4..1636e98 100644 +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( offsetof(struct fast_select_queue_request, handle) == 12 ); -+C_ASSERT( sizeof(struct fast_select_queue_request) == 16 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, handle) == 12 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, signaled) == 16 ); -+C_ASSERT( sizeof(struct fast_unselect_queue_request) == 24 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_fast_alert_event_reply, handle) == 8 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_reply) == 16 ); ++C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); ++C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); ++C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); ++C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); +diff --git a/server/request_trace.h b/server/request_trace.h +index cf0aab07ca0..283f1c1774a 100644 +--- a/server/request_trace.h ++++ b/server/request_trace.h +@@ -3339,6 +3339,45 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep + fprintf( stderr, " enable=%d", req->enable ); + } + ++static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) ++{ ++} ++ ++static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ ++static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ ++static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++ fprintf( stderr, ", type=%d", req->type ); ++ fprintf( stderr, ", access=%08x", req->access ); ++} ++ ++static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) ++{ ++} ++ ++static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) ++{ ++ fprintf( stderr, " signaled=%d", req->signaled ); ++} ++ ++static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) ++{ ++} ++ ++static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ + typedef void (*dump_func)( const void *req ); + + static const dump_func req_dumpers[REQ_NB_REQUESTS] = +@@ -3635,6 +3674,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = + (dump_func)dump_resume_process_request, + (dump_func)dump_get_next_thread_request, + (dump_func)dump_set_keyboard_repeat_request, ++ (dump_func)dump_get_linux_sync_device_request, ++ (dump_func)dump_get_linux_sync_obj_request, ++ (dump_func)dump_select_inproc_queue_request, ++ (dump_func)dump_unselect_inproc_queue_request, ++ (dump_func)dump_get_inproc_alert_event_request, + }; + + static const dump_func reply_dumpers[REQ_NB_REQUESTS] = +@@ -3931,6 +3975,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = + NULL, + (dump_func)dump_get_next_thread_reply, + (dump_func)dump_set_keyboard_repeat_reply, ++ (dump_func)dump_get_linux_sync_device_reply, ++ (dump_func)dump_get_linux_sync_obj_reply, ++ NULL, ++ NULL, ++ (dump_func)dump_get_inproc_alert_event_reply, + }; + + static const char * const req_names[REQ_NB_REQUESTS] = +@@ -4227,6 +4276,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = + "resume_process", + "get_next_thread", + "set_keyboard_repeat", ++ "get_linux_sync_device", ++ "get_linux_sync_obj", ++ "select_inproc_queue", ++ "unselect_inproc_queue", ++ "get_inproc_alert_event", + }; + + static const struct diff --git a/server/semaphore.c b/server/semaphore.c -index 53b42a8..9940919 100644 +index 53b42a886df..bc7436b5673 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -55,12 +55,15 @@ struct semaphore struct object obj; /* object header */ unsigned int count; /* current count */ unsigned int max; /* maximum possible count */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* fast synchronization object */ }; static void semaphore_dump( struct object *obj, int verbose ); static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ); ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); +static void semaphore_destroy( struct object *obj ); static const struct object_ops semaphore_ops = @@ -3877,7 +4061,7 @@ index 53b42a8..9940919 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_fast_sync, /* get_fast_sync */ ++ semaphore_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + semaphore_destroy /* destroy */ @@ -3888,7 +4072,7 @@ index 53b42a8..9940919 100644 /* initialize it if it didn't already exist */ sem->count = initial; sem->max = max; -+ sem->fast_sync = NULL; ++ sem->inproc_sync = NULL; } } return sem; @@ -3896,99 +4080,99 @@ index 53b42a8..9940919 100644 return release_semaphore( sem, 1, NULL ); } -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ) ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (!semaphore->fast_sync) -+ semaphore->fast_sync = fast_create_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->fast_sync) grab_object( semaphore->fast_sync ); -+ return semaphore->fast_sync; ++ if (!semaphore->inproc_sync) ++ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); ++ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); ++ return semaphore->inproc_sync; +} + +static void semaphore_destroy( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (semaphore->fast_sync) release_object( semaphore->fast_sync ); ++ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); +} + /* create a semaphore */ DECL_HANDLER(create_semaphore) { diff --git a/server/serial.c b/server/serial.c -index d665eb7..5c210d1 100644 +index 209f2e9174e..93753328d4d 100644 --- a/server/serial.c +++ b/server/serial.c -@@ -97,6 +97,7 @@ static const struct object_ops serial_ops = +@@ -103,6 +103,7 @@ static const struct object_ops serial_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; diff --git a/server/signal.c b/server/signal.c -index 19b76d4..e5def3d 100644 +index 19b76d44c16..85d16baa98c 100644 --- a/server/signal.c +++ b/server/signal.c @@ -74,6 +74,7 @@ static const struct object_ops handler_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; diff --git a/server/sock.c b/server/sock.c -index 8a95cad..587a312 100644 +index 32d622aaebc..09366ea7dde 100644 --- a/server/sock.c +++ b/server/sock.c -@@ -465,6 +465,7 @@ static const struct object_ops sock_ops = +@@ -483,6 +483,7 @@ static const struct object_ops sock_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ sock_close_handle, /* close_handle */ sock_destroy /* destroy */ }; -@@ -3572,6 +3573,7 @@ static const struct object_ops ifchange_ops = +@@ -3611,6 +3612,7 @@ static const struct object_ops ifchange_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ifchange_destroy /* destroy */ }; -@@ -3793,6 +3795,7 @@ static const struct object_ops socket_device_ops = +@@ -3832,6 +3834,7 @@ static const struct object_ops socket_device_ops = default_unlink_name, /* unlink_name */ socket_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/symlink.c b/server/symlink.c -index dd28efd..4a7cf68 100644 +index 74b60162c01..f0314f2ee90 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -83,6 +83,7 @@ static const struct object_ops symlink_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ }; diff --git a/server/thread.c b/server/thread.c -index 55bd63d..b9fb8d5 100644 +index b3ce5d9ac95..a05a96d8728 100644 --- a/server/thread.c +++ b/server/thread.c @@ -108,6 +108,7 @@ static const struct object_ops thread_apc_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_apc_destroy /* destroy */ }; @@ -3996,7 +4180,7 @@ index 55bd63d..b9fb8d5 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4004,7 +4188,7 @@ index 55bd63d..b9fb8d5 100644 static unsigned int thread_map_access( struct object *obj, unsigned int access ); static void thread_poll_event( struct fd *fd, int event ); static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *thread_get_fast_sync( struct object *obj ); ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); static void destroy_thread( struct object *obj ); static const struct object_ops thread_ops = @@ -4012,7 +4196,7 @@ index 55bd63d..b9fb8d5 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_fast_sync, /* get_fast_sync */ ++ thread_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; @@ -4020,119 +4204,137 @@ index 55bd63d..b9fb8d5 100644 thread->token = NULL; thread->desc = NULL; thread->desc_len = 0; -+ thread->fast_sync = NULL; -+ thread->fast_alert_event = NULL; ++ thread->inproc_sync = NULL; ++ thread->inproc_alert_event = NULL; thread->creation_time = current_time; thread->exit_time = 0; -@@ -396,6 +402,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) +@@ -397,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) return &thread->kernel_object; } -+static struct fast_sync *thread_get_fast_sync( struct object *obj ) ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) +{ + struct thread *thread = (struct thread *)obj; + -+ if (!thread->fast_sync) -+ thread->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->fast_sync) grab_object( thread->fast_sync ); -+ return thread->fast_sync; ++ if (!thread->inproc_sync) ++ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); ++ if (thread->inproc_sync) grab_object( thread->inproc_sync ); ++ return thread->inproc_sync; +} + /* cleanup everything that is no longer needed by a dead thread */ /* used by destroy_thread and kill_thread */ static void cleanup_thread( struct thread *thread ) -@@ -450,6 +466,8 @@ static void destroy_thread( struct object *obj ) +@@ -452,6 +468,8 @@ static void destroy_thread( struct object *obj ) release_object( thread->process ); if (thread->id) free_ptid( thread->id ); if (thread->token) release_object( thread->token ); -+ if (thread->fast_sync) release_object( thread->fast_sync ); -+ if (thread->fast_alert_event) release_object( thread->fast_alert_event ); ++ if (thread->inproc_sync) release_object( thread->inproc_sync ); ++ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); } /* dump a thread on stdout for debugging purposes */ -@@ -1143,8 +1161,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr +@@ -1149,8 +1167,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr grab_object( apc ); list_add_tail( queue, &apc->entry ); if (!list_prev( queue, &apc->entry )) /* first one */ + { wake_thread( thread ); -+ if (apc->call.type == APC_USER && thread->fast_alert_event) -+ set_event( thread->fast_alert_event ); ++ if (apc->call.type == APC_USER && thread->inproc_alert_event) ++ set_event( thread->inproc_alert_event ); + } + return 1; } -@@ -1175,6 +1198,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty +@@ -1181,6 +1204,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty apc->executed = 1; wake_up( &apc->obj, 0 ); release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); return; } } -@@ -1189,6 +1214,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system +@@ -1195,6 +1220,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system { apc = LIST_ENTRY( ptr, struct thread_apc, entry ); list_remove( ptr ); + -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); } return apc; } -@@ -1286,6 +1314,7 @@ void kill_thread( struct thread *thread, int violent_death ) +@@ -1292,6 +1320,7 @@ void kill_thread( struct thread *thread, int violent_death ) kill_console_processes( thread, 0 ); abandon_mutexes( thread ); wake_up( &thread->obj, 0 ); -+ fast_set_event( thread->fast_sync ); ++ set_inproc_event( thread->inproc_sync ); if (violent_death) send_thread_signal( thread, SIGQUIT ); cleanup_thread( thread ); remove_process_thread( thread->process, thread ); -@@ -2029,3 +2058,12 @@ DECL_HANDLER(get_next_thread) +@@ -2035,3 +2064,12 @@ DECL_HANDLER(get_next_thread) set_error( STATUS_NO_MORE_ENTRIES ); release_object( process ); } + -+DECL_HANDLER(get_fast_alert_event) ++DECL_HANDLER(get_inproc_alert_event) +{ -+ if (!current->fast_alert_event) -+ current->fast_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); ++ if (!current->inproc_alert_event) ++ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); + -+ if (current->fast_alert_event) -+ reply->handle = alloc_handle( current->process, current->fast_alert_event, SYNCHRONIZE, 0 ); ++ if (current->inproc_alert_event) ++ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); +} diff --git a/server/thread.h b/server/thread.h -index 766ed78..9bf4b48 100644 +index 754e617b484..c75512ded87 100644 --- a/server/thread.h +++ b/server/thread.h -@@ -91,6 +91,8 @@ struct thread +@@ -93,6 +93,8 @@ struct thread data_size_t desc_len; /* thread description length in bytes */ WCHAR *desc; /* thread description string */ struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ struct event *fast_alert_event; /* fast synchronization alert event */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ struct event *inproc_alert_event; /* in-process synchronization alert event */ }; extern struct thread *current; diff --git a/server/timer.c b/server/timer.c -index 96dc9d0..854a8e1 100644 +index b0b6ec81535..08aa62292f0 100644 --- a/server/timer.c +++ b/server/timer.c -@@ -61,11 +61,13 @@ struct timer - struct thread *thread; /* thread that set the APC function */ - client_ptr_t callback; /* callback APC function */ - client_ptr_t arg; /* callback argument */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ +@@ -52,20 +52,22 @@ struct type_descr timer_type = + + struct timer + { +- struct object obj; /* object header */ +- int manual; /* manual reset */ +- int signaled; /* current signaled state */ +- unsigned int period; /* timer period in ms */ +- abstime_t when; /* next expiration */ +- struct timeout_user *timeout; /* timeout user */ +- struct thread *thread; /* thread that set the APC function */ +- client_ptr_t callback; /* callback APC function */ +- client_ptr_t arg; /* callback argument */ ++ struct object obj; /* object header */ ++ int manual; /* manual reset */ ++ int signaled; /* current signaled state */ ++ unsigned int period; /* timer period in ms */ ++ abstime_t when; /* next expiration */ ++ struct timeout_user *timeout; /* timeout user */ ++ struct thread *thread; /* thread that set the APC function */ ++ client_ptr_t callback; /* callback APC function */ ++ client_ptr_t arg; /* callback argument */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void timer_dump( struct object *obj, int verbose ); static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *timer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); static void timer_destroy( struct object *obj ); static const struct object_ops timer_ops = @@ -4140,7 +4342,7 @@ index 96dc9d0..854a8e1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_fast_sync, /* get_fast_sync */ ++ timer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; @@ -4148,7 +4350,7 @@ index 96dc9d0..854a8e1 100644 timer->period = 0; timer->timeout = NULL; timer->thread = NULL; -+ timer->fast_sync = NULL; ++ timer->inproc_sync = NULL; } } return timer; @@ -4156,7 +4358,7 @@ index 96dc9d0..854a8e1 100644 /* wake up waiters */ timer->signaled = 1; wake_up( &timer->obj, 0 ); -+ fast_set_event( timer->fast_sync ); ++ set_inproc_event( timer->inproc_sync ); } /* cancel a running timer */ @@ -4164,7 +4366,7 @@ index 96dc9d0..854a8e1 100644 { period = 0; /* period doesn't make any sense for a manual timer */ timer->signaled = 0; -+ fast_reset_event( timer->fast_sync ); ++ reset_inproc_event( timer->inproc_sync ); } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; @@ -4172,17 +4374,17 @@ index 96dc9d0..854a8e1 100644 if (!timer->manual) timer->signaled = 0; } -+static struct fast_sync *timer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) +{ + struct timer *timer = (struct timer *)obj; + -+ if (!timer->fast_sync) ++ if (!timer->inproc_sync) + { -+ enum fast_sync_type type = timer->manual ? FAST_SYNC_MANUAL_SERVER : FAST_SYNC_AUTO_SERVER; -+ timer->fast_sync = fast_create_event( type, timer->signaled ); ++ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; ++ timer->inproc_sync = create_inproc_event( type, timer->signaled ); + } -+ if (timer->fast_sync) grab_object( timer->fast_sync ); -+ return timer->fast_sync; ++ if (timer->inproc_sync) grab_object( timer->inproc_sync ); ++ return timer->inproc_sync; +} + static void timer_destroy( struct object *obj ) @@ -4192,146 +4394,43 @@ index 96dc9d0..854a8e1 100644 if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); -+ if (timer->fast_sync) release_object( timer->fast_sync ); ++ if (timer->inproc_sync) release_object( timer->inproc_sync ); } /* create a timer */ diff --git a/server/token.c b/server/token.c -index 4df8d2e..42562fd 100644 +index 7e20c670a16..844ad2814f4 100644 --- a/server/token.c +++ b/server/token.c -@@ -155,6 +155,7 @@ static const struct object_ops token_ops = +@@ -157,6 +157,7 @@ static const struct object_ops token_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ token_destroy /* destroy */ }; -diff --git a/server/request_trace.h b/server/request_trace.h -index af96565..c027f4b 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -4603,18 +4603,59 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req - fprintf( stderr, " handle=%04x", req->handle ); - } - -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) -+{ -+} -+ -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", type=%d", req->type ); -+ fprintf( stderr, ", access=%08x", req->access ); -+} -+ -+static void dump_fast_select_queue_request( const struct fast_select_queue_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_fast_unselect_queue_request( const struct fast_unselect_queue_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", signaled=%d", req->signaled ); -+} -+ -+static void dump_get_fast_alert_event_request( const struct get_fast_alert_event_request *req ) -+{ -+} -+ - static void dump_set_keyboard_repeat_request( const struct set_keyboard_repeat_request *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - fprintf( stderr, ", delay=%d", req->delay ); - fprintf( stderr, ", period=%d", req->period ); - } - - static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_reply *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - } - -+static void dump_get_fast_alert_event_reply( const struct get_fast_alert_event_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ - typedef void (*dump_func)( const void *req ); - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = { -@@ -4889,7 +4930,12 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_suspend_process_request, - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, - (dump_func)dump_set_keyboard_repeat_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_fast_select_queue_request, -+ (dump_func)dump_fast_unselect_queue_request, -+ (dump_func)dump_get_fast_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { -@@ -5177,7 +5223,12 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { - NULL, - NULL, - (dump_func)dump_get_next_thread_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, - (dump_func)dump_set_keyboard_repeat_reply, -+ NULL, -+ (dump_func)dump_get_fast_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = { -@@ -5465,7 +5516,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = { - "suspend_process", - "resume_process", - "get_next_thread", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "fast_select_queue", -+ "fast_unselect_queue", - "set_keyboard_repeat", -+ "get_fast_alert_event", - }; - - static const struct diff --git a/server/window.c b/server/window.c -index 242e93f..8ddf78e 100644 +index 2af70b09102..291aab520d7 100644 --- a/server/window.c +++ b/server/window.c @@ -119,6 +119,7 @@ static const struct object_ops window_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ window_destroy /* destroy */ }; diff --git a/server/winstation.c b/server/winstation.c -index 80126ad..8aab32d 100644 +index 8611c893cde..e3f0a870d02 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -88,6 +88,7 @@ static const struct object_ops winstation_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -4339,88 +4438,10 @@ index 80126ad..8aab32d 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; -From a0534129d9131289457d2967e557992c59d2e0de Mon Sep 17 00:00:00 2001 -From: Kirill Artemev -Date: Thu, 4 Jul 2024 11:00:19 +0500 -Subject: [PATCH] ntsync5: rebase - -Signed-off-by: Kirill Artemev ---- - server/queue.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 58 insertions(+) - -diff --git a/server/queue.c b/server/queue.c -index 4f58b795b7e..2185bf72964 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -4015,6 +4015,64 @@ DECL_HANDLER(update_rawinput_devices) - } - } - -+DECL_HANDLER(fast_select_queue) -+{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; -+ -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ /* a thread can only wait on its own queue */ -+ if (current->queue != queue || queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -+ set_event( current->process->idle_event ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_fast_wait = 1; -+ } -+ -+ release_object( queue ); -+} -+ -+DECL_HANDLER(fast_unselect_queue) -+{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; -+ -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ -+ if (current->queue != queue || !queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_fast_wait = 0; -+ } -+ -+ release_object( queue ); -+} -+ - DECL_HANDLER(set_keyboard_repeat) - { - struct desktop *desktop; -- -2.45.2 +2.47.1 + diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-protonify.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-protonify.patch index b395c4e64..8fb2b81dc 100644 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-protonify.patch +++ b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-protonify.patch @@ -1,8 +1,73 @@ +From 0b446d37ae366bf9921bc7f99f313ffe1a7530b2 Mon Sep 17 00:00:00 2001 +From: Kirill Artemev +Date: Fri, 20 Dec 2024 21:54:47 +0500 +Subject: [PATCH] ntsync7-mainline + +Signed-off-by: Kirill Artemev +--- + configure | 6 + + configure.ac | 1 + + dlls/kernel32/tests/sync.c | 79 +++ + dlls/ntdll/unix/file.c | 2 +- + dlls/ntdll/unix/process.c | 2 +- + dlls/ntdll/unix/server.c | 28 +- + dlls/ntdll/unix/sync.c | 1007 +++++++++++++++++++++++++++++- + dlls/ntdll/unix/thread.c | 2 +- + dlls/ntdll/unix/unix_private.h | 9 +- + dlls/ntdll/unix/virtual.c | 1 + + dlls/webservices/tests/channel.c | 3 + + include/config.h.in | 3 + + include/wine/server_protocol.h | 97 ++- + server/Makefile.in | 1 + + server/async.c | 2 + + server/atom.c | 1 + + server/change.c | 1 + + server/clipboard.c | 1 + + server/completion.c | 25 +- + server/console.c | 85 ++- + server/debugger.c | 23 + + server/device.c | 33 +- + server/directory.c | 2 + + server/event.c | 53 +- + server/fd.c | 31 +- + server/file.c | 1 + + server/file.h | 1 + + server/handle.c | 1 + + server/hook.c | 1 + + server/inproc_sync.c | 437 +++++++++++++ + server/mailslot.c | 4 + + server/mapping.c | 3 + + server/mutex.c | 39 +- + server/named_pipe.c | 6 + + server/object.c | 8 + + server/object.h | 14 + + server/process.c | 34 + + server/process.h | 1 + + server/protocol.def | 47 ++ + server/queue.c | 88 ++- + server/registry.c | 1 + + server/request.c | 1 + + server/request_handlers.h | 25 + + server/request_trace.h | 54 ++ + server/semaphore.c | 24 +- + server/serial.c | 1 + + server/signal.c | 1 + + server/sock.c | 3 + + server/symlink.c | 1 + + server/thread.c | 38 ++ + server/thread.h | 2 + + server/timer.c | 38 +- + server/token.c | 1 + + server/window.c | 1 + + server/winstation.c | 2 + + 55 files changed, 2343 insertions(+), 33 deletions(-) + create mode 100644 server/inproc_sync.c + diff --git a/configure b/configure -index 0468aea..f8142f8 100755 +index beba1346b6a..da17410a661 100755 --- a/configure +++ b/configure -@@ -7979,6 +7979,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes +@@ -7734,6 +7734,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h @@ -16,7 +81,7 @@ index 0468aea..f8142f8 100755 ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" if test "x$ac_cv_header_linux_param_h" = xyes diff --git a/configure.ac b/configure.ac -index 31c2fa2..e064df8 100644 +index 6596f653fb1..c3f925a55a5 100644 --- a/configure.ac +++ b/configure.ac @@ -383,6 +383,7 @@ AC_CHECK_HEADERS(\ @@ -28,10 +93,10 @@ index 31c2fa2..e064df8 100644 linux/serial.h \ linux/types.h \ diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index c06ced4..c5d2713 100644 +index 49420e4519f..2c69073db10 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c -@@ -2871,6 +2871,84 @@ static void test_QueueUserAPC(void) +@@ -2904,6 +2904,84 @@ static void test_QueueUserAPC(void) ok(apc_count == 1, "APC count %u\n", apc_count); } @@ -116,7 +181,7 @@ index c06ced4..c5d2713 100644 START_TEST(sync) { char **argv; -@@ -2941,5 +3019,6 @@ START_TEST(sync) +@@ -2974,5 +3052,6 @@ START_TEST(sync) test_srwlock_example(); test_alertable_wait(); test_apc_deadlock(); @@ -124,10 +189,10 @@ index c06ced4..c5d2713 100644 test_crit_section(); } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index d292d93..17e7266 100644 +index 8bc69557057..755a6e844a4 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6372,7 +6372,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void +@@ -6451,7 +6451,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void } if (handle) { @@ -137,10 +202,10 @@ index d292d93..17e7266 100644 } else /* Unix lock conflict, sleep a bit and retry */ diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index cc2d820..8ee2afe 100644 +index c3a730379a4..db4d096acd1 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c -@@ -922,7 +922,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ +@@ -920,7 +920,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ /* wait for the new process info to be ready */ @@ -150,7 +215,7 @@ index cc2d820..8ee2afe 100644 { req->info = wine_server_obj_handle( process_info ); diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index f3ffd99..6e0ecf9 100644 +index b40e7c2a1d7..3579e4f454d 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */ @@ -162,7 +227,7 @@ index f3ffd99..6e0ecf9 100644 /* atomically exchange a 64-bit value */ static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val ) -@@ -789,6 +789,21 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f +@@ -789,6 +789,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI } @@ -184,7 +249,7 @@ index f3ffd99..6e0ecf9 100644 /*********************************************************************** * NtContinue (NTDLL.@) */ -@@ -850,7 +865,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a +@@ -865,7 +880,7 @@ unsigned int server_queue_process_apc( HANDLE process, const union apc_call *cal } else { @@ -193,7 +258,7 @@ index f3ffd99..6e0ecf9 100644 SERVER_START_REQ( get_apc_result ) { -@@ -1753,12 +1768,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE +@@ -1793,12 +1808,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE return result.dup_handle.status; } @@ -206,12 +271,12 @@ index f3ffd99..6e0ecf9 100644 if (options & DUPLICATE_CLOSE_SOURCE) + { fd = remove_fd_from_cache( source ); -+ close_fast_sync_obj( source ); ++ close_inproc_sync_obj( source ); + } SERVER_START_REQ( dup_handle ) { -@@ -1824,12 +1844,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) +@@ -1864,12 +1884,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) return STATUS_SUCCESS; @@ -223,13 +288,13 @@ index f3ffd99..6e0ecf9 100644 * retrieve it again */ fd = remove_fd_from_cache( handle ); -+ close_fast_sync_obj( handle ); ++ close_inproc_sync_obj( handle ); + SERVER_START_REQ( close_handle ) { req->handle = wine_server_obj_handle( handle ); diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index e070233..6e7fd4e 100644 +index d486b50001d..c3203debc0b 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -30,9 +30,11 @@ @@ -275,7 +340,7 @@ index e070233..6e7fd4e 100644 /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { -@@ -241,6 +249,902 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at +@@ -301,6 +309,901 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at } @@ -283,44 +348,44 @@ index e070233..6e7fd4e 100644 + +static int get_linux_sync_device(void) +{ -+ static LONG fast_sync_fd = -2; ++ static LONG device = -2; + -+ if (fast_sync_fd == -2) ++ if (device == -2) + { -+ HANDLE device; ++ HANDLE handle; + int fd, needs_close; + NTSTATUS ret; + + SERVER_START_REQ( get_linux_sync_device ) + { -+ if (!(ret = wine_server_call( req ))) device = wine_server_ptr_handle( reply->handle ); ++ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + if (!ret) + { -+ if (!server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )) ++ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) + { -+ if (InterlockedCompareExchange( &fast_sync_fd, fd, -2 ) != -2) ++ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) + { + /* someone beat us to it */ + if (needs_close) close( fd ); -+ NtClose( device ); ++ NtClose( handle ); + } + /* otherwise don't close the device */ + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); -+ NtClose( device ); ++ InterlockedCompareExchange( &device, -1, -2 ); ++ NtClose( handle ); + } + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); ++ InterlockedCompareExchange( &device, -1, -2 ); + } + } -+ return fast_sync_fd; ++ return device; +} + +/* It's possible for synchronization primitives to remain alive even after being @@ -328,10 +393,10 @@ index e070233..6e7fd4e 100644 + * documented as being undefined behaviour by Microsoft, but it works, and some + * applications rely on it. This means we need to refcount handles, and defer + * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the fast synchronization ++ * by having each client process hold a handle to the in-process synchronization + * object, as well as a private refcount. When the client refcount reaches zero, + * it closes the handle; when all handles are closed, the server deletes the -+ * fast synchronization object. ++ * in-process synchronization object. + * + * We also need this for signal-and-wait. The signal and wait operations aren't + * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE @@ -357,20 +422,20 @@ index e070233..6e7fd4e 100644 + * the same handle immediately reallocated to a different object. This should be + * a very rare situation, and in that case we simply don't cache the handle. + */ -+struct fast_sync_cache_entry ++struct inproc_sync_cache_entry +{ + LONG refcount; + int fd; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + unsigned int access; + BOOL closed; -+ /* handle to the underlying fast sync object, stored as obj_handle_t to save -+ * space */ ++ /* handle to the underlying in-process sync object, stored as obj_handle_t ++ * to save space */ + obj_handle_t handle; +}; + + -+static void release_fast_sync_obj( struct fast_sync_cache_entry *cache ) ++static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) +{ + /* save the handle and fd now; as soon as the refcount hits 0 we cannot + * access the cache anymore */ @@ -398,52 +463,52 @@ index e070233..6e7fd4e 100644 +} + + -+#define FAST_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct fast_sync_cache_entry)) -+#define FAST_SYNC_CACHE_ENTRIES 128 ++#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) ++#define INPROC_SYNC_CACHE_ENTRIES 128 + -+static struct fast_sync_cache_entry *fast_sync_cache[FAST_SYNC_CACHE_ENTRIES]; -+static struct fast_sync_cache_entry fast_sync_cache_initial_block[FAST_SYNC_CACHE_BLOCK_SIZE]; ++static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; ++static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; + -+static inline unsigned int fast_sync_handle_to_index( HANDLE handle, unsigned int *entry ) ++static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) +{ + unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / FAST_SYNC_CACHE_BLOCK_SIZE; -+ return idx % FAST_SYNC_CACHE_BLOCK_SIZE; ++ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; ++ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; +} + + -+static struct fast_sync_cache_entry *cache_fast_sync_obj( HANDLE handle, obj_handle_t fast_sync, int fd, -+ enum fast_sync_type type, unsigned int access ) ++static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, ++ enum inproc_sync_type type, unsigned int access ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + sigset_t sigset; + int refcount; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES) + { + FIXME( "too many allocated handles, not caching %p\n", handle ); + return NULL; + } + -+ if (!fast_sync_cache[entry]) /* do we need to allocate a new block of entries? */ ++ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ + { -+ if (!entry) fast_sync_cache[0] = fast_sync_cache_initial_block; ++ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; + else + { -+ static const size_t size = FAST_SYNC_CACHE_BLOCK_SIZE * sizeof(struct fast_sync_cache_entry); ++ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); + void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); + if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&fast_sync_cache[entry], ptr, NULL )) ++ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) + munmap( ptr, size ); /* someone beat us to it */ + } + } + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same + * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_fast_sync_obj() and close_handle. */ ++ * being cached again between close_inproc_sync_obj() and close_handle. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) @@ -457,13 +522,13 @@ index e070233..6e7fd4e 100644 + return NULL; + } + -+ cache->handle = fast_sync; ++ cache->handle = inproc_sync; + cache->fd = fd; + cache->type = type; + cache->access = access; + cache->closed = FALSE; + /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_fast_sync_obj()]. ++ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. + * Set the refcount to 2 (one for the handle, one for the caller). */ + refcount = InterlockedExchange( &cache->refcount, 2 ); + assert( !refcount ); @@ -487,18 +552,18 @@ index e070233..6e7fd4e 100644 +} + + -+static struct fast_sync_cache_entry *get_cached_fast_sync_obj( HANDLE handle ) ++static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES || !fast_sync_cache[entry]) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) + return NULL; + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* this load needs acquire semantics [paired with the store in -+ * cache_fast_sync_obj()] */ ++ * cache_inproc_sync_obj()] */ + if (!interlocked_inc_if_nonzero( &cache->refcount )) + return NULL; + @@ -508,7 +573,7 @@ index e070233..6e7fd4e 100644 + * handle value might have been reused for another object in the + * meantime, in which case we have to report that valid object, so + * force the caller to check the server. */ -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return NULL; + } + @@ -516,30 +581,31 @@ index e070233..6e7fd4e 100644 +} + + -+static BOOL fast_sync_types_match( enum fast_sync_type a, enum fast_sync_type b ) ++static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) +{ + if (a == b) return TRUE; -+ if (a == FAST_SYNC_AUTO_EVENT && b == FAST_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == FAST_SYNC_AUTO_EVENT && a == FAST_SYNC_MANUAL_EVENT) return TRUE; ++ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; ++ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; + return FALSE; +} + + +/* returns a pointer to a cache entry; if the object could not be cached, + * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_fast_sync_obj( HANDLE handle, enum fast_sync_type desired_type, ACCESS_MASK desired_access, -+ struct fast_sync_cache_entry *stack_cache, -+ struct fast_sync_cache_entry **ret_cache ) ++static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, ++ ACCESS_MASK desired_access, ++ struct inproc_sync_cache_entry *stack_cache, ++ struct inproc_sync_cache_entry **ret_cache ) +{ -+ struct fast_sync_cache_entry *cache; -+ obj_handle_t fast_sync_handle; -+ enum fast_sync_type type; ++ struct inproc_sync_cache_entry *cache; ++ obj_handle_t inproc_sync_handle; ++ enum inproc_sync_type type; + unsigned int access; + int fd, needs_close; + NTSTATUS ret; + + /* try to find it in the cache already */ -+ if ((cache = get_cached_fast_sync_obj( handle ))) ++ if ((cache = get_cached_inproc_sync_obj( handle ))) + { + *ret_cache = cache; + return STATUS_SUCCESS; @@ -551,7 +617,7 @@ index e070233..6e7fd4e 100644 + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { -+ fast_sync_handle = reply->handle; ++ inproc_sync_handle = reply->handle; + access = reply->access; + type = reply->type; + } @@ -560,15 +626,15 @@ index e070233..6e7fd4e 100644 + + if (ret) return ret; + -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( fast_sync_handle ), ++ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), + 0, &fd, &needs_close, NULL, NULL ))) + return ret; + -+ cache = cache_fast_sync_obj( handle, fast_sync_handle, fd, type, access ); ++ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); + if (!cache) + { + cache = stack_cache; -+ cache->handle = fast_sync_handle; ++ cache->handle = inproc_sync_handle; + cache->fd = fd; + cache->type = type; + cache->access = access; @@ -578,15 +644,15 @@ index e070233..6e7fd4e 100644 + + *ret_cache = cache; + -+ if (desired_type && !fast_sync_types_match( cache->type, desired_type )) ++ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + + if ((cache->access & desired_access) != desired_access) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_ACCESS_DENIED; + } + @@ -595,16 +661,16 @@ index e070233..6e7fd4e 100644 + + +/* caller must hold fd_cache_mutex */ -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ -+ struct fast_sync_cache_entry *cache = get_cached_fast_sync_obj( handle ); ++ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); + + if (cache) + { + cache->closed = TRUE; + /* once for the reference we just grabbed, and once for the handle */ -+ release_fast_sync_obj( cache ); -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + } +} + @@ -613,7 +679,7 @@ index e070233..6e7fd4e 100644 +{ + NTSTATUS ret; + -+ ret = ioctl( obj, NTSYNC_IOC_SEM_POST, &count ); ++ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); + if (ret < 0) + { + if (errno == EOVERFLOW) @@ -626,18 +692,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -656,18 +722,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_semaphore_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -685,18 +751,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_set_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -714,18 +780,18 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_reset_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -743,23 +809,23 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_pulse_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + + -+static NTSTATUS linux_query_event_obj( int obj, enum fast_sync_type type, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) +{ + struct ntsync_event_args args = {0}; + NTSTATUS ret; @@ -767,24 +833,24 @@ index e070233..6e7fd4e 100644 + ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); + if (ret < 0) + return errno_to_status( errno ); -+ info->EventType = (type == FAST_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; ++ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; + info->EventState = args.signaled; + return STATUS_SUCCESS; +} + + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_event_obj( cache->fd, cache->type, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -811,17 +877,17 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, 0, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) + return ret; + + ret = linux_release_mutex_obj( cache->fd, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -852,71 +918,69 @@ index e070233..6e7fd4e 100644 +} + + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, ++ &stack_cache, &cache ))) + return ret; + + ret = linux_query_mutex_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + -+static void select_queue( HANDLE queue ) ++static void select_queue(void) +{ -+ SERVER_START_REQ( fast_select_queue ) ++ SERVER_START_REQ( select_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static void unselect_queue( HANDLE queue, BOOL signaled ) ++static void unselect_queue( BOOL signaled ) +{ -+ SERVER_START_REQ( fast_unselect_queue ) ++ SERVER_START_REQ( unselect_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + req->signaled = signaled; + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static int get_fast_alert_obj(void) ++static int get_inproc_alert_obj(void) +{ + struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + HANDLE alert_handle; + unsigned int ret; + -+ if (!data->fast_alert_obj) ++ if (data->linux_alert_obj == -1) + { -+ SERVER_START_REQ( get_fast_alert_event ) ++ SERVER_START_REQ( get_inproc_alert_event ) + { + if ((ret = wine_server_call( req ))) -+ ERR( "failed to get fast alert event, status %#x\n", ret ); ++ ERR( "failed to get inproc alert event, status %#x\n", ret ); + alert_handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + -+ if ((ret = get_fast_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get fast alert obj, status %#x\n", ret ); -+ data->fast_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_fast_sync_obj() won't close it. ++ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) ++ ERR( "failed to get inproc alert obj, status %#x\n", ret ); ++ data->linux_alert_obj = cache->fd; ++ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. + * Manhandling the cache entry here is fine since we're the only thread + * that can access our own alert event. */ + cache->fd = -1; -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + NtClose( alert_handle ); + } + -+ return data->fast_alert_obj; ++ return data->linux_alert_obj; +} + +static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, @@ -948,7 +1012,7 @@ index e070233..6e7fd4e 100644 + args.index = ~0u; + + if (alertable) -+ args.alert = get_fast_alert_obj(); ++ args.alert = get_inproc_alert_obj(); + + if (wait_any || count == 1) + request = NTSYNC_IOC_WAIT_ANY; @@ -981,10 +1045,10 @@ index e070233..6e7fd4e 100644 + return errno_to_status( errno ); +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry stack_cache[64], *cache[64]; ++ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; + int device, objs[64]; + HANDLE queue = NULL; + NTSTATUS ret; @@ -995,13 +1059,13 @@ index e070233..6e7fd4e 100644 + + for (i = 0; i < count; ++i) + { -+ if ((ret = get_fast_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) ++ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) + { + for (j = 0; j < i; ++j) -+ release_fast_sync_obj( cache[j] ); ++ release_inproc_sync_obj( cache[j] ); + return ret; + } -+ if (cache[i]->type == FAST_SYNC_QUEUE) ++ if (cache[i]->type == INPROC_SYNC_QUEUE) + queue = handles[i]; + + objs[i] = cache[i]->fd; @@ -1009,32 +1073,32 @@ index e070233..6e7fd4e 100644 + + /* It's common to wait on the message queue alone. Some applications wait + * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through fast_wait_objs(), and since we only -+ * need to go through that path if we're waiting on other objects, just -+ * delegate to the server if we're only waiting on the message queue. */ ++ * instead of one when going through inproc_wait(), and since we only need ++ * to go through that path if we're waiting on other objects, just delegate ++ * to the server if we're only waiting on the message queue. */ + if (count == 1 && queue) + { -+ release_fast_sync_obj( cache[0] ); ++ release_inproc_sync_obj( cache[0] ); + return server_wait_for_object( handles[0], alertable, timeout ); + } + -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + + ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); + -+ if (queue) unselect_queue( queue, handles[ret] == queue ); ++ if (queue) unselect_queue( handles[ret] == queue ); + + for (i = 0; i < count; ++i) -+ release_fast_sync_obj( cache[i] ); ++ release_inproc_sync_obj( cache[i] ); + + return ret; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct fast_sync_cache_entry wait_stack_cache, *wait_cache; ++ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; ++ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; + HANDLE queue = NULL; + NTSTATUS ret; + int device; @@ -1042,58 +1106,58 @@ index e070233..6e7fd4e 100644 + if ((device = get_linux_sync_device()) < 0) + return STATUS_NOT_IMPLEMENTED; + -+ if ((ret = get_fast_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) ++ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) + return ret; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + if (!(signal_cache->access & EVENT_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + break; + + default: + /* can't be signaled */ -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + -+ if ((ret = get_fast_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) ++ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return ret; + } + -+ if (wait_cache->type == FAST_SYNC_QUEUE) ++ if (wait_cache->type == INPROC_SYNC_QUEUE) + queue = wait; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + ret = linux_set_event_obj( signal_cache->fd, NULL ); + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + ret = linux_release_mutex_obj( signal_cache->fd, NULL ); + break; + @@ -1104,70 +1168,70 @@ index e070233..6e7fd4e 100644 + + if (!ret) + { -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( queue, !ret ); ++ if (queue) unselect_queue( !ret ); + } + -+ release_fast_sync_obj( signal_cache ); -+ release_fast_sync_obj( wait_cache ); ++ release_inproc_sync_obj( signal_cache ); ++ release_inproc_sync_obj( wait_cache ); + return ret; +} + +#else + -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ +} + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} @@ -1178,7 +1242,7 @@ index e070233..6e7fd4e 100644 /****************************************************************************** * NtCreateSemaphore (NTDLL.@) */ -@@ -251,6 +1155,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ +@@ -311,6 +1214,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ data_size_t len; struct object_attributes *objattr; @@ -1188,7 +1252,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -278,6 +1185,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC +@@ -338,6 +1244,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC { unsigned int ret; @@ -1197,11 +1261,11 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -315,6 +1224,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla +@@ -375,6 +1283,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + return ret; @@ -1210,19 +1274,19 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_semaphore ) { req->handle = wine_server_obj_handle( handle ); -@@ -337,6 +1252,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous +@@ -397,6 +1311,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous { unsigned int ret; + TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); + -+ if ((ret = fast_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_semaphore ) { req->handle = wine_server_obj_handle( handle ); -@@ -361,6 +1281,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ +@@ -421,6 +1340,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr; @@ -1232,7 +1296,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -388,6 +1311,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT +@@ -448,6 +1370,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret; @@ -1241,47 +1305,47 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -413,6 +1338,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) +@@ -473,6 +1397,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -432,6 +1362,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) +@@ -492,6 +1421,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -461,6 +1396,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) +@@ -521,6 +1455,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) { unsigned int ret; + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( event_op ) { req->handle = wine_server_obj_handle( handle ); -@@ -492,6 +1432,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, +@@ -552,6 +1491,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); + return ret; @@ -1290,7 +1354,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_event ) { req->handle = wine_server_obj_handle( handle ); -@@ -517,6 +1463,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT +@@ -577,6 +1522,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT data_size_t len; struct object_attributes *objattr; @@ -1300,7 +1364,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -542,6 +1491,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A +@@ -602,6 +1550,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A { unsigned int ret; @@ -1309,23 +1373,23 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -567,6 +1518,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) +@@ -627,6 +1577,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) { unsigned int ret; + TRACE( "handle %p, prev_count %p\n", handle, prev_count ); + -+ if ((ret = fast_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) + return ret; + SERVER_START_REQ( release_mutex ) { req->handle = wine_server_obj_handle( handle ); -@@ -597,6 +1553,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, +@@ -657,6 +1612,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; -+ if ((ret = fast_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); + return ret; @@ -1334,7 +1398,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( query_mutex ) { req->handle = wine_server_obj_handle( handle ); -@@ -1325,6 +2287,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ +@@ -1426,6 +2387,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ data_size_t len; struct object_attributes *objattr; @@ -1344,7 +1408,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1352,6 +2317,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT +@@ -1453,6 +2417,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT { unsigned int ret; @@ -1353,7 +1417,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -1405,6 +2372,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) +@@ -1506,6 +2472,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) { unsigned int ret; @@ -1362,7 +1426,7 @@ index e070233..6e7fd4e 100644 SERVER_START_REQ( cancel_timer ) { req->handle = wine_server_obj_handle( handle ); -@@ -1473,13 +2442,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO +@@ -1574,13 +2542,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO { union select_op select_op; UINT i, flags = SELECT_INTERRUPTIBLE; @@ -1377,7 +1441,7 @@ index e070233..6e7fd4e 100644 + TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); + } + -+ if ((ret = fast_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + { + TRACE( "-> %#x\n", ret ); + return ret; @@ -1393,7 +1457,7 @@ index e070233..6e7fd4e 100644 } -@@ -1500,9 +2485,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, +@@ -1601,9 +2585,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, { union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1403,13 +1467,13 @@ index e070233..6e7fd4e 100644 if (!signal) return STATUS_INVALID_HANDLE; -+ if ((ret = fast_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + return ret; + if (alertable) flags |= SELECT_ALERTABLE; select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1735,6 +2726,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, +@@ -1836,6 +2826,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, data_size_t len; struct object_attributes *objattr; @@ -1419,7 +1483,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1759,6 +2753,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE +@@ -1860,6 +2853,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE { unsigned int ret; @@ -1428,7 +1492,7 @@ index e070233..6e7fd4e 100644 *handle = 0; if ((ret = validate_open_object_attributes( attr ))) return ret; -@@ -1785,6 +2781,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, +@@ -1886,6 +2881,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1437,7 +1501,7 @@ index e070233..6e7fd4e 100644 if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE; -@@ -1804,6 +2802,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, +@@ -1905,6 +2902,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, union select_op select_op; UINT flags = SELECT_INTERRUPTIBLE; @@ -1446,7 +1510,7 @@ index e070233..6e7fd4e 100644 if (!handle) handle = keyed_event; if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; if (alertable) flags |= SELECT_ALERTABLE; -@@ -2019,7 +2019,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * +@@ -2049,7 +3048,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * } SERVER_END_REQ; if (status != STATUS_PENDING) return status; @@ -1455,7 +1519,7 @@ index e070233..6e7fd4e 100644 else status = STATUS_TIMEOUT; if (status != WAIT_OBJECT_0) return status; -@@ -2081,7 +2081,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM +@@ -2111,7 +3110,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM assert( status == STATUS_USER_APC ); goto done; } @@ -1465,10 +1529,10 @@ index e070233..6e7fd4e 100644 if (status != WAIT_OBJECT_0) goto done; diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 3d151e7..68339d7 100644 +index cec6b3cb106..74b4eb9673a 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c -@@ -1798,7 +1798,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma +@@ -1801,7 +1801,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma if (ret == STATUS_PENDING) { @@ -1478,18 +1542,18 @@ index 3d151e7..68339d7 100644 SERVER_START_REQ( get_thread_context ) { diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index b278ab8..2226096 100644 +index f840045f841..8201e2934f3 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -101,6 +101,7 @@ struct ntdll_thread_data +@@ -112,6 +112,7 @@ struct ntdll_thread_data PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ void *jmp_buf; /* setjmp buffer for exception handling */ -+ int fast_alert_obj; /* fd for the fast alert event */ ++ int linux_alert_obj; /* fd for the linux in-process alert event */ }; C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -194,6 +195,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); +@@ -205,6 +206,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); extern void start_server( BOOL debug ); @@ -1498,24 +1562,24 @@ index b278ab8..2226096 100644 extern unsigned int server_call_unlocked( void *req_ptr ); extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -201,6 +204,7 @@ extern unsigned int server_select( const select_op_t *select_op, data_size_t siz - timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, +@@ -212,6 +215,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t + timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc ); + extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags, const LARGE_INTEGER *timeout ); +extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, union apc_result *result ); extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -360,6 +364,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); +@@ -378,6 +382,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); extern void dbg_init(void); -+extern void close_fast_sync_obj( HANDLE handle ); ++extern void close_inproc_sync_obj( HANDLE handle ); + extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ); extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -368,6 +374,7 @@ extern void call_raise_user_exception_dispatcher(void); +@@ -386,6 +392,7 @@ extern void call_raise_user_exception_dispatcher(void); #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ #define TICKSPERSEC 10000000 @@ -1523,7 +1587,7 @@ index b278ab8..2226096 100644 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -426,7 +433,7 @@ static inline async_data_t server_async( HANDLE handle, struct async_fileio *use +@@ -451,7 +458,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) { @@ -1532,8 +1596,20 @@ index b278ab8..2226096 100644 } static inline BOOL in_wow64_call(void) +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index 0c0a12c394d..7567362a542 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -3689,6 +3689,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) + thread_data->reply_fd = -1; + thread_data->wait_fd[0] = -1; + thread_data->wait_fd[1] = -1; ++ thread_data->linux_alert_obj = -1; + list_add_head( &teb_list, &thread_data->entry ); + return teb; + } diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027f..ddcf896 100644 +index c64027fb86d..ddcf8964f23 100644 --- a/dlls/webservices/tests/channel.c +++ b/dlls/webservices/tests/channel.c @@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { @@ -1547,10 +1623,10 @@ index c64027f..ddcf896 100644 { char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; diff --git a/include/config.h.in b/include/config.h.in -index 65743b5..456344b 100644 +index 6033d8674f3..7fb12090dfe 100644 --- a/include/config.h.in +++ b/include/config.h.in -@@ -180,6 +180,9 @@ +@@ -189,6 +189,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_MAJOR_H @@ -1561,22 +1637,22 @@ index 65743b5..456344b 100644 #undef HAVE_LINUX_PARAM_H diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index 48e778c..e809f98 100644 +index f524a3dc8b5..a6c74fa79e0 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h -@@ -5649,6 +5649,88 @@ struct get_next_thread_reply +@@ -5881,6 +5881,86 @@ struct set_keyboard_repeat_reply }; -+enum fast_sync_type ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + @@ -1611,38 +1687,36 @@ index 48e778c..e809f98 100644 + + + -+struct fast_select_queue_request ++struct select_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; ++ char __pad_12[4]; +}; -+struct fast_select_queue_reply ++struct select_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct fast_unselect_queue_request ++struct unselect_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; + int signaled; -+ char __pad_20[4]; +}; -+struct fast_unselect_queue_reply ++struct unselect_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct get_fast_alert_event_request ++struct get_inproc_alert_event_request +{ + struct request_header __header; + char __pad_12[4]; +}; -+struct get_fast_alert_event_reply ++struct get_inproc_alert_event_reply +{ + struct reply_header __header; + obj_handle_t handle; @@ -1653,218 +1727,221 @@ index 48e778c..e809f98 100644 enum request { REQ_new_process, -@@ -5936,7 +6018,12 @@ enum request - REQ_suspend_process, +@@ -6175,6 +6255,11 @@ enum request REQ_resume_process, REQ_get_next_thread, + REQ_set_keyboard_repeat, + REQ_get_linux_sync_device, + REQ_get_linux_sync_obj, -+ REQ_fast_select_queue, -+ REQ_fast_unselect_queue, - REQ_set_keyboard_repeat, -+ REQ_get_fast_alert_event, ++ REQ_select_inproc_queue, ++ REQ_unselect_inproc_queue, ++ REQ_get_inproc_alert_event, REQ_NB_REQUESTS }; -@@ -6228,7 +6315,12 @@ union generic_request - struct suspend_process_request suspend_process_request; +@@ -6474,6 +6559,11 @@ union generic_request struct resume_process_request resume_process_request; struct get_next_thread_request get_next_thread_request; + struct set_keyboard_repeat_request set_keyboard_repeat_request; + struct get_linux_sync_device_request get_linux_sync_device_request; + struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct fast_select_queue_request fast_select_queue_request; -+ struct fast_unselect_queue_request fast_unselect_queue_request; - struct set_keyboard_repeat_request set_keyboard_repeat_request; -+ struct get_fast_alert_event_request get_fast_alert_event_request; ++ struct select_inproc_queue_request select_inproc_queue_request; ++ struct unselect_inproc_queue_request unselect_inproc_queue_request; ++ struct get_inproc_alert_event_request get_inproc_alert_event_request; }; union generic_reply { -@@ -6518,7 +6610,12 @@ union generic_reply - struct suspend_process_reply suspend_process_reply; +@@ -6771,8 +6861,13 @@ union generic_reply struct resume_process_reply resume_process_reply; struct get_next_thread_reply get_next_thread_reply; + struct set_keyboard_repeat_reply set_keyboard_repeat_reply; + struct get_linux_sync_device_reply get_linux_sync_device_reply; + struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct fast_select_queue_reply fast_select_queue_reply; -+ struct fast_unselect_queue_reply fast_unselect_queue_reply; - struct set_keyboard_repeat_reply set_keyboard_repeat_reply; -+ struct get_fast_alert_event_reply get_fast_alert_event_reply; ++ struct select_inproc_queue_reply select_inproc_queue_reply; ++ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; ++ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; }; - /* ### protocol_version begin ### */ +-#define SERVER_PROTOCOL_VERSION 854 ++#define SERVER_PROTOCOL_VERSION 855 + + #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/Makefile.in b/server/Makefile.in -index 7b46b92..d21bd55 100644 +index 7e571ac2ba6..91ec73dabc5 100644 --- a/server/Makefile.in +++ b/server/Makefile.in -@@ -12,6 +12,7 @@ SOURCES = \ - device.c \ - directory.c \ - event.c \ -+ fast_sync.c \ - fd.c \ +@@ -16,6 +16,7 @@ SOURCES = \ file.c \ handle.c \ + hook.c \ ++ inproc_sync.c \ + mach.c \ + mailslot.c \ + main.c \ diff --git a/server/async.c b/server/async.c -index 80129ac..02fb966 100644 +index d2d929c9709..e8b50a72f7e 100644 --- a/server/async.c +++ b/server/async.c -@@ -89,6 +89,7 @@ static const struct object_ops async_ops = +@@ -90,6 +90,7 @@ static const struct object_ops async_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ async_destroy /* destroy */ }; -@@ -698,6 +699,7 @@ static const struct object_ops iosb_ops = +@@ -710,6 +711,7 @@ static const struct object_ops iosb_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ iosb_destroy /* destroy */ }; diff --git a/server/atom.c b/server/atom.c -index ff0799f..ba320c4 100644 +index ff0799f5880..04951e628ba 100644 --- a/server/atom.c +++ b/server/atom.c @@ -91,6 +91,7 @@ static const struct object_ops atom_table_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; diff --git a/server/change.c b/server/change.c -index f773ccf..d902578 100644 +index f42ce066340..92d321c8784 100644 --- a/server/change.c +++ b/server/change.c @@ -124,6 +124,7 @@ static const struct object_ops dir_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; diff --git a/server/clipboard.c b/server/clipboard.c -index 8118a46..de9f84f 100644 +index 91f159bc7c9..a2258ae869d 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ clipboard_destroy /* destroy */ }; diff --git a/server/completion.c b/server/completion.c -index 6933195..5ec6d20 100644 +index 99680ae0680..529ed9d7956 100644 --- a/server/completion.c +++ b/server/completion.c -@@ -77,6 +77,7 @@ +@@ -77,6 +77,7 @@ struct completion struct list wait_queue; unsigned int depth; int closed; -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; }; static void completion_wait_dump( struct object*, int ); -@@ -104,6 +105,7 @@ +@@ -104,6 +105,7 @@ static const struct object_ops completion_wait_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ completion_wait_destroy /* destroy */ }; -@@ -149,12 +151,17 @@ - msg = LIST_ENTRY( msg_entry, struct comp_msg, queue_entry ); - --wait->completion->depth; - list_remove( &msg->queue_entry ); -+ if (list_empty( &wait->completion->queue )) -+ { -+ fast_reset_event( wait->completion->fast_sync ); -+ } - if (wait->msg) free( wait->msg ); - wait->msg = msg; - } - +@@ -156,6 +158,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent static void completion_dump( struct object*, int ); static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *completion_get_fast_sync( struct object *obj ); static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); static void completion_destroy( struct object * ); -@@ -178,6 +185,7 @@ + static const struct object_ops completion_ops = +@@ -178,6 +181,7 @@ static const struct object_ops completion_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_fast_sync, /* get_fast_sync */ ++ completion_get_inproc_sync,/* get_inproc_sync */ completion_close_handle, /* close_handle */ completion_destroy /* destroy */ }; -@@ -191,6 +199,7 @@ +@@ -191,6 +195,7 @@ static void completion_destroy( struct object *obj) { free( tmp ); } -+ if (completion->fast_sync) release_object( completion->fast_sync ); ++ if (completion->inproc_sync) release_object( completion->inproc_sync ); } static void completion_dump( struct object *obj, int verbose ) -@@ -261,6 +270,16 @@ +@@ -228,6 +233,7 @@ static int completion_close_handle( struct object *obj, struct process *process, + } + completion->closed = 1; + wake_up( obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); + return 1; + } + +@@ -261,6 +267,16 @@ static struct completion_wait *create_completion_wait( struct thread *thread ) return wait; } -+static struct fast_sync *completion_get_fast_sync( struct object *obj ) ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) +{ + struct completion *completion = (struct completion *)obj; + -+ if (!completion->fast_sync) -+ completion->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->fast_sync) grab_object( completion->fast_sync ); -+ return completion->fast_sync; ++ if (!completion->inproc_sync) ++ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); ++ if (completion->inproc_sync) grab_object( completion->inproc_sync ); ++ return completion->inproc_sync; +} + static struct completion *create_completion( struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent, const struct security_descriptor *sd ) -@@ -275,6 +294,7 @@ +@@ -275,6 +291,7 @@ static struct completion *create_completion( struct object *root, const struct u list_init( &completion->wait_queue ); completion->depth = 0; completion->closed = 0; -+ completion->fast_sync = NULL; ++ completion->inproc_sync = NULL; } } -@@ -308,6 +328,7 @@ +@@ -307,7 +324,11 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ + wake_up( &wait->obj, 1 ); if (list_empty( &completion->queue )) return; } - if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ fast_set_event( completion->fast_sync ); +- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); ++ if (!list_empty( &completion->queue )) ++ { ++ wake_up( &completion->obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); ++ } } /* create a completion */ -@@ -404,6 +425,8 @@ +@@ -408,6 +429,8 @@ DECL_HANDLER(remove_completion) reply->information = msg->information; free( msg ); reply->wait_handle = 0; + if (list_empty( &completion->queue )) -+ fast_reset_event( completion->fast_sync ); ++ reset_inproc_event( completion->inproc_sync ); } release_object( completion ); diff --git a/server/console.c b/server/console.c -index b64283b..17708df 100644 +index c3e7bf57e92..b4058f2d002 100644 --- a/server/console.c +++ b/server/console.c @@ -61,6 +61,7 @@ struct console struct fd *fd; /* for bare console, attached input fd */ struct async_queue ioctl_q; /* ioctl queue */ struct async_queue read_q; /* read queue */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_dump( struct object *obj, int verbose ); @@ -1872,7 +1949,7 @@ index b64283b..17708df 100644 static struct object *console_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *console_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ); static const struct object_ops console_ops = { @@ -1880,7 +1957,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ console_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_fast_sync, /* get_fast_sync */ ++ console_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_destroy /* destroy */ }; @@ -1888,7 +1965,7 @@ index b64283b..17708df 100644 unsigned int once_input : 1; /* flag if input thread has already been requested */ int term_fd; /* UNIX terminal fd */ struct termios termios; /* original termios */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_server_dump( struct object *obj, int verbose ); @@ -1896,7 +1973,7 @@ index b64283b..17708df 100644 unsigned int attr, struct object *root ); static struct object *console_server_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); static const struct object_ops console_server_ops = { @@ -1904,7 +1981,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ console_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_fast_sync, /* get_fast_sync */ ++ console_server_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_server_destroy /* destroy */ }; @@ -1912,7 +1989,7 @@ index b64283b..17708df 100644 static struct fd *screen_buffer_get_fd( struct object *obj ); static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); static const struct object_ops screen_buffer_ops = { @@ -1920,7 +1997,7 @@ index b64283b..17708df 100644 NULL, /* unlink_name */ screen_buffer_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_fast_sync, /* get_fast_sync */ ++ screen_buffer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; @@ -1928,7 +2005,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -1936,7 +2013,7 @@ index b64283b..17708df 100644 unsigned int sharing, unsigned int options ); static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); static void console_input_destroy( struct object *obj ); static const struct object_ops console_input_ops = @@ -1944,7 +2021,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_input_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_fast_sync, /* get_fast_sync */ ++ console_input_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -1952,7 +2029,7 @@ index b64283b..17708df 100644 static struct fd *console_output_get_fd( struct object *obj ); static struct object *console_output_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); static void console_output_destroy( struct object *obj ); static const struct object_ops console_output_ops = @@ -1960,7 +2037,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_output_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_fast_sync, /* get_fast_sync */ ++ console_output_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_output_destroy /* destroy */ }; @@ -1968,7 +2045,7 @@ index b64283b..17708df 100644 default_unlink_name, /* unlink_name */ console_connection_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ console_connection_close_handle, /* close_handle */ console_connection_destroy /* destroy */ }; @@ -1976,7 +2053,7 @@ index b64283b..17708df 100644 console->server = NULL; console->fd = NULL; console->last_id = 0; -+ console->fast_sync = NULL; ++ console->inproc_sync = NULL; init_async_queue( &console->ioctl_q ); init_async_queue( &console->read_q ); @@ -1984,7 +2061,7 @@ index b64283b..17708df 100644 } list_add_tail( &server->queue, &ioctl->entry ); wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); if (async) set_error( STATUS_PENDING ); return 1; } @@ -1992,7 +2069,7 @@ index b64283b..17708df 100644 server->console->server = NULL; server->console = NULL; wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); } } @@ -2001,32 +2078,32 @@ index b64283b..17708df 100644 if (console->fd) release_object( console->fd ); + -+ if (console->fast_sync) release_object( console->fast_sync ); ++ if (console->inproc_sync) release_object( console->inproc_sync ); } static struct object *create_console_connection( struct console *console ) -@@ -811,6 +830,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access +@@ -817,6 +836,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access return grab_object( obj ); } -+static struct fast_sync *console_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ) +{ + struct console *console = (struct console *)obj; + -+ if (!console->fast_sync) -+ console->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->fast_sync) grab_object( console->fast_sync ); -+ return console->fast_sync; ++ if (!console->inproc_sync) ++ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); ++ if (console->inproc_sync) grab_object( console->inproc_sync ); ++ return console->inproc_sync; +} + static void screen_buffer_dump( struct object *obj, int verbose ) { struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -860,6 +889,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) +@@ -866,6 +895,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) return NULL; } -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) +{ + struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; + if (!screen_buffer->input) @@ -2034,81 +2111,81 @@ index b64283b..17708df 100644 + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( &screen_buffer->input->obj ); ++ return console_get_inproc_sync( &screen_buffer->input->obj ); +} + static void console_server_dump( struct object *obj, int verbose ) { assert( obj->ops == &console_server_ops ); -@@ -872,6 +912,7 @@ static void console_server_destroy( struct object *obj ) +@@ -878,6 +918,7 @@ static void console_server_destroy( struct object *obj ) assert( obj->ops == &console_server_ops ); disconnect_console_server( server ); if (server->fd) release_object( server->fd ); -+ if (server->fast_sync) release_object( server->fast_sync ); ++ if (server->inproc_sync) release_object( server->inproc_sync ); } static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -926,6 +967,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int +@@ -938,6 +979,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) +{ + struct console_server *server = (struct console_server *)obj; + int signaled = !server->console || !list_empty( &server->queue ); + -+ if (!server->fast_sync) -+ server->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (server->fast_sync) grab_object( server->fast_sync ); -+ return server->fast_sync; ++ if (!server->inproc_sync) ++ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (server->inproc_sync) grab_object( server->inproc_sync ); ++ return server->inproc_sync; +} + static struct object *create_console_server( void ) { struct console_server *server; -@@ -937,6 +989,7 @@ static struct object *create_console_server( void ) +@@ -949,6 +1001,7 @@ static struct object *create_console_server( void ) server->term_fd = -1; list_init( &server->queue ); list_init( &server->read_queue ); -+ server->fast_sync = NULL; ++ server->inproc_sync = NULL; server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!server->fd) { -@@ -1402,6 +1455,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int +@@ -1414,6 +1467,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_input_destroy( struct object *obj ) { struct console_input *console_input = (struct console_input *)obj; -@@ -1474,6 +1537,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int +@@ -1486,6 +1549,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int return grab_object( obj ); } -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console || !current->process->console->active) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_output_destroy( struct object *obj ) { struct console_output *console_output = (struct console_output *)obj; -@@ -1531,11 +1604,16 @@ DECL_HANDLER(get_next_console_request) +@@ -1543,11 +1616,16 @@ DECL_HANDLER(get_next_console_request) if (!server->console->renderer) server->console->renderer = current; @@ -2116,43 +2193,43 @@ index b64283b..17708df 100644 + if (!req->signal) + { + server->console->signaled = 0; -+ fast_reset_event( server->console->fast_sync ); ++ reset_inproc_event( server->console->inproc_sync ); + } else if (!server->console->signaled) { server->console->signaled = 1; wake_up( &server->console->obj, 0 ); -+ fast_set_event( server->console->fast_sync ); ++ set_inproc_event( server->console->inproc_sync ); } if (req->read) -@@ -1557,6 +1635,8 @@ DECL_HANDLER(get_next_console_request) +@@ -1569,6 +1647,8 @@ DECL_HANDLER(get_next_console_request) /* set result of previous ioctl */ ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); list_remove( &ioctl->entry ); + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); } if (ioctl) -@@ -1643,5 +1723,8 @@ DECL_HANDLER(get_next_console_request) +@@ -1655,5 +1735,8 @@ DECL_HANDLER(get_next_console_request) set_error( STATUS_PENDING ); } + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); + release_object( server ); } diff --git a/server/debugger.c b/server/debugger.c -index c59a0ab..7975fc4 100644 +index 39a740e07e5..35449172eaa 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -71,6 +71,7 @@ struct debug_obj struct object obj; /* object header */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; @@ -2160,14 +2237,14 @@ index c59a0ab..7975fc4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; static void debug_obj_dump( struct object *obj, int verbose ); static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ); ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); static void debug_obj_destroy( struct object *obj ); static const struct object_ops debug_obj_ops = @@ -2175,7 +2252,7 @@ index c59a0ab..7975fc4 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_fast_sync, /* get_fast_sync */ ++ debug_obj_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_obj_destroy /* destroy */ }; @@ -2183,7 +2260,7 @@ index c59a0ab..7975fc4 100644 /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -2191,7 +2268,7 @@ index c59a0ab..7975fc4 100644 { grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -2199,15 +2276,15 @@ index c59a0ab..7975fc4 100644 return find_event_to_send( debug_obj ) != NULL; } -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ) ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) +{ + struct debug_obj *debug_obj = (struct debug_obj *)obj; + int signaled = find_event_to_send( debug_obj ) != NULL; + -+ if (!debug_obj->fast_sync) -+ debug_obj->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->fast_sync) grab_object( debug_obj->fast_sync ); -+ return debug_obj->fast_sync; ++ if (!debug_obj->inproc_sync) ++ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); ++ return debug_obj->inproc_sync; +} + static void debug_obj_destroy( struct object *obj ) @@ -2218,7 +2295,7 @@ index c59a0ab..7975fc4 100644 while ((ptr = list_head( &debug_obj->event_queue ))) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); + -+ if (debug_obj->fast_sync) release_object( debug_obj->fast_sync ); ++ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); } struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -2226,7 +2303,7 @@ index c59a0ab..7975fc4 100644 { debug_obj->flags = flags; list_init( &debug_obj->event_queue ); -+ debug_obj->fast_sync = NULL; ++ debug_obj->inproc_sync = NULL; } } return debug_obj; @@ -2236,19 +2313,19 @@ index c59a0ab..7975fc4 100644 set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); + + if (!find_event_to_send( debug_obj )) -+ fast_reset_event( debug_obj->fast_sync ); ++ reset_inproc_event( debug_obj->inproc_sync ); } else { diff --git a/server/device.c b/server/device.c -index 436dac6..698fee6 100644 +index cab09700d8c..72410c2da8b 100644 --- a/server/device.c +++ b/server/device.c @@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ irp_call_destroy /* destroy */ }; @@ -2256,12 +2333,12 @@ index 436dac6..698fee6 100644 struct list requests; /* list of pending irps across all devices */ struct irp_call *current_call; /* call currently executed on client side */ struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void device_manager_dump( struct object *obj, int verbose ); static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ); ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); static void device_manager_destroy( struct object *obj ); static const struct object_ops device_manager_ops = @@ -2269,7 +2346,7 @@ index 436dac6..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_fast_sync, /* get_fast_sync */ ++ device_manager_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_manager_destroy /* destroy */ }; @@ -2277,7 +2354,7 @@ index 436dac6..698fee6 100644 default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -2285,11 +2362,11 @@ index 436dac6..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ device_file_close_handle, /* close_handle */ device_file_destroy /* destroy */ }; -@@ -417,7 +423,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i +@@ -418,7 +424,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); list_add_tail( &manager->requests, &irp->mgr_entry ); @@ -2298,75 +2375,75 @@ index 436dac6..698fee6 100644 + { + /* first one */ + wake_up( &manager->obj, 0 ); -+ fast_set_event( manager->fast_sync ); ++ set_inproc_event( manager->inproc_sync ); + } } static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -751,6 +762,9 @@ static void delete_file( struct device_file *file ) +@@ -752,6 +763,9 @@ static void delete_file( struct device_file *file ) set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); } + if (list_empty( &file->device->manager->requests )) -+ fast_reset_event( file->device->manager->fast_sync ); ++ reset_inproc_event( file->device->manager->inproc_sync ); + release_object( file ); } -@@ -782,6 +796,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry +@@ -783,6 +797,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry return !list_empty( &manager->requests ); } -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ) ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) +{ + struct device_manager *manager = (struct device_manager *)obj; + -+ if (!manager->fast_sync) -+ manager->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->fast_sync) grab_object( manager->fast_sync ); -+ return manager->fast_sync; ++ if (!manager->inproc_sync) ++ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); ++ if (manager->inproc_sync) grab_object( manager->inproc_sync ); ++ return manager->inproc_sync; +} + static void device_manager_destroy( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; -@@ -816,6 +840,8 @@ static void device_manager_destroy( struct object *obj ) +@@ -817,6 +841,8 @@ static void device_manager_destroy( struct object *obj ) assert( !irp->file && !irp->async ); release_object( irp ); } + -+ if (manager->fast_sync) release_object( manager->fast_sync ); ++ if (manager->inproc_sync) release_object( manager->inproc_sync ); } static struct device_manager *create_device_manager(void) -@@ -825,6 +851,7 @@ static struct device_manager *create_device_manager(void) +@@ -826,6 +852,7 @@ static struct device_manager *create_device_manager(void) if ((manager = alloc_object( &device_manager_ops ))) { manager->current_call = NULL; -+ manager->fast_sync = NULL; ++ manager->inproc_sync = NULL; list_init( &manager->devices ); list_init( &manager->requests ); wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -@@ -1014,6 +1041,10 @@ DECL_HANDLER(get_next_device_request) +@@ -1015,6 +1042,10 @@ DECL_HANDLER(get_next_device_request) } list_remove( &irp->mgr_entry ); list_init( &irp->mgr_entry ); + + if (list_empty( &manager->requests )) -+ fast_reset_event( manager->fast_sync ); ++ reset_inproc_event( manager->inproc_sync ); + /* we already own the object if it's only on manager queue */ if (irp->file) grab_object( irp ); manager->current_call = irp; diff --git a/server/directory.c b/server/directory.c -index e521a7b..4e7fc5e 100644 +index fd689c561bc..40cb9b95999 100644 --- a/server/directory.c +++ b/server/directory.c @@ -81,6 +81,7 @@ static const struct object_ops object_type_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -2374,19 +2451,19 @@ index e521a7b..4e7fc5e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ }; diff --git a/server/event.c b/server/event.c -index f1b79b1..b750a22 100644 +index ad7c09acc99..4fb44d70039 100644 --- a/server/event.c +++ b/server/event.c @@ -56,6 +56,7 @@ struct event struct list kernel_object; /* list of kernel object pointers */ int manual_reset; /* is it a manual reset event? */ int signaled; /* event has been signaled */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void event_dump( struct object *obj, int verbose ); @@ -2394,7 +2471,7 @@ index f1b79b1..b750a22 100644 static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int event_signal( struct object *obj, unsigned int access); static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ); +static void event_destroy( struct object *obj ); static const struct object_ops event_ops = @@ -2403,7 +2480,7 @@ index f1b79b1..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_fast_sync, /* get_fast_sync */ ++ event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + event_destroy /* destroy */ @@ -2414,12 +2491,12 @@ index f1b79b1..b750a22 100644 struct keyed_event { struct object obj; /* object header */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void keyed_event_dump( struct object *obj, int verbose ); static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); +static void keyed_event_destroy( struct object *obj ); static const struct object_ops keyed_event_ops = @@ -2428,7 +2505,7 @@ index f1b79b1..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_fast_sync, /* get_fast_sync */ ++ keyed_event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + keyed_event_destroy /* destroy */ @@ -2439,7 +2516,7 @@ index f1b79b1..b750a22 100644 list_init( &event->kernel_object ); event->manual_reset = manual_reset; event->signaled = initial_state; -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -2447,13 +2524,13 @@ index f1b79b1..b750a22 100644 event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ wake_up( &event->obj, !event->manual_reset ); -+ fast_set_event( event->fast_sync ); ++ set_inproc_event( event->inproc_sync ); } void reset_event( struct event *event ) { event->signaled = 0; -+ fast_reset_event( event->fast_sync ); ++ reset_inproc_event( event->inproc_sync ); } static void event_dump( struct object *obj, int verbose ) @@ -2461,24 +2538,24 @@ index f1b79b1..b750a22 100644 return &event->kernel_object; } -+static struct fast_sync *event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (!event->fast_sync) ++ if (!event->inproc_sync) + { -+ enum fast_sync_type type = event->manual_reset ? FAST_SYNC_MANUAL_EVENT : FAST_SYNC_AUTO_EVENT; -+ event->fast_sync = fast_create_event( type, event->signaled ); ++ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; ++ event->inproc_sync = create_inproc_event( type, event->signaled ); + } -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void event_destroy( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, @@ -2488,7 +2565,7 @@ index f1b79b1..b750a22 100644 if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -2496,34 +2573,187 @@ index f1b79b1..b750a22 100644 return 0; } -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (!event->fast_sync) -+ event->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, 1 ); -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (!event->inproc_sync) ++ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void keyed_event_destroy( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + /* create an event */ DECL_HANDLER(create_event) { -diff --git a/server/fast_sync.c b/server/fast_sync.c +diff --git a/server/fd.c b/server/fd.c +index ce32e7f8397..77ac22b9655 100644 +--- a/server/fd.c ++++ b/server/fd.c +@@ -154,6 +154,7 @@ struct fd + struct completion *completion; /* completion object attached to this fd */ + apc_param_t comp_key; /* completion key to set in completion events */ + unsigned int comp_flags; /* completion flags */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ + }; + + static void fd_dump( struct object *obj, int verbose ); +@@ -179,6 +180,7 @@ static const struct object_ops fd_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + fd_destroy /* destroy */ + }; +@@ -220,6 +222,7 @@ static const struct object_ops device_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + device_destroy /* destroy */ + }; +@@ -260,6 +263,7 @@ static const struct object_ops inode_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + inode_destroy /* destroy */ + }; +@@ -302,6 +306,7 @@ static const struct object_ops file_lock_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + no_destroy /* destroy */ + }; +@@ -1572,6 +1577,7 @@ static void fd_destroy( struct object *obj ) + if (fd->unix_fd != -1) close( fd->unix_fd ); + free( fd->unix_name ); + } ++ if (fd->inproc_sync) release_object( fd->inproc_sync ); + } + + /* check if the desired access is possible without violating */ +@@ -1690,6 +1696,7 @@ static struct fd *alloc_fd_object(void) + fd->poll_index = -1; + fd->completion = NULL; + fd->comp_flags = 0; ++ fd->inproc_sync = NULL; + init_async_queue( &fd->read_q ); + init_async_queue( &fd->write_q ); + init_async_queue( &fd->wait_q ); +@@ -1730,6 +1737,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use + fd->poll_index = -1; + fd->completion = NULL; + fd->comp_flags = 0; ++ fd->inproc_sync = NULL; + fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; + init_async_queue( &fd->read_q ); + init_async_queue( &fd->write_q ); +@@ -2140,7 +2148,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) + { + if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; + fd->signaled = signaled; +- if (signaled) wake_up( fd->user, 0 ); ++ if (signaled) ++ { ++ wake_up( fd->user, 0 ); ++ set_inproc_event( fd->inproc_sync ); ++ } ++ else ++ { ++ reset_inproc_event( fd->inproc_sync ); ++ } + } + + /* check if events are pending and if yes return which one(s) */ +@@ -2166,6 +2182,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) + return ret; + } + ++struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) ++{ ++ struct fd *fd = get_obj_fd( obj ); ++ struct inproc_sync *ret; ++ ++ if (!fd->inproc_sync) ++ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); ++ ret = fd->inproc_sync; ++ release_object( fd ); ++ if (ret) grab_object( ret ); ++ return ret; ++} ++ + int default_fd_get_poll_events( struct fd *fd ) + { + int events = 0; +diff --git a/server/file.c b/server/file.c +index 8f6566a0077..bab203b1914 100644 +--- a/server/file.c ++++ b/server/file.c +@@ -106,6 +106,7 @@ static const struct object_ops file_ops = + NULL, /* unlink_name */ + file_open_file, /* open_file */ + file_get_kernel_obj_list, /* get_kernel_obj_list */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + file_destroy /* destroy */ + }; +diff --git a/server/file.h b/server/file.h +index 4f5fc7b26f1..882976e9e02 100644 +--- a/server/file.h ++++ b/server/file.h +@@ -109,6 +109,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre + extern void get_nt_name( struct fd *fd, struct unicode_str *name ); + + extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); ++extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); + 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 +index e65831b3b22..29b43789372 100644 +--- a/server/handle.c ++++ b/server/handle.c +@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + handle_table_destroy /* destroy */ + }; +diff --git a/server/hook.c b/server/hook.c +index c2d2823cd61..c45900549fc 100644 +--- a/server/hook.c ++++ b/server/hook.c +@@ -93,6 +93,7 @@ static const struct object_ops hook_table_ops = + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + hook_table_destroy /* destroy */ + }; +diff --git a/server/inproc_sync.c b/server/inproc_sync.c new file mode 100644 -index 0000000..fed6eb9 +index 00000000000..6dd50d79bc0 --- /dev/null -+++ b/server/fast_sync.c -@@ -0,0 +1,434 @@ ++++ b/server/inproc_sync.c +@@ -0,0 +1,437 @@ +/* -+ * Fast synchronization primitives ++ * In-process synchronization primitives + * + * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers + * @@ -2577,7 +2807,7 @@ index 0000000..fed6eb9 +static void linux_device_dump( struct object *obj, int verbose ); +static struct fd *linux_device_get_fd( struct object *obj ); +static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ); ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); + +static const struct object_ops linux_device_ops = +{ @@ -2599,16 +2829,16 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_device_destroy /* destroy */ +}; + -+static const struct fd_ops fast_sync_fd_ops = ++static const struct fd_ops inproc_sync_fd_ops = +{ + default_fd_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ -+ fast_sync_get_fd_type, /* get_fd_type */ ++ inproc_sync_get_fd_type, /* get_fd_type */ + no_fd_read, /* read */ + no_fd_write, /* write */ + no_fd_flush, /* flush */ @@ -2624,7 +2854,7 @@ index 0000000..fed6eb9 +{ + struct linux_device *device = (struct linux_device *)obj; + assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "Fast synchronization device fd=%p\n", device->fd ); ++ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); +} + +static struct fd *linux_device_get_fd( struct object *obj ) @@ -2641,7 +2871,7 @@ index 0000000..fed6eb9 + linux_device_object = NULL; +} + -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ) ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) +{ + return FD_TYPE_FILE; +} @@ -2688,7 +2918,7 @@ index 0000000..fed6eb9 + return NULL; + } + -+ if (!(device->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &device->obj, 0 ))) ++ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) + { + release_object( device ); + initialized = 1; @@ -2701,10 +2931,10 @@ index 0000000..fed6eb9 + return device; +} + -+struct fast_sync ++struct inproc_sync +{ + struct object obj; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + struct fd *fd; +}; + @@ -2714,7 +2944,7 @@ index 0000000..fed6eb9 + +static const struct object_ops linux_obj_ops = +{ -+ sizeof(struct fast_sync), /* size */ ++ sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + linux_obj_dump, /* dump */ + no_add_queue, /* add_queue */ @@ -2732,80 +2962,81 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_obj_destroy /* destroy */ +}; + +static void linux_obj_dump( struct object *obj, int verbose ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "Fast synchronization object type=%u fd=%p\n", fast_sync->type, fast_sync->fd ); ++ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); +} + +static void linux_obj_destroy( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ if (fast_sync->fd) release_object( fast_sync->fd ); ++ if (inproc_sync->fd) release_object( inproc_sync->fd ); +} + +static struct fd *linux_obj_get_fd( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( fast_sync->fd ); ++ return (struct fd *)grab_object( inproc_sync->fd ); +} + -+static struct fast_sync *create_fast_sync( enum fast_sync_type type, int unix_fd ) ++static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) +{ -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if (!(fast_sync = alloc_object( &linux_obj_ops ))) ++ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) + { + close( unix_fd ); + return NULL; + } + -+ fast_sync->type = type; ++ inproc_sync->type = type; + -+ if (!(fast_sync->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &fast_sync->obj, 0 ))) ++ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) + { -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + return NULL; + } + -+ return fast_sync; ++ return inproc_sync; +} + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ -+ struct ntsync_event_args args = {0}; ++ struct ntsync_event_args args; + struct linux_device *device; ++ int event; + + if (!(device = get_linux_device())) return NULL; + + args.signaled = signaled; + switch (type) + { -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_AUTO_SERVER: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_AUTO_SERVER: + args.manual = 0; + break; + -+ case FAST_SYNC_MANUAL_EVENT: -+ case FAST_SYNC_MANUAL_SERVER: -+ case FAST_SYNC_QUEUE: ++ case INPROC_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_MANUAL_SERVER: ++ case INPROC_SYNC_QUEUE: + args.manual = 1; + break; + -+ case FAST_SYNC_MUTEX: -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_MUTEX: ++ case INPROC_SYNC_SEMAPHORE: + assert(0); + break; + } -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args ) < 0) ++ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2813,19 +3044,20 @@ index 0000000..fed6eb9 + } + release_object( device ); + -+ return create_fast_sync( type, args.event ); ++ return create_inproc_sync( type, event ); +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ -+ struct ntsync_sem_args args = {0}; ++ struct ntsync_sem_args args; + struct linux_device *device; ++ int semaphore; + + if (!(device = get_linux_device())) return NULL; + + args.count = count; + args.max = max; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args ) < 0) ++ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2834,19 +3066,20 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_SEMAPHORE, args.sem ); ++ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ -+ struct ntsync_mutex_args args = {0}; ++ struct ntsync_mutex_args args; + struct linux_device *device; ++ int mutex; + + if (!(device = get_linux_device())) return NULL; + + args.owner = owner; + args.count = count; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args ) < 0) ++ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -2855,65 +3088,65 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_MUTEX, args.mutex ); ++ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); +} + -+void fast_reset_event( struct fast_sync *fast_sync ) ++void reset_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); +} + +#else + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ +} + -+void fast_reset_event( struct fast_sync *obj ) ++void reset_inproc_event( struct inproc_sync *obj ) +{ +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ +} + @@ -2941,14 +3174,14 @@ index 0000000..fed6eb9 + + if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) + { -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if ((fast_sync = obj->ops->get_fast_sync( obj ))) ++ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) + { -+ reply->handle = alloc_handle( current->process, fast_sync, 0, 0 ); -+ reply->type = fast_sync->type; ++ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); ++ reply->type = inproc_sync->type; + reply->access = get_handle_access( current->process, req->handle ); -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + } + release_object( obj ); + } @@ -2956,204 +3189,51 @@ index 0000000..fed6eb9 + set_error( STATUS_NOT_IMPLEMENTED ); +#endif +} -diff --git a/server/fd.c b/server/fd.c -index fc7f7be..00507ec 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -156,6 +156,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -181,6 +182,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -222,6 +224,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -262,6 +265,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -304,6 +308,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1565,6 +1570,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -+ if (fd->fast_sync) release_object( fd->fast_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1683,6 +1689,7 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->fast_sync = NULL; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); - init_async_queue( &fd->wait_q ); -@@ -1723,6 +1730,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->fast_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); -@@ -2139,7 +2147,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ fast_set_event( fd->fast_sync ); -+ } -+ else -+ { -+ fast_reset_event( fd->fast_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2165,6 +2181,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - -+struct fast_sync *default_fd_get_fast_sync( struct object *obj ) -+{ -+ struct fd *fd = get_obj_fd( obj ); -+ struct fast_sync *ret; -+ -+ if (!fd->fast_sync) -+ fd->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->fast_sync; -+ release_object( fd ); -+ if (ret) grab_object( ret ); -+ return ret; -+} -+ - int default_fd_get_poll_events( struct fd *fd ) - { - int events = 0; -diff --git a/server/file.c b/server/file.c -index 76c6878..1191303 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -106,6 +106,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index 7f2d163..2ec50aa 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -108,6 +108,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -+extern struct fast_sync *default_fd_get_fast_sync( struct object *obj ); - 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 -index ef243e0..782889d 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index 5abdf39..5a00699 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -92,6 +92,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; diff --git a/server/mailslot.c b/server/mailslot.c -index 2d8697e..d9807b4 100644 +index b14954ad6c3..701ac35f393 100644 --- a/server/mailslot.c +++ b/server/mailslot.c -@@ -86,6 +86,7 @@ static const struct object_ops mailslot_ops = +@@ -93,6 +93,7 @@ static const struct object_ops mailslot_ops = default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync,/* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; -@@ -145,6 +146,7 @@ static const struct object_ops mail_writer_ops = +@@ -154,6 +155,7 @@ static const struct object_ops mail_writer_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; -@@ -208,6 +210,7 @@ static const struct object_ops mailslot_device_ops = +@@ -219,6 +221,7 @@ static const struct object_ops mailslot_device_ops = default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ }; -@@ -238,6 +241,7 @@ static const struct object_ops mailslot_device_file_ops = +@@ -249,6 +252,7 @@ static const struct object_ops mailslot_device_file_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_file_destroy /* destroy */ }; diff --git a/server/mapping.c b/server/mapping.c -index ff99b45..e1cf700 100644 +index 4bdd7c5080a..7c715a87457 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -79,6 +79,7 @@ static const struct object_ops ranges_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ranges_destroy /* destroy */ }; @@ -3161,7 +3241,7 @@ index ff99b45..e1cf700 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ shared_map_destroy /* destroy */ }; @@ -3169,19 +3249,19 @@ index ff99b45..e1cf700 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; diff --git a/server/mutex.c b/server/mutex.c -index af0efe7..167c236 100644 +index af0efe72132..a4374317760 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -38,6 +38,8 @@ static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; -+static struct list fast_mutexes = LIST_INIT(fast_mutexes); ++static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); + struct type_descr mutex_type = { @@ -3190,8 +3270,8 @@ index af0efe7..167c236 100644 unsigned int count; /* recursion count */ int abandoned; /* has it been abandoned? */ struct list entry; /* entry in owner thread mutex list */ -+ struct list fast_mutexes_entry; /* entry in fast_mutexes list */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void mutex_dump( struct object *obj, int verbose ); @@ -3199,7 +3279,7 @@ index af0efe7..167c236 100644 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void mutex_destroy( struct object *obj ); static int mutex_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ); ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); static const struct object_ops mutex_ops = { @@ -3207,7 +3287,7 @@ index af0efe7..167c236 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_fast_sync, /* get_fast_sync */ ++ mutex_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; @@ -3215,11 +3295,11 @@ index af0efe7..167c236 100644 mutex->owner = NULL; mutex->abandoned = 0; if (owned) do_grab( mutex, current ); -+ mutex->fast_sync = NULL; ++ mutex->inproc_sync = NULL; } } return mutex; -@@ -134,16 +141,22 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str +@@ -134,16 +141,20 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str void abandon_mutexes( struct thread *thread ) { @@ -3236,28 +3316,26 @@ index af0efe7..167c236 100644 do_release( mutex ); } + -+ LIST_FOR_EACH_ENTRY(mutex, &fast_mutexes, struct mutex, fast_mutexes_entry) -+ { -+ fast_abandon_mutex( thread->id, mutex->fast_sync ); -+ } ++ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) ++ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); } static void mutex_dump( struct object *obj, int verbose ) -@@ -189,14 +202,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) +@@ -189,14 +200,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) return 1; } -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ) ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) +{ + struct mutex *mutex = (struct mutex *)obj; + -+ if (!mutex->fast_sync) ++ if (!mutex->inproc_sync) + { -+ mutex->fast_sync = fast_create_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->fast_sync) list_add_tail( &fast_mutexes, &mutex->fast_mutexes_entry ); ++ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); ++ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); + } -+ if (mutex->fast_sync) grab_object( mutex->fast_sync ); -+ return mutex->fast_sync; ++ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); ++ return mutex->inproc_sync; +} + static void mutex_destroy( struct object *obj ) @@ -3273,23 +3351,23 @@ index af0efe7..167c236 100644 + mutex->count = 0; + do_release( mutex ); + } -+ if (mutex->fast_sync) ++ if (mutex->inproc_sync) + { -+ release_object( mutex->fast_sync ); -+ list_remove( &mutex->fast_mutexes_entry ); ++ release_object( mutex->inproc_sync ); ++ list_remove( &mutex->inproc_mutexes_entry ); + } } /* create a mutex */ diff --git a/server/named_pipe.c b/server/named_pipe.c -index f3404a3..6d8cb3e 100644 +index 59a90c36663..04e8f49fb79 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops = default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -3297,7 +3375,7 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ pipe_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -3305,7 +3383,7 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_end_destroy /* destroy */ }; @@ -3313,7 +3391,7 @@ index f3404a3..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ }; @@ -3321,27 +3399,27 @@ index f3404a3..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_file_destroy /* destroy */ }; -@@ -357,6 +356,7 @@ +@@ -351,6 +356,7 @@ static const struct object_ops named_pipe_dir_ops = NULL, /* unlink_name */ named_pipe_dir_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_dir_destroy /* destroy */ }; diff --git a/server/object.c b/server/object.c -index 89e541f..6c6568e 100644 +index cd368ef724a..b07bc59bde1 100644 --- a/server/object.c +++ b/server/object.c @@ -120,6 +120,7 @@ static const struct object_ops apc_reserve_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -3349,15 +3427,15 @@ index 89e541f..6c6568e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; -@@ -538,6 +538,12 @@ struct fd *no_get_fd( struct object *obj ) +@@ -639,6 +641,12 @@ struct fd *no_get_fd( struct object *obj ) return NULL; } -+struct fast_sync *no_get_fast_sync( struct object *obj ) ++struct inproc_sync *no_get_inproc_sync( struct object *obj ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; @@ -3367,14 +3445,14 @@ index 89e541f..6c6568e 100644 { return map_access( access, &obj->ops->type->mapping ); diff --git a/server/object.h b/server/object.h -index d4d6653..b1147bc 100644 +index 7555f564a08..b1612623b0f 100644 --- a/server/object.h +++ b/server/object.h @@ -42,6 +42,7 @@ struct async; struct async_queue; struct winstation; struct object_type; -+struct fast_sync; ++struct inproc_sync; struct unicode_str @@ -3382,38 +3460,38 @@ index d4d6653..b1147bc 100644 unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable fast-synchronization handle to this object */ -+ struct fast_sync *(*get_fast_sync)(struct object *); ++ /* get a client-waitable in-process synchronization handle to this object */ ++ struct inproc_sync *(*get_inproc_sync)(struct object *); /* close a handle to this object */ int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ -@@ -219,6 +222,17 @@ extern void reset_event( struct event *event ); +@@ -228,6 +231,17 @@ extern void reset_event( struct event *event ); extern void abandon_mutexes( struct thread *thread ); -+/* fast-synchronization functions */ ++/* in-process synchronization functions */ + -+extern struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ); -+extern struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ); -+extern struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ); -+extern void fast_set_event( struct fast_sync *obj ); -+extern void fast_reset_event( struct fast_sync *obj ); -+extern void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ); ++extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); ++extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); ++extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); ++extern void set_inproc_event( struct inproc_sync *obj ); ++extern void reset_inproc_event( struct inproc_sync *obj ); ++extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); + -+extern struct fast_sync *no_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); + /* serial functions */ int get_serial_async_timeout(struct object *obj, int type, int count); diff --git a/server/process.c b/server/process.c -index f6d1641..1c2cc8b 100644 +index e06350f7311..fed2f95bd30 100644 --- a/server/process.c +++ b/server/process.c @@ -94,6 +94,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access static struct security_descriptor *process_get_sd( struct object *obj ); static void process_poll_event( struct fd *fd, int event ); static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *process_get_fast_sync( struct object *obj ); ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ); static void process_destroy( struct object *obj ); static void terminate_process( struct process *process, struct thread *skip, int exit_code ); @@ -3421,7 +3499,7 @@ index f6d1641..1c2cc8b 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_fast_sync, /* get_fast_sync */ ++ process_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -3429,7 +3507,7 @@ index f6d1641..1c2cc8b 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; @@ -3437,7 +3515,7 @@ index f6d1641..1c2cc8b 100644 static void job_dump( struct object *obj, int verbose ); static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *job_get_fast_sync( struct object *obj ); ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ); static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void job_destroy( struct object *obj ); @@ -3445,7 +3523,7 @@ index f6d1641..1c2cc8b 100644 struct job *parent; struct list parent_job_entry; /* list entry for parent job */ struct list child_job_list; /* list of child jobs */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static const struct object_ops job_ops = @@ -3453,7 +3531,7 @@ index f6d1641..1c2cc8b 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_fast_sync, /* get_fast_sync */ ++ job_get_inproc_sync, /* get_inproc_sync */ job_close_handle, /* close_handle */ job_destroy /* destroy */ }; @@ -3461,7 +3539,7 @@ index f6d1641..1c2cc8b 100644 job->completion_port = NULL; job->completion_key = 0; job->parent = NULL; -+ job->fast_sync = NULL; ++ job->inproc_sync = NULL; } } return job; @@ -3469,17 +3547,17 @@ index f6d1641..1c2cc8b 100644 job->terminating = 0; job->signaled = 1; wake_up( &job->obj, 0 ); -+ fast_set_event( job->fast_sync ); ++ set_inproc_event( job->inproc_sync ); +} + -+static struct fast_sync *job_get_fast_sync( struct object *obj ) ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ) +{ + struct job *job = (struct job *)obj; + -+ if (!job->fast_sync) -+ job->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->fast_sync) grab_object( job->fast_sync ); -+ return job->fast_sync; ++ if (!job->inproc_sync) ++ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); ++ if (job->inproc_sync) grab_object( job->inproc_sync ); ++ return job->inproc_sync; } static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) @@ -3488,94 +3566,94 @@ index f6d1641..1c2cc8b 100644 release_object( job->parent ); } + -+ if (job->fast_sync) release_object( job->fast_sync ); ++ if (job->inproc_sync) release_object( job->inproc_sync ); } static void job_dump( struct object *obj, int verbose ) -@@ -683,6 +703,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla +@@ -684,6 +704,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla process->rawinput_device_count = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; -+ process->fast_sync = NULL; ++ process->inproc_sync = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); list_init( &process->rawinput_entry ); list_init( &process->kernel_object ); -@@ -789,6 +810,8 @@ static void process_destroy( struct object *obj ) +@@ -784,6 +805,8 @@ static void process_destroy( struct object *obj ) free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); + -+ if (process->fast_sync) release_object( process->fast_sync ); ++ if (process->inproc_sync) release_object( process->inproc_sync ); } /* dump a process on stdout for debugging purposes */ -@@ -820,6 +843,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) +@@ -817,6 +840,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) return &process->kernel_object; } -+static struct fast_sync *process_get_fast_sync( struct object *obj ) ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ) +{ + struct process *process = (struct process *)obj; + -+ if (!process->fast_sync) -+ process->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->fast_sync) grab_object( process->fast_sync ); -+ return process->fast_sync; ++ if (!process->inproc_sync) ++ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); ++ if (process->inproc_sync) grab_object( process->inproc_sync ); ++ return process->inproc_sync; +} + static struct security_descriptor *process_get_sd( struct object *obj ) { static struct security_descriptor *process_default_sd; -@@ -984,6 +1017,7 @@ static void process_killed( struct process *process ) +@@ -981,6 +1014,7 @@ static void process_killed( struct process *process ) release_job_process( process ); start_sigkill_timer( process ); wake_up( &process->obj, 0 ); -+ fast_set_event( process->fast_sync ); ++ set_inproc_event( process->inproc_sync ); } /* add a thread to a process running threads list */ diff --git a/server/process.h b/server/process.h -index 1e73e9d..2140427 100644 +index 96814ab7cf8..667e2506672 100644 --- a/server/process.h +++ b/server/process.h @@ -86,6 +86,7 @@ struct process struct list rawinput_entry; /* entry in the rawinput process list */ struct list kernel_object; /* list of kernel object pointers */ struct pe_image_info image_info; /* main exe image info */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; /* process functions */ diff --git a/server/protocol.def b/server/protocol.def -index f6d644d..e477d3b 100644 +index 4b9c4dc8e5c..85ab00ea704 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -3888,13 +3888,61 @@ struct handle_info +@@ -4076,3 +4076,50 @@ struct handle_info @REPLY - obj_handle_t handle; /* next thread handle */ + int enable; /* previous state of auto-repeat enable */ @END + + -+enum fast_sync_type ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + -+/* Obtain a handle to the fast synchronization device object */ ++/* Obtain a handle to the ntsync device object */ +@REQ(get_linux_sync_device) +@REPLY + obj_handle_t handle; /* handle to the device */ +@END + + -+/* Get the fast synchronization object associated with the given handle */ ++/* Get the in-process synchronization object associated with the given handle */ +@REQ(get_linux_sync_obj) + obj_handle_t handle; /* handle to the object */ +@REPLY @@ -3586,79 +3664,68 @@ index f6d644d..e477d3b 100644 + + +/* Begin a client-side wait on a message queue */ -+@REQ(fast_select_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(select_inproc_queue) +@END + + +/* End a client-side wait on a message queue */ -+@REQ(fast_unselect_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(unselect_inproc_queue) + int signaled; /* was the queue signaled? */ +@END - - - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ - int delay; /* auto-repeat delay in ms */ - int period; /* auto-repeat period in ms */ - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END + -+/* Get an event handle to be used for thread alerts with fast synchronization */ -+@REQ(get_fast_alert_event) ++ ++/* Get an event handle to be used for thread alerts with in-process synchronization */ ++@REQ(get_inproc_alert_event) +@REPLY + obj_handle_t handle; /* handle to the event */ +@END diff --git a/server/queue.c b/server/queue.c -index ed099b3..b4a1c53 100644 +index 47870884644..19a5e7aa9b8 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -145,6 +145,8 @@ struct msg_queue +@@ -133,6 +133,8 @@ struct msg_queue timeout_t last_get_msg; /* time of last get message call */ int keystate_lock; /* owns an input keystate lock */ const queue_shm_t *shared; /* queue in session shared memory */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ int in_fast_wait; /* are we in a client-side wait? */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ int in_inproc_wait; /* are we in a client-side wait? */ }; struct hotkey -@@ -162,6 +164,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent +@@ -150,6 +152,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ); static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ); static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ); ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); static void msg_queue_destroy( struct object *obj ); static void msg_queue_poll_event( struct fd *fd, int event ); static void thread_input_dump( struct object *obj, int verbose ); -@@ -188,6 +191,7 @@ static const struct object_ops msg_queue_ops = +@@ -176,6 +179,7 @@ static const struct object_ops msg_queue_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_fast_sync, /* get_fast_sync */ ++ msg_queue_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; -@@ -225,6 +229,7 @@ static const struct object_ops thread_input_ops = +@@ -213,6 +217,7 @@ static const struct object_ops thread_input_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; -@@ -313,6 +318,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ +@@ -312,6 +317,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->hooks = NULL; queue->last_get_msg = current_time; queue->keystate_lock = 0; -+ queue->fast_sync = NULL; -+ queue->in_fast_wait = 0; ++ queue->inproc_sync = NULL; ++ queue->in_inproc_wait = 0; list_init( &queue->send_result ); list_init( &queue->callback_result ); list_init( &queue->pending_timers ); -@@ -599,7 +606,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) +@@ -728,7 +735,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) } SHARED_WRITE_END; @@ -3666,64 +3733,62 @@ index ed099b3..b4a1c53 100644 + if (is_signaled( queue )) + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } } /* clear some queue bits */ -@@ -612,6 +623,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits +@@ -748,6 +759,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits if (queue->keystate_lock) unlock_input_keystate( queue->input ); queue->keystate_lock = 0; } + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } /* check if message is matched by the filter */ -@@ -1091,6 +1104,10 @@ static int is_queue_hung( struct msg_queue *queue ) +@@ -1227,6 +1240,10 @@ static int is_queue_hung( struct msg_queue *queue ) if (get_wait_queue_thread(entry)->queue == queue) return 0; /* thread is waiting on queue -> not hung */ } + -+ if (queue->in_fast_wait) ++ if (queue->in_inproc_wait) + return 0; /* thread is waiting on queue in absentia -> not hung */ + return 1; } -@@ -1151,6 +1168,19 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en +@@ -1292,6 +1309,17 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en shared->changed_mask = 0; } SHARED_WRITE_END; -+ -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); +} + -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ) ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) +{ + struct msg_queue *queue = (struct msg_queue *)obj; -+ const queue_shm_t *queue_shm = queue->shared; + -+ if (!queue->fast_sync) -+ queue->fast_sync = fast_create_event( FAST_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->fast_sync) grab_object( queue->fast_sync ); -+ return queue->fast_sync; ++ if (!queue->inproc_sync) ++ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); ++ if (queue->inproc_sync) grab_object( queue->inproc_sync ); ++ return queue->inproc_sync; } static void msg_queue_destroy( struct object *obj ) -@@ -1190,6 +1218,7 @@ static void msg_queue_destroy( struct object *obj ) +@@ -1337,6 +1365,7 @@ static void msg_queue_destroy( struct object *obj ) if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); -+ if (queue->fast_sync) release_object( queue->fast_sync ); ++ if (queue->inproc_sync) release_object( queue->inproc_sync ); } static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1200,6 +1229,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) +@@ -1347,6 +1376,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); } static void thread_input_dump( struct object *obj, int verbose ) @@ -3735,101 +3800,142 @@ index ed099b3..b4a1c53 100644 + else + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } + } + else + { -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } } } -@@ -2831,6 +2873,9 @@ DECL_HANDLER(get_queue_status) +@@ -3136,6 +3174,9 @@ DECL_HANDLER(get_queue_status) shared->changed_bits &= ~req->clear_bits; } SHARED_WRITE_END; + + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } else reply->wake_bits = reply->changed_bits = 0; } -@@ -3020,6 +3064,9 @@ DECL_HANDLER(get_message) - if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT; - if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; +@@ -3333,6 +3374,9 @@ DECL_HANDLER(get_message) + } + SHARED_WRITE_END; + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); + /* then check for posted messages */ if ((filter & QS_POSTMESSAGE) && get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3073,6 +3120,7 @@ DECL_HANDLER(get_message) +@@ -3392,6 +3436,7 @@ DECL_HANDLER(get_message) } SHARED_WRITE_END; -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); set_error( STATUS_PENDING ); /* FIXME */ } +@@ -4183,3 +4228,42 @@ DECL_HANDLER(set_keyboard_repeat) + + release_object( desktop ); + } ++ ++DECL_HANDLER(select_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ check_thread_queue_idle( current ); ++ ++ if (queue->fd) ++ set_fd_events( queue->fd, POLLIN ); ++ ++ queue->in_inproc_wait = 1; ++ } ++} ++ ++DECL_HANDLER(unselect_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (!queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ if (queue->fd) ++ set_fd_events( queue->fd, 0 ); ++ ++ if (req->signaled) ++ msg_queue_satisfied( &queue->obj, NULL ); ++ ++ queue->in_inproc_wait = 0; ++ } ++} diff --git a/server/registry.c b/server/registry.c -index 804cfcc..f6bb34e 100644 +index 3f02faaaefd..65beb11702d 100644 --- a/server/registry.c +++ b/server/registry.c @@ -192,6 +192,7 @@ static const struct object_ops key_ops = key_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ key_close_handle, /* close_handle */ key_destroy /* destroy */ }; diff --git a/server/request.c b/server/request.c -index 2691e0c..e0585be 100644 +index 2254315b79e..24a4f779e68 100644 --- a/server/request.c +++ b/server/request.c -@@ -102,6 +102,7 @@ static const struct object_ops master_socket_ops = +@@ -101,6 +101,7 @@ static const struct object_ops master_socket_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; diff --git a/server/request_handlers.h b/server/request_handlers.h -index eb6b8f4..1636e98 100644 ---- a/server/request_handlers.h 2024-11-18 18:02:30.072599085 +0500 -+++ b/server/request_handlers.h 2024-11-18 18:14:42.357268807 +0500 -@@ -298,7 +298,12 @@ - DECL_HANDLER(suspend_process); +index fb03e421562..1d88b63dff3 100644 +--- a/server/request_handlers.h ++++ b/server/request_handlers.h +@@ -299,6 +299,11 @@ DECL_HANDLER(suspend_process); DECL_HANDLER(resume_process); DECL_HANDLER(get_next_thread); + DECL_HANDLER(set_keyboard_repeat); +DECL_HANDLER(get_linux_sync_device); +DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(fast_select_queue); -+DECL_HANDLER(fast_unselect_queue); - DECL_HANDLER(set_keyboard_repeat); -+DECL_HANDLER(get_fast_alert_event); ++DECL_HANDLER(select_inproc_queue); ++DECL_HANDLER(unselect_inproc_queue); ++DECL_HANDLER(get_inproc_alert_event); typedef void (*req_handler)( const void *req, void *reply ); static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -599,7 +599,12 @@ - (req_handler)req_suspend_process, +@@ -595,6 +600,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_resume_process, (req_handler)req_get_next_thread, + (req_handler)req_set_keyboard_repeat, + (req_handler)req_get_linux_sync_device, + (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_fast_select_queue, -+ (req_handler)req_fast_unselect_queue, - (req_handler)req_set_keyboard_repeat, -+ (req_handler)req_get_fast_alert_event, ++ (req_handler)req_select_inproc_queue, ++ (req_handler)req_unselect_inproc_queue, ++ (req_handler)req_get_inproc_alert_event, }; C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,9 +2276,26 @@ - C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); - C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); - C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); +@@ -2268,3 +2278,18 @@ C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); +C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); +C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); @@ -3839,36 +3945,114 @@ index eb6b8f4..1636e98 100644 +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( offsetof(struct fast_select_queue_request, handle) == 12 ); -+C_ASSERT( sizeof(struct fast_select_queue_request) == 16 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, handle) == 12 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, signaled) == 16 ); -+C_ASSERT( sizeof(struct fast_unselect_queue_request) == 24 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_fast_alert_event_reply, handle) == 8 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_reply) == 16 ); ++C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); ++C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); ++C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); ++C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); +diff --git a/server/request_trace.h b/server/request_trace.h +index cf0aab07ca0..283f1c1774a 100644 +--- a/server/request_trace.h ++++ b/server/request_trace.h +@@ -3339,6 +3339,45 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep + fprintf( stderr, " enable=%d", req->enable ); + } + ++static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) ++{ ++} ++ ++static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ ++static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ ++static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++ fprintf( stderr, ", type=%d", req->type ); ++ fprintf( stderr, ", access=%08x", req->access ); ++} ++ ++static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) ++{ ++} ++ ++static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) ++{ ++ fprintf( stderr, " signaled=%d", req->signaled ); ++} ++ ++static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) ++{ ++} ++ ++static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) ++{ ++ fprintf( stderr, " handle=%04x", req->handle ); ++} ++ + typedef void (*dump_func)( const void *req ); + + static const dump_func req_dumpers[REQ_NB_REQUESTS] = +@@ -3635,6 +3674,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = + (dump_func)dump_resume_process_request, + (dump_func)dump_get_next_thread_request, + (dump_func)dump_set_keyboard_repeat_request, ++ (dump_func)dump_get_linux_sync_device_request, ++ (dump_func)dump_get_linux_sync_obj_request, ++ (dump_func)dump_select_inproc_queue_request, ++ (dump_func)dump_unselect_inproc_queue_request, ++ (dump_func)dump_get_inproc_alert_event_request, + }; + + static const dump_func reply_dumpers[REQ_NB_REQUESTS] = +@@ -3931,6 +3975,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = + NULL, + (dump_func)dump_get_next_thread_reply, + (dump_func)dump_set_keyboard_repeat_reply, ++ (dump_func)dump_get_linux_sync_device_reply, ++ (dump_func)dump_get_linux_sync_obj_reply, ++ NULL, ++ NULL, ++ (dump_func)dump_get_inproc_alert_event_reply, + }; + + static const char * const req_names[REQ_NB_REQUESTS] = +@@ -4227,6 +4276,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = + "resume_process", + "get_next_thread", + "set_keyboard_repeat", ++ "get_linux_sync_device", ++ "get_linux_sync_obj", ++ "select_inproc_queue", ++ "unselect_inproc_queue", ++ "get_inproc_alert_event", + }; + + static const struct diff --git a/server/semaphore.c b/server/semaphore.c -index 53b42a8..9940919 100644 +index 53b42a886df..bc7436b5673 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -55,12 +55,15 @@ struct semaphore struct object obj; /* object header */ unsigned int count; /* current count */ unsigned int max; /* maximum possible count */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* fast synchronization object */ }; static void semaphore_dump( struct object *obj, int verbose ); static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ); ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); +static void semaphore_destroy( struct object *obj ); static const struct object_ops semaphore_ops = @@ -3877,7 +4061,7 @@ index 53b42a8..9940919 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_fast_sync, /* get_fast_sync */ ++ semaphore_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + semaphore_destroy /* destroy */ @@ -3888,7 +4072,7 @@ index 53b42a8..9940919 100644 /* initialize it if it didn't already exist */ sem->count = initial; sem->max = max; -+ sem->fast_sync = NULL; ++ sem->inproc_sync = NULL; } } return sem; @@ -3896,99 +4080,99 @@ index 53b42a8..9940919 100644 return release_semaphore( sem, 1, NULL ); } -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ) ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (!semaphore->fast_sync) -+ semaphore->fast_sync = fast_create_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->fast_sync) grab_object( semaphore->fast_sync ); -+ return semaphore->fast_sync; ++ if (!semaphore->inproc_sync) ++ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); ++ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); ++ return semaphore->inproc_sync; +} + +static void semaphore_destroy( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (semaphore->fast_sync) release_object( semaphore->fast_sync ); ++ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); +} + /* create a semaphore */ DECL_HANDLER(create_semaphore) { diff --git a/server/serial.c b/server/serial.c -index d665eb7..5c210d1 100644 +index 209f2e9174e..93753328d4d 100644 --- a/server/serial.c +++ b/server/serial.c -@@ -97,6 +97,7 @@ static const struct object_ops serial_ops = +@@ -103,6 +103,7 @@ static const struct object_ops serial_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; diff --git a/server/signal.c b/server/signal.c -index 19b76d4..e5def3d 100644 +index 19b76d44c16..85d16baa98c 100644 --- a/server/signal.c +++ b/server/signal.c @@ -74,6 +74,7 @@ static const struct object_ops handler_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; diff --git a/server/sock.c b/server/sock.c -index 8a95cad..587a312 100644 +index 32d622aaebc..09366ea7dde 100644 --- a/server/sock.c +++ b/server/sock.c -@@ -465,6 +465,7 @@ static const struct object_ops sock_ops = +@@ -483,6 +483,7 @@ static const struct object_ops sock_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ sock_close_handle, /* close_handle */ sock_destroy /* destroy */ }; -@@ -3572,6 +3573,7 @@ static const struct object_ops ifchange_ops = +@@ -3611,6 +3612,7 @@ static const struct object_ops ifchange_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ifchange_destroy /* destroy */ }; -@@ -3793,6 +3795,7 @@ static const struct object_ops socket_device_ops = +@@ -3832,6 +3834,7 @@ static const struct object_ops socket_device_ops = default_unlink_name, /* unlink_name */ socket_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/symlink.c b/server/symlink.c -index dd28efd..4a7cf68 100644 +index 74b60162c01..f0314f2ee90 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -83,6 +83,7 @@ static const struct object_ops symlink_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ }; diff --git a/server/thread.c b/server/thread.c -index 55bd63d..b9fb8d5 100644 +index b3ce5d9ac95..a05a96d8728 100644 --- a/server/thread.c +++ b/server/thread.c @@ -108,6 +108,7 @@ static const struct object_ops thread_apc_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_apc_destroy /* destroy */ }; @@ -3996,7 +4180,7 @@ index 55bd63d..b9fb8d5 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4004,7 +4188,7 @@ index 55bd63d..b9fb8d5 100644 static unsigned int thread_map_access( struct object *obj, unsigned int access ); static void thread_poll_event( struct fd *fd, int event ); static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *thread_get_fast_sync( struct object *obj ); ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); static void destroy_thread( struct object *obj ); static const struct object_ops thread_ops = @@ -4012,7 +4196,7 @@ index 55bd63d..b9fb8d5 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_fast_sync, /* get_fast_sync */ ++ thread_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; @@ -4020,119 +4204,137 @@ index 55bd63d..b9fb8d5 100644 thread->token = NULL; thread->desc = NULL; thread->desc_len = 0; -+ thread->fast_sync = NULL; -+ thread->fast_alert_event = NULL; ++ thread->inproc_sync = NULL; ++ thread->inproc_alert_event = NULL; thread->creation_time = current_time; thread->exit_time = 0; -@@ -396,6 +402,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) +@@ -397,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) return &thread->kernel_object; } -+static struct fast_sync *thread_get_fast_sync( struct object *obj ) ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) +{ + struct thread *thread = (struct thread *)obj; + -+ if (!thread->fast_sync) -+ thread->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->fast_sync) grab_object( thread->fast_sync ); -+ return thread->fast_sync; ++ if (!thread->inproc_sync) ++ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); ++ if (thread->inproc_sync) grab_object( thread->inproc_sync ); ++ return thread->inproc_sync; +} + /* cleanup everything that is no longer needed by a dead thread */ /* used by destroy_thread and kill_thread */ static void cleanup_thread( struct thread *thread ) -@@ -450,6 +466,8 @@ static void destroy_thread( struct object *obj ) +@@ -452,6 +468,8 @@ static void destroy_thread( struct object *obj ) release_object( thread->process ); if (thread->id) free_ptid( thread->id ); if (thread->token) release_object( thread->token ); -+ if (thread->fast_sync) release_object( thread->fast_sync ); -+ if (thread->fast_alert_event) release_object( thread->fast_alert_event ); ++ if (thread->inproc_sync) release_object( thread->inproc_sync ); ++ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); } /* dump a thread on stdout for debugging purposes */ -@@ -1143,8 +1161,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr +@@ -1149,8 +1167,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr grab_object( apc ); list_add_tail( queue, &apc->entry ); if (!list_prev( queue, &apc->entry )) /* first one */ + { wake_thread( thread ); -+ if (apc->call.type == APC_USER && thread->fast_alert_event) -+ set_event( thread->fast_alert_event ); ++ if (apc->call.type == APC_USER && thread->inproc_alert_event) ++ set_event( thread->inproc_alert_event ); + } + return 1; } -@@ -1175,6 +1198,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty +@@ -1181,6 +1204,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty apc->executed = 1; wake_up( &apc->obj, 0 ); release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); return; } } -@@ -1189,6 +1214,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system +@@ -1195,6 +1220,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system { apc = LIST_ENTRY( ptr, struct thread_apc, entry ); list_remove( ptr ); + -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); } return apc; } -@@ -1286,6 +1314,7 @@ void kill_thread( struct thread *thread, int violent_death ) +@@ -1292,6 +1320,7 @@ void kill_thread( struct thread *thread, int violent_death ) kill_console_processes( thread, 0 ); abandon_mutexes( thread ); wake_up( &thread->obj, 0 ); -+ fast_set_event( thread->fast_sync ); ++ set_inproc_event( thread->inproc_sync ); if (violent_death) send_thread_signal( thread, SIGQUIT ); cleanup_thread( thread ); remove_process_thread( thread->process, thread ); -@@ -2029,3 +2058,12 @@ DECL_HANDLER(get_next_thread) +@@ -2035,3 +2064,12 @@ DECL_HANDLER(get_next_thread) set_error( STATUS_NO_MORE_ENTRIES ); release_object( process ); } + -+DECL_HANDLER(get_fast_alert_event) ++DECL_HANDLER(get_inproc_alert_event) +{ -+ if (!current->fast_alert_event) -+ current->fast_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); ++ if (!current->inproc_alert_event) ++ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); + -+ if (current->fast_alert_event) -+ reply->handle = alloc_handle( current->process, current->fast_alert_event, SYNCHRONIZE, 0 ); ++ if (current->inproc_alert_event) ++ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); +} diff --git a/server/thread.h b/server/thread.h -index 766ed78..9bf4b48 100644 +index 754e617b484..c75512ded87 100644 --- a/server/thread.h +++ b/server/thread.h -@@ -91,6 +91,8 @@ struct thread +@@ -93,6 +93,8 @@ struct thread data_size_t desc_len; /* thread description length in bytes */ WCHAR *desc; /* thread description string */ struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ struct event *fast_alert_event; /* fast synchronization alert event */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ struct event *inproc_alert_event; /* in-process synchronization alert event */ }; extern struct thread *current; diff --git a/server/timer.c b/server/timer.c -index 96dc9d0..854a8e1 100644 +index b0b6ec81535..08aa62292f0 100644 --- a/server/timer.c +++ b/server/timer.c -@@ -61,11 +61,13 @@ struct timer - struct thread *thread; /* thread that set the APC function */ - client_ptr_t callback; /* callback APC function */ - client_ptr_t arg; /* callback argument */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ +@@ -52,20 +52,22 @@ struct type_descr timer_type = + + struct timer + { +- struct object obj; /* object header */ +- int manual; /* manual reset */ +- int signaled; /* current signaled state */ +- unsigned int period; /* timer period in ms */ +- abstime_t when; /* next expiration */ +- struct timeout_user *timeout; /* timeout user */ +- struct thread *thread; /* thread that set the APC function */ +- client_ptr_t callback; /* callback APC function */ +- client_ptr_t arg; /* callback argument */ ++ struct object obj; /* object header */ ++ int manual; /* manual reset */ ++ int signaled; /* current signaled state */ ++ unsigned int period; /* timer period in ms */ ++ abstime_t when; /* next expiration */ ++ struct timeout_user *timeout; /* timeout user */ ++ struct thread *thread; /* thread that set the APC function */ ++ client_ptr_t callback; /* callback APC function */ ++ client_ptr_t arg; /* callback argument */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void timer_dump( struct object *obj, int verbose ); static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *timer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); static void timer_destroy( struct object *obj ); static const struct object_ops timer_ops = @@ -4140,7 +4342,7 @@ index 96dc9d0..854a8e1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_fast_sync, /* get_fast_sync */ ++ timer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; @@ -4148,7 +4350,7 @@ index 96dc9d0..854a8e1 100644 timer->period = 0; timer->timeout = NULL; timer->thread = NULL; -+ timer->fast_sync = NULL; ++ timer->inproc_sync = NULL; } } return timer; @@ -4156,7 +4358,7 @@ index 96dc9d0..854a8e1 100644 /* wake up waiters */ timer->signaled = 1; wake_up( &timer->obj, 0 ); -+ fast_set_event( timer->fast_sync ); ++ set_inproc_event( timer->inproc_sync ); } /* cancel a running timer */ @@ -4164,7 +4366,7 @@ index 96dc9d0..854a8e1 100644 { period = 0; /* period doesn't make any sense for a manual timer */ timer->signaled = 0; -+ fast_reset_event( timer->fast_sync ); ++ reset_inproc_event( timer->inproc_sync ); } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; @@ -4172,17 +4374,17 @@ index 96dc9d0..854a8e1 100644 if (!timer->manual) timer->signaled = 0; } -+static struct fast_sync *timer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) +{ + struct timer *timer = (struct timer *)obj; + -+ if (!timer->fast_sync) ++ if (!timer->inproc_sync) + { -+ enum fast_sync_type type = timer->manual ? FAST_SYNC_MANUAL_SERVER : FAST_SYNC_AUTO_SERVER; -+ timer->fast_sync = fast_create_event( type, timer->signaled ); ++ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; ++ timer->inproc_sync = create_inproc_event( type, timer->signaled ); + } -+ if (timer->fast_sync) grab_object( timer->fast_sync ); -+ return timer->fast_sync; ++ if (timer->inproc_sync) grab_object( timer->inproc_sync ); ++ return timer->inproc_sync; +} + static void timer_destroy( struct object *obj ) @@ -4192,146 +4394,43 @@ index 96dc9d0..854a8e1 100644 if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); -+ if (timer->fast_sync) release_object( timer->fast_sync ); ++ if (timer->inproc_sync) release_object( timer->inproc_sync ); } /* create a timer */ diff --git a/server/token.c b/server/token.c -index 4df8d2e..42562fd 100644 +index 7e20c670a16..844ad2814f4 100644 --- a/server/token.c +++ b/server/token.c -@@ -155,6 +155,7 @@ static const struct object_ops token_ops = +@@ -157,6 +157,7 @@ static const struct object_ops token_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ token_destroy /* destroy */ }; -diff --git a/server/request_trace.h b/server/request_trace.h -index af96565..c027f4b 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -4603,18 +4603,59 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req - fprintf( stderr, " handle=%04x", req->handle ); - } - -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) -+{ -+} -+ -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", type=%d", req->type ); -+ fprintf( stderr, ", access=%08x", req->access ); -+} -+ -+static void dump_fast_select_queue_request( const struct fast_select_queue_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_fast_unselect_queue_request( const struct fast_unselect_queue_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", signaled=%d", req->signaled ); -+} -+ -+static void dump_get_fast_alert_event_request( const struct get_fast_alert_event_request *req ) -+{ -+} -+ - static void dump_set_keyboard_repeat_request( const struct set_keyboard_repeat_request *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - fprintf( stderr, ", delay=%d", req->delay ); - fprintf( stderr, ", period=%d", req->period ); - } - - static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_reply *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - } - -+static void dump_get_fast_alert_event_reply( const struct get_fast_alert_event_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ - typedef void (*dump_func)( const void *req ); - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = { -@@ -4889,7 +4930,12 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_suspend_process_request, - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, - (dump_func)dump_set_keyboard_repeat_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_fast_select_queue_request, -+ (dump_func)dump_fast_unselect_queue_request, -+ (dump_func)dump_get_fast_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { -@@ -5177,7 +5223,12 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { - NULL, - NULL, - (dump_func)dump_get_next_thread_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, - (dump_func)dump_set_keyboard_repeat_reply, -+ NULL, -+ (dump_func)dump_get_fast_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = { -@@ -5465,7 +5516,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = { - "suspend_process", - "resume_process", - "get_next_thread", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "fast_select_queue", -+ "fast_unselect_queue", - "set_keyboard_repeat", -+ "get_fast_alert_event", - }; - - static const struct diff --git a/server/window.c b/server/window.c -index 242e93f..8ddf78e 100644 +index 2af70b09102..291aab520d7 100644 --- a/server/window.c +++ b/server/window.c @@ -119,6 +119,7 @@ static const struct object_ops window_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ window_destroy /* destroy */ }; diff --git a/server/winstation.c b/server/winstation.c -index 80126ad..8aab32d 100644 +index 8611c893cde..e3f0a870d02 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -88,6 +88,7 @@ static const struct object_ops winstation_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -4339,88 +4438,10 @@ index 80126ad..8aab32d 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; -From a0534129d9131289457d2967e557992c59d2e0de Mon Sep 17 00:00:00 2001 -From: Kirill Artemev -Date: Thu, 4 Jul 2024 11:00:19 +0500 -Subject: [PATCH] ntsync5: rebase - -Signed-off-by: Kirill Artemev ---- - server/queue.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 58 insertions(+) - -diff --git a/server/queue.c b/server/queue.c -index 4f58b795b7e..2185bf72964 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -4015,6 +4015,64 @@ DECL_HANDLER(update_rawinput_devices) - } - } - -+DECL_HANDLER(fast_select_queue) -+{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; -+ -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ /* a thread can only wait on its own queue */ -+ if (current->queue != queue || queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -+ set_event( current->process->idle_event ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_fast_wait = 1; -+ } -+ -+ release_object( queue ); -+} -+ -+DECL_HANDLER(fast_unselect_queue) -+{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; -+ -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ -+ if (current->queue != queue || !queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_fast_wait = 0; -+ } -+ -+ release_object( queue ); -+} -+ - DECL_HANDLER(set_keyboard_repeat) - { - struct desktop *desktop; -- -2.45.2 +2.47.1 + diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging-protonify.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging-protonify.patch index 51c2aea0e..884a267d0 100644 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging-protonify.patch +++ b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging-protonify.patch @@ -2271,7 +2271,7 @@ index 0d4b320..dba7645 100644 if (options & DUPLICATE_CLOSE_SOURCE) + { fd = remove_fd_from_cache( source ); -+ close_fast_sync_obj( source ); ++ close_inproc_sync_obj( source ); + } SERVER_START_REQ( dup_handle ) @@ -2290,7 +2290,7 @@ index 0d4b320..dba7645 100644 - if (do_esync()) - esync_close( handle ); -+ close_fast_sync_obj( handle ); ++ close_inproc_sync_obj( handle ); SERVER_START_REQ( close_handle ) { @@ -2349,7 +2349,7 @@ index 1072265..a9a0a2c 100644 /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { -@@ -239,6 +246,902 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at +@@ -301,6 +309,901 @@ } @@ -2357,44 +2357,44 @@ index 1072265..a9a0a2c 100644 + +static int get_linux_sync_device(void) +{ -+ static LONG fast_sync_fd = -2; ++ static LONG device = -2; + -+ if (fast_sync_fd == -2) ++ if (device == -2) + { -+ HANDLE device; ++ HANDLE handle; + int fd, needs_close; + NTSTATUS ret; + + SERVER_START_REQ( get_linux_sync_device ) + { -+ if (!(ret = wine_server_call( req ))) device = wine_server_ptr_handle( reply->handle ); ++ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + if (!ret) + { -+ if (!server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )) ++ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) + { -+ if (InterlockedCompareExchange( &fast_sync_fd, fd, -2 ) != -2) ++ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) + { + /* someone beat us to it */ + if (needs_close) close( fd ); -+ NtClose( device ); ++ NtClose( handle ); + } + /* otherwise don't close the device */ + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); -+ NtClose( device ); ++ InterlockedCompareExchange( &device, -1, -2 ); ++ NtClose( handle ); + } + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); ++ InterlockedCompareExchange( &device, -1, -2 ); + } + } -+ return fast_sync_fd; ++ return device; +} + +/* It's possible for synchronization primitives to remain alive even after being @@ -2402,10 +2402,10 @@ index 1072265..a9a0a2c 100644 + * documented as being undefined behaviour by Microsoft, but it works, and some + * applications rely on it. This means we need to refcount handles, and defer + * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the fast synchronization ++ * by having each client process hold a handle to the in-process synchronization + * object, as well as a private refcount. When the client refcount reaches zero, + * it closes the handle; when all handles are closed, the server deletes the -+ * fast synchronization object. ++ * in-process synchronization object. + * + * We also need this for signal-and-wait. The signal and wait operations aren't + * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE @@ -2431,20 +2431,20 @@ index 1072265..a9a0a2c 100644 + * the same handle immediately reallocated to a different object. This should be + * a very rare situation, and in that case we simply don't cache the handle. + */ -+struct fast_sync_cache_entry ++struct inproc_sync_cache_entry +{ + LONG refcount; + int fd; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + unsigned int access; + BOOL closed; -+ /* handle to the underlying fast sync object, stored as obj_handle_t to save -+ * space */ ++ /* handle to the underlying in-process sync object, stored as obj_handle_t ++ * to save space */ + obj_handle_t handle; +}; + + -+static void release_fast_sync_obj( struct fast_sync_cache_entry *cache ) ++static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) +{ + /* save the handle and fd now; as soon as the refcount hits 0 we cannot + * access the cache anymore */ @@ -2472,52 +2472,52 @@ index 1072265..a9a0a2c 100644 +} + + -+#define FAST_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct fast_sync_cache_entry)) -+#define FAST_SYNC_CACHE_ENTRIES 128 ++#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) ++#define INPROC_SYNC_CACHE_ENTRIES 128 + -+static struct fast_sync_cache_entry *fast_sync_cache[FAST_SYNC_CACHE_ENTRIES]; -+static struct fast_sync_cache_entry fast_sync_cache_initial_block[FAST_SYNC_CACHE_BLOCK_SIZE]; ++static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; ++static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; + -+static inline unsigned int fast_sync_handle_to_index( HANDLE handle, unsigned int *entry ) ++static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) +{ + unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / FAST_SYNC_CACHE_BLOCK_SIZE; -+ return idx % FAST_SYNC_CACHE_BLOCK_SIZE; ++ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; ++ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; +} + + -+static struct fast_sync_cache_entry *cache_fast_sync_obj( HANDLE handle, obj_handle_t fast_sync, int fd, -+ enum fast_sync_type type, unsigned int access ) ++static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, ++ enum inproc_sync_type type, unsigned int access ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + sigset_t sigset; + int refcount; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES) + { + FIXME( "too many allocated handles, not caching %p\n", handle ); + return NULL; + } + -+ if (!fast_sync_cache[entry]) /* do we need to allocate a new block of entries? */ ++ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ + { -+ if (!entry) fast_sync_cache[0] = fast_sync_cache_initial_block; ++ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; + else + { -+ static const size_t size = FAST_SYNC_CACHE_BLOCK_SIZE * sizeof(struct fast_sync_cache_entry); ++ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); + void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); + if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&fast_sync_cache[entry], ptr, NULL )) ++ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) + munmap( ptr, size ); /* someone beat us to it */ + } + } + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same + * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_fast_sync_obj() and close_handle. */ ++ * being cached again between close_inproc_sync_obj() and close_handle. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) @@ -2531,13 +2531,13 @@ index 1072265..a9a0a2c 100644 + return NULL; + } + -+ cache->handle = fast_sync; ++ cache->handle = inproc_sync; + cache->fd = fd; + cache->type = type; + cache->access = access; + cache->closed = FALSE; + /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_fast_sync_obj()]. ++ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. + * Set the refcount to 2 (one for the handle, one for the caller). */ + refcount = InterlockedExchange( &cache->refcount, 2 ); + assert( !refcount ); @@ -2561,18 +2561,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static struct fast_sync_cache_entry *get_cached_fast_sync_obj( HANDLE handle ) ++static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES || !fast_sync_cache[entry]) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) + return NULL; + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* this load needs acquire semantics [paired with the store in -+ * cache_fast_sync_obj()] */ ++ * cache_inproc_sync_obj()] */ + if (!interlocked_inc_if_nonzero( &cache->refcount )) + return NULL; + @@ -2582,7 +2582,7 @@ index 1072265..a9a0a2c 100644 + * handle value might have been reused for another object in the + * meantime, in which case we have to report that valid object, so + * force the caller to check the server. */ -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return NULL; + } + @@ -2590,30 +2590,31 @@ index 1072265..a9a0a2c 100644 +} + + -+static BOOL fast_sync_types_match( enum fast_sync_type a, enum fast_sync_type b ) ++static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) +{ + if (a == b) return TRUE; -+ if (a == FAST_SYNC_AUTO_EVENT && b == FAST_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == FAST_SYNC_AUTO_EVENT && a == FAST_SYNC_MANUAL_EVENT) return TRUE; ++ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; ++ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; + return FALSE; +} + + +/* returns a pointer to a cache entry; if the object could not be cached, + * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_fast_sync_obj( HANDLE handle, enum fast_sync_type desired_type, ACCESS_MASK desired_access, -+ struct fast_sync_cache_entry *stack_cache, -+ struct fast_sync_cache_entry **ret_cache ) ++static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, ++ ACCESS_MASK desired_access, ++ struct inproc_sync_cache_entry *stack_cache, ++ struct inproc_sync_cache_entry **ret_cache ) +{ -+ struct fast_sync_cache_entry *cache; -+ obj_handle_t fast_sync_handle; -+ enum fast_sync_type type; ++ struct inproc_sync_cache_entry *cache; ++ obj_handle_t inproc_sync_handle; ++ enum inproc_sync_type type; + unsigned int access; + int fd, needs_close; + NTSTATUS ret; + + /* try to find it in the cache already */ -+ if ((cache = get_cached_fast_sync_obj( handle ))) ++ if ((cache = get_cached_inproc_sync_obj( handle ))) + { + *ret_cache = cache; + return STATUS_SUCCESS; @@ -2625,7 +2626,7 @@ index 1072265..a9a0a2c 100644 + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { -+ fast_sync_handle = reply->handle; ++ inproc_sync_handle = reply->handle; + access = reply->access; + type = reply->type; + } @@ -2634,15 +2635,15 @@ index 1072265..a9a0a2c 100644 + + if (ret) return ret; + -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( fast_sync_handle ), ++ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), + 0, &fd, &needs_close, NULL, NULL ))) + return ret; + -+ cache = cache_fast_sync_obj( handle, fast_sync_handle, fd, type, access ); ++ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); + if (!cache) + { + cache = stack_cache; -+ cache->handle = fast_sync_handle; ++ cache->handle = inproc_sync_handle; + cache->fd = fd; + cache->type = type; + cache->access = access; @@ -2652,15 +2653,15 @@ index 1072265..a9a0a2c 100644 + + *ret_cache = cache; + -+ if (desired_type && !fast_sync_types_match( cache->type, desired_type )) ++ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + + if ((cache->access & desired_access) != desired_access) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_ACCESS_DENIED; + } + @@ -2669,16 +2670,16 @@ index 1072265..a9a0a2c 100644 + + +/* caller must hold fd_cache_mutex */ -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ -+ struct fast_sync_cache_entry *cache = get_cached_fast_sync_obj( handle ); ++ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); + + if (cache) + { + cache->closed = TRUE; + /* once for the reference we just grabbed, and once for the handle */ -+ release_fast_sync_obj( cache ); -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + } +} + @@ -2687,7 +2688,7 @@ index 1072265..a9a0a2c 100644 +{ + NTSTATUS ret; + -+ ret = ioctl( obj, NTSYNC_IOC_SEM_POST, &count ); ++ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); + if (ret < 0) + { + if (errno == EOVERFLOW) @@ -2700,18 +2701,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2730,18 +2731,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_semaphore_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2759,18 +2760,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_set_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2788,18 +2789,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_reset_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2817,23 +2818,23 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_pulse_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + + -+static NTSTATUS linux_query_event_obj( int obj, enum fast_sync_type type, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) +{ + struct ntsync_event_args args = {0}; + NTSTATUS ret; @@ -2841,24 +2842,24 @@ index 1072265..a9a0a2c 100644 + ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); + if (ret < 0) + return errno_to_status( errno ); -+ info->EventType = (type == FAST_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; ++ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; + info->EventState = args.signaled; + return STATUS_SUCCESS; +} + + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_event_obj( cache->fd, cache->type, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2885,17 +2886,17 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, 0, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) + return ret; + + ret = linux_release_mutex_obj( cache->fd, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2926,71 +2927,69 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, ++ &stack_cache, &cache ))) + return ret; + + ret = linux_query_mutex_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + -+static void select_queue( HANDLE queue ) ++static void select_queue(void) +{ -+ SERVER_START_REQ( fast_select_queue ) ++ SERVER_START_REQ( select_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static void unselect_queue( HANDLE queue, BOOL signaled ) ++static void unselect_queue( BOOL signaled ) +{ -+ SERVER_START_REQ( fast_unselect_queue ) ++ SERVER_START_REQ( unselect_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + req->signaled = signaled; + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static int get_fast_alert_obj(void) ++static int get_inproc_alert_obj(void) +{ + struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + HANDLE alert_handle; + unsigned int ret; + -+ if (!data->fast_alert_obj) ++ if (data->linux_alert_obj == -1) + { -+ SERVER_START_REQ( get_fast_alert_event ) ++ SERVER_START_REQ( get_inproc_alert_event ) + { + if ((ret = wine_server_call( req ))) -+ ERR( "failed to get fast alert event, status %#x\n", ret ); ++ ERR( "failed to get inproc alert event, status %#x\n", ret ); + alert_handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + -+ if ((ret = get_fast_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get fast alert obj, status %#x\n", ret ); -+ data->fast_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_fast_sync_obj() won't close it. ++ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) ++ ERR( "failed to get inproc alert obj, status %#x\n", ret ); ++ data->linux_alert_obj = cache->fd; ++ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. + * Manhandling the cache entry here is fine since we're the only thread + * that can access our own alert event. */ + cache->fd = -1; -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + NtClose( alert_handle ); + } + -+ return data->fast_alert_obj; ++ return data->linux_alert_obj; +} + +static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, @@ -3022,7 +3021,7 @@ index 1072265..a9a0a2c 100644 + args.index = ~0u; + + if (alertable) -+ args.alert = get_fast_alert_obj(); ++ args.alert = get_inproc_alert_obj(); + + if (wait_any || count == 1) + request = NTSYNC_IOC_WAIT_ANY; @@ -3055,10 +3054,10 @@ index 1072265..a9a0a2c 100644 + return errno_to_status( errno ); +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry stack_cache[64], *cache[64]; ++ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; + int device, objs[64]; + HANDLE queue = NULL; + NTSTATUS ret; @@ -3069,13 +3068,13 @@ index 1072265..a9a0a2c 100644 + + for (i = 0; i < count; ++i) + { -+ if ((ret = get_fast_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) ++ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) + { + for (j = 0; j < i; ++j) -+ release_fast_sync_obj( cache[j] ); ++ release_inproc_sync_obj( cache[j] ); + return ret; + } -+ if (cache[i]->type == FAST_SYNC_QUEUE) ++ if (cache[i]->type == INPROC_SYNC_QUEUE) + queue = handles[i]; + + objs[i] = cache[i]->fd; @@ -3083,32 +3082,32 @@ index 1072265..a9a0a2c 100644 + + /* It's common to wait on the message queue alone. Some applications wait + * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through fast_wait_objs(), and since we only -+ * need to go through that path if we're waiting on other objects, just -+ * delegate to the server if we're only waiting on the message queue. */ ++ * instead of one when going through inproc_wait(), and since we only need ++ * to go through that path if we're waiting on other objects, just delegate ++ * to the server if we're only waiting on the message queue. */ + if (count == 1 && queue) + { -+ release_fast_sync_obj( cache[0] ); ++ release_inproc_sync_obj( cache[0] ); + return server_wait_for_object( handles[0], alertable, timeout ); + } + -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + + ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); + -+ if (queue) unselect_queue( queue, handles[ret] == queue ); ++ if (queue) unselect_queue( handles[ret] == queue ); + + for (i = 0; i < count; ++i) -+ release_fast_sync_obj( cache[i] ); ++ release_inproc_sync_obj( cache[i] ); + + return ret; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct fast_sync_cache_entry wait_stack_cache, *wait_cache; ++ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; ++ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; + HANDLE queue = NULL; + NTSTATUS ret; + int device; @@ -3116,58 +3115,58 @@ index 1072265..a9a0a2c 100644 + if ((device = get_linux_sync_device()) < 0) + return STATUS_NOT_IMPLEMENTED; + -+ if ((ret = get_fast_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) ++ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) + return ret; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + if (!(signal_cache->access & EVENT_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + break; + + default: + /* can't be signaled */ -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + -+ if ((ret = get_fast_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) ++ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return ret; + } + -+ if (wait_cache->type == FAST_SYNC_QUEUE) ++ if (wait_cache->type == INPROC_SYNC_QUEUE) + queue = wait; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + ret = linux_set_event_obj( signal_cache->fd, NULL ); + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + ret = linux_release_mutex_obj( signal_cache->fd, NULL ); + break; + @@ -3178,70 +3177,70 @@ index 1072265..a9a0a2c 100644 + + if (!ret) + { -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( queue, !ret ); ++ if (queue) unselect_queue( !ret ); + } + -+ release_fast_sync_obj( signal_cache ); -+ release_fast_sync_obj( wait_cache ); ++ release_inproc_sync_obj( signal_cache ); ++ release_inproc_sync_obj( wait_cache ); + return ret; +} + +#else + -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ +} + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} @@ -3289,7 +3288,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_semaphore( handle, info, ret_len ); -+ if ((ret = fast_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + return ret; @@ -3305,7 +3304,7 @@ index 1072265..a9a0a2c 100644 - return esync_release_semaphore( handle, count, previous ); + TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); + -+ if ((ret = fast_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( release_semaphore ) @@ -3352,7 +3351,7 @@ index 1072265..a9a0a2c 100644 - return esync_set_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3368,7 +3367,7 @@ index 1072265..a9a0a2c 100644 - return esync_reset_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ if ((ret = fast_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3381,7 +3380,7 @@ index 1072265..a9a0a2c 100644 - return esync_pulse_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3392,7 +3391,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_event( handle, info, ret_len ); -+ if ((ret = fast_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); + return ret; @@ -3438,7 +3437,7 @@ index 1072265..a9a0a2c 100644 - return esync_release_mutex( handle, prev_count ); + TRACE( "handle %p, prev_count %p\n", handle, prev_count ); + -+ if ((ret = fast_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( release_mutex ) @@ -3449,7 +3448,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_mutex( handle, info, ret_len ); -+ if ((ret = fast_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); + return ret; @@ -3504,7 +3503,7 @@ index 1072265..a9a0a2c 100644 + TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); + } + -+ if ((ret = fast_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + { + TRACE( "-> %#x\n", ret ); + return ret; @@ -3532,7 +3531,7 @@ index 1072265..a9a0a2c 100644 if (!signal) return STATUS_INVALID_HANDLE; -+ if ((ret = fast_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + return ret; + if (alertable) flags |= SELECT_ALERTABLE; @@ -3622,7 +3621,7 @@ index 4e5b282..fc5b259 100644 PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ void *jmp_buf; /* setjmp buffer for exception handling */ -+ int fast_alert_obj; /* fd for the fast alert event */ ++ int linux_alert_obj; /* fd for the linux in-process alert event */ }; C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); @@ -3647,7 +3646,7 @@ index 4e5b282..fc5b259 100644 extern void dbg_init(void); -+extern void close_fast_sync_obj( HANDLE handle ); ++extern void close_inproc_sync_obj( HANDLE handle ); + extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ); @@ -3673,7 +3672,7 @@ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 1e1af8c..a54ac45 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c -@@ -3712,7 +3712,6 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) +@@ -3712,11 +3712,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; @@ -3681,40 +3680,11 @@ index 1e1af8c..a54ac45 100644 thread_data->request_fd = -1; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; -diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c -index 02193b8..eb733f6 100644 ---- a/dlls/rpcrt4/rpc_server.c -+++ b/dlls/rpcrt4/rpc_server.c -@@ -701,6 +701,10 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) - } - LeaveCriticalSection(&cps->cs); - -+ EnterCriticalSection(&listen_cs); -+ CloseHandle(cps->server_thread); -+ cps->server_thread = NULL; -+ LeaveCriticalSection(&listen_cs); - TRACE("done\n"); - return 0; + thread_data->wait_fd[1] = -1; ++ thread_data->linux_alert_obj = -1; + list_add_head( &teb_list, &thread_data->entry ); + return teb; } -@@ -1566,10 +1570,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) - LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) - { - if ((wait_thread = protseq->server_thread)) -- { -- protseq->server_thread = NULL; - break; -- } - } - LeaveCriticalSection(&server_cs); - if (!wait_thread) -@@ -1578,7 +1579,6 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) - TRACE("waiting for thread %lu\n", GetThreadId(wait_thread)); - LeaveCriticalSection(&listen_cs); - WaitForSingleObject(wait_thread, INFINITE); -- CloseHandle(wait_thread); - EnterCriticalSection(&listen_cs); - } - if (listen_done_event == event) diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c index c64027f..ddcf896 100644 --- a/dlls/webservices/tests/channel.c @@ -3757,19 +3727,19 @@ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 34655d1..1f8e10a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h -@@ -5634,6 +5634,88 @@ struct get_next_thread_reply +@@ -5881,6 +5881,86 @@ }; - - -+enum fast_sync_type + + ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + @@ -3804,38 +3774,36 @@ index 34655d1..1f8e10a 100644 + + + -+struct fast_select_queue_request ++struct select_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; ++ char __pad_12[4]; +}; -+struct fast_select_queue_reply ++struct select_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct fast_unselect_queue_request ++struct unselect_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; + int signaled; -+ char __pad_20[4]; +}; -+struct fast_unselect_queue_reply ++struct unselect_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct get_fast_alert_event_request ++struct get_inproc_alert_event_request +{ + struct request_header __header; + char __pad_12[4]; +}; -+struct get_fast_alert_event_reply ++struct get_inproc_alert_event_reply +{ + struct reply_header __header; + obj_handle_t handle; @@ -3854,13 +3822,13 @@ index 34655d1..1f8e10a 100644 - REQ_open_esync, - REQ_get_esync_fd, - REQ_esync_msgwait, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_fast_select_queue, -+ REQ_fast_unselect_queue, REQ_set_keyboard_repeat, - REQ_get_esync_apc_fd, -+ REQ_get_fast_alert_event, ++ REQ_get_linux_sync_device, ++ REQ_get_linux_sync_obj, ++ REQ_select_inproc_queue, ++ REQ_unselect_inproc_queue, ++ REQ_get_inproc_alert_event, REQ_NB_REQUESTS }; @@ -3872,13 +3840,13 @@ index 34655d1..1f8e10a 100644 - struct open_esync_request open_esync_request; - struct get_esync_fd_request get_esync_fd_request; - struct esync_msgwait_request esync_msgwait_request; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct fast_select_queue_request fast_select_queue_request; -+ struct fast_unselect_queue_request fast_unselect_queue_request; struct set_keyboard_repeat_request set_keyboard_repeat_request; - struct get_esync_apc_fd_request get_esync_apc_fd_request; -+ struct get_fast_alert_event_request get_fast_alert_event_request; ++ struct get_linux_sync_device_request get_linux_sync_device_request; ++ struct get_linux_sync_obj_request get_linux_sync_obj_request; ++ struct select_inproc_queue_request select_inproc_queue_request; ++ struct unselect_inproc_queue_request unselect_inproc_queue_request; ++ struct get_inproc_alert_event_request get_inproc_alert_event_request; }; union generic_reply { @@ -3890,13 +3858,13 @@ index 34655d1..1f8e10a 100644 - struct open_esync_reply open_esync_reply; - struct get_esync_fd_reply get_esync_fd_reply; - struct esync_msgwait_reply esync_msgwait_reply; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct fast_select_queue_reply fast_select_queue_reply; -+ struct fast_unselect_queue_reply fast_unselect_queue_reply; struct set_keyboard_repeat_reply set_keyboard_repeat_reply; - struct get_esync_apc_fd_reply get_esync_apc_fd_reply; -+ struct get_fast_alert_event_reply get_fast_alert_event_reply; ++ struct get_linux_sync_device_reply get_linux_sync_device_reply; ++ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; ++ struct select_inproc_queue_reply select_inproc_queue_reply; ++ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; ++ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; }; /* ### protocol_version begin ### */ @@ -3910,7 +3878,7 @@ index b164193..b30df66 100644 directory.c \ - esync.c \ event.c \ -+ fast_sync.c \ ++ inproc_sync.c \ fd.c \ file.c \ handle.c \ @@ -3930,7 +3898,7 @@ index b0f9fe4..02fb966 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ async_destroy /* destroy */ }; @@ -3946,7 +3914,7 @@ index b0f9fe4..02fb966 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ iosb_destroy /* destroy */ }; @@ -3966,7 +3934,7 @@ index d9824de..ba320c4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; @@ -3986,7 +3954,7 @@ index ec61711..dafa7e8 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; @@ -4006,7 +3974,7 @@ index 8b265f2..de9f84f 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ clipboard_destroy /* destroy */ }; @@ -4014,15 +3982,15 @@ diff --git a/server/completion.c b/server/completion.c index 3d4be86..5ec6d20 100644 --- a/server/completion.c +++ b/server/completion.c -@@ -61,6 +61,7 @@ struct completion +@@ -77,6 +77,7 @@ struct list wait_queue; unsigned int depth; int closed; -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; }; static void completion_wait_dump( struct object*, int ); -@@ -92,21 +92,21 @@ static const struct object_ops completion_wait_ops = +@@ -92,7 +93,6 @@ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_wait_signaled, /* signaled */ @@ -4030,44 +3998,23 @@ index 3d4be86..5ec6d20 100644 completion_wait_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - no_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ +@@ -105,6 +105,7 @@ NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ completion_wait_destroy /* destroy */ }; - - static void completion_wait_destroy( struct object *obj ) -@@ -75,24 +77,28 @@ static const struct object_ops completion_ops = - msg = LIST_ENTRY( msg_entry, struct comp_msg, queue_entry ); - --wait->completion->depth; - list_remove( &msg->queue_entry ); -+ if (list_empty( &wait->completion->queue )) -+ { -+ fast_reset_event( wait->completion->fast_sync ); -+ } - if (wait->msg) free( wait->msg ); - wait->msg = msg; - } +@@ -156,6 +157,7 @@ static void completion_dump( struct object*, int ); static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *completion_get_fast_sync( struct object *obj ); ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void completion_destroy( struct object * ); - static const struct object_ops completion_ops = - { - sizeof(struct completion), /* size */ - &completion_type, /* type */ - completion_dump, /* dump */ +@@ -167,7 +169,6 @@ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_signaled, /* signaled */ @@ -4075,61 +4022,74 @@ index 3d4be86..5ec6d20 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -87,6 +88,7 @@ static const struct object_ops completion_ops = +@@ -180,6 +181,7 @@ default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_fast_sync, /* get_fast_sync */ ++ completion_get_inproc_sync,/* get_inproc_sync */ completion_close_handle, /* close_handle */ completion_destroy /* destroy */ }; -@@ -110,6 +112,7 @@ static void completion_destroy( struct object *obj) +@@ -193,6 +195,7 @@ { free( tmp ); } -+ if (completion->fast_sync) release_object( completion->fast_sync ); ++ if (completion->inproc_sync) release_object( completion->inproc_sync ); } static void completion_dump( struct object *obj, int verbose ) -@@ -127,6 +130,16 @@ static int completion_signaled( struct object *obj, struct wait_queue_entry *ent - return !list_empty( &completion->queue ); +@@ -230,6 +233,7 @@ + } + completion->closed = 1; + wake_up( obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); + return 1; + } + +@@ -263,6 +267,16 @@ + return wait; } -+static struct fast_sync *completion_get_fast_sync( struct object *obj ) ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) +{ + struct completion *completion = (struct completion *)obj; + -+ if (!completion->fast_sync) -+ completion->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->fast_sync) grab_object( completion->fast_sync ); -+ return completion->fast_sync; ++ if (!completion->inproc_sync) ++ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); ++ if (completion->inproc_sync) grab_object( completion->inproc_sync ); ++ return completion->inproc_sync; +} + static struct completion *create_completion( struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent, const struct security_descriptor *sd ) -@@ -139,6 +152,7 @@ static struct completion *create_completion( struct object *root, const struct u - { - list_init( &completion->queue ); +@@ -277,6 +291,7 @@ + list_init( &completion->wait_queue ); completion->depth = 0; completion->closed = 0; -+ completion->fast_sync = NULL; ++ completion->inproc_sync = NULL; } } -@@ -166,6 +180,7 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ + +@@ -309,7 +324,11 @@ + wake_up( &wait->obj, 1 ); if (list_empty( &completion->queue )) return; } - if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ fast_set_event( completion->fast_sync ); +- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); ++ if (!list_empty( &completion->queue )) ++ { ++ wake_up( &completion->obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); ++ } } /* create a completion */ -@@ -232,6 +247,8 @@ DECL_HANDLER(remove_completion) +@@ -410,6 +429,8 @@ reply->information = msg->information; free( msg ); reply->wait_handle = 0; + if (list_empty( &completion->queue )) -+ fast_reset_event( completion->fast_sync ); ++ reset_inproc_event( completion->inproc_sync ); } release_object( completion ); @@ -4149,7 +4109,7 @@ index dbd4a97..17708df 100644 struct fd *fd; /* for bare console, attached input fd */ struct async_queue ioctl_q; /* ioctl queue */ struct async_queue read_q; /* read queue */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_dump( struct object *obj, int verbose ); @@ -4157,7 +4117,7 @@ index dbd4a97..17708df 100644 static struct object *console_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *console_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ); static const struct object_ops console_ops = { @@ -4173,7 +4133,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ console_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_fast_sync, /* get_fast_sync */ ++ console_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_destroy /* destroy */ }; @@ -4198,7 +4158,7 @@ index dbd4a97..17708df 100644 - int esync_fd; + int term_fd; /* UNIX terminal fd */ + struct termios termios; /* original termios */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_server_dump( struct object *obj, int verbose ); @@ -4210,7 +4170,7 @@ index dbd4a97..17708df 100644 unsigned int attr, struct object *root ); static struct object *console_server_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); static const struct object_ops console_server_ops = { @@ -4226,7 +4186,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ console_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_fast_sync, /* get_fast_sync */ ++ console_server_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_server_destroy /* destroy */ }; @@ -4234,7 +4194,7 @@ index dbd4a97..17708df 100644 static struct fd *screen_buffer_get_fd( struct object *obj ); static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); static const struct object_ops screen_buffer_ops = { @@ -4250,7 +4210,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ screen_buffer_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_fast_sync, /* get_fast_sync */ ++ screen_buffer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; @@ -4266,7 +4226,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4274,7 +4234,7 @@ index dbd4a97..17708df 100644 unsigned int sharing, unsigned int options ); static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); static void console_input_destroy( struct object *obj ); static const struct object_ops console_input_ops = @@ -4290,7 +4250,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_input_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_fast_sync, /* get_fast_sync */ ++ console_input_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -4298,7 +4258,7 @@ index dbd4a97..17708df 100644 static struct fd *console_output_get_fd( struct object *obj ); static struct object *console_output_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); static void console_output_destroy( struct object *obj ); static const struct object_ops console_output_ops = @@ -4314,7 +4274,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_output_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_fast_sync, /* get_fast_sync */ ++ console_output_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_output_destroy /* destroy */ }; @@ -4330,7 +4290,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_connection_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ console_connection_close_handle, /* close_handle */ console_connection_destroy /* destroy */ }; @@ -4338,7 +4298,7 @@ index dbd4a97..17708df 100644 console->server = NULL; console->fd = NULL; console->last_id = 0; -+ console->fast_sync = NULL; ++ console->inproc_sync = NULL; init_async_queue( &console->ioctl_q ); init_async_queue( &console->read_q ); @@ -4346,7 +4306,7 @@ index dbd4a97..17708df 100644 } list_add_tail( &server->queue, &ioctl->entry ); wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); if (async) set_error( STATUS_PENDING ); return 1; } @@ -4363,7 +4323,7 @@ index dbd4a97..17708df 100644 server->console->server = NULL; server->console = NULL; wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); } } @@ -4372,7 +4332,7 @@ index dbd4a97..17708df 100644 if (console->fd) release_object( console->fd ); + -+ if (console->fast_sync) release_object( console->fast_sync ); ++ if (console->inproc_sync) release_object( console->inproc_sync ); } static struct object *create_console_connection( struct console *console ) @@ -4380,14 +4340,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ) +{ + struct console *console = (struct console *)obj; + -+ if (!console->fast_sync) -+ console->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->fast_sync) grab_object( console->fast_sync ); -+ return console->fast_sync; ++ if (!console->inproc_sync) ++ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); ++ if (console->inproc_sync) grab_object( console->inproc_sync ); ++ return console->inproc_sync; +} + static void screen_buffer_dump( struct object *obj, int verbose ) @@ -4397,7 +4357,7 @@ index dbd4a97..17708df 100644 return NULL; } -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) +{ + struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; + if (!screen_buffer->input) @@ -4405,7 +4365,7 @@ index dbd4a97..17708df 100644 + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( &screen_buffer->input->obj ); ++ return console_get_inproc_sync( &screen_buffer->input->obj ); +} + static void console_server_dump( struct object *obj, int verbose ) @@ -4416,7 +4376,7 @@ index dbd4a97..17708df 100644 disconnect_console_server( server ); if (server->fd) release_object( server->fd ); - if (do_esync()) close( server->esync_fd ); -+ if (server->fast_sync) release_object( server->fast_sync ); ++ if (server->inproc_sync) release_object( server->inproc_sync ); } static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, @@ -4438,15 +4398,15 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) +{ + struct console_server *server = (struct console_server *)obj; + int signaled = !server->console || !list_empty( &server->queue ); + -+ if (!server->fast_sync) -+ server->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (server->fast_sync) grab_object( server->fast_sync ); -+ return server->fast_sync; ++ if (!server->inproc_sync) ++ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (server->inproc_sync) grab_object( server->inproc_sync ); ++ return server->inproc_sync; +} + static struct object *create_console_server( void ) @@ -4456,7 +4416,7 @@ index dbd4a97..17708df 100644 server->term_fd = -1; list_init( &server->queue ); list_init( &server->read_queue ); -+ server->fast_sync = NULL; ++ server->inproc_sync = NULL; server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!server->fd) { @@ -4475,14 +4435,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_input_destroy( struct object *obj ) @@ -4492,14 +4452,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console || !current->process->console->active) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_output_destroy( struct object *obj ) @@ -4513,13 +4473,13 @@ index dbd4a97..17708df 100644 + if (!req->signal) + { + server->console->signaled = 0; -+ fast_reset_event( server->console->fast_sync ); ++ reset_inproc_event( server->console->inproc_sync ); + } else if (!server->console->signaled) { server->console->signaled = 1; wake_up( &server->console->obj, 0 ); -+ fast_set_event( server->console->fast_sync ); ++ set_inproc_event( server->console->inproc_sync ); } if (req->read) @@ -4530,7 +4490,7 @@ index dbd4a97..17708df 100644 - if (do_esync() && list_empty( &server->queue )) - esync_clear( server->esync_fd ); + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); } if (ioctl) @@ -4542,7 +4502,7 @@ index dbd4a97..17708df 100644 - esync_clear( server->esync_fd ); + + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); release_object( server ); } @@ -4554,7 +4514,7 @@ index ca04d4c..7975fc4 100644 struct object obj; /* object header */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; @@ -4570,14 +4530,14 @@ index ca04d4c..7975fc4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; static void debug_obj_dump( struct object *obj, int verbose ); static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ); ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); static void debug_obj_destroy( struct object *obj ); static const struct object_ops debug_obj_ops = @@ -4593,7 +4553,7 @@ index ca04d4c..7975fc4 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_fast_sync, /* get_fast_sync */ ++ debug_obj_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_obj_destroy /* destroy */ }; @@ -4601,7 +4561,7 @@ index ca04d4c..7975fc4 100644 /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -4609,7 +4569,7 @@ index ca04d4c..7975fc4 100644 { grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -4617,15 +4577,15 @@ index ca04d4c..7975fc4 100644 return find_event_to_send( debug_obj ) != NULL; } -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ) ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) +{ + struct debug_obj *debug_obj = (struct debug_obj *)obj; + int signaled = find_event_to_send( debug_obj ) != NULL; + -+ if (!debug_obj->fast_sync) -+ debug_obj->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->fast_sync) grab_object( debug_obj->fast_sync ); -+ return debug_obj->fast_sync; ++ if (!debug_obj->inproc_sync) ++ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); ++ return debug_obj->inproc_sync; +} + static void debug_obj_destroy( struct object *obj ) @@ -4636,7 +4596,7 @@ index ca04d4c..7975fc4 100644 while ((ptr = list_head( &debug_obj->event_queue ))) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); + -+ if (debug_obj->fast_sync) release_object( debug_obj->fast_sync ); ++ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); } struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -4644,7 +4604,7 @@ index ca04d4c..7975fc4 100644 { debug_obj->flags = flags; list_init( &debug_obj->event_queue ); -+ debug_obj->fast_sync = NULL; ++ debug_obj->inproc_sync = NULL; } } return debug_obj; @@ -4654,7 +4614,7 @@ index ca04d4c..7975fc4 100644 set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); + + if (!find_event_to_send( debug_obj )) -+ fast_reset_event( debug_obj->fast_sync ); ++ reset_inproc_event( debug_obj->inproc_sync ); } else { @@ -4682,7 +4642,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ irp_call_destroy /* destroy */ }; @@ -4691,13 +4651,13 @@ index c45d010..698fee6 100644 struct irp_call *current_call; /* call currently executed on client side */ struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void device_manager_dump( struct object *obj, int verbose ); static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ); -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ); ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); static void device_manager_destroy( struct object *obj ); static const struct object_ops device_manager_ops = @@ -4713,7 +4673,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_fast_sync, /* get_fast_sync */ ++ device_manager_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_manager_destroy /* destroy */ }; @@ -4729,7 +4689,7 @@ index c45d010..698fee6 100644 default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -4745,7 +4705,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ device_file_close_handle, /* close_handle */ device_file_destroy /* destroy */ }; @@ -4758,7 +4718,7 @@ index c45d010..698fee6 100644 + { + /* first one */ + wake_up( &manager->obj, 0 ); -+ fast_set_event( manager->fast_sync ); ++ set_inproc_event( manager->inproc_sync ); + } } @@ -4775,7 +4735,7 @@ index c45d010..698fee6 100644 } + if (list_empty( &file->device->manager->requests )) -+ fast_reset_event( file->device->manager->fast_sync ); ++ reset_inproc_event( file->device->manager->inproc_sync ); + release_object( file ); } @@ -4785,16 +4745,16 @@ index c45d010..698fee6 100644 } -static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ) -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ) ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; - *type = ESYNC_MANUAL_SERVER; - return manager->esync_fd; + -+ if (!manager->fast_sync) -+ manager->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->fast_sync) grab_object( manager->fast_sync ); -+ return manager->fast_sync; ++ if (!manager->inproc_sync) ++ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); ++ if (manager->inproc_sync) grab_object( manager->inproc_sync ); ++ return manager->inproc_sync; } static void device_manager_destroy( struct object *obj ) @@ -4804,7 +4764,7 @@ index c45d010..698fee6 100644 - if (do_esync()) - close( manager->esync_fd ); -+ if (manager->fast_sync) release_object( manager->fast_sync ); ++ if (manager->inproc_sync) release_object( manager->inproc_sync ); } static struct device_manager *create_device_manager(void) @@ -4812,7 +4772,7 @@ index c45d010..698fee6 100644 if ((manager = alloc_object( &device_manager_ops ))) { manager->current_call = NULL; -+ manager->fast_sync = NULL; ++ manager->inproc_sync = NULL; list_init( &manager->devices ); list_init( &manager->requests ); wine_rb_init( &manager->kernel_objects, compare_kernel_object ); @@ -4828,7 +4788,7 @@ index c45d010..698fee6 100644 list_init( &irp->mgr_entry ); + + if (list_empty( &manager->requests )) -+ fast_reset_event( manager->fast_sync ); ++ reset_inproc_event( manager->inproc_sync ); + /* we already own the object if it's only on manager queue */ if (irp->file) grab_object( irp ); @@ -4855,7 +4815,7 @@ index bc161b9..8e32abb 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4871,7 +4831,7 @@ index bc161b9..8e32abb 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ }; @@ -5527,7 +5487,7 @@ index f4ca3e4..b750a22 100644 int manual_reset; /* is it a manual reset event? */ int signaled; /* event has been signaled */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void event_dump( struct object *obj, int verbose ); @@ -5536,7 +5496,7 @@ index f4ca3e4..b750a22 100644 -static int event_get_esync_fd( struct object *obj, enum esync_type *type ); static int event_signal( struct object *obj, unsigned int access); static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ); static void event_destroy( struct object *obj ); static const struct object_ops event_ops = @@ -5552,7 +5512,7 @@ index f4ca3e4..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_fast_sync, /* get_fast_sync */ ++ event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ event_destroy /* destroy */ }; @@ -5560,12 +5520,12 @@ index f4ca3e4..b750a22 100644 struct keyed_event { struct object obj; /* object header */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void keyed_event_dump( struct object *obj, int verbose ); static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); +static void keyed_event_destroy( struct object *obj ); static const struct object_ops keyed_event_ops = @@ -5582,7 +5542,7 @@ index f4ca3e4..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_fast_sync, /* get_fast_sync */ ++ keyed_event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + keyed_event_destroy /* destroy */ @@ -5596,7 +5556,7 @@ index f4ca3e4..b750a22 100644 - - if (do_esync()) - event->esync_fd = esync_create_fd( initial_state, 0 ); -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -5624,7 +5584,7 @@ index f4ca3e4..b750a22 100644 event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ wake_up( &event->obj, !event->manual_reset ); -+ fast_set_event( event->fast_sync ); ++ set_inproc_event( event->inproc_sync ); } void reset_event( struct event *event ) @@ -5638,7 +5598,7 @@ index f4ca3e4..b750a22 100644 - - if (do_esync()) - esync_clear( event->esync_fd ); -+ fast_reset_event( event->fast_sync ); ++ reset_inproc_event( event->inproc_sync ); } static void event_dump( struct object *obj, int verbose ) @@ -5660,17 +5620,17 @@ index f4ca3e4..b750a22 100644 return &event->kernel_object; } -+static struct fast_sync *event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (!event->fast_sync) ++ if (!event->inproc_sync) + { -+ enum fast_sync_type type = event->manual_reset ? FAST_SYNC_MANUAL_EVENT : FAST_SYNC_AUTO_EVENT; -+ event->fast_sync = fast_create_event( type, event->signaled ); ++ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; ++ event->inproc_sync = create_inproc_event( type, event->signaled ); + } -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + static void event_destroy( struct object *obj ) @@ -5679,7 +5639,7 @@ index f4ca3e4..b750a22 100644 - if (do_esync()) - close( event->esync_fd ); -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); } struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, @@ -5687,7 +5647,7 @@ index f4ca3e4..b750a22 100644 if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -5695,34 +5655,34 @@ index f4ca3e4..b750a22 100644 return 0; } -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (!event->fast_sync) -+ event->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, 1 ); -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (!event->inproc_sync) ++ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void keyed_event_destroy( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + /* create an event */ DECL_HANDLER(create_event) { -diff --git a/server/fast_sync.c b/server/fast_sync.c +diff --git a/server/inproc_sync.c b/server/inproc_sync.c new file mode 100644 index 0000000..fed6eb9 --- /dev/null -+++ b/server/fast_sync.c -@@ -0,0 +1,434 @@ ++++ b/server/inproc_sync.c +@@ -0,0 +1,437 @@ +/* -+ * Fast synchronization primitives ++ * In-process synchronization primitives + * + * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers + * @@ -5776,7 +5736,7 @@ index 0000000..fed6eb9 +static void linux_device_dump( struct object *obj, int verbose ); +static struct fd *linux_device_get_fd( struct object *obj ); +static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ); ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); + +static const struct object_ops linux_device_ops = +{ @@ -5798,16 +5758,16 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_device_destroy /* destroy */ +}; + -+static const struct fd_ops fast_sync_fd_ops = ++static const struct fd_ops inproc_sync_fd_ops = +{ + default_fd_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ -+ fast_sync_get_fd_type, /* get_fd_type */ ++ inproc_sync_get_fd_type, /* get_fd_type */ + no_fd_read, /* read */ + no_fd_write, /* write */ + no_fd_flush, /* flush */ @@ -5823,7 +5783,7 @@ index 0000000..fed6eb9 +{ + struct linux_device *device = (struct linux_device *)obj; + assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "Fast synchronization device fd=%p\n", device->fd ); ++ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); +} + +static struct fd *linux_device_get_fd( struct object *obj ) @@ -5840,7 +5800,7 @@ index 0000000..fed6eb9 + linux_device_object = NULL; +} + -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ) ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) +{ + return FD_TYPE_FILE; +} @@ -5887,7 +5847,7 @@ index 0000000..fed6eb9 + return NULL; + } + -+ if (!(device->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &device->obj, 0 ))) ++ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) + { + release_object( device ); + initialized = 1; @@ -5900,10 +5860,10 @@ index 0000000..fed6eb9 + return device; +} + -+struct fast_sync ++struct inproc_sync +{ + struct object obj; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + struct fd *fd; +}; + @@ -5913,7 +5873,7 @@ index 0000000..fed6eb9 + +static const struct object_ops linux_obj_ops = +{ -+ sizeof(struct fast_sync), /* size */ ++ sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + linux_obj_dump, /* dump */ + no_add_queue, /* add_queue */ @@ -5931,80 +5891,81 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_obj_destroy /* destroy */ +}; + +static void linux_obj_dump( struct object *obj, int verbose ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "Fast synchronization object type=%u fd=%p\n", fast_sync->type, fast_sync->fd ); ++ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); +} + +static void linux_obj_destroy( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ if (fast_sync->fd) release_object( fast_sync->fd ); ++ if (inproc_sync->fd) release_object( inproc_sync->fd ); +} + +static struct fd *linux_obj_get_fd( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( fast_sync->fd ); ++ return (struct fd *)grab_object( inproc_sync->fd ); +} + -+static struct fast_sync *create_fast_sync( enum fast_sync_type type, int unix_fd ) ++static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) +{ -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if (!(fast_sync = alloc_object( &linux_obj_ops ))) ++ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) + { + close( unix_fd ); + return NULL; + } + -+ fast_sync->type = type; ++ inproc_sync->type = type; + -+ if (!(fast_sync->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &fast_sync->obj, 0 ))) ++ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) + { -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + return NULL; + } + -+ return fast_sync; ++ return inproc_sync; +} + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ -+ struct ntsync_event_args args = {0}; ++ struct ntsync_event_args args; + struct linux_device *device; ++ int event; + + if (!(device = get_linux_device())) return NULL; + + args.signaled = signaled; + switch (type) + { -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_AUTO_SERVER: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_AUTO_SERVER: + args.manual = 0; + break; + -+ case FAST_SYNC_MANUAL_EVENT: -+ case FAST_SYNC_MANUAL_SERVER: -+ case FAST_SYNC_QUEUE: ++ case INPROC_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_MANUAL_SERVER: ++ case INPROC_SYNC_QUEUE: + args.manual = 1; + break; + -+ case FAST_SYNC_MUTEX: -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_MUTEX: ++ case INPROC_SYNC_SEMAPHORE: + assert(0); + break; + } -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args ) < 0) ++ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6012,19 +5973,20 @@ index 0000000..fed6eb9 + } + release_object( device ); + -+ return create_fast_sync( type, args.event ); ++ return create_inproc_sync( type, event ); +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ -+ struct ntsync_sem_args args = {0}; ++ struct ntsync_sem_args args; + struct linux_device *device; ++ int semaphore; + + if (!(device = get_linux_device())) return NULL; + + args.count = count; + args.max = max; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args ) < 0) ++ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6033,19 +5995,20 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_SEMAPHORE, args.sem ); ++ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ -+ struct ntsync_mutex_args args = {0}; ++ struct ntsync_mutex_args args; + struct linux_device *device; ++ int mutex; + + if (!(device = get_linux_device())) return NULL; + + args.owner = owner; + args.count = count; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args ) < 0) ++ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6054,65 +6017,65 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_MUTEX, args.mutex ); ++ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); +} + -+void fast_reset_event( struct fast_sync *fast_sync ) ++void reset_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); +} + +#else + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ +} + -+void fast_reset_event( struct fast_sync *obj ) ++void reset_inproc_event( struct inproc_sync *obj ) +{ +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ +} + @@ -6140,14 +6103,14 @@ index 0000000..fed6eb9 + + if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) + { -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if ((fast_sync = obj->ops->get_fast_sync( obj ))) ++ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) + { -+ reply->handle = alloc_handle( current->process, fast_sync, 0, 0 ); -+ reply->type = fast_sync->type; ++ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); ++ reply->type = inproc_sync->type; + reply->access = get_handle_access( current->process, req->handle ); -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + } + release_object( obj ); + } @@ -6172,7 +6135,7 @@ index a6782b0..f00e22d 100644 apc_param_t comp_key; /* completion key to set in completion events */ unsigned int comp_flags; /* completion flags */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void fd_dump( struct object *obj, int verbose ); @@ -6188,7 +6151,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ fd_destroy /* destroy */ }; @@ -6204,7 +6167,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -6220,7 +6183,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ inode_destroy /* destroy */ }; @@ -6236,7 +6199,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6247,7 +6210,7 @@ index a6782b0..f00e22d 100644 - - if (do_esync()) - close( fd->esync_fd ); -+ if (fd->fast_sync) release_object( fd->fast_sync ); ++ if (fd->inproc_sync) release_object( fd->inproc_sync ); } /* check if the desired access is possible without violating */ @@ -6256,7 +6219,7 @@ index a6782b0..f00e22d 100644 fd->completion = NULL; fd->comp_flags = 0; - fd->esync_fd = -1; -+ fd->fast_sync = NULL; ++ fd->inproc_sync = NULL; init_async_queue( &fd->read_q ); init_async_queue( &fd->write_q ); init_async_queue( &fd->wait_q ); @@ -6273,7 +6236,7 @@ index a6782b0..f00e22d 100644 fd->poll_index = -1; fd->completion = NULL; fd->comp_flags = 0; -+ fd->fast_sync = NULL; ++ fd->inproc_sync = NULL; fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - fd->esync_fd = -1; init_async_queue( &fd->read_q ); @@ -6298,11 +6261,11 @@ index a6782b0..f00e22d 100644 + if (signaled) + { + wake_up( fd->user, 0 ); -+ fast_set_event( fd->fast_sync ); ++ set_inproc_event( fd->inproc_sync ); + } + else + { -+ fast_reset_event( fd->fast_sync ); ++ reset_inproc_event( fd->inproc_sync ); + } } @@ -6312,16 +6275,16 @@ index a6782b0..f00e22d 100644 } -int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ) -+struct fast_sync *default_fd_get_fast_sync( struct object *obj ) ++struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) { struct fd *fd = get_obj_fd( obj ); - int ret = fd->esync_fd; - *type = ESYNC_MANUAL_SERVER; -+ struct fast_sync *ret; ++ struct inproc_sync *ret; + -+ if (!fd->fast_sync) -+ fd->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->fast_sync; ++ if (!fd->inproc_sync) ++ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); ++ ret = fd->inproc_sync; release_object( fd ); + if (ret) grab_object( ret ); return ret; @@ -6343,7 +6306,7 @@ index 828a21c..c6bdbef 100644 NULL, /* unlink_name */ file_open_file, /* open_file */ file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ file_destroy /* destroy */ }; @@ -6356,7 +6319,7 @@ index abad355..6b4fa51 100644 extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ); -+extern struct fast_sync *default_fd_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); 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 ); @@ -6376,7 +6339,7 @@ index cf6afe4..e07f32c 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handle_table_destroy /* destroy */ }; @@ -6396,7 +6359,7 @@ index da351d6..5a00699 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ hook_table_destroy /* destroy */ }; @@ -6416,7 +6379,7 @@ index 4cf9b73..d9807b4 100644 default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync,/* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; @@ -6432,7 +6395,7 @@ index 4cf9b73..d9807b4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; @@ -6448,7 +6411,7 @@ index 4cf9b73..d9807b4 100644 default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ }; @@ -6464,7 +6427,7 @@ index 4cf9b73..d9807b4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_file_destroy /* destroy */ }; @@ -6506,7 +6469,7 @@ index 88de806..c3cba90 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ranges_destroy /* destroy */ }; @@ -6522,7 +6485,7 @@ index 88de806..c3cba90 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ shared_map_destroy /* destroy */ }; @@ -6538,7 +6501,7 @@ index 88de806..c3cba90 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; @@ -6550,7 +6513,7 @@ index 4785a83..167c236 100644 static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; -+static struct list fast_mutexes = LIST_INIT(fast_mutexes); ++static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); + struct type_descr mutex_type = { @@ -6559,8 +6522,8 @@ index 4785a83..167c236 100644 unsigned int count; /* recursion count */ int abandoned; /* has it been abandoned? */ struct list entry; /* entry in owner thread mutex list */ -+ struct list fast_mutexes_entry; /* entry in fast_mutexes list */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void mutex_dump( struct object *obj, int verbose ); @@ -6568,7 +6531,7 @@ index 4785a83..167c236 100644 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void mutex_destroy( struct object *obj ); static int mutex_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ); ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); static const struct object_ops mutex_ops = { @@ -6584,7 +6547,7 @@ index 4785a83..167c236 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_fast_sync, /* get_fast_sync */ ++ mutex_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; @@ -6592,7 +6555,7 @@ index 4785a83..167c236 100644 mutex->owner = NULL; mutex->abandoned = 0; if (owned) do_grab( mutex, current ); -+ mutex->fast_sync = NULL; ++ mutex->inproc_sync = NULL; } } return mutex; @@ -6613,9 +6576,9 @@ index 4785a83..167c236 100644 do_release( mutex ); } + -+ LIST_FOR_EACH_ENTRY(mutex, &fast_mutexes, struct mutex, fast_mutexes_entry) ++ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) + { -+ fast_abandon_mutex( thread->id, mutex->fast_sync ); ++ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); + } } @@ -6624,17 +6587,17 @@ index 4785a83..167c236 100644 return 1; } -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ) ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) +{ + struct mutex *mutex = (struct mutex *)obj; + -+ if (!mutex->fast_sync) ++ if (!mutex->inproc_sync) + { -+ mutex->fast_sync = fast_create_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->fast_sync) list_add_tail( &fast_mutexes, &mutex->fast_mutexes_entry ); ++ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); ++ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); + } -+ if (mutex->fast_sync) grab_object( mutex->fast_sync ); -+ return mutex->fast_sync; ++ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); ++ return mutex->inproc_sync; +} + static void mutex_destroy( struct object *obj ) @@ -6650,10 +6613,10 @@ index 4785a83..167c236 100644 + mutex->count = 0; + do_release( mutex ); + } -+ if (mutex->fast_sync) ++ if (mutex->inproc_sync) + { -+ release_object( mutex->fast_sync ); -+ list_remove( &mutex->fast_mutexes_entry ); ++ release_object( mutex->inproc_sync ); ++ list_remove( &mutex->inproc_mutexes_entry ); + } } @@ -6674,7 +6637,7 @@ index a90ec60..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -6690,7 +6653,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ pipe_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -6706,7 +6669,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_end_destroy /* destroy */ }; @@ -6722,7 +6685,7 @@ index a90ec60..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ }; @@ -6738,7 +6701,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_file_destroy /* destroy */ }; @@ -6754,7 +6717,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ named_pipe_dir_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_dir_destroy /* destroy */ }; @@ -6779,7 +6742,7 @@ index 29f1ea9..33fc18c 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6800,7 +6763,7 @@ index 29f1ea9..33fc18c 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6808,7 +6771,7 @@ index 29f1ea9..33fc18c 100644 return NULL; } -+struct fast_sync *no_get_fast_sync( struct object *obj ) ++struct inproc_sync *no_get_inproc_sync( struct object *obj ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; @@ -6825,7 +6788,7 @@ index 6f4bca8..f028a8e 100644 struct async_queue; struct winstation; struct object_type; -+struct fast_sync; ++struct inproc_sync; struct unicode_str @@ -6842,8 +6805,8 @@ index 6f4bca8..f028a8e 100644 unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable fast-synchronization handle to this object */ -+ struct fast_sync *(*get_fast_sync)(struct object *); ++ /* get a client-waitable in-process synchronization handle to this object */ ++ struct inproc_sync *(*get_inproc_sync)(struct object *); /* close a handle to this object */ int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ @@ -6851,16 +6814,16 @@ index 6f4bca8..f028a8e 100644 extern void abandon_mutexes( struct thread *thread ); -+/* fast-synchronization functions */ ++/* in-process synchronization functions */ + -+extern struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ); -+extern struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ); -+extern struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ); -+extern void fast_set_event( struct fast_sync *obj ); -+extern void fast_reset_event( struct fast_sync *obj ); -+extern void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ); ++extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); ++extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); ++extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); ++extern void set_inproc_event( struct inproc_sync *obj ); ++extern void reset_inproc_event( struct inproc_sync *obj ); ++extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); + -+extern struct fast_sync *no_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); + /* serial functions */ @@ -6881,7 +6844,7 @@ index 6d66a7c..34451c1 100644 static struct security_descriptor *process_get_sd( struct object *obj ); static void process_poll_event( struct fd *fd, int event ); static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *process_get_fast_sync( struct object *obj ); ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ); static void process_destroy( struct object *obj ); -static int process_get_esync_fd( struct object *obj, enum esync_type *type ); static void terminate_process( struct process *process, struct thread *skip, int exit_code ); @@ -6899,7 +6862,7 @@ index 6d66a7c..34451c1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_fast_sync, /* get_fast_sync */ ++ process_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -6915,7 +6878,7 @@ index 6d66a7c..34451c1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; @@ -6923,7 +6886,7 @@ index 6d66a7c..34451c1 100644 static void job_dump( struct object *obj, int verbose ); static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *job_get_fast_sync( struct object *obj ); ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ); static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void job_destroy( struct object *obj ); @@ -6931,7 +6894,7 @@ index 6d66a7c..34451c1 100644 struct job *parent; struct list parent_job_entry; /* list entry for parent job */ struct list child_job_list; /* list of child jobs */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static const struct object_ops job_ops = @@ -6947,7 +6910,7 @@ index 6d66a7c..34451c1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_fast_sync, /* get_fast_sync */ ++ job_get_inproc_sync, /* get_inproc_sync */ job_close_handle, /* close_handle */ job_destroy /* destroy */ }; @@ -6955,7 +6918,7 @@ index 6d66a7c..34451c1 100644 job->completion_port = NULL; job->completion_key = 0; job->parent = NULL; -+ job->fast_sync = NULL; ++ job->inproc_sync = NULL; } } return job; @@ -6963,17 +6926,17 @@ index 6d66a7c..34451c1 100644 job->terminating = 0; job->signaled = 1; wake_up( &job->obj, 0 ); -+ fast_set_event( job->fast_sync ); ++ set_inproc_event( job->inproc_sync ); +} + -+static struct fast_sync *job_get_fast_sync( struct object *obj ) ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ) +{ + struct job *job = (struct job *)obj; + -+ if (!job->fast_sync) -+ job->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->fast_sync) grab_object( job->fast_sync ); -+ return job->fast_sync; ++ if (!job->inproc_sync) ++ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); ++ if (job->inproc_sync) grab_object( job->inproc_sync ); ++ return job->inproc_sync; } static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) @@ -6982,7 +6945,7 @@ index 6d66a7c..34451c1 100644 release_object( job->parent ); } + -+ if (job->fast_sync) release_object( job->fast_sync ); ++ if (job->inproc_sync) release_object( job->inproc_sync ); } static void job_dump( struct object *obj, int verbose ) @@ -6990,7 +6953,7 @@ index 6d66a7c..34451c1 100644 process->rawinput_device_count = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; -+ process->fast_sync = NULL; ++ process->inproc_sync = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); list_init( &process->rawinput_entry ); - process->esync_fd = -1; @@ -7013,7 +6976,7 @@ index 6d66a7c..34451c1 100644 free( process->image ); - if (do_esync()) close( process->esync_fd ); + -+ if (process->fast_sync) release_object( process->fast_sync ); ++ if (process->inproc_sync) release_object( process->inproc_sync ); } /* dump a process on stdout for debugging purposes */ @@ -7035,14 +6998,14 @@ index 6d66a7c..34451c1 100644 return &process->kernel_object; } -+static struct fast_sync *process_get_fast_sync( struct object *obj ) ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ) +{ + struct process *process = (struct process *)obj; + -+ if (!process->fast_sync) -+ process->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->fast_sync) grab_object( process->fast_sync ); -+ return process->fast_sync; ++ if (!process->inproc_sync) ++ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); ++ if (process->inproc_sync) grab_object( process->inproc_sync ); ++ return process->inproc_sync; +} + static struct security_descriptor *process_get_sd( struct object *obj ) @@ -7052,7 +7015,7 @@ index 6d66a7c..34451c1 100644 release_job_process( process ); start_sigkill_timer( process ); wake_up( &process->obj, 0 ); -+ fast_set_event( process->fast_sync ); ++ set_inproc_event( process->inproc_sync ); } /* add a thread to a process running threads list */ @@ -7065,7 +7028,7 @@ index bedd8bb..2140427 100644 struct list kernel_object; /* list of kernel object pointers */ struct pe_image_info image_info; /* main exe image info */ - int esync_fd; /* esync file descriptor (signaled on exit) */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; /* process functions */ @@ -7081,13 +7044,13 @@ index 4983691..7bc4208 100644 /* Iterate thread list for process */ @REQ(get_next_thread) obj_handle_t process; /* process handle */ -@@ -3898,63 +3899,60 @@ struct handle_info +@@ -3898,63 +3899,58 @@ struct handle_info obj_handle_t handle; /* next thread handle */ @END -enum esync_type + -+enum fast_sync_type ++enum inproc_sync_type { - ESYNC_SEMAPHORE = 1, - ESYNC_AUTO_EVENT, @@ -7096,13 +7059,13 @@ index 4983691..7bc4208 100644 - ESYNC_AUTO_SERVER, - ESYNC_MANUAL_SERVER, - ESYNC_QUEUE, -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, }; -/* Create a new eventfd-based synchronization object */ @@ -7129,7 +7092,7 @@ index 4983691..7bc4208 100644 - int type; /* type of esync object (above) */ - VARARG(name,unicode_str); /* object name */ + -+/* Get the fast synchronization object associated with the given handle */ ++/* Get the in-process synchronization object associated with the given handle */ +@REQ(get_linux_sync_obj) + obj_handle_t handle; /* handle to the object */ @REPLY @@ -7149,16 +7112,14 @@ index 4983691..7bc4208 100644 - unsigned int shm_idx; + +/* Begin a client-side wait on a message queue */ -+@REQ(fast_select_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(select_inproc_queue) @END -@REQ(esync_msgwait) - int in_msgwait; /* are we in a message wait? */ + +/* End a client-side wait on a message queue */ -+@REQ(fast_unselect_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(unselect_inproc_queue) + int signaled; /* was the queue signaled? */ @END @@ -7174,8 +7135,8 @@ index 4983691..7bc4208 100644 -/* Retrieve the fd to wait on for user APCs. */ -@REQ(get_esync_apc_fd) + -+/* Get an event handle to be used for thread alerts with fast synchronization */ -+@REQ(get_fast_alert_event) ++/* Get an event handle to be used for thread alerts with in-process synchronization */ ++@REQ(get_inproc_alert_event) +@REPLY + obj_handle_t handle; /* handle to the event */ @END @@ -7197,8 +7158,8 @@ index fee3a8d..287a56e 100644 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 */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ int in_fast_wait; /* are we in a client-side wait? */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ int in_inproc_wait; /* are we in a client-side wait? */ }; struct hotkey @@ -7208,7 +7169,7 @@ index fee3a8d..287a56e 100644 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 ); static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ); ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); static void msg_queue_destroy( struct object *obj ); static void msg_queue_poll_event( struct fd *fd, int event ); static void thread_input_dump( struct object *obj, int verbose ); @@ -7224,7 +7185,7 @@ index fee3a8d..287a56e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_fast_sync, /* get_fast_sync */ ++ msg_queue_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; @@ -7240,7 +7201,7 @@ index fee3a8d..287a56e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; @@ -7250,8 +7211,8 @@ index fee3a8d..287a56e 100644 queue->ignore_post_msg = 0; - queue->esync_fd = -1; - queue->esync_in_msgwait = 0; -+ queue->fast_sync = NULL; -+ queue->in_fast_wait = 0; ++ queue->inproc_sync = NULL; ++ queue->in_inproc_wait = 0; list_init( &queue->send_result ); list_init( &queue->callback_result ); list_init( &queue->pending_timers ); @@ -7288,7 +7249,7 @@ index fee3a8d..287a56e 100644 + if (is_signaled( queue )) + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } } @@ -7301,7 +7262,7 @@ index fee3a8d..287a56e 100644 - if (do_esync() && !is_signaled( queue )) - esync_clear( queue->esync_fd ); + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } /* check if message is matched by the filter */ @@ -7311,12 +7272,12 @@ index fee3a8d..287a56e 100644 - if (do_esync() && queue->esync_in_msgwait) - return 0; /* thread is waiting on queue in absentia -> not hung */ -+ if (queue->in_fast_wait) ++ if (queue->in_inproc_wait) + return 0; /* thread is waiting on queue in absentia -> not hung */ return 1; } -@@ -1168,24 +1167,30 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr +@@ -1168,24 +1167,29 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr return ret || is_signaled( queue ); } @@ -7335,14 +7296,14 @@ index fee3a8d..287a56e 100644 + } + SHARED_WRITE_END; + -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } -static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ) ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) { struct msg_queue *queue = (struct msg_queue *)obj; - const queue_shm_t *queue_shm = queue->shared; +- const queue_shm_t *queue_shm = queue->shared; - SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) - { @@ -7350,10 +7311,10 @@ index fee3a8d..287a56e 100644 - shared->changed_mask = 0; - } - SHARED_WRITE_END; -+ if (!queue->fast_sync) -+ queue->fast_sync = fast_create_event( FAST_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->fast_sync) grab_object( queue->fast_sync ); -+ return queue->fast_sync; ++ if (!queue->inproc_sync) ++ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); ++ if (queue->inproc_sync) grab_object( queue->inproc_sync ); ++ return queue->inproc_sync; } static void msg_queue_destroy( struct object *obj ) @@ -7362,7 +7323,7 @@ index fee3a8d..287a56e 100644 if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); - if (do_esync()) close( queue->esync_fd ); -+ if (queue->fast_sync) release_object( queue->fast_sync ); ++ if (queue->inproc_sync) release_object( queue->inproc_sync ); } static void msg_queue_poll_event( struct fd *fd, int event ) @@ -7370,7 +7331,7 @@ index fee3a8d..287a56e 100644 if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); } static void thread_input_dump( struct object *obj, int verbose ) @@ -7381,12 +7342,12 @@ index fee3a8d..287a56e 100644 + else + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } + } + else + { -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); - } - else wake_up( &queue->obj, 0 ); } @@ -7402,7 +7363,7 @@ index fee3a8d..287a56e 100644 - if (do_esync() && !is_signaled( queue )) - esync_clear( queue->esync_fd ); + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } else reply->wake_bits = reply->changed_bits = 0; } @@ -7411,7 +7372,7 @@ index fee3a8d..287a56e 100644 if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); + /* then check for posted messages */ if ((filter & QS_POSTMESSAGE) && @@ -7421,7 +7382,7 @@ index fee3a8d..287a56e 100644 } SHARED_WRITE_END; -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); set_error( STATUS_PENDING ); /* FIXME */ - - if (do_esync() && !is_signaled( queue )) @@ -7446,7 +7407,7 @@ index 4454de3..dd5c556 100644 key_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ key_close_handle, /* close_handle */ key_destroy /* destroy */ }; @@ -7466,7 +7427,7 @@ index ca83fdb..8c50f99 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; @@ -7482,13 +7443,13 @@ index eb6b8f4..1636e98 100644 -DECL_HANDLER(open_esync); -DECL_HANDLER(get_esync_fd); -DECL_HANDLER(esync_msgwait); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(fast_select_queue); -+DECL_HANDLER(fast_unselect_queue); DECL_HANDLER(set_keyboard_repeat); -DECL_HANDLER(get_esync_apc_fd); -+DECL_HANDLER(get_fast_alert_event); ++DECL_HANDLER(get_linux_sync_device); ++DECL_HANDLER(get_linux_sync_obj); ++DECL_HANDLER(select_inproc_queue); ++DECL_HANDLER(unselect_inproc_queue); ++DECL_HANDLER(get_inproc_alert_event); typedef void (*req_handler)( const void *req, void *reply ); static const req_handler req_handlers[REQ_NB_REQUESTS] = @@ -7500,17 +7461,17 @@ index eb6b8f4..1636e98 100644 - (req_handler)req_open_esync, - (req_handler)req_get_esync_fd, - (req_handler)req_esync_msgwait, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_fast_select_queue, -+ (req_handler)req_fast_unselect_queue, (req_handler)req_set_keyboard_repeat, - (req_handler)req_get_esync_apc_fd, -+ (req_handler)req_get_fast_alert_event, ++ (req_handler)req_get_linux_sync_device, ++ (req_handler)req_get_linux_sync_obj, ++ (req_handler)req_select_inproc_queue, ++ (req_handler)req_unselect_inproc_queue, ++ (req_handler)req_get_inproc_alert_event, }; C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,35 +2276,26 @@ +@@ -2276,35 +2276,24 @@ C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); @@ -7539,6 +7500,13 @@ index eb6b8f4..1636e98 100644 -C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 ); -C_ASSERT( offsetof(struct esync_msgwait_request, in_msgwait) == 12 ); -C_ASSERT( sizeof(struct esync_msgwait_request) == 16 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); +-C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); +C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); +C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); @@ -7548,21 +7516,12 @@ index eb6b8f4..1636e98 100644 +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( offsetof(struct fast_select_queue_request, handle) == 12 ); -+C_ASSERT( sizeof(struct fast_select_queue_request) == 16 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, handle) == 12 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, signaled) == 16 ); -+C_ASSERT( sizeof(struct fast_unselect_queue_request) == 24 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_fast_alert_event_reply, handle) == 8 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); --C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_reply) == 16 ); ++C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); ++C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); ++C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); ++C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); diff --git a/server/semaphore.c b/server/semaphore.c index e3889f2..9940919 100644 --- a/server/semaphore.c @@ -7571,14 +7530,14 @@ index e3889f2..9940919 100644 struct object obj; /* object header */ unsigned int count; /* current count */ unsigned int max; /* maximum possible count */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* fast synchronization object */ }; static void semaphore_dump( struct object *obj, int verbose ); static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ); ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); +static void semaphore_destroy( struct object *obj ); static const struct object_ops semaphore_ops = @@ -7595,7 +7554,7 @@ index e3889f2..9940919 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_fast_sync, /* get_fast_sync */ ++ semaphore_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + semaphore_destroy /* destroy */ @@ -7606,7 +7565,7 @@ index e3889f2..9940919 100644 /* initialize it if it didn't already exist */ sem->count = initial; sem->max = max; -+ sem->fast_sync = NULL; ++ sem->inproc_sync = NULL; } } return sem; @@ -7614,21 +7573,21 @@ index e3889f2..9940919 100644 return release_semaphore( sem, 1, NULL ); } -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ) ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (!semaphore->fast_sync) -+ semaphore->fast_sync = fast_create_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->fast_sync) grab_object( semaphore->fast_sync ); -+ return semaphore->fast_sync; ++ if (!semaphore->inproc_sync) ++ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); ++ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); ++ return semaphore->inproc_sync; +} + +static void semaphore_destroy( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (semaphore->fast_sync) release_object( semaphore->fast_sync ); ++ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); +} + /* create a semaphore */ @@ -7650,7 +7609,7 @@ index 11e204e..5c210d1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; @@ -7670,7 +7629,7 @@ index 55cd6aa..e5def3d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; @@ -7690,7 +7649,7 @@ index 104321b..3fb2e29 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ sock_close_handle, /* close_handle */ sock_destroy /* destroy */ }; @@ -7706,7 +7665,7 @@ index 104321b..3fb2e29 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ifchange_destroy /* destroy */ }; @@ -7722,7 +7681,7 @@ index 104321b..3fb2e29 100644 default_unlink_name, /* unlink_name */ socket_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -7742,7 +7701,7 @@ index c7f3441..4a7cf68 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ }; @@ -7770,7 +7729,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_apc_destroy /* destroy */ }; @@ -7786,7 +7745,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -7798,7 +7757,7 @@ index 2ce94b4..8f603fc 100644 static unsigned int thread_map_access( struct object *obj, unsigned int access ); static void thread_poll_event( struct fd *fd, int event ); static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *thread_get_fast_sync( struct object *obj ); ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); static void destroy_thread( struct object *obj ); static const struct object_ops thread_ops = @@ -7814,7 +7773,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_fast_sync, /* get_fast_sync */ ++ thread_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; @@ -7831,8 +7790,8 @@ index 2ce94b4..8f603fc 100644 thread->token = NULL; thread->desc = NULL; thread->desc_len = 0; -+ thread->fast_sync = NULL; -+ thread->fast_alert_event = NULL; ++ thread->inproc_sync = NULL; ++ thread->inproc_alert_event = NULL; - thread->exit_poll = NULL; thread->creation_time = current_time; @@ -7853,14 +7812,14 @@ index 2ce94b4..8f603fc 100644 return &thread->kernel_object; } -+static struct fast_sync *thread_get_fast_sync( struct object *obj ) ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) +{ + struct thread *thread = (struct thread *)obj; + -+ if (!thread->fast_sync) -+ thread->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->fast_sync) grab_object( thread->fast_sync ); -+ return thread->fast_sync; ++ if (!thread->inproc_sync) ++ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); ++ if (thread->inproc_sync) grab_object( thread->inproc_sync ); ++ return thread->inproc_sync; +} + /* cleanup everything that is no longer needed by a dead thread */ @@ -7873,8 +7832,8 @@ index 2ce94b4..8f603fc 100644 - - if (do_esync()) - close( thread->esync_fd ); -+ if (thread->fast_sync) release_object( thread->fast_sync ); -+ if (thread->fast_alert_event) release_object( thread->fast_alert_event ); ++ if (thread->inproc_sync) release_object( thread->inproc_sync ); ++ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); } /* dump a thread on stdout for debugging purposes */ @@ -7909,8 +7868,8 @@ index 2ce94b4..8f603fc 100644 - if (do_esync() && queue == &thread->user_apc) - esync_wake_fd( thread->esync_apc_fd ); -+ if (apc->call.type == APC_USER && thread->fast_alert_event) -+ set_event( thread->fast_alert_event ); ++ if (apc->call.type == APC_USER && thread->inproc_alert_event) ++ set_event( thread->inproc_alert_event ); } return 1; @@ -7918,8 +7877,8 @@ index 2ce94b4..8f603fc 100644 apc->executed = 1; wake_up( &apc->obj, 0 ); release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); return; } } @@ -7932,8 +7891,8 @@ index 2ce94b4..8f603fc 100644 - if (do_esync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc )) - esync_clear( thread->esync_apc_fd ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); + } return apc; } @@ -7971,8 +7930,8 @@ index 2ce94b4..8f603fc 100644 abandon_mutexes( thread ); - if (do_esync()) - esync_abandon_mutexes( thread ); -+ fast_set_event( thread->fast_sync ); + wake_up( &thread->obj, 0 ); ++ set_inproc_event( thread->inproc_sync ); + if (violent_death) send_thread_signal( thread, SIGQUIT ); - if (violent_death) - { @@ -7988,13 +7947,13 @@ index 2ce94b4..8f603fc 100644 release_object( process ); } + -+DECL_HANDLER(get_fast_alert_event) ++DECL_HANDLER(get_inproc_alert_event) +{ -+ if (!current->fast_alert_event) -+ current->fast_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); ++ if (!current->inproc_alert_event) ++ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); + -+ if (current->fast_alert_event) -+ reply->handle = alloc_handle( current->process, current->fast_alert_event, SYNCHRONIZE, 0 ); ++ if (current->inproc_alert_event) ++ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); +} diff --git a/server/thread.h b/server/thread.h index 10e9e28..cb4643a 100644 @@ -8013,8 +7972,8 @@ index 10e9e28..cb4643a 100644 WCHAR *desc; /* thread description string */ struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ - struct timeout_user *exit_poll; /* poll if the thread/process has exited already */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ struct event *fast_alert_event; /* fast synchronization alert event */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ struct event *inproc_alert_event; /* in-process synchronization alert event */ }; extern struct thread *current; @@ -8035,14 +7994,14 @@ index 36645a2..854a8e1 100644 client_ptr_t callback; /* callback APC function */ client_ptr_t arg; /* callback argument */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void timer_dump( struct object *obj, int verbose ); static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); -static int timer_get_esync_fd( struct object *obj, enum esync_type *type ); static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *timer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); static void timer_destroy( struct object *obj ); static const struct object_ops timer_ops = @@ -8058,7 +8017,7 @@ index 36645a2..854a8e1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_fast_sync, /* get_fast_sync */ ++ timer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; @@ -8070,7 +8029,7 @@ index 36645a2..854a8e1 100644 - - if (do_esync()) - timer->esync_fd = esync_create_fd( 0, 0 ); -+ timer->fast_sync = NULL; ++ timer->inproc_sync = NULL; } } return timer; @@ -8078,7 +8037,7 @@ index 36645a2..854a8e1 100644 /* wake up waiters */ timer->signaled = 1; wake_up( &timer->obj, 0 ); -+ fast_set_event( timer->fast_sync ); ++ set_inproc_event( timer->inproc_sync ); } /* cancel a running timer */ @@ -8089,7 +8048,7 @@ index 36645a2..854a8e1 100644 - - if (do_esync()) - esync_clear( timer->esync_fd ); -+ fast_reset_event( timer->fast_sync ); ++ reset_inproc_event( timer->inproc_sync ); } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; @@ -8108,19 +8067,19 @@ index 36645a2..854a8e1 100644 } -static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct fast_sync *timer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) { struct timer *timer = (struct timer *)obj; - assert( obj->ops == &timer_ops ); - if (!timer->manual) timer->signaled = 0; + -+ if (!timer->fast_sync) ++ if (!timer->inproc_sync) + { -+ enum fast_sync_type type = timer->manual ? FAST_SYNC_MANUAL_SERVER : FAST_SYNC_AUTO_SERVER; -+ timer->fast_sync = fast_create_event( type, timer->signaled ); ++ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; ++ timer->inproc_sync = create_inproc_event( type, timer->signaled ); + } -+ if (timer->fast_sync) grab_object( timer->fast_sync ); -+ return timer->fast_sync; ++ if (timer->inproc_sync) grab_object( timer->inproc_sync ); ++ return timer->inproc_sync; } static void timer_destroy( struct object *obj ) @@ -8129,7 +8088,7 @@ index 36645a2..854a8e1 100644 if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); - if (do_esync()) close( timer->esync_fd ); -+ if (timer->fast_sync) release_object( timer->fast_sync ); ++ if (timer->inproc_sync) release_object( timer->inproc_sync ); } /* create a timer */ @@ -8149,7 +8108,7 @@ index 8b4d2f0..42562fd 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ token_destroy /* destroy */ }; @@ -8157,7 +8116,7 @@ diff --git a/server/request_trace.h b/server/request_trace.h index af96565..c027f4b 100644 --- a/server/request_trace.h +++ b/server/request_trace.h -@@ -4619,67 +4619,56 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req +@@ -4619,67 +4619,54 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req fprintf( stderr, " handle=%04x", req->handle ); } @@ -8200,22 +8159,21 @@ index af96565..c027f4b 100644 } -static void dump_get_esync_fd_request( const struct get_esync_fd_request *req ) -+static void dump_fast_select_queue_request( const struct fast_select_queue_request *req ) ++static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) { - fprintf( stderr, " handle=%04x", req->handle ); +- fprintf( stderr, " handle=%04x", req->handle ); } -static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req ) -+static void dump_fast_unselect_queue_request( const struct fast_unselect_queue_request *req ) ++static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) { - fprintf( stderr, " type=%d", req->type ); - fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, " handle=%04x", req->handle ); + fprintf( stderr, ", signaled=%d", req->signaled ); } -static void dump_esync_msgwait_request( const struct esync_msgwait_request *req ) -+static void dump_get_fast_alert_event_request( const struct get_fast_alert_event_request *req ) ++static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) { - fprintf( stderr, " in_msgwait=%d", req->in_msgwait ); } @@ -8233,7 +8191,7 @@ index af96565..c027f4b 100644 } -static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request *req ) -+static void dump_get_fast_alert_event_reply( const struct get_fast_alert_event_reply *req ) ++static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) { + fprintf( stderr, " handle=%04x", req->handle ); } @@ -8250,9 +8208,9 @@ index af96565..c027f4b 100644 - (dump_func)dump_get_esync_apc_fd_request, + (dump_func)dump_get_linux_sync_device_request, + (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_fast_select_queue_request, -+ (dump_func)dump_fast_unselect_queue_request, -+ (dump_func)dump_get_fast_alert_event_request, ++ (dump_func)dump_select_inproc_queue_request, ++ (dump_func)dump_unselect_inproc_queue_request, ++ (dump_func)dump_get_inproc_alert_event_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -8263,12 +8221,14 @@ index af96565..c027f4b 100644 - (dump_func)dump_create_esync_reply, - (dump_func)dump_open_esync_reply, - (dump_func)dump_get_esync_fd_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, NULL, (dump_func)dump_set_keyboard_repeat_reply, NULL, -+ (dump_func)dump_get_fast_alert_event_reply, ++ (dump_func)dump_get_linux_sync_device_reply, ++ (dump_func)dump_get_linux_sync_obj_reply, ++ NULL, ++ NULL, ++ (dump_func)dump_get_inproc_alert_event_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -8280,13 +8240,13 @@ index af96565..c027f4b 100644 - "open_esync", - "get_esync_fd", - "esync_msgwait", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "fast_select_queue", -+ "fast_unselect_queue", "set_keyboard_repeat", - "get_esync_apc_fd", -+ "get_fast_alert_event", ++ "get_linux_sync_device", ++ "get_linux_sync_obj", ++ "select_inproc_queue", ++ "unselect_inproc_queue", ++ "get_inproc_alert_event", }; static const struct @@ -8306,7 +8266,7 @@ index feac54e..f52e118 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ window_destroy /* destroy */ }; @@ -8326,7 +8286,7 @@ index 4ef21d9..2719c9e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -8342,76 +8302,64 @@ index 4ef21d9..2719c9e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; -From 9c4c5779b6f87c27e73a4cb5a0973896c26c8d31 Mon Sep 17 00:00:00 2001 -From: Kirill Artemev -Date: Wed, 3 Jul 2024 18:39:15 +0500 -Subject: [PATCH] test3 - -Signed-off-by: Kirill Artemev ---- - server/queue.c | 55 +++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 46 insertions(+), 9 deletions(-) - -diff --git a/server/queue.c b/server/queue.c -index 0c9c043d68f..c911ae3e574 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -4020,21 +4020,60 @@ DECL_HANDLER(update_rawinput_devices) +--- a/server/queue.c 2024-12-20 20:01:39.879368500 +0500 ++++ b/server/queue.c 2024-12-20 20:03:11.782212833 +0500 +@@ -4252,23 +4252,6 @@ } } -DECL_HANDLER(esync_msgwait) -+DECL_HANDLER(fast_select_queue) - { +-{ - struct msg_queue *queue = get_current_queue(); -+ struct msg_queue *queue; - const queue_shm_t *queue_shm; - +- const queue_shm_t *queue_shm; +- - if (!queue) return; -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; - queue_shm = queue->shared; +- queue_shm = queue->shared; - queue->esync_in_msgwait = req->in_msgwait; -+ /* a thread can only wait on its own queue */ -+ if (current->queue != queue || queue->in_fast_wait) +- +- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) +- set_event( current->process->idle_event ); +- +- /* and start/stop waiting on the driver */ +- if (queue->fd) +- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); +-} +- + DECL_HANDLER(set_keyboard_repeat) + { + struct desktop *desktop; +@@ -4288,3 +4271,41 @@ + release_object( desktop ); + } + ++DECL_HANDLER(select_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (queue->in_inproc_wait) + { + set_error( STATUS_ACCESS_DENIED ); + } + else + { -+ if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -+ set_event( current->process->idle_event ); ++ check_thread_queue_idle( current ); + + if (queue->fd) + set_fd_events( queue->fd, POLLIN ); - -- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -- set_event( current->process->idle_event ); -+ queue->in_fast_wait = 1; ++ ++ queue->in_inproc_wait = 1; + } - -- /* and start/stop waiting on the driver */ -- if (queue->fd) -- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); -+ release_object( queue ); +} + -+DECL_HANDLER(fast_unselect_queue) ++DECL_HANDLER(unselect_inproc_queue) +{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; ++ struct msg_queue *queue = current->queue; + -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ if (current->queue != queue || !queue->in_fast_wait) ++ if (!queue->in_inproc_wait) + { + set_error( STATUS_ACCESS_DENIED ); + } @@ -8423,12 +8371,6 @@ index 0c9c043d68f..c911ae3e574 100644 + if (req->signaled) + msg_queue_satisfied( &queue->obj, NULL ); + -+ queue->in_fast_wait = 0; ++ queue->in_inproc_wait = 0; + } -+ -+ release_object( queue ); - } - - DECL_HANDLER(set_keyboard_repeat) --- -2.45.2 ++} diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging.patch index ebb49648a..f6488c417 100644 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging.patch +++ b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync5-staging.patch @@ -2259,7 +2259,7 @@ index 0d4b320..dba7645 100644 if (options & DUPLICATE_CLOSE_SOURCE) + { fd = remove_fd_from_cache( source ); -+ close_fast_sync_obj( source ); ++ close_inproc_sync_obj( source ); + } SERVER_START_REQ( dup_handle ) @@ -2278,7 +2278,7 @@ index 0d4b320..dba7645 100644 - if (do_esync()) - esync_close( handle ); -+ close_fast_sync_obj( handle ); ++ close_inproc_sync_obj( handle ); SERVER_START_REQ( close_handle ) { @@ -2337,7 +2337,7 @@ index 1072265..a9a0a2c 100644 /* return a monotonic time counter, in Win32 ticks */ static inline ULONGLONG monotonic_counter(void) { -@@ -239,6 +246,902 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at +@@ -301,6 +309,901 @@ } @@ -2345,44 +2345,44 @@ index 1072265..a9a0a2c 100644 + +static int get_linux_sync_device(void) +{ -+ static LONG fast_sync_fd = -2; ++ static LONG device = -2; + -+ if (fast_sync_fd == -2) ++ if (device == -2) + { -+ HANDLE device; ++ HANDLE handle; + int fd, needs_close; + NTSTATUS ret; + + SERVER_START_REQ( get_linux_sync_device ) + { -+ if (!(ret = wine_server_call( req ))) device = wine_server_ptr_handle( reply->handle ); ++ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + if (!ret) + { -+ if (!server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )) ++ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) + { -+ if (InterlockedCompareExchange( &fast_sync_fd, fd, -2 ) != -2) ++ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) + { + /* someone beat us to it */ + if (needs_close) close( fd ); -+ NtClose( device ); ++ NtClose( handle ); + } + /* otherwise don't close the device */ + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); -+ NtClose( device ); ++ InterlockedCompareExchange( &device, -1, -2 ); ++ NtClose( handle ); + } + } + else + { -+ InterlockedCompareExchange( &fast_sync_fd, -1, -2 ); ++ InterlockedCompareExchange( &device, -1, -2 ); + } + } -+ return fast_sync_fd; ++ return device; +} + +/* It's possible for synchronization primitives to remain alive even after being @@ -2390,10 +2390,10 @@ index 1072265..a9a0a2c 100644 + * documented as being undefined behaviour by Microsoft, but it works, and some + * applications rely on it. This means we need to refcount handles, and defer + * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the fast synchronization ++ * by having each client process hold a handle to the in-process synchronization + * object, as well as a private refcount. When the client refcount reaches zero, + * it closes the handle; when all handles are closed, the server deletes the -+ * fast synchronization object. ++ * in-process synchronization object. + * + * We also need this for signal-and-wait. The signal and wait operations aren't + * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE @@ -2419,20 +2419,20 @@ index 1072265..a9a0a2c 100644 + * the same handle immediately reallocated to a different object. This should be + * a very rare situation, and in that case we simply don't cache the handle. + */ -+struct fast_sync_cache_entry ++struct inproc_sync_cache_entry +{ + LONG refcount; + int fd; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + unsigned int access; + BOOL closed; -+ /* handle to the underlying fast sync object, stored as obj_handle_t to save -+ * space */ ++ /* handle to the underlying in-process sync object, stored as obj_handle_t ++ * to save space */ + obj_handle_t handle; +}; + + -+static void release_fast_sync_obj( struct fast_sync_cache_entry *cache ) ++static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) +{ + /* save the handle and fd now; as soon as the refcount hits 0 we cannot + * access the cache anymore */ @@ -2460,52 +2460,52 @@ index 1072265..a9a0a2c 100644 +} + + -+#define FAST_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct fast_sync_cache_entry)) -+#define FAST_SYNC_CACHE_ENTRIES 128 ++#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) ++#define INPROC_SYNC_CACHE_ENTRIES 128 + -+static struct fast_sync_cache_entry *fast_sync_cache[FAST_SYNC_CACHE_ENTRIES]; -+static struct fast_sync_cache_entry fast_sync_cache_initial_block[FAST_SYNC_CACHE_BLOCK_SIZE]; ++static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; ++static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; + -+static inline unsigned int fast_sync_handle_to_index( HANDLE handle, unsigned int *entry ) ++static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) +{ + unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / FAST_SYNC_CACHE_BLOCK_SIZE; -+ return idx % FAST_SYNC_CACHE_BLOCK_SIZE; ++ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; ++ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; +} + + -+static struct fast_sync_cache_entry *cache_fast_sync_obj( HANDLE handle, obj_handle_t fast_sync, int fd, -+ enum fast_sync_type type, unsigned int access ) ++static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, ++ enum inproc_sync_type type, unsigned int access ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + sigset_t sigset; + int refcount; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES) + { + FIXME( "too many allocated handles, not caching %p\n", handle ); + return NULL; + } + -+ if (!fast_sync_cache[entry]) /* do we need to allocate a new block of entries? */ ++ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ + { -+ if (!entry) fast_sync_cache[0] = fast_sync_cache_initial_block; ++ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; + else + { -+ static const size_t size = FAST_SYNC_CACHE_BLOCK_SIZE * sizeof(struct fast_sync_cache_entry); ++ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); + void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); + if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&fast_sync_cache[entry], ptr, NULL )) ++ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) + munmap( ptr, size ); /* someone beat us to it */ + } + } + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same + * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_fast_sync_obj() and close_handle. */ ++ * being cached again between close_inproc_sync_obj() and close_handle. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) @@ -2519,13 +2519,13 @@ index 1072265..a9a0a2c 100644 + return NULL; + } + -+ cache->handle = fast_sync; ++ cache->handle = inproc_sync; + cache->fd = fd; + cache->type = type; + cache->access = access; + cache->closed = FALSE; + /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_fast_sync_obj()]. ++ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. + * Set the refcount to 2 (one for the handle, one for the caller). */ + refcount = InterlockedExchange( &cache->refcount, 2 ); + assert( !refcount ); @@ -2549,18 +2549,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static struct fast_sync_cache_entry *get_cached_fast_sync_obj( HANDLE handle ) ++static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) +{ -+ unsigned int entry, idx = fast_sync_handle_to_index( handle, &entry ); -+ struct fast_sync_cache_entry *cache; ++ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); ++ struct inproc_sync_cache_entry *cache; + -+ if (entry >= FAST_SYNC_CACHE_ENTRIES || !fast_sync_cache[entry]) ++ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) + return NULL; + -+ cache = &fast_sync_cache[entry][idx]; ++ cache = &inproc_sync_cache[entry][idx]; + + /* this load needs acquire semantics [paired with the store in -+ * cache_fast_sync_obj()] */ ++ * cache_inproc_sync_obj()] */ + if (!interlocked_inc_if_nonzero( &cache->refcount )) + return NULL; + @@ -2570,7 +2570,7 @@ index 1072265..a9a0a2c 100644 + * handle value might have been reused for another object in the + * meantime, in which case we have to report that valid object, so + * force the caller to check the server. */ -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return NULL; + } + @@ -2578,30 +2578,31 @@ index 1072265..a9a0a2c 100644 +} + + -+static BOOL fast_sync_types_match( enum fast_sync_type a, enum fast_sync_type b ) ++static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) +{ + if (a == b) return TRUE; -+ if (a == FAST_SYNC_AUTO_EVENT && b == FAST_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == FAST_SYNC_AUTO_EVENT && a == FAST_SYNC_MANUAL_EVENT) return TRUE; ++ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; ++ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; + return FALSE; +} + + +/* returns a pointer to a cache entry; if the object could not be cached, + * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_fast_sync_obj( HANDLE handle, enum fast_sync_type desired_type, ACCESS_MASK desired_access, -+ struct fast_sync_cache_entry *stack_cache, -+ struct fast_sync_cache_entry **ret_cache ) ++static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, ++ ACCESS_MASK desired_access, ++ struct inproc_sync_cache_entry *stack_cache, ++ struct inproc_sync_cache_entry **ret_cache ) +{ -+ struct fast_sync_cache_entry *cache; -+ obj_handle_t fast_sync_handle; -+ enum fast_sync_type type; ++ struct inproc_sync_cache_entry *cache; ++ obj_handle_t inproc_sync_handle; ++ enum inproc_sync_type type; + unsigned int access; + int fd, needs_close; + NTSTATUS ret; + + /* try to find it in the cache already */ -+ if ((cache = get_cached_fast_sync_obj( handle ))) ++ if ((cache = get_cached_inproc_sync_obj( handle ))) + { + *ret_cache = cache; + return STATUS_SUCCESS; @@ -2613,7 +2614,7 @@ index 1072265..a9a0a2c 100644 + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { -+ fast_sync_handle = reply->handle; ++ inproc_sync_handle = reply->handle; + access = reply->access; + type = reply->type; + } @@ -2622,15 +2623,15 @@ index 1072265..a9a0a2c 100644 + + if (ret) return ret; + -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( fast_sync_handle ), ++ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), + 0, &fd, &needs_close, NULL, NULL ))) + return ret; + -+ cache = cache_fast_sync_obj( handle, fast_sync_handle, fd, type, access ); ++ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); + if (!cache) + { + cache = stack_cache; -+ cache->handle = fast_sync_handle; ++ cache->handle = inproc_sync_handle; + cache->fd = fd; + cache->type = type; + cache->access = access; @@ -2640,15 +2641,15 @@ index 1072265..a9a0a2c 100644 + + *ret_cache = cache; + -+ if (desired_type && !fast_sync_types_match( cache->type, desired_type )) ++ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + + if ((cache->access & desired_access) != desired_access) + { -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return STATUS_ACCESS_DENIED; + } + @@ -2657,16 +2658,16 @@ index 1072265..a9a0a2c 100644 + + +/* caller must hold fd_cache_mutex */ -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ -+ struct fast_sync_cache_entry *cache = get_cached_fast_sync_obj( handle ); ++ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); + + if (cache) + { + cache->closed = TRUE; + /* once for the reference we just grabbed, and once for the handle */ -+ release_fast_sync_obj( cache ); -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + } +} + @@ -2675,7 +2676,7 @@ index 1072265..a9a0a2c 100644 +{ + NTSTATUS ret; + -+ ret = ioctl( obj, NTSYNC_IOC_SEM_POST, &count ); ++ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); + if (ret < 0) + { + if (errno == EOVERFLOW) @@ -2688,18 +2689,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2718,18 +2719,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, ++ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_semaphore_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2747,18 +2748,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_set_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2776,18 +2777,18 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_reset_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2805,23 +2806,23 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_MODIFY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_pulse_event_obj( cache->fd, prev_state ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + + -+static NTSTATUS linux_query_event_obj( int obj, enum fast_sync_type type, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) +{ + struct ntsync_event_args args = {0}; + NTSTATUS ret; @@ -2829,24 +2830,24 @@ index 1072265..a9a0a2c 100644 + ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); + if (ret < 0) + return errno_to_status( errno ); -+ info->EventType = (type == FAST_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; ++ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; + info->EventState = args.signaled; + return STATUS_SUCCESS; +} + + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, ++ EVENT_QUERY_STATE, &stack_cache, &cache ))) + return ret; + + ret = linux_query_event_obj( cache->fd, cache->type, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2873,17 +2874,17 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, 0, &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) + return ret; + + ret = linux_release_mutex_obj( cache->fd, prev_count ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + @@ -2914,71 +2915,69 @@ index 1072265..a9a0a2c 100644 +} + + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + NTSTATUS ret; + -+ if ((ret = get_fast_sync_obj( handle, FAST_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) ++ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, ++ &stack_cache, &cache ))) + return ret; + + ret = linux_query_mutex_obj( cache->fd, info ); + -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + return ret; +} + -+static void select_queue( HANDLE queue ) ++static void select_queue(void) +{ -+ SERVER_START_REQ( fast_select_queue ) ++ SERVER_START_REQ( select_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static void unselect_queue( HANDLE queue, BOOL signaled ) ++static void unselect_queue( BOOL signaled ) +{ -+ SERVER_START_REQ( fast_unselect_queue ) ++ SERVER_START_REQ( unselect_inproc_queue ) + { -+ req->handle = wine_server_obj_handle( queue ); + req->signaled = signaled; + wine_server_call( req ); + } + SERVER_END_REQ; +} + -+static int get_fast_alert_obj(void) ++static int get_inproc_alert_obj(void) +{ + struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct fast_sync_cache_entry stack_cache, *cache; ++ struct inproc_sync_cache_entry stack_cache, *cache; + HANDLE alert_handle; + unsigned int ret; + -+ if (!data->fast_alert_obj) ++ if (data->linux_alert_obj == -1) + { -+ SERVER_START_REQ( get_fast_alert_event ) ++ SERVER_START_REQ( get_inproc_alert_event ) + { + if ((ret = wine_server_call( req ))) -+ ERR( "failed to get fast alert event, status %#x\n", ret ); ++ ERR( "failed to get inproc alert event, status %#x\n", ret ); + alert_handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + -+ if ((ret = get_fast_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get fast alert obj, status %#x\n", ret ); -+ data->fast_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_fast_sync_obj() won't close it. ++ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) ++ ERR( "failed to get inproc alert obj, status %#x\n", ret ); ++ data->linux_alert_obj = cache->fd; ++ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. + * Manhandling the cache entry here is fine since we're the only thread + * that can access our own alert event. */ + cache->fd = -1; -+ release_fast_sync_obj( cache ); ++ release_inproc_sync_obj( cache ); + NtClose( alert_handle ); + } + -+ return data->fast_alert_obj; ++ return data->linux_alert_obj; +} + +static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, @@ -3010,7 +3009,7 @@ index 1072265..a9a0a2c 100644 + args.index = ~0u; + + if (alertable) -+ args.alert = get_fast_alert_obj(); ++ args.alert = get_inproc_alert_obj(); + + if (wait_any || count == 1) + request = NTSYNC_IOC_WAIT_ANY; @@ -3043,10 +3042,10 @@ index 1072265..a9a0a2c 100644 + return errno_to_status( errno ); +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry stack_cache[64], *cache[64]; ++ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; + int device, objs[64]; + HANDLE queue = NULL; + NTSTATUS ret; @@ -3057,13 +3056,13 @@ index 1072265..a9a0a2c 100644 + + for (i = 0; i < count; ++i) + { -+ if ((ret = get_fast_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) ++ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) + { + for (j = 0; j < i; ++j) -+ release_fast_sync_obj( cache[j] ); ++ release_inproc_sync_obj( cache[j] ); + return ret; + } -+ if (cache[i]->type == FAST_SYNC_QUEUE) ++ if (cache[i]->type == INPROC_SYNC_QUEUE) + queue = handles[i]; + + objs[i] = cache[i]->fd; @@ -3071,32 +3070,32 @@ index 1072265..a9a0a2c 100644 + + /* It's common to wait on the message queue alone. Some applications wait + * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through fast_wait_objs(), and since we only -+ * need to go through that path if we're waiting on other objects, just -+ * delegate to the server if we're only waiting on the message queue. */ ++ * instead of one when going through inproc_wait(), and since we only need ++ * to go through that path if we're waiting on other objects, just delegate ++ * to the server if we're only waiting on the message queue. */ + if (count == 1 && queue) + { -+ release_fast_sync_obj( cache[0] ); ++ release_inproc_sync_obj( cache[0] ); + return server_wait_for_object( handles[0], alertable, timeout ); + } + -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + + ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); + -+ if (queue) unselect_queue( queue, handles[ret] == queue ); ++ if (queue) unselect_queue( handles[ret] == queue ); + + for (i = 0; i < count; ++i) -+ release_fast_sync_obj( cache[i] ); ++ release_inproc_sync_obj( cache[i] ); + + return ret; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ -+ struct fast_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct fast_sync_cache_entry wait_stack_cache, *wait_cache; ++ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; ++ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; + HANDLE queue = NULL; + NTSTATUS ret; + int device; @@ -3104,58 +3103,58 @@ index 1072265..a9a0a2c 100644 + if ((device = get_linux_sync_device()) < 0) + return STATUS_NOT_IMPLEMENTED; + -+ if ((ret = get_fast_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) ++ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) + return ret; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + if (!(signal_cache->access & EVENT_MODIFY_STATE)) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_ACCESS_DENIED; + } + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + break; + + default: + /* can't be signaled */ -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return STATUS_OBJECT_TYPE_MISMATCH; + } + -+ if ((ret = get_fast_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) ++ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) + { -+ release_fast_sync_obj( signal_cache ); ++ release_inproc_sync_obj( signal_cache ); + return ret; + } + -+ if (wait_cache->type == FAST_SYNC_QUEUE) ++ if (wait_cache->type == INPROC_SYNC_QUEUE) + queue = wait; + + switch (signal_cache->type) + { -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_SEMAPHORE: + ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); + break; + -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_MANUAL_EVENT: + ret = linux_set_event_obj( signal_cache->fd, NULL ); + break; + -+ case FAST_SYNC_MUTEX: ++ case INPROC_SYNC_MUTEX: + ret = linux_release_mutex_obj( signal_cache->fd, NULL ); + break; + @@ -3166,70 +3165,70 @@ index 1072265..a9a0a2c 100644 + + if (!ret) + { -+ if (queue) select_queue( queue ); ++ if (queue) select_queue(); + ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( queue, !ret ); ++ if (queue) unselect_queue( !ret ); + } + -+ release_fast_sync_obj( signal_cache ); -+ release_fast_sync_obj( wait_cache ); ++ release_inproc_sync_obj( signal_cache ); ++ release_inproc_sync_obj( wait_cache ); + return ret; +} + +#else + -+void close_fast_sync_obj( HANDLE handle ) ++void close_inproc_sync_obj( HANDLE handle ) +{ +} + -+static NTSTATUS fast_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) ++static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_set_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_reset_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_pulse_event( HANDLE handle, LONG *prev_state ) ++static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_release_mutex( HANDLE handle, LONG *prev_count ) ++static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) ++static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + -+static NTSTATUS fast_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) ++static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, ++ BOOLEAN alertable, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} @@ -3277,7 +3276,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_semaphore( handle, info, ret_len ); -+ if ((ret = fast_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + return ret; @@ -3293,7 +3292,7 @@ index 1072265..a9a0a2c 100644 - return esync_release_semaphore( handle, count, previous ); + TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); + -+ if ((ret = fast_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( release_semaphore ) @@ -3340,7 +3339,7 @@ index 1072265..a9a0a2c 100644 - return esync_set_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3356,7 +3355,7 @@ index 1072265..a9a0a2c 100644 - return esync_reset_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ if ((ret = fast_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3369,7 +3368,7 @@ index 1072265..a9a0a2c 100644 - return esync_pulse_event( handle ); + TRACE( "handle %p, prev_state %p\n", handle, prev_state ); + -+ if ((ret = fast_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( event_op ) @@ -3380,7 +3379,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_event( handle, info, ret_len ); -+ if ((ret = fast_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); + return ret; @@ -3426,7 +3425,7 @@ index 1072265..a9a0a2c 100644 - return esync_release_mutex( handle, prev_count ); + TRACE( "handle %p, prev_count %p\n", handle, prev_count ); + -+ if ((ret = fast_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) + return ret; SERVER_START_REQ( release_mutex ) @@ -3437,7 +3436,7 @@ index 1072265..a9a0a2c 100644 - if (do_esync()) - return esync_query_mutex( handle, info, ret_len ); -+ if ((ret = fast_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) + { + if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); + return ret; @@ -3492,7 +3491,7 @@ index 1072265..a9a0a2c 100644 + TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); + } + -+ if ((ret = fast_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + { + TRACE( "-> %#x\n", ret ); + return ret; @@ -3520,7 +3519,7 @@ index 1072265..a9a0a2c 100644 if (!signal) return STATUS_INVALID_HANDLE; -+ if ((ret = fast_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) ++ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + return ret; + if (alertable) flags |= SELECT_ALERTABLE; @@ -3610,7 +3609,7 @@ index 4e5b282..fc5b259 100644 PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ void *jmp_buf; /* setjmp buffer for exception handling */ -+ int fast_alert_obj; /* fd for the fast alert event */ ++ int linux_alert_obj; /* fd for the linux in-process alert event */ }; C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); @@ -3635,7 +3634,7 @@ index 4e5b282..fc5b259 100644 extern void dbg_init(void); -+extern void close_fast_sync_obj( HANDLE handle ); ++extern void close_inproc_sync_obj( HANDLE handle ); + extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ); @@ -3661,7 +3660,7 @@ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 1e1af8c..a54ac45 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c -@@ -3712,7 +3712,6 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) +@@ -3712,11 +3712,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; @@ -3669,40 +3668,11 @@ index 1e1af8c..a54ac45 100644 thread_data->request_fd = -1; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; -diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c -index 02193b8..eb733f6 100644 ---- a/dlls/rpcrt4/rpc_server.c -+++ b/dlls/rpcrt4/rpc_server.c -@@ -701,6 +701,10 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) - } - LeaveCriticalSection(&cps->cs); - -+ EnterCriticalSection(&listen_cs); -+ CloseHandle(cps->server_thread); -+ cps->server_thread = NULL; -+ LeaveCriticalSection(&listen_cs); - TRACE("done\n"); - return 0; + thread_data->wait_fd[1] = -1; ++ thread_data->linux_alert_obj = -1; + list_add_head( &teb_list, &thread_data->entry ); + return teb; } -@@ -1566,10 +1570,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) - LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) - { - if ((wait_thread = protseq->server_thread)) -- { -- protseq->server_thread = NULL; - break; -- } - } - LeaveCriticalSection(&server_cs); - if (!wait_thread) -@@ -1578,7 +1579,6 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) - TRACE("waiting for thread %lu\n", GetThreadId(wait_thread)); - LeaveCriticalSection(&listen_cs); - WaitForSingleObject(wait_thread, INFINITE); -- CloseHandle(wait_thread); - EnterCriticalSection(&listen_cs); - } - if (listen_done_event == event) diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c index c64027f..ddcf896 100644 --- a/dlls/webservices/tests/channel.c @@ -3745,19 +3715,19 @@ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 34655d1..1f8e10a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h -@@ -5634,6 +5634,88 @@ struct get_next_thread_reply +@@ -5881,6 +5881,86 @@ }; - - -+enum fast_sync_type + + ++enum inproc_sync_type +{ -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, +}; + + @@ -3792,38 +3762,36 @@ index 34655d1..1f8e10a 100644 + + + -+struct fast_select_queue_request ++struct select_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; ++ char __pad_12[4]; +}; -+struct fast_select_queue_reply ++struct select_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct fast_unselect_queue_request ++struct unselect_inproc_queue_request +{ + struct request_header __header; -+ obj_handle_t handle; + int signaled; -+ char __pad_20[4]; +}; -+struct fast_unselect_queue_reply ++struct unselect_inproc_queue_reply +{ + struct reply_header __header; +}; + + + -+struct get_fast_alert_event_request ++struct get_inproc_alert_event_request +{ + struct request_header __header; + char __pad_12[4]; +}; -+struct get_fast_alert_event_reply ++struct get_inproc_alert_event_reply +{ + struct reply_header __header; + obj_handle_t handle; @@ -3842,13 +3810,13 @@ index 34655d1..1f8e10a 100644 - REQ_open_esync, - REQ_get_esync_fd, - REQ_esync_msgwait, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_fast_select_queue, -+ REQ_fast_unselect_queue, REQ_set_keyboard_repeat, - REQ_get_esync_apc_fd, -+ REQ_get_fast_alert_event, ++ REQ_get_linux_sync_device, ++ REQ_get_linux_sync_obj, ++ REQ_select_inproc_queue, ++ REQ_unselect_inproc_queue, ++ REQ_get_inproc_alert_event, REQ_NB_REQUESTS }; @@ -3860,13 +3828,13 @@ index 34655d1..1f8e10a 100644 - struct open_esync_request open_esync_request; - struct get_esync_fd_request get_esync_fd_request; - struct esync_msgwait_request esync_msgwait_request; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct fast_select_queue_request fast_select_queue_request; -+ struct fast_unselect_queue_request fast_unselect_queue_request; struct set_keyboard_repeat_request set_keyboard_repeat_request; - struct get_esync_apc_fd_request get_esync_apc_fd_request; -+ struct get_fast_alert_event_request get_fast_alert_event_request; ++ struct get_linux_sync_device_request get_linux_sync_device_request; ++ struct get_linux_sync_obj_request get_linux_sync_obj_request; ++ struct select_inproc_queue_request select_inproc_queue_request; ++ struct unselect_inproc_queue_request unselect_inproc_queue_request; ++ struct get_inproc_alert_event_request get_inproc_alert_event_request; }; union generic_reply { @@ -3878,13 +3846,13 @@ index 34655d1..1f8e10a 100644 - struct open_esync_reply open_esync_reply; - struct get_esync_fd_reply get_esync_fd_reply; - struct esync_msgwait_reply esync_msgwait_reply; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct fast_select_queue_reply fast_select_queue_reply; -+ struct fast_unselect_queue_reply fast_unselect_queue_reply; struct set_keyboard_repeat_reply set_keyboard_repeat_reply; - struct get_esync_apc_fd_reply get_esync_apc_fd_reply; -+ struct get_fast_alert_event_reply get_fast_alert_event_reply; ++ struct get_linux_sync_device_reply get_linux_sync_device_reply; ++ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; ++ struct select_inproc_queue_reply select_inproc_queue_reply; ++ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; ++ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; }; /* ### protocol_version begin ### */ @@ -3898,7 +3866,7 @@ index b164193..b30df66 100644 directory.c \ - esync.c \ event.c \ -+ fast_sync.c \ ++ inproc_sync.c \ fd.c \ file.c \ handle.c \ @@ -3918,7 +3886,7 @@ index b0f9fe4..02fb966 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ async_destroy /* destroy */ }; @@ -3934,7 +3902,7 @@ index b0f9fe4..02fb966 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ iosb_destroy /* destroy */ }; @@ -3954,7 +3922,7 @@ index d9824de..ba320c4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; @@ -3974,7 +3942,7 @@ index ec61711..dafa7e8 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; @@ -3994,7 +3962,7 @@ index 8b265f2..de9f84f 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ clipboard_destroy /* destroy */ }; @@ -4002,15 +3970,15 @@ diff --git a/server/completion.c b/server/completion.c index 3d4be86..5ec6d20 100644 --- a/server/completion.c +++ b/server/completion.c -@@ -61,6 +61,7 @@ struct completion +@@ -77,6 +77,7 @@ struct list wait_queue; unsigned int depth; int closed; -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; }; static void completion_wait_dump( struct object*, int ); -@@ -92,21 +92,21 @@ static const struct object_ops completion_wait_ops = +@@ -92,7 +93,6 @@ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_wait_signaled, /* signaled */ @@ -4018,44 +3986,23 @@ index 3d4be86..5ec6d20 100644 completion_wait_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - no_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ +@@ -105,6 +105,7 @@ NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ completion_wait_destroy /* destroy */ }; - - static void completion_wait_destroy( struct object *obj ) -@@ -75,24 +77,28 @@ static const struct object_ops completion_ops = - msg = LIST_ENTRY( msg_entry, struct comp_msg, queue_entry ); - --wait->completion->depth; - list_remove( &msg->queue_entry ); -+ if (list_empty( &wait->completion->queue )) -+ { -+ fast_reset_event( wait->completion->fast_sync ); -+ } - if (wait->msg) free( wait->msg ); - wait->msg = msg; - } +@@ -156,6 +157,7 @@ static void completion_dump( struct object*, int ); static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *completion_get_fast_sync( struct object *obj ); ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void completion_destroy( struct object * ); - static const struct object_ops completion_ops = - { - sizeof(struct completion), /* size */ - &completion_type, /* type */ - completion_dump, /* dump */ +@@ -167,7 +169,6 @@ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_signaled, /* signaled */ @@ -4063,61 +4010,74 @@ index 3d4be86..5ec6d20 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -88,6 +89,7 @@ static const struct object_ops completion_ops = +@@ -180,6 +181,7 @@ default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_fast_sync, /* get_fast_sync */ ++ completion_get_inproc_sync,/* get_inproc_sync */ completion_close_handle, /* close_handle */ completion_destroy /* destroy */ }; -@@ -110,6 +112,7 @@ static void completion_destroy( struct object *obj) +@@ -193,6 +195,7 @@ { free( tmp ); } -+ if (completion->fast_sync) release_object( completion->fast_sync ); ++ if (completion->inproc_sync) release_object( completion->inproc_sync ); } static void completion_dump( struct object *obj, int verbose ) -@@ -127,6 +130,16 @@ static int completion_signaled( struct object *obj, struct wait_queue_entry *ent - return !list_empty( &completion->queue ); +@@ -230,6 +233,7 @@ + } + completion->closed = 1; + wake_up( obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); + return 1; } -+static struct fast_sync *completion_get_fast_sync( struct object *obj ) +@@ -263,6 +267,16 @@ + return wait; + } + ++static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) +{ + struct completion *completion = (struct completion *)obj; + -+ if (!completion->fast_sync) -+ completion->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->fast_sync) grab_object( completion->fast_sync ); -+ return completion->fast_sync; ++ if (!completion->inproc_sync) ++ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); ++ if (completion->inproc_sync) grab_object( completion->inproc_sync ); ++ return completion->inproc_sync; +} + static struct completion *create_completion( struct object *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent, const struct security_descriptor *sd ) -@@ -139,6 +152,7 @@ static struct completion *create_completion( struct object *root, const struct u - { - list_init( &completion->queue ); +@@ -277,6 +291,7 @@ + list_init( &completion->wait_queue ); completion->depth = 0; completion->closed = 0; -+ completion->fast_sync = NULL; ++ completion->inproc_sync = NULL; } } -@@ -166,6 +180,7 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ + +@@ -309,7 +324,11 @@ + wake_up( &wait->obj, 1 ); if (list_empty( &completion->queue )) return; } - if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ fast_set_event( completion->fast_sync ); +- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); ++ if (!list_empty( &completion->queue )) ++ { ++ wake_up( &completion->obj, 0 ); ++ set_inproc_event( completion->inproc_sync ); ++ } } /* create a completion */ -@@ -232,6 +247,8 @@ DECL_HANDLER(remove_completion) +@@ -410,6 +429,8 @@ reply->information = msg->information; free( msg ); reply->wait_handle = 0; + if (list_empty( &completion->queue )) -+ fast_reset_event( completion->fast_sync ); ++ reset_inproc_event( completion->inproc_sync ); } release_object( completion ); @@ -4137,7 +4097,7 @@ index dbd4a97..17708df 100644 struct fd *fd; /* for bare console, attached input fd */ struct async_queue ioctl_q; /* ioctl queue */ struct async_queue read_q; /* read queue */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_dump( struct object *obj, int verbose ); @@ -4145,7 +4105,7 @@ index dbd4a97..17708df 100644 static struct object *console_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *console_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ); static const struct object_ops console_ops = { @@ -4161,7 +4121,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ console_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_fast_sync, /* get_fast_sync */ ++ console_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_destroy /* destroy */ }; @@ -4186,7 +4146,7 @@ index dbd4a97..17708df 100644 - int esync_fd; + int term_fd; /* UNIX terminal fd */ + struct termios termios; /* original termios */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void console_server_dump( struct object *obj, int verbose ); @@ -4198,7 +4158,7 @@ index dbd4a97..17708df 100644 unsigned int attr, struct object *root ); static struct object *console_server_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); static const struct object_ops console_server_ops = { @@ -4214,7 +4174,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ console_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_fast_sync, /* get_fast_sync */ ++ console_server_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_server_destroy /* destroy */ }; @@ -4222,7 +4182,7 @@ index dbd4a97..17708df 100644 static struct fd *screen_buffer_get_fd( struct object *obj ); static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); static const struct object_ops screen_buffer_ops = { @@ -4238,7 +4198,7 @@ index dbd4a97..17708df 100644 NULL, /* unlink_name */ screen_buffer_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_fast_sync, /* get_fast_sync */ ++ screen_buffer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; @@ -4254,7 +4214,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4262,7 +4222,7 @@ index dbd4a97..17708df 100644 unsigned int sharing, unsigned int options ); static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); static void console_input_destroy( struct object *obj ); static const struct object_ops console_input_ops = @@ -4278,7 +4238,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_input_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_fast_sync, /* get_fast_sync */ ++ console_input_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -4286,7 +4246,7 @@ index dbd4a97..17708df 100644 static struct fd *console_output_get_fd( struct object *obj ); static struct object *console_output_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ); ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); static void console_output_destroy( struct object *obj ); static const struct object_ops console_output_ops = @@ -4302,7 +4262,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_output_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_fast_sync, /* get_fast_sync */ ++ console_output_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ console_output_destroy /* destroy */ }; @@ -4318,7 +4278,7 @@ index dbd4a97..17708df 100644 default_unlink_name, /* unlink_name */ console_connection_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ console_connection_close_handle, /* close_handle */ console_connection_destroy /* destroy */ }; @@ -4326,7 +4286,7 @@ index dbd4a97..17708df 100644 console->server = NULL; console->fd = NULL; console->last_id = 0; -+ console->fast_sync = NULL; ++ console->inproc_sync = NULL; init_async_queue( &console->ioctl_q ); init_async_queue( &console->read_q ); @@ -4334,7 +4294,7 @@ index dbd4a97..17708df 100644 } list_add_tail( &server->queue, &ioctl->entry ); wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); if (async) set_error( STATUS_PENDING ); return 1; } @@ -4351,7 +4311,7 @@ index dbd4a97..17708df 100644 server->console->server = NULL; server->console = NULL; wake_up( &server->obj, 0 ); -+ fast_set_event( server->fast_sync ); ++ set_inproc_event( server->inproc_sync ); } } @@ -4360,7 +4320,7 @@ index dbd4a97..17708df 100644 if (console->fd) release_object( console->fd ); + -+ if (console->fast_sync) release_object( console->fast_sync ); ++ if (console->inproc_sync) release_object( console->inproc_sync ); } static struct object *create_console_connection( struct console *console ) @@ -4368,14 +4328,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_get_inproc_sync( struct object *obj ) +{ + struct console *console = (struct console *)obj; + -+ if (!console->fast_sync) -+ console->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->fast_sync) grab_object( console->fast_sync ); -+ return console->fast_sync; ++ if (!console->inproc_sync) ++ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); ++ if (console->inproc_sync) grab_object( console->inproc_sync ); ++ return console->inproc_sync; +} + static void screen_buffer_dump( struct object *obj, int verbose ) @@ -4385,7 +4345,7 @@ index dbd4a97..17708df 100644 return NULL; } -+static struct fast_sync *screen_buffer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) +{ + struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; + if (!screen_buffer->input) @@ -4393,7 +4353,7 @@ index dbd4a97..17708df 100644 + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( &screen_buffer->input->obj ); ++ return console_get_inproc_sync( &screen_buffer->input->obj ); +} + static void console_server_dump( struct object *obj, int verbose ) @@ -4404,7 +4364,7 @@ index dbd4a97..17708df 100644 disconnect_console_server( server ); if (server->fd) release_object( server->fd ); - if (do_esync()) close( server->esync_fd ); -+ if (server->fast_sync) release_object( server->fast_sync ); ++ if (server->inproc_sync) release_object( server->inproc_sync ); } static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, @@ -4426,15 +4386,15 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_server_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) +{ + struct console_server *server = (struct console_server *)obj; + int signaled = !server->console || !list_empty( &server->queue ); + -+ if (!server->fast_sync) -+ server->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (server->fast_sync) grab_object( server->fast_sync ); -+ return server->fast_sync; ++ if (!server->inproc_sync) ++ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (server->inproc_sync) grab_object( server->inproc_sync ); ++ return server->inproc_sync; +} + static struct object *create_console_server( void ) @@ -4444,7 +4404,7 @@ index dbd4a97..17708df 100644 server->term_fd = -1; list_init( &server->queue ); list_init( &server->read_queue ); -+ server->fast_sync = NULL; ++ server->inproc_sync = NULL; server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!server->fd) { @@ -4463,14 +4423,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_input_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_input_destroy( struct object *obj ) @@ -4480,14 +4440,14 @@ index dbd4a97..17708df 100644 return grab_object( obj ); } -+static struct fast_sync *console_output_get_fast_sync( struct object *obj ) ++static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) +{ + if (!current->process->console || !current->process->console->active) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } -+ return console_get_fast_sync( ¤t->process->console->obj ); ++ return console_get_inproc_sync( ¤t->process->console->obj ); +} + static void console_output_destroy( struct object *obj ) @@ -4501,13 +4461,13 @@ index dbd4a97..17708df 100644 + if (!req->signal) + { + server->console->signaled = 0; -+ fast_reset_event( server->console->fast_sync ); ++ reset_inproc_event( server->console->inproc_sync ); + } else if (!server->console->signaled) { server->console->signaled = 1; wake_up( &server->console->obj, 0 ); -+ fast_set_event( server->console->fast_sync ); ++ set_inproc_event( server->console->inproc_sync ); } if (req->read) @@ -4518,7 +4478,7 @@ index dbd4a97..17708df 100644 - if (do_esync() && list_empty( &server->queue )) - esync_clear( server->esync_fd ); + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); } if (ioctl) @@ -4530,7 +4490,7 @@ index dbd4a97..17708df 100644 - esync_clear( server->esync_fd ); + + if (list_empty( &server->queue )) -+ fast_reset_event( server->fast_sync ); ++ reset_inproc_event( server->inproc_sync ); release_object( server ); } @@ -4542,7 +4502,7 @@ index ca04d4c..7975fc4 100644 struct object obj; /* object header */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; @@ -4558,14 +4518,14 @@ index ca04d4c..7975fc4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; static void debug_obj_dump( struct object *obj, int verbose ); static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ); ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); static void debug_obj_destroy( struct object *obj ); static const struct object_ops debug_obj_ops = @@ -4581,7 +4541,7 @@ index ca04d4c..7975fc4 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_fast_sync, /* get_fast_sync */ ++ debug_obj_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ debug_obj_destroy /* destroy */ }; @@ -4589,7 +4549,7 @@ index ca04d4c..7975fc4 100644 /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -4597,7 +4557,7 @@ index ca04d4c..7975fc4 100644 { grab_object( debug_obj ); wake_up( &debug_obj->obj, 0 ); -+ fast_set_event( debug_obj->fast_sync ); ++ set_inproc_event( debug_obj->inproc_sync ); release_object( debug_obj ); } } @@ -4605,15 +4565,15 @@ index ca04d4c..7975fc4 100644 return find_event_to_send( debug_obj ) != NULL; } -+static struct fast_sync *debug_obj_get_fast_sync( struct object *obj ) ++static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) +{ + struct debug_obj *debug_obj = (struct debug_obj *)obj; + int signaled = find_event_to_send( debug_obj ) != NULL; + -+ if (!debug_obj->fast_sync) -+ debug_obj->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->fast_sync) grab_object( debug_obj->fast_sync ); -+ return debug_obj->fast_sync; ++ if (!debug_obj->inproc_sync) ++ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); ++ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); ++ return debug_obj->inproc_sync; +} + static void debug_obj_destroy( struct object *obj ) @@ -4624,7 +4584,7 @@ index ca04d4c..7975fc4 100644 while ((ptr = list_head( &debug_obj->event_queue ))) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); + -+ if (debug_obj->fast_sync) release_object( debug_obj->fast_sync ); ++ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); } struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -4632,7 +4592,7 @@ index ca04d4c..7975fc4 100644 { debug_obj->flags = flags; list_init( &debug_obj->event_queue ); -+ debug_obj->fast_sync = NULL; ++ debug_obj->inproc_sync = NULL; } } return debug_obj; @@ -4642,7 +4602,7 @@ index ca04d4c..7975fc4 100644 set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); + + if (!find_event_to_send( debug_obj )) -+ fast_reset_event( debug_obj->fast_sync ); ++ reset_inproc_event( debug_obj->inproc_sync ); } else { @@ -4670,7 +4630,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ irp_call_destroy /* destroy */ }; @@ -4679,13 +4639,13 @@ index c45d010..698fee6 100644 struct irp_call *current_call; /* call currently executed on client side */ struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void device_manager_dump( struct object *obj, int verbose ); static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ); -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ); ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); static void device_manager_destroy( struct object *obj ); static const struct object_ops device_manager_ops = @@ -4701,7 +4661,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_fast_sync, /* get_fast_sync */ ++ device_manager_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_manager_destroy /* destroy */ }; @@ -4717,7 +4677,7 @@ index c45d010..698fee6 100644 default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -4733,7 +4693,7 @@ index c45d010..698fee6 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ device_file_close_handle, /* close_handle */ device_file_destroy /* destroy */ }; @@ -4746,7 +4706,7 @@ index c45d010..698fee6 100644 + { + /* first one */ + wake_up( &manager->obj, 0 ); -+ fast_set_event( manager->fast_sync ); ++ set_inproc_event( manager->inproc_sync ); + } } @@ -4763,7 +4723,7 @@ index c45d010..698fee6 100644 } + if (list_empty( &file->device->manager->requests )) -+ fast_reset_event( file->device->manager->fast_sync ); ++ reset_inproc_event( file->device->manager->inproc_sync ); + release_object( file ); } @@ -4773,16 +4733,16 @@ index c45d010..698fee6 100644 } -static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ) -+static struct fast_sync *device_manager_get_fast_sync( struct object *obj ) ++static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; - *type = ESYNC_MANUAL_SERVER; - return manager->esync_fd; + -+ if (!manager->fast_sync) -+ manager->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->fast_sync) grab_object( manager->fast_sync ); -+ return manager->fast_sync; ++ if (!manager->inproc_sync) ++ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); ++ if (manager->inproc_sync) grab_object( manager->inproc_sync ); ++ return manager->inproc_sync; } static void device_manager_destroy( struct object *obj ) @@ -4792,7 +4752,7 @@ index c45d010..698fee6 100644 - if (do_esync()) - close( manager->esync_fd ); -+ if (manager->fast_sync) release_object( manager->fast_sync ); ++ if (manager->inproc_sync) release_object( manager->inproc_sync ); } static struct device_manager *create_device_manager(void) @@ -4800,7 +4760,7 @@ index c45d010..698fee6 100644 if ((manager = alloc_object( &device_manager_ops ))) { manager->current_call = NULL; -+ manager->fast_sync = NULL; ++ manager->inproc_sync = NULL; list_init( &manager->devices ); list_init( &manager->requests ); wine_rb_init( &manager->kernel_objects, compare_kernel_object ); @@ -4816,7 +4776,7 @@ index c45d010..698fee6 100644 list_init( &irp->mgr_entry ); + + if (list_empty( &manager->requests )) -+ fast_reset_event( manager->fast_sync ); ++ reset_inproc_event( manager->inproc_sync ); + /* we already own the object if it's only on manager queue */ if (irp->file) grab_object( irp ); @@ -4843,7 +4803,7 @@ index bc161b9..8e32abb 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -4859,7 +4819,7 @@ index bc161b9..8e32abb 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ }; @@ -5515,7 +5475,7 @@ index f4ca3e4..b750a22 100644 int manual_reset; /* is it a manual reset event? */ int signaled; /* event has been signaled */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void event_dump( struct object *obj, int verbose ); @@ -5524,7 +5484,7 @@ index f4ca3e4..b750a22 100644 -static int event_get_esync_fd( struct object *obj, enum esync_type *type ); static int event_signal( struct object *obj, unsigned int access); static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ); static void event_destroy( struct object *obj ); static const struct object_ops event_ops = @@ -5540,7 +5500,7 @@ index f4ca3e4..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_fast_sync, /* get_fast_sync */ ++ event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ event_destroy /* destroy */ }; @@ -5548,12 +5508,12 @@ index f4ca3e4..b750a22 100644 struct keyed_event { struct object obj; /* object header */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void keyed_event_dump( struct object *obj, int verbose ); static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ); ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); +static void keyed_event_destroy( struct object *obj ); static const struct object_ops keyed_event_ops = @@ -5570,7 +5530,7 @@ index f4ca3e4..b750a22 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_fast_sync, /* get_fast_sync */ ++ keyed_event_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + keyed_event_destroy /* destroy */ @@ -5584,7 +5544,7 @@ index f4ca3e4..b750a22 100644 - - if (do_esync()) - event->esync_fd = esync_create_fd( initial_state, 0 ); -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -5612,7 +5572,7 @@ index f4ca3e4..b750a22 100644 event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ wake_up( &event->obj, !event->manual_reset ); -+ fast_set_event( event->fast_sync ); ++ set_inproc_event( event->inproc_sync ); } void reset_event( struct event *event ) @@ -5626,7 +5586,7 @@ index f4ca3e4..b750a22 100644 - - if (do_esync()) - esync_clear( event->esync_fd ); -+ fast_reset_event( event->fast_sync ); ++ reset_inproc_event( event->inproc_sync ); } static void event_dump( struct object *obj, int verbose ) @@ -5648,17 +5608,17 @@ index f4ca3e4..b750a22 100644 return &event->kernel_object; } -+static struct fast_sync *event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *event_get_inproc_sync( struct object *obj ) +{ + struct event *event = (struct event *)obj; + -+ if (!event->fast_sync) ++ if (!event->inproc_sync) + { -+ enum fast_sync_type type = event->manual_reset ? FAST_SYNC_MANUAL_EVENT : FAST_SYNC_AUTO_EVENT; -+ event->fast_sync = fast_create_event( type, event->signaled ); ++ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; ++ event->inproc_sync = create_inproc_event( type, event->signaled ); + } -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + static void event_destroy( struct object *obj ) @@ -5667,7 +5627,7 @@ index f4ca3e4..b750a22 100644 - if (do_esync()) - close( event->esync_fd ); -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); } struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, @@ -5675,7 +5635,7 @@ index f4ca3e4..b750a22 100644 if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ -+ event->fast_sync = NULL; ++ event->inproc_sync = NULL; } } return event; @@ -5683,34 +5643,34 @@ index f4ca3e4..b750a22 100644 return 0; } -+static struct fast_sync *keyed_event_get_fast_sync( struct object *obj ) ++static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (!event->fast_sync) -+ event->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, 1 ); -+ if (event->fast_sync) grab_object( event->fast_sync ); -+ return event->fast_sync; ++ if (!event->inproc_sync) ++ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); ++ if (event->inproc_sync) grab_object( event->inproc_sync ); ++ return event->inproc_sync; +} + +static void keyed_event_destroy( struct object *obj ) +{ + struct keyed_event *event = (struct keyed_event *)obj; + -+ if (event->fast_sync) release_object( event->fast_sync ); ++ if (event->inproc_sync) release_object( event->inproc_sync ); +} + /* create an event */ DECL_HANDLER(create_event) { -diff --git a/server/fast_sync.c b/server/fast_sync.c +diff --git a/server/inproc_sync.c b/server/inproc_sync.c new file mode 100644 index 0000000..fed6eb9 --- /dev/null -+++ b/server/fast_sync.c -@@ -0,0 +1,434 @@ ++++ b/server/inproc_sync.c +@@ -0,0 +1,437 @@ +/* -+ * Fast synchronization primitives ++ * In-process synchronization primitives + * + * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers + * @@ -5764,7 +5724,7 @@ index 0000000..fed6eb9 +static void linux_device_dump( struct object *obj, int verbose ); +static struct fd *linux_device_get_fd( struct object *obj ); +static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ); ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); + +static const struct object_ops linux_device_ops = +{ @@ -5786,16 +5746,16 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_device_destroy /* destroy */ +}; + -+static const struct fd_ops fast_sync_fd_ops = ++static const struct fd_ops inproc_sync_fd_ops = +{ + default_fd_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ -+ fast_sync_get_fd_type, /* get_fd_type */ ++ inproc_sync_get_fd_type, /* get_fd_type */ + no_fd_read, /* read */ + no_fd_write, /* write */ + no_fd_flush, /* flush */ @@ -5811,7 +5771,7 @@ index 0000000..fed6eb9 +{ + struct linux_device *device = (struct linux_device *)obj; + assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "Fast synchronization device fd=%p\n", device->fd ); ++ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); +} + +static struct fd *linux_device_get_fd( struct object *obj ) @@ -5828,7 +5788,7 @@ index 0000000..fed6eb9 + linux_device_object = NULL; +} + -+static enum server_fd_type fast_sync_get_fd_type( struct fd *fd ) ++static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) +{ + return FD_TYPE_FILE; +} @@ -5875,7 +5835,7 @@ index 0000000..fed6eb9 + return NULL; + } + -+ if (!(device->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &device->obj, 0 ))) ++ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) + { + release_object( device ); + initialized = 1; @@ -5888,10 +5848,10 @@ index 0000000..fed6eb9 + return device; +} + -+struct fast_sync ++struct inproc_sync +{ + struct object obj; -+ enum fast_sync_type type; ++ enum inproc_sync_type type; + struct fd *fd; +}; + @@ -5901,7 +5861,7 @@ index 0000000..fed6eb9 + +static const struct object_ops linux_obj_ops = +{ -+ sizeof(struct fast_sync), /* size */ ++ sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + linux_obj_dump, /* dump */ + no_add_queue, /* add_queue */ @@ -5919,80 +5879,81 @@ index 0000000..fed6eb9 + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ + no_close_handle, /* close_handle */ + linux_obj_destroy /* destroy */ +}; + +static void linux_obj_dump( struct object *obj, int verbose ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "Fast synchronization object type=%u fd=%p\n", fast_sync->type, fast_sync->fd ); ++ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); +} + +static void linux_obj_destroy( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ if (fast_sync->fd) release_object( fast_sync->fd ); ++ if (inproc_sync->fd) release_object( inproc_sync->fd ); +} + +static struct fd *linux_obj_get_fd( struct object *obj ) +{ -+ struct fast_sync *fast_sync = (struct fast_sync *)obj; ++ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; + assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( fast_sync->fd ); ++ return (struct fd *)grab_object( inproc_sync->fd ); +} + -+static struct fast_sync *create_fast_sync( enum fast_sync_type type, int unix_fd ) ++static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) +{ -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if (!(fast_sync = alloc_object( &linux_obj_ops ))) ++ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) + { + close( unix_fd ); + return NULL; + } + -+ fast_sync->type = type; ++ inproc_sync->type = type; + -+ if (!(fast_sync->fd = create_anonymous_fd( &fast_sync_fd_ops, unix_fd, &fast_sync->obj, 0 ))) ++ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) + { -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + return NULL; + } + -+ return fast_sync; ++ return inproc_sync; +} + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ -+ struct ntsync_event_args args = {0}; ++ struct ntsync_event_args args; + struct linux_device *device; ++ int event; + + if (!(device = get_linux_device())) return NULL; + + args.signaled = signaled; + switch (type) + { -+ case FAST_SYNC_AUTO_EVENT: -+ case FAST_SYNC_AUTO_SERVER: ++ case INPROC_SYNC_AUTO_EVENT: ++ case INPROC_SYNC_AUTO_SERVER: + args.manual = 0; + break; + -+ case FAST_SYNC_MANUAL_EVENT: -+ case FAST_SYNC_MANUAL_SERVER: -+ case FAST_SYNC_QUEUE: ++ case INPROC_SYNC_MANUAL_EVENT: ++ case INPROC_SYNC_MANUAL_SERVER: ++ case INPROC_SYNC_QUEUE: + args.manual = 1; + break; + -+ case FAST_SYNC_MUTEX: -+ case FAST_SYNC_SEMAPHORE: ++ case INPROC_SYNC_MUTEX: ++ case INPROC_SYNC_SEMAPHORE: + assert(0); + break; + } -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args ) < 0) ++ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6000,19 +5961,20 @@ index 0000000..fed6eb9 + } + release_object( device ); + -+ return create_fast_sync( type, args.event ); ++ return create_inproc_sync( type, event ); +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ -+ struct ntsync_sem_args args = {0}; ++ struct ntsync_sem_args args; + struct linux_device *device; ++ int semaphore; + + if (!(device = get_linux_device())) return NULL; + + args.count = count; + args.max = max; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args ) < 0) ++ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6021,19 +5983,20 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_SEMAPHORE, args.sem ); ++ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ -+ struct ntsync_mutex_args args = {0}; ++ struct ntsync_mutex_args args; + struct linux_device *device; ++ int mutex; + + if (!(device = get_linux_device())) return NULL; + + args.owner = owner; + args.count = count; -+ if (ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args ) < 0) ++ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) + { + file_set_error(); + release_object( device ); @@ -6042,65 +6005,65 @@ index 0000000..fed6eb9 + + release_object( device ); + -+ return create_fast_sync( FAST_SYNC_MUTEX, args.mutex ); ++ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); +} + -+void fast_reset_event( struct fast_sync *fast_sync ) ++void reset_inproc_event( struct inproc_sync *inproc_sync ) +{ + __u32 count; + -+ if (!fast_sync) return; ++ if (!inproc_sync) return; + -+ if (debug_level) fprintf( stderr, "fast_set_event %p\n", fast_sync->fd ); ++ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); + -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ -+ ioctl( get_unix_fd( fast_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); ++ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); +} + +#else + -+struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ) ++struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ) ++struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ) ++struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + -+void fast_set_event( struct fast_sync *fast_sync ) ++void set_inproc_event( struct inproc_sync *inproc_sync ) +{ +} + -+void fast_reset_event( struct fast_sync *obj ) ++void reset_inproc_event( struct inproc_sync *obj ) +{ +} + -+void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ) ++void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) +{ +} + @@ -6128,14 +6091,14 @@ index 0000000..fed6eb9 + + if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) + { -+ struct fast_sync *fast_sync; ++ struct inproc_sync *inproc_sync; + -+ if ((fast_sync = obj->ops->get_fast_sync( obj ))) ++ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) + { -+ reply->handle = alloc_handle( current->process, fast_sync, 0, 0 ); -+ reply->type = fast_sync->type; ++ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); ++ reply->type = inproc_sync->type; + reply->access = get_handle_access( current->process, req->handle ); -+ release_object( fast_sync ); ++ release_object( inproc_sync ); + } + release_object( obj ); + } @@ -6160,7 +6123,7 @@ index a6782b0..f00e22d 100644 apc_param_t comp_key; /* completion key to set in completion events */ unsigned int comp_flags; /* completion flags */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void fd_dump( struct object *obj, int verbose ); @@ -6176,7 +6139,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ fd_destroy /* destroy */ }; @@ -6192,7 +6155,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -6208,7 +6171,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ inode_destroy /* destroy */ }; @@ -6224,7 +6187,7 @@ index a6782b0..f00e22d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6235,7 +6198,7 @@ index a6782b0..f00e22d 100644 - - if (do_esync()) - close( fd->esync_fd ); -+ if (fd->fast_sync) release_object( fd->fast_sync ); ++ if (fd->inproc_sync) release_object( fd->inproc_sync ); } /* check if the desired access is possible without violating */ @@ -6244,7 +6207,7 @@ index a6782b0..f00e22d 100644 fd->completion = NULL; fd->comp_flags = 0; - fd->esync_fd = -1; -+ fd->fast_sync = NULL; ++ fd->inproc_sync = NULL; init_async_queue( &fd->read_q ); init_async_queue( &fd->write_q ); init_async_queue( &fd->wait_q ); @@ -6261,7 +6224,7 @@ index a6782b0..f00e22d 100644 fd->poll_index = -1; fd->completion = NULL; fd->comp_flags = 0; -+ fd->fast_sync = NULL; ++ fd->inproc_sync = NULL; fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - fd->esync_fd = -1; init_async_queue( &fd->read_q ); @@ -6286,11 +6249,11 @@ index a6782b0..f00e22d 100644 + if (signaled) + { + wake_up( fd->user, 0 ); -+ fast_set_event( fd->fast_sync ); ++ set_inproc_event( fd->inproc_sync ); + } + else + { -+ fast_reset_event( fd->fast_sync ); ++ reset_inproc_event( fd->inproc_sync ); + } } @@ -6300,16 +6263,16 @@ index a6782b0..f00e22d 100644 } -int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ) -+struct fast_sync *default_fd_get_fast_sync( struct object *obj ) ++struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) { struct fd *fd = get_obj_fd( obj ); - int ret = fd->esync_fd; - *type = ESYNC_MANUAL_SERVER; -+ struct fast_sync *ret; ++ struct inproc_sync *ret; + -+ if (!fd->fast_sync) -+ fd->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->fast_sync; ++ if (!fd->inproc_sync) ++ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); ++ ret = fd->inproc_sync; release_object( fd ); + if (ret) grab_object( ret ); return ret; @@ -6331,7 +6294,7 @@ index 828a21c..c6bdbef 100644 NULL, /* unlink_name */ file_open_file, /* open_file */ file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ file_destroy /* destroy */ }; @@ -6344,7 +6307,7 @@ index abad355..6b4fa51 100644 extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ); -+extern struct fast_sync *default_fd_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); 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 ); @@ -6364,7 +6327,7 @@ index cf6afe4..e07f32c 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handle_table_destroy /* destroy */ }; @@ -6384,7 +6347,7 @@ index da351d6..5a00699 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ hook_table_destroy /* destroy */ }; @@ -6404,7 +6367,7 @@ index 4cf9b73..d9807b4 100644 default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync,/* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; @@ -6420,7 +6383,7 @@ index 4cf9b73..d9807b4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; @@ -6436,7 +6399,7 @@ index 4cf9b73..d9807b4 100644 default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ }; @@ -6452,7 +6415,7 @@ index 4cf9b73..d9807b4 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mailslot_device_file_destroy /* destroy */ }; @@ -6494,7 +6457,7 @@ index 88de806..c3cba90 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ranges_destroy /* destroy */ }; @@ -6510,7 +6473,7 @@ index 88de806..c3cba90 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ shared_map_destroy /* destroy */ }; @@ -6526,7 +6489,7 @@ index 88de806..c3cba90 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; @@ -6538,7 +6501,7 @@ index 4785a83..167c236 100644 static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; -+static struct list fast_mutexes = LIST_INIT(fast_mutexes); ++static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); + struct type_descr mutex_type = { @@ -6547,8 +6510,8 @@ index 4785a83..167c236 100644 unsigned int count; /* recursion count */ int abandoned; /* has it been abandoned? */ struct list entry; /* entry in owner thread mutex list */ -+ struct list fast_mutexes_entry; /* entry in fast_mutexes list */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ ++ struct inproc_sync *inproc_sync;/* in-process synchronization object */ }; static void mutex_dump( struct object *obj, int verbose ); @@ -6556,7 +6519,7 @@ index 4785a83..167c236 100644 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void mutex_destroy( struct object *obj ); static int mutex_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ); ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); static const struct object_ops mutex_ops = { @@ -6572,7 +6535,7 @@ index 4785a83..167c236 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_fast_sync, /* get_fast_sync */ ++ mutex_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; @@ -6580,7 +6543,7 @@ index 4785a83..167c236 100644 mutex->owner = NULL; mutex->abandoned = 0; if (owned) do_grab( mutex, current ); -+ mutex->fast_sync = NULL; ++ mutex->inproc_sync = NULL; } } return mutex; @@ -6601,9 +6564,9 @@ index 4785a83..167c236 100644 do_release( mutex ); } + -+ LIST_FOR_EACH_ENTRY(mutex, &fast_mutexes, struct mutex, fast_mutexes_entry) ++ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) + { -+ fast_abandon_mutex( thread->id, mutex->fast_sync ); ++ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); + } } @@ -6612,17 +6575,17 @@ index 4785a83..167c236 100644 return 1; } -+static struct fast_sync *mutex_get_fast_sync( struct object *obj ) ++static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) +{ + struct mutex *mutex = (struct mutex *)obj; + -+ if (!mutex->fast_sync) ++ if (!mutex->inproc_sync) + { -+ mutex->fast_sync = fast_create_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->fast_sync) list_add_tail( &fast_mutexes, &mutex->fast_mutexes_entry ); ++ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); ++ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); + } -+ if (mutex->fast_sync) grab_object( mutex->fast_sync ); -+ return mutex->fast_sync; ++ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); ++ return mutex->inproc_sync; +} + static void mutex_destroy( struct object *obj ) @@ -6638,10 +6601,10 @@ index 4785a83..167c236 100644 + mutex->count = 0; + do_release( mutex ); + } -+ if (mutex->fast_sync) ++ if (mutex->inproc_sync) + { -+ release_object( mutex->fast_sync ); -+ list_remove( &mutex->fast_mutexes_entry ); ++ release_object( mutex->inproc_sync ); ++ list_remove( &mutex->inproc_mutexes_entry ); + } } @@ -6662,7 +6625,7 @@ index a90ec60..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -6678,7 +6641,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ pipe_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -6694,7 +6657,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ async_close_obj_handle, /* close_handle */ pipe_end_destroy /* destroy */ }; @@ -6710,7 +6673,7 @@ index a90ec60..6d8cb3e 100644 default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ }; @@ -6726,7 +6689,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_device_file_destroy /* destroy */ }; @@ -6742,7 +6705,7 @@ index a90ec60..6d8cb3e 100644 NULL, /* unlink_name */ named_pipe_dir_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ named_pipe_dir_destroy /* destroy */ }; @@ -6767,7 +6730,7 @@ index 29f1ea9..33fc18c 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6788,7 +6751,7 @@ index 29f1ea9..33fc18c 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -6796,7 +6759,7 @@ index 29f1ea9..33fc18c 100644 return NULL; } -+struct fast_sync *no_get_fast_sync( struct object *obj ) ++struct inproc_sync *no_get_inproc_sync( struct object *obj ) +{ + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; @@ -6813,7 +6776,7 @@ index 6f4bca8..f028a8e 100644 struct async_queue; struct winstation; struct object_type; -+struct fast_sync; ++struct inproc_sync; struct unicode_str @@ -6830,8 +6793,8 @@ index 6f4bca8..f028a8e 100644 unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable fast-synchronization handle to this object */ -+ struct fast_sync *(*get_fast_sync)(struct object *); ++ /* get a client-waitable in-process synchronization handle to this object */ ++ struct inproc_sync *(*get_inproc_sync)(struct object *); /* close a handle to this object */ int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ @@ -6839,16 +6802,16 @@ index 6f4bca8..f028a8e 100644 extern void abandon_mutexes( struct thread *thread ); -+/* fast-synchronization functions */ ++/* in-process synchronization functions */ + -+extern struct fast_sync *fast_create_event( enum fast_sync_type type, int signaled ); -+extern struct fast_sync *fast_create_semaphore( unsigned int count, unsigned int max ); -+extern struct fast_sync *fast_create_mutex( thread_id_t owner, unsigned int count ); -+extern void fast_set_event( struct fast_sync *obj ); -+extern void fast_reset_event( struct fast_sync *obj ); -+extern void fast_abandon_mutex( thread_id_t tid, struct fast_sync *fast_sync ); ++extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); ++extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); ++extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); ++extern void set_inproc_event( struct inproc_sync *obj ); ++extern void reset_inproc_event( struct inproc_sync *obj ); ++extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); + -+extern struct fast_sync *no_get_fast_sync( struct object *obj ); ++extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); + /* serial functions */ @@ -6869,7 +6832,7 @@ index 6d66a7c..34451c1 100644 static struct security_descriptor *process_get_sd( struct object *obj ); static void process_poll_event( struct fd *fd, int event ); static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *process_get_fast_sync( struct object *obj ); ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ); static void process_destroy( struct object *obj ); -static int process_get_esync_fd( struct object *obj, enum esync_type *type ); static void terminate_process( struct process *process, struct thread *skip, int exit_code ); @@ -6887,7 +6850,7 @@ index 6d66a7c..34451c1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_fast_sync, /* get_fast_sync */ ++ process_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -6903,7 +6866,7 @@ index 6d66a7c..34451c1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; @@ -6911,7 +6874,7 @@ index 6d66a7c..34451c1 100644 static void job_dump( struct object *obj, int verbose ); static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *job_get_fast_sync( struct object *obj ); ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ); static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void job_destroy( struct object *obj ); @@ -6919,7 +6882,7 @@ index 6d66a7c..34451c1 100644 struct job *parent; struct list parent_job_entry; /* list entry for parent job */ struct list child_job_list; /* list of child jobs */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static const struct object_ops job_ops = @@ -6935,7 +6898,7 @@ index 6d66a7c..34451c1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_fast_sync, /* get_fast_sync */ ++ job_get_inproc_sync, /* get_inproc_sync */ job_close_handle, /* close_handle */ job_destroy /* destroy */ }; @@ -6943,7 +6906,7 @@ index 6d66a7c..34451c1 100644 job->completion_port = NULL; job->completion_key = 0; job->parent = NULL; -+ job->fast_sync = NULL; ++ job->inproc_sync = NULL; } } return job; @@ -6951,17 +6914,17 @@ index 6d66a7c..34451c1 100644 job->terminating = 0; job->signaled = 1; wake_up( &job->obj, 0 ); -+ fast_set_event( job->fast_sync ); ++ set_inproc_event( job->inproc_sync ); +} + -+static struct fast_sync *job_get_fast_sync( struct object *obj ) ++static struct inproc_sync *job_get_inproc_sync( struct object *obj ) +{ + struct job *job = (struct job *)obj; + -+ if (!job->fast_sync) -+ job->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->fast_sync) grab_object( job->fast_sync ); -+ return job->fast_sync; ++ if (!job->inproc_sync) ++ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); ++ if (job->inproc_sync) grab_object( job->inproc_sync ); ++ return job->inproc_sync; } static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) @@ -6970,7 +6933,7 @@ index 6d66a7c..34451c1 100644 release_object( job->parent ); } + -+ if (job->fast_sync) release_object( job->fast_sync ); ++ if (job->inproc_sync) release_object( job->inproc_sync ); } static void job_dump( struct object *obj, int verbose ) @@ -6978,7 +6941,7 @@ index 6d66a7c..34451c1 100644 process->rawinput_device_count = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; -+ process->fast_sync = NULL; ++ process->inproc_sync = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); list_init( &process->rawinput_entry ); - process->esync_fd = -1; @@ -7001,7 +6964,7 @@ index 6d66a7c..34451c1 100644 free( process->image ); - if (do_esync()) close( process->esync_fd ); + -+ if (process->fast_sync) release_object( process->fast_sync ); ++ if (process->inproc_sync) release_object( process->inproc_sync ); } /* dump a process on stdout for debugging purposes */ @@ -7023,14 +6986,14 @@ index 6d66a7c..34451c1 100644 return &process->kernel_object; } -+static struct fast_sync *process_get_fast_sync( struct object *obj ) ++static struct inproc_sync *process_get_inproc_sync( struct object *obj ) +{ + struct process *process = (struct process *)obj; + -+ if (!process->fast_sync) -+ process->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->fast_sync) grab_object( process->fast_sync ); -+ return process->fast_sync; ++ if (!process->inproc_sync) ++ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); ++ if (process->inproc_sync) grab_object( process->inproc_sync ); ++ return process->inproc_sync; +} + static struct security_descriptor *process_get_sd( struct object *obj ) @@ -7040,7 +7003,7 @@ index 6d66a7c..34451c1 100644 release_job_process( process ); start_sigkill_timer( process ); wake_up( &process->obj, 0 ); -+ fast_set_event( process->fast_sync ); ++ set_inproc_event( process->inproc_sync ); } /* add a thread to a process running threads list */ @@ -7053,7 +7016,7 @@ index bedd8bb..2140427 100644 struct list kernel_object; /* list of kernel object pointers */ struct pe_image_info image_info; /* main exe image info */ - int esync_fd; /* esync file descriptor (signaled on exit) */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; /* process functions */ @@ -7069,13 +7032,13 @@ index 4983691..7bc4208 100644 /* Iterate thread list for process */ @REQ(get_next_thread) obj_handle_t process; /* process handle */ -@@ -3898,63 +3899,60 @@ struct handle_info +@@ -3898,63 +3899,58 @@ struct handle_info obj_handle_t handle; /* next thread handle */ @END -enum esync_type + -+enum fast_sync_type ++enum inproc_sync_type { - ESYNC_SEMAPHORE = 1, - ESYNC_AUTO_EVENT, @@ -7084,13 +7047,13 @@ index 4983691..7bc4208 100644 - ESYNC_AUTO_SERVER, - ESYNC_MANUAL_SERVER, - ESYNC_QUEUE, -+ FAST_SYNC_SEMAPHORE = 1, -+ FAST_SYNC_MUTEX, -+ FAST_SYNC_AUTO_EVENT, -+ FAST_SYNC_MANUAL_EVENT, -+ FAST_SYNC_AUTO_SERVER, -+ FAST_SYNC_MANUAL_SERVER, -+ FAST_SYNC_QUEUE, ++ INPROC_SYNC_SEMAPHORE = 1, ++ INPROC_SYNC_MUTEX, ++ INPROC_SYNC_AUTO_EVENT, ++ INPROC_SYNC_MANUAL_EVENT, ++ INPROC_SYNC_AUTO_SERVER, ++ INPROC_SYNC_MANUAL_SERVER, ++ INPROC_SYNC_QUEUE, }; -/* Create a new eventfd-based synchronization object */ @@ -7117,7 +7080,7 @@ index 4983691..7bc4208 100644 - int type; /* type of esync object (above) */ - VARARG(name,unicode_str); /* object name */ + -+/* Get the fast synchronization object associated with the given handle */ ++/* Get the in-process synchronization object associated with the given handle */ +@REQ(get_linux_sync_obj) + obj_handle_t handle; /* handle to the object */ @REPLY @@ -7137,16 +7100,14 @@ index 4983691..7bc4208 100644 - unsigned int shm_idx; + +/* Begin a client-side wait on a message queue */ -+@REQ(fast_select_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(select_inproc_queue) @END -@REQ(esync_msgwait) - int in_msgwait; /* are we in a message wait? */ + +/* End a client-side wait on a message queue */ -+@REQ(fast_unselect_queue) -+ obj_handle_t handle; /* handle to the queue */ ++@REQ(unselect_inproc_queue) + int signaled; /* was the queue signaled? */ @END @@ -7158,12 +7119,12 @@ index 4983691..7bc4208 100644 @REPLY int enable; /* previous state of auto-repeat enable */ @END - + -/* Retrieve the fd to wait on for user APCs. */ -@REQ(get_esync_apc_fd) + -+/* Get an event handle to be used for thread alerts with fast synchronization */ -+@REQ(get_fast_alert_event) ++/* Get an event handle to be used for thread alerts with in-process synchronization */ ++@REQ(get_inproc_alert_event) +@REPLY + obj_handle_t handle; /* handle to the event */ @END @@ -7185,8 +7146,8 @@ index fee3a8d..287a56e 100644 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 */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ int in_fast_wait; /* are we in a client-side wait? */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ int in_inproc_wait; /* are we in a client-side wait? */ }; struct hotkey @@ -7196,7 +7157,7 @@ index fee3a8d..287a56e 100644 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 ); static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ); ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); static void msg_queue_destroy( struct object *obj ); static void msg_queue_poll_event( struct fd *fd, int event ); static void thread_input_dump( struct object *obj, int verbose ); @@ -7212,7 +7173,7 @@ index fee3a8d..287a56e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_fast_sync, /* get_fast_sync */ ++ msg_queue_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; @@ -7228,18 +7189,18 @@ index fee3a8d..287a56e 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; -@@ -321,32 +320,29 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ +@@ -321,33 +320,30 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->last_get_msg = current_time; queue->keystate_lock = 0; queue->ignore_post_msg = 0; - queue->esync_fd = -1; - queue->esync_in_msgwait = 0; -+ queue->fast_sync = NULL; -+ queue->in_fast_wait = 0; ++ queue->inproc_sync = NULL; ++ queue->in_inproc_wait = 0; list_init( &queue->send_result ); list_init( &queue->callback_result ); list_init( &queue->pending_timers ); @@ -7266,8 +7227,9 @@ index fee3a8d..287a56e 100644 - queue->esync_fd = esync_create_fd( 0, 0 ); - thread->queue = queue; - -@@ -607,7 +603,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) + } + +@@ -606,7 +602,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) } SHARED_WRITE_END; @@ -7275,7 +7237,7 @@ index fee3a8d..287a56e 100644 + if (is_signaled( queue )) + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } } @@ -7288,7 +7250,7 @@ index fee3a8d..287a56e 100644 - if (do_esync() && !is_signaled( queue )) - esync_clear( queue->esync_fd ); + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } /* check if message is matched by the filter */ @@ -7298,12 +7260,12 @@ index fee3a8d..287a56e 100644 - if (do_esync() && queue->esync_in_msgwait) - return 0; /* thread is waiting on queue in absentia -> not hung */ -+ if (queue->in_fast_wait) ++ if (queue->in_inproc_wait) + return 0; /* thread is waiting on queue in absentia -> not hung */ return 1; } -@@ -1168,24 +1167,30 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr +@@ -1168,24 +1167,29 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr return ret || is_signaled( queue ); } @@ -7322,14 +7284,14 @@ index fee3a8d..287a56e 100644 + } + SHARED_WRITE_END; + -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } -static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct fast_sync *msg_queue_get_fast_sync( struct object *obj ) ++static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) { struct msg_queue *queue = (struct msg_queue *)obj; - const queue_shm_t *queue_shm = queue->shared; +- const queue_shm_t *queue_shm = queue->shared; - SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) - { @@ -7337,10 +7299,10 @@ index fee3a8d..287a56e 100644 - shared->changed_mask = 0; - } - SHARED_WRITE_END; -+ if (!queue->fast_sync) -+ queue->fast_sync = fast_create_event( FAST_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->fast_sync) grab_object( queue->fast_sync ); -+ return queue->fast_sync; ++ if (!queue->inproc_sync) ++ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); ++ if (queue->inproc_sync) grab_object( queue->inproc_sync ); ++ return queue->inproc_sync; } static void msg_queue_destroy( struct object *obj ) @@ -7349,7 +7311,7 @@ index fee3a8d..287a56e 100644 if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); - if (do_esync()) close( queue->esync_fd ); -+ if (queue->fast_sync) release_object( queue->fast_sync ); ++ if (queue->inproc_sync) release_object( queue->inproc_sync ); } static void msg_queue_poll_event( struct fd *fd, int event ) @@ -7357,7 +7319,7 @@ index fee3a8d..287a56e 100644 if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); } static void thread_input_dump( struct object *obj, int verbose ) @@ -7368,12 +7330,12 @@ index fee3a8d..287a56e 100644 + else + { + wake_up( &queue->obj, 0 ); -+ fast_set_event( queue->fast_sync ); ++ set_inproc_event( queue->inproc_sync ); + } + } + else + { -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); - } - else wake_up( &queue->obj, 0 ); } @@ -7382,15 +7344,14 @@ index fee3a8d..287a56e 100644 - esync_clear( queue->esync_fd ); } } -@@ -2867,9 +2880,9 @@ DECL_HANDLER(get_queue_status) - shared->changed_bits &= ~req->clear_bits; +@@ -2867,8 +2880,8 @@ DECL_HANDLER(get_queue_status) } SHARED_WRITE_END; - if (do_esync() && !is_signaled( queue )) - esync_clear( queue->esync_fd ); + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); } else reply->wake_bits = reply->changed_bits = 0; } @@ -7399,16 +7360,17 @@ index fee3a8d..287a56e 100644 if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; + if (!is_signaled( queue )) -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); + /* then check for posted messages */ if ((filter & QS_POSTMESSAGE) && get_posted_message( queue, queue->ignore_post_msg, get_win, req->get_first, req->get_last, req->flags, reply )) @@ -3119,11 +3134,8 @@ DECL_HANDLER(get_message) + shared->changed_mask = req->changed_mask; } SHARED_WRITE_END; -+ fast_reset_event( queue->fast_sync ); ++ reset_inproc_event( queue->inproc_sync ); set_error( STATUS_PENDING ); /* FIXME */ - - if (do_esync() && !is_signaled( queue )) @@ -7417,76 +7379,6 @@ index fee3a8d..287a56e 100644 return; found_msg: -@@ -4020,21 +4020,60 @@ DECL_HANDLER(update_rawinput_devices) - } - } - --DECL_HANDLER(esync_msgwait) -+DECL_HANDLER(fast_select_queue) - { -- struct msg_queue *queue = get_current_queue(); -+ struct msg_queue *queue; - const queue_shm_t *queue_shm; - -- if (!queue) return; -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; - queue_shm = queue->shared; -- queue->esync_in_msgwait = req->in_msgwait; -+ /* a thread can only wait on its own queue */ -+ if (current->queue != queue || queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -+ set_event( current->process->idle_event ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); - -- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -- set_event( current->process->idle_event ); -+ queue->in_fast_wait = 1; -+ } - -- /* and start/stop waiting on the driver */ -- if (queue->fd) -- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); -+ release_object( queue ); -+} -+ -+DECL_HANDLER(fast_unselect_queue) -+{ -+ struct msg_queue *queue; -+ const queue_shm_t *queue_shm; -+ -+ if (!(queue = (struct msg_queue *)get_handle_obj( current->process, req->handle, -+ SYNCHRONIZE, &msg_queue_ops ))) -+ return; -+ -+ queue_shm = queue->shared; -+ if (current->queue != queue || !queue->in_fast_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_fast_wait = 0; -+ } -+ -+ release_object( queue ); - } - - DECL_HANDLER(set_keyboard_repeat) diff --git a/server/registry.c b/server/registry.c index 4454de3..dd5c556 100644 --- a/server/registry.c @@ -7503,7 +7395,7 @@ index 4454de3..dd5c556 100644 key_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ key_close_handle, /* close_handle */ key_destroy /* destroy */ }; @@ -7523,7 +7415,7 @@ index ca83fdb..8c50f99 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; @@ -7539,13 +7431,13 @@ index eb6b8f4..1636e98 100644 -DECL_HANDLER(open_esync); -DECL_HANDLER(get_esync_fd); -DECL_HANDLER(esync_msgwait); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(fast_select_queue); -+DECL_HANDLER(fast_unselect_queue); DECL_HANDLER(set_keyboard_repeat); -DECL_HANDLER(get_esync_apc_fd); -+DECL_HANDLER(get_fast_alert_event); ++DECL_HANDLER(get_linux_sync_device); ++DECL_HANDLER(get_linux_sync_obj); ++DECL_HANDLER(select_inproc_queue); ++DECL_HANDLER(unselect_inproc_queue); ++DECL_HANDLER(get_inproc_alert_event); typedef void (*req_handler)( const void *req, void *reply ); static const req_handler req_handlers[REQ_NB_REQUESTS] = @@ -7557,17 +7449,17 @@ index eb6b8f4..1636e98 100644 - (req_handler)req_open_esync, - (req_handler)req_get_esync_fd, - (req_handler)req_esync_msgwait, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_fast_select_queue, -+ (req_handler)req_fast_unselect_queue, (req_handler)req_set_keyboard_repeat, - (req_handler)req_get_esync_apc_fd, -+ (req_handler)req_get_fast_alert_event, ++ (req_handler)req_get_linux_sync_device, ++ (req_handler)req_get_linux_sync_obj, ++ (req_handler)req_select_inproc_queue, ++ (req_handler)req_unselect_inproc_queue, ++ (req_handler)req_get_inproc_alert_event, }; C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,35 +2276,26 @@ +@@ -2276,35 +2276,24 @@ C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); @@ -7596,6 +7488,13 @@ index eb6b8f4..1636e98 100644 -C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 ); -C_ASSERT( offsetof(struct esync_msgwait_request, in_msgwait) == 12 ); -C_ASSERT( sizeof(struct esync_msgwait_request) == 16 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); + C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); + C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); +-C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); +C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); +C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); @@ -7605,21 +7504,12 @@ index eb6b8f4..1636e98 100644 +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); +C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); +C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( offsetof(struct fast_select_queue_request, handle) == 12 ); -+C_ASSERT( sizeof(struct fast_select_queue_request) == 16 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, handle) == 12 ); -+C_ASSERT( offsetof(struct fast_unselect_queue_request, signaled) == 16 ); -+C_ASSERT( sizeof(struct fast_unselect_queue_request) == 24 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_fast_alert_event_reply, handle) == 8 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); --C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); -+C_ASSERT( sizeof(struct get_fast_alert_event_reply) == 16 ); ++C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); ++C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); ++C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); ++C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); ++C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); diff --git a/server/semaphore.c b/server/semaphore.c index e3889f2..9940919 100644 --- a/server/semaphore.c @@ -7628,14 +7518,14 @@ index e3889f2..9940919 100644 struct object obj; /* object header */ unsigned int count; /* current count */ unsigned int max; /* maximum possible count */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* fast synchronization object */ }; static void semaphore_dump( struct object *obj, int verbose ); static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ); ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); +static void semaphore_destroy( struct object *obj ); static const struct object_ops semaphore_ops = @@ -7652,7 +7542,7 @@ index e3889f2..9940919 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_fast_sync, /* get_fast_sync */ ++ semaphore_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + semaphore_destroy /* destroy */ @@ -7663,7 +7553,7 @@ index e3889f2..9940919 100644 /* initialize it if it didn't already exist */ sem->count = initial; sem->max = max; -+ sem->fast_sync = NULL; ++ sem->inproc_sync = NULL; } } return sem; @@ -7671,21 +7561,21 @@ index e3889f2..9940919 100644 return release_semaphore( sem, 1, NULL ); } -+static struct fast_sync *semaphore_get_fast_sync( struct object *obj ) ++static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (!semaphore->fast_sync) -+ semaphore->fast_sync = fast_create_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->fast_sync) grab_object( semaphore->fast_sync ); -+ return semaphore->fast_sync; ++ if (!semaphore->inproc_sync) ++ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); ++ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); ++ return semaphore->inproc_sync; +} + +static void semaphore_destroy( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + -+ if (semaphore->fast_sync) release_object( semaphore->fast_sync ); ++ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); +} + /* create a semaphore */ @@ -7707,7 +7597,7 @@ index 11e204e..5c210d1 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; @@ -7727,7 +7617,7 @@ index 55cd6aa..e5def3d 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; @@ -7747,7 +7637,7 @@ index 104321b..3fb2e29 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_fast_sync, /* get_fast_sync */ ++ default_fd_get_inproc_sync, /* get_inproc_sync */ sock_close_handle, /* close_handle */ sock_destroy /* destroy */ }; @@ -7763,7 +7653,7 @@ index 104321b..3fb2e29 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ ifchange_destroy /* destroy */ }; @@ -7779,7 +7669,7 @@ index 104321b..3fb2e29 100644 default_unlink_name, /* unlink_name */ socket_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -7799,7 +7689,7 @@ index c7f3441..4a7cf68 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ }; @@ -7827,7 +7717,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ thread_apc_destroy /* destroy */ }; @@ -7843,7 +7733,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -7855,7 +7745,7 @@ index 2ce94b4..8f603fc 100644 static unsigned int thread_map_access( struct object *obj, unsigned int access ); static void thread_poll_event( struct fd *fd, int event ); static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct fast_sync *thread_get_fast_sync( struct object *obj ); ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); static void destroy_thread( struct object *obj ); static const struct object_ops thread_ops = @@ -7871,7 +7761,7 @@ index 2ce94b4..8f603fc 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_fast_sync, /* get_fast_sync */ ++ thread_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; @@ -7888,8 +7778,8 @@ index 2ce94b4..8f603fc 100644 thread->token = NULL; thread->desc = NULL; thread->desc_len = 0; -+ thread->fast_sync = NULL; -+ thread->fast_alert_event = NULL; ++ thread->inproc_sync = NULL; ++ thread->inproc_alert_event = NULL; - thread->exit_poll = NULL; thread->creation_time = current_time; @@ -7910,14 +7800,14 @@ index 2ce94b4..8f603fc 100644 return &thread->kernel_object; } -+static struct fast_sync *thread_get_fast_sync( struct object *obj ) ++static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) +{ + struct thread *thread = (struct thread *)obj; + -+ if (!thread->fast_sync) -+ thread->fast_sync = fast_create_event( FAST_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->fast_sync) grab_object( thread->fast_sync ); -+ return thread->fast_sync; ++ if (!thread->inproc_sync) ++ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); ++ if (thread->inproc_sync) grab_object( thread->inproc_sync ); ++ return thread->inproc_sync; +} + /* cleanup everything that is no longer needed by a dead thread */ @@ -7930,8 +7820,8 @@ index 2ce94b4..8f603fc 100644 - - if (do_esync()) - close( thread->esync_fd ); -+ if (thread->fast_sync) release_object( thread->fast_sync ); -+ if (thread->fast_alert_event) release_object( thread->fast_alert_event ); ++ if (thread->inproc_sync) release_object( thread->inproc_sync ); ++ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); } /* dump a thread on stdout for debugging purposes */ @@ -7966,8 +7856,8 @@ index 2ce94b4..8f603fc 100644 - if (do_esync() && queue == &thread->user_apc) - esync_wake_fd( thread->esync_apc_fd ); -+ if (apc->call.type == APC_USER && thread->fast_alert_event) -+ set_event( thread->fast_alert_event ); ++ if (apc->call.type == APC_USER && thread->inproc_alert_event) ++ set_event( thread->inproc_alert_event ); } return 1; @@ -7975,8 +7865,8 @@ index 2ce94b4..8f603fc 100644 apc->executed = 1; wake_up( &apc->obj, 0 ); release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); return; } } @@ -7989,8 +7879,8 @@ index 2ce94b4..8f603fc 100644 - if (do_esync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc )) - esync_clear( thread->esync_apc_fd ); -+ if (list_empty( &thread->user_apc ) && thread->fast_alert_event) -+ reset_event( thread->fast_alert_event ); ++ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) ++ reset_event( thread->inproc_alert_event ); + } return apc; } @@ -8028,8 +7918,8 @@ index 2ce94b4..8f603fc 100644 abandon_mutexes( thread ); - if (do_esync()) - esync_abandon_mutexes( thread ); -+ fast_set_event( thread->fast_sync ); + wake_up( &thread->obj, 0 ); ++ set_inproc_event( thread->inproc_sync ); + if (violent_death) send_thread_signal( thread, SIGQUIT ); - if (violent_death) - { @@ -8045,13 +7935,13 @@ index 2ce94b4..8f603fc 100644 release_object( process ); } + -+DECL_HANDLER(get_fast_alert_event) ++DECL_HANDLER(get_inproc_alert_event) +{ -+ if (!current->fast_alert_event) -+ current->fast_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); ++ if (!current->inproc_alert_event) ++ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); + -+ if (current->fast_alert_event) -+ reply->handle = alloc_handle( current->process, current->fast_alert_event, SYNCHRONIZE, 0 ); ++ if (current->inproc_alert_event) ++ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); +} diff --git a/server/thread.h b/server/thread.h index 10e9e28..cb4643a 100644 @@ -8070,8 +7960,8 @@ index 10e9e28..cb4643a 100644 WCHAR *desc; /* thread description string */ struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ - struct timeout_user *exit_poll; /* poll if the thread/process has exited already */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ -+ struct event *fast_alert_event; /* fast synchronization alert event */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ ++ struct event *inproc_alert_event; /* in-process synchronization alert event */ }; extern struct thread *current; @@ -8092,14 +7982,14 @@ index 36645a2..854a8e1 100644 client_ptr_t callback; /* callback APC function */ client_ptr_t arg; /* callback argument */ - int esync_fd; /* esync file descriptor */ -+ struct fast_sync *fast_sync; /* fast synchronization object */ ++ struct inproc_sync *inproc_sync; /* in-process synchronization object */ }; static void timer_dump( struct object *obj, int verbose ); static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); -static int timer_get_esync_fd( struct object *obj, enum esync_type *type ); static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct fast_sync *timer_get_fast_sync( struct object *obj ); ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); static void timer_destroy( struct object *obj ); static const struct object_ops timer_ops = @@ -8115,7 +8005,7 @@ index 36645a2..854a8e1 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_fast_sync, /* get_fast_sync */ ++ timer_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; @@ -8127,7 +8017,7 @@ index 36645a2..854a8e1 100644 - - if (do_esync()) - timer->esync_fd = esync_create_fd( 0, 0 ); -+ timer->fast_sync = NULL; ++ timer->inproc_sync = NULL; } } return timer; @@ -8135,7 +8025,7 @@ index 36645a2..854a8e1 100644 /* wake up waiters */ timer->signaled = 1; wake_up( &timer->obj, 0 ); -+ fast_set_event( timer->fast_sync ); ++ set_inproc_event( timer->inproc_sync ); } /* cancel a running timer */ @@ -8146,7 +8036,7 @@ index 36645a2..854a8e1 100644 - - if (do_esync()) - esync_clear( timer->esync_fd ); -+ fast_reset_event( timer->fast_sync ); ++ reset_inproc_event( timer->inproc_sync ); } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; @@ -8165,19 +8055,19 @@ index 36645a2..854a8e1 100644 } -static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct fast_sync *timer_get_fast_sync( struct object *obj ) ++static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) { struct timer *timer = (struct timer *)obj; - assert( obj->ops == &timer_ops ); - if (!timer->manual) timer->signaled = 0; + -+ if (!timer->fast_sync) ++ if (!timer->inproc_sync) + { -+ enum fast_sync_type type = timer->manual ? FAST_SYNC_MANUAL_SERVER : FAST_SYNC_AUTO_SERVER; -+ timer->fast_sync = fast_create_event( type, timer->signaled ); ++ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; ++ timer->inproc_sync = create_inproc_event( type, timer->signaled ); + } -+ if (timer->fast_sync) grab_object( timer->fast_sync ); -+ return timer->fast_sync; ++ if (timer->inproc_sync) grab_object( timer->inproc_sync ); ++ return timer->inproc_sync; } static void timer_destroy( struct object *obj ) @@ -8186,7 +8076,7 @@ index 36645a2..854a8e1 100644 if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); - if (do_esync()) close( timer->esync_fd ); -+ if (timer->fast_sync) release_object( timer->fast_sync ); ++ if (timer->inproc_sync) release_object( timer->inproc_sync ); } /* create a timer */ @@ -8206,7 +8096,7 @@ index 8b4d2f0..42562fd 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ token_destroy /* destroy */ }; @@ -8214,7 +8104,7 @@ diff --git a/server/request_trace.h b/server/request_trace.h index af96565..c027f4b 100644 --- a/server/request_trace.h +++ b/server/request_trace.h -@@ -4619,67 +4619,56 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req +@@ -4619,67 +4619,54 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req fprintf( stderr, " handle=%04x", req->handle ); } @@ -8257,22 +8147,21 @@ index af96565..c027f4b 100644 } -static void dump_get_esync_fd_request( const struct get_esync_fd_request *req ) -+static void dump_fast_select_queue_request( const struct fast_select_queue_request *req ) ++static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) { - fprintf( stderr, " handle=%04x", req->handle ); +- fprintf( stderr, " handle=%04x", req->handle ); } -static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req ) -+static void dump_fast_unselect_queue_request( const struct fast_unselect_queue_request *req ) ++static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) { - fprintf( stderr, " type=%d", req->type ); - fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, " handle=%04x", req->handle ); + fprintf( stderr, ", signaled=%d", req->signaled ); } -static void dump_esync_msgwait_request( const struct esync_msgwait_request *req ) -+static void dump_get_fast_alert_event_request( const struct get_fast_alert_event_request *req ) ++static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) { - fprintf( stderr, " in_msgwait=%d", req->in_msgwait ); } @@ -8290,7 +8179,7 @@ index af96565..c027f4b 100644 } -static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request *req ) -+static void dump_get_fast_alert_event_reply( const struct get_fast_alert_event_reply *req ) ++static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) { + fprintf( stderr, " handle=%04x", req->handle ); } @@ -8307,9 +8196,9 @@ index af96565..c027f4b 100644 - (dump_func)dump_get_esync_apc_fd_request, + (dump_func)dump_get_linux_sync_device_request, + (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_fast_select_queue_request, -+ (dump_func)dump_fast_unselect_queue_request, -+ (dump_func)dump_get_fast_alert_event_request, ++ (dump_func)dump_select_inproc_queue_request, ++ (dump_func)dump_unselect_inproc_queue_request, ++ (dump_func)dump_get_inproc_alert_event_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -8320,16 +8209,18 @@ index af96565..c027f4b 100644 - (dump_func)dump_create_esync_reply, - (dump_func)dump_open_esync_reply, - (dump_func)dump_get_esync_fd_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, NULL, (dump_func)dump_set_keyboard_repeat_reply, NULL, -+ (dump_func)dump_get_fast_alert_event_reply, ++ (dump_func)dump_get_linux_sync_device_reply, ++ (dump_func)dump_get_linux_sync_obj_reply, ++ NULL, ++ NULL, ++ (dump_func)dump_get_inproc_alert_event_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { -@@ -5549,11 +5538,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = { +@@ -5549,11 +5538,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "suspend_process", "resume_process", "get_next_thread", @@ -8337,13 +8228,13 @@ index af96565..c027f4b 100644 - "open_esync", - "get_esync_fd", - "esync_msgwait", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "fast_select_queue", -+ "fast_unselect_queue", "set_keyboard_repeat", - "get_esync_apc_fd", -+ "get_fast_alert_event", ++ "get_linux_sync_device", ++ "get_linux_sync_obj", ++ "select_inproc_queue", ++ "unselect_inproc_queue", ++ "get_inproc_alert_event", }; static const struct @@ -8363,7 +8254,7 @@ index feac54e..f52e118 100644 NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ no_close_handle, /* close_handle */ window_destroy /* destroy */ }; @@ -8383,7 +8274,7 @@ index 4ef21d9..2719c9e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -8399,7 +8290,75 @@ index 4ef21d9..2719c9e 100644 default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_fast_sync, /* get_fast_sync */ ++ no_get_inproc_sync, /* get_inproc_sync */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; +--- a/server/queue.c 2024-12-20 20:01:39.879368500 +0500 ++++ b/server/queue.c 2024-12-20 20:03:11.782212833 +0500 +@@ -4252,23 +4252,6 @@ + } + } + +-DECL_HANDLER(esync_msgwait) +-{ +- struct msg_queue *queue = get_current_queue(); +- const queue_shm_t *queue_shm; +- +- if (!queue) return; +- queue_shm = queue->shared; +- queue->esync_in_msgwait = req->in_msgwait; +- +- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) +- set_event( current->process->idle_event ); +- +- /* and start/stop waiting on the driver */ +- if (queue->fd) +- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); +-} +- + DECL_HANDLER(set_keyboard_repeat) + { + struct desktop *desktop; +@@ -4288,3 +4271,41 @@ + release_object( desktop ); + } + ++DECL_HANDLER(select_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ check_thread_queue_idle( current ); ++ ++ if (queue->fd) ++ set_fd_events( queue->fd, POLLIN ); ++ ++ queue->in_inproc_wait = 1; ++ } ++} ++ ++DECL_HANDLER(unselect_inproc_queue) ++{ ++ struct msg_queue *queue = current->queue; ++ ++ if (!queue->in_inproc_wait) ++ { ++ set_error( STATUS_ACCESS_DENIED ); ++ } ++ else ++ { ++ if (queue->fd) ++ set_fd_events( queue->fd, 0 ); ++ ++ if (req->signaled) ++ msg_queue_satisfied( &queue->obj, NULL ); ++ ++ queue->in_inproc_wait = 0; ++ } ++} diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-mainline.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-mainline.patch deleted file mode 100644 index 8fb2b81dc..000000000 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-mainline.patch +++ /dev/null @@ -1,4447 +0,0 @@ -From 0b446d37ae366bf9921bc7f99f313ffe1a7530b2 Mon Sep 17 00:00:00 2001 -From: Kirill Artemev -Date: Fri, 20 Dec 2024 21:54:47 +0500 -Subject: [PATCH] ntsync7-mainline - -Signed-off-by: Kirill Artemev ---- - configure | 6 + - configure.ac | 1 + - dlls/kernel32/tests/sync.c | 79 +++ - dlls/ntdll/unix/file.c | 2 +- - dlls/ntdll/unix/process.c | 2 +- - dlls/ntdll/unix/server.c | 28 +- - dlls/ntdll/unix/sync.c | 1007 +++++++++++++++++++++++++++++- - dlls/ntdll/unix/thread.c | 2 +- - dlls/ntdll/unix/unix_private.h | 9 +- - dlls/ntdll/unix/virtual.c | 1 + - dlls/webservices/tests/channel.c | 3 + - include/config.h.in | 3 + - include/wine/server_protocol.h | 97 ++- - server/Makefile.in | 1 + - server/async.c | 2 + - server/atom.c | 1 + - server/change.c | 1 + - server/clipboard.c | 1 + - server/completion.c | 25 +- - server/console.c | 85 ++- - server/debugger.c | 23 + - server/device.c | 33 +- - server/directory.c | 2 + - server/event.c | 53 +- - server/fd.c | 31 +- - server/file.c | 1 + - server/file.h | 1 + - server/handle.c | 1 + - server/hook.c | 1 + - server/inproc_sync.c | 437 +++++++++++++ - server/mailslot.c | 4 + - server/mapping.c | 3 + - server/mutex.c | 39 +- - server/named_pipe.c | 6 + - server/object.c | 8 + - server/object.h | 14 + - server/process.c | 34 + - server/process.h | 1 + - server/protocol.def | 47 ++ - server/queue.c | 88 ++- - server/registry.c | 1 + - server/request.c | 1 + - server/request_handlers.h | 25 + - server/request_trace.h | 54 ++ - server/semaphore.c | 24 +- - server/serial.c | 1 + - server/signal.c | 1 + - server/sock.c | 3 + - server/symlink.c | 1 + - server/thread.c | 38 ++ - server/thread.h | 2 + - server/timer.c | 38 +- - server/token.c | 1 + - server/window.c | 1 + - server/winstation.c | 2 + - 55 files changed, 2343 insertions(+), 33 deletions(-) - create mode 100644 server/inproc_sync.c - -diff --git a/configure b/configure -index beba1346b6a..da17410a661 100755 ---- a/configure -+++ b/configure -@@ -7734,6 +7734,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes - then : - printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h - -+fi -+ac_fn_c_check_header_compile "$LINENO" "linux/ntsync.h" "ac_cv_header_linux_ntsync_h" "$ac_includes_default" -+if test "x$ac_cv_header_linux_ntsync_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_LINUX_NTSYNC_H 1" >>confdefs.h -+ - fi - ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" - if test "x$ac_cv_header_linux_param_h" = xyes -diff --git a/configure.ac b/configure.ac -index 6596f653fb1..c3f925a55a5 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -383,6 +383,7 @@ AC_CHECK_HEADERS(\ - linux/input.h \ - linux/ioctl.h \ - linux/major.h \ -+ linux/ntsync.h \ - linux/param.h \ - linux/serial.h \ - linux/types.h \ -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 49420e4519f..2c69073db10 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -2904,6 +2904,84 @@ static void test_QueueUserAPC(void) - ok(apc_count == 1, "APC count %u\n", apc_count); - } - -+static int zigzag_state, zigzag_count[2], zigzag_stop; -+ -+static DWORD CALLBACK zigzag_event0(void *arg) -+{ -+ HANDLE *events = arg; -+ -+ while (!zigzag_stop) -+ { -+ WaitForSingleObject(events[0], INFINITE); -+ ResetEvent(events[0]); -+ ok(zigzag_state == 0, "got wrong state %d\n", zigzag_state); -+ zigzag_state++; -+ SetEvent(events[1]); -+ zigzag_count[0]++; -+ } -+ trace("thread 0 got done\n"); -+ return 0; -+} -+ -+static DWORD CALLBACK zigzag_event1(void *arg) -+{ -+ HANDLE *events = arg; -+ -+ while (!zigzag_stop) -+ { -+ WaitForSingleObject(events[1], INFINITE); -+ ResetEvent(events[1]); -+ ok(zigzag_state == 1, "got wrong state %d\n", zigzag_state); -+ zigzag_state--; -+ SetEvent(events[0]); -+ zigzag_count[1]++; -+ } -+ trace("thread 1 got done\n"); -+ return 0; -+} -+ -+static void test_zigzag_event(void) -+{ -+ /* The basic idea is to test SetEvent/Wait back and forth between two -+ * threads. Each thread clears their own event, sets some common data, -+ * signals the other's, then waits on their own. We make sure the common -+ * data is always in the right state. We also print performance data. */ -+ -+ HANDLE threads[2], events[2]; -+ BOOL ret; -+ -+ events[0] = CreateEventA(NULL, FALSE, FALSE, NULL); -+ events[1] = CreateEventA(NULL, FALSE, FALSE, NULL); -+ -+ threads[0] = CreateThread(NULL, 0, zigzag_event0, events, 0, NULL); -+ threads[1] = CreateThread(NULL, 0, zigzag_event1, events, 0, NULL); -+ -+ zigzag_state = 0; -+ zigzag_count[0] = zigzag_count[1] = 0; -+ zigzag_stop = 0; -+ -+ trace("starting zigzag test (events)\n"); -+ SetEvent(events[0]); -+ Sleep(2000); -+ zigzag_stop = 1; -+ ret = WaitForMultipleObjects(2, threads, FALSE, INFINITE); -+ trace("%d\n", ret); -+ ok(ret == 0 || ret == 1, "wait failed: %u\n", ret); -+ -+ ok(zigzag_count[0] == zigzag_count[1] || zigzag_count[0] == zigzag_count[1] + 1, -+ "count did not match: %d != %d\n", zigzag_count[0], zigzag_count[1]); -+ -+ /* signal the other thread to finish, if it didn't already -+ * (in theory they both would at the same time, but there's a slight race on teardown if we get -+ * thread 1 SetEvent -> thread 0 ResetEvent -> thread 0 Wait -> thread 1 exits */ -+ zigzag_state = 1-ret; -+ SetEvent(events[1-ret]); -+ ret = WaitForSingleObject(threads[1-ret], 1000); -+ ok(!ret, "wait failed: %u\n", ret); -+ -+ trace("count: %d\n", zigzag_count[0]); -+} -+ - START_TEST(sync) - { - char **argv; -@@ -2974,5 +3052,6 @@ START_TEST(sync) - test_srwlock_example(); - test_alertable_wait(); - test_apc_deadlock(); -+ test_zigzag_event(); - test_crit_section(); - } -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 8bc69557057..755a6e844a4 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -6451,7 +6451,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void - } - if (handle) - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - NtClose( handle ); - } - else /* Unix lock conflict, sleep a bit and retry */ -diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index c3a730379a4..db4d096acd1 100644 ---- a/dlls/ntdll/unix/process.c -+++ b/dlls/ntdll/unix/process.c -@@ -920,7 +920,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ - - /* wait for the new process info to be ready */ - -- NtWaitForSingleObject( process_info, FALSE, NULL ); -+ server_wait_for_object( process_info, FALSE, NULL ); - SERVER_START_REQ( get_new_process_info ) - { - req->info = wine_server_obj_handle( process_info ); -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index b40e7c2a1d7..3579e4f454d 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */ - static int fd_socket = -1; /* socket to exchange file descriptors with the server */ - static int initial_cwd = -1; - static pid_t server_pid; --static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER; -+pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER; - - /* atomically exchange a 64-bit value */ - static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val ) -@@ -789,6 +789,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI - } - - -+/* helper function to perform a server-side wait on an internal handle without -+ * using the fast synchronization path */ -+unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ) -+{ -+ union select_op select_op; -+ UINT flags = SELECT_INTERRUPTIBLE; -+ -+ if (alertable) flags |= SELECT_ALERTABLE; -+ -+ select_op.wait.op = SELECT_WAIT; -+ select_op.wait.handles[0] = wine_server_obj_handle( handle ); -+ return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); -+} -+ -+ - /*********************************************************************** - * NtContinue (NTDLL.@) - */ -@@ -865,7 +880,7 @@ unsigned int server_queue_process_apc( HANDLE process, const union apc_call *cal - } - else - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - - SERVER_START_REQ( get_apc_result ) - { -@@ -1793,12 +1808,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE - return result.dup_handle.status; - } - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - if (options & DUPLICATE_CLOSE_SOURCE) -+ { - fd = remove_fd_from_cache( source ); -+ close_inproc_sync_obj( source ); -+ } - - SERVER_START_REQ( dup_handle ) - { -@@ -1864,12 +1884,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) - if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) - return STATUS_SUCCESS; - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - fd = remove_fd_from_cache( handle ); - -+ close_inproc_sync_obj( handle ); -+ - SERVER_START_REQ( close_handle ) - { - req->handle = wine_server_obj_handle( handle ); -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index d486b50001d..c3203debc0b 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -30,9 +30,11 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #ifdef HAVE_SYS_SYSCALL_H - #include -@@ -48,6 +50,7 @@ - #endif - #include - #include -+#include - #include - #include - #include -@@ -57,6 +60,9 @@ - #ifdef HAVE_KQUEUE - # include - #endif -+#ifdef HAVE_LINUX_NTSYNC_H -+# include -+#endif - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -74,9 +80,11 @@ HANDLE keyed_event = 0; - static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - { - if (!timeout) return "(infinite)"; -- return wine_dbgstr_longlong( timeout->QuadPart ); -+ return wine_dbg_sprintf( "%lld.%07ld", (long long)(timeout->QuadPart / TICKSPERSEC), -+ (long)(timeout->QuadPart % TICKSPERSEC) ); - } - -+ - /* return a monotonic time counter, in Win32 ticks */ - static inline ULONGLONG monotonic_counter(void) - { -@@ -301,6 +309,901 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at - } - - -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+static int get_linux_sync_device(void) -+{ -+ static LONG device = -2; -+ -+ if (device == -2) -+ { -+ HANDLE handle; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ SERVER_START_REQ( get_linux_sync_device ) -+ { -+ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if (!ret) -+ { -+ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) -+ { -+ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) -+ { -+ /* someone beat us to it */ -+ if (needs_close) close( fd ); -+ NtClose( handle ); -+ } -+ /* otherwise don't close the device */ -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ NtClose( handle ); -+ } -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ } -+ } -+ return device; -+} -+ -+/* It's possible for synchronization primitives to remain alive even after being -+ * closed, because a thread is still waiting on them. It's rare in practice, and -+ * documented as being undefined behaviour by Microsoft, but it works, and some -+ * applications rely on it. This means we need to refcount handles, and defer -+ * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the in-process synchronization -+ * object, as well as a private refcount. When the client refcount reaches zero, -+ * it closes the handle; when all handles are closed, the server deletes the -+ * in-process synchronization object. -+ * -+ * We also need this for signal-and-wait. The signal and wait operations aren't -+ * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE -+ * for the wait—we need to either do both operations or neither. That means we -+ * need to grab references to both objects, and prevent them from being -+ * destroyed before we're done with them. -+ * -+ * We want lookup of objects from the cache to be very fast; ideally, it should -+ * be lock-free. We achieve this by using atomic modifications to "refcount", -+ * and guaranteeing that all other fields are valid and correct *as long as* -+ * refcount is nonzero, and we store the entire structure in memory which will -+ * never be freed. -+ * -+ * This means that acquiring the object can't use a simple atomic increment; it -+ * has to use a compare-and-swap loop to ensure that it doesn't try to increment -+ * an object with a zero refcount. That's still leagues better than a real lock, -+ * though, and release can be a single atomic decrement. -+ * -+ * It also means that threads modifying the cache need to take a lock, to -+ * prevent other threads from writing to it concurrently. -+ * -+ * It's possible for an object currently in use (by a waiter) to be closed and -+ * the same handle immediately reallocated to a different object. This should be -+ * a very rare situation, and in that case we simply don't cache the handle. -+ */ -+struct inproc_sync_cache_entry -+{ -+ LONG refcount; -+ int fd; -+ enum inproc_sync_type type; -+ unsigned int access; -+ BOOL closed; -+ /* handle to the underlying in-process sync object, stored as obj_handle_t -+ * to save space */ -+ obj_handle_t handle; -+}; -+ -+ -+static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) -+{ -+ /* save the handle and fd now; as soon as the refcount hits 0 we cannot -+ * access the cache anymore */ -+ HANDLE handle = wine_server_ptr_handle( cache->handle ); -+ int fd = cache->fd; -+ LONG refcount = InterlockedDecrement( &cache->refcount ); -+ -+ assert( refcount >= 0 ); -+ -+ if (!refcount) -+ { -+ NTSTATUS ret; -+ -+ /* we can't call NtClose here as we may be inside fd_cache_mutex */ -+ SERVER_START_REQ( close_handle ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ ret = wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+ -+ assert( !ret ); -+ close( fd ); -+ } -+} -+ -+ -+#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) -+#define INPROC_SYNC_CACHE_ENTRIES 128 -+ -+static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; -+static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; -+ -+static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) -+{ -+ unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; -+ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; -+} -+ -+ -+static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, -+ enum inproc_sync_type type, unsigned int access ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ sigset_t sigset; -+ int refcount; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES) -+ { -+ FIXME( "too many allocated handles, not caching %p\n", handle ); -+ return NULL; -+ } -+ -+ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ -+ { -+ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; -+ else -+ { -+ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); -+ void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); -+ if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) -+ munmap( ptr, size ); /* someone beat us to it */ -+ } -+ } -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same -+ * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_inproc_sync_obj() and close_handle. */ -+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) -+ { -+ /* We lost the race with another thread trying to cache this object, or -+ * the handle is currently being used for another object (i.e. it was -+ * closed and then reused). We have no way of knowing which, and in the -+ * latter case we can't cache this object until the old one is -+ * completely destroyed, so always return failure. */ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ return NULL; -+ } -+ -+ cache->handle = inproc_sync; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. -+ * Set the refcount to 2 (one for the handle, one for the caller). */ -+ refcount = InterlockedExchange( &cache->refcount, 2 ); -+ assert( !refcount ); -+ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ return cache; -+} -+ -+ -+/* returns the previous value */ -+static inline LONG interlocked_inc_if_nonzero( LONG *dest ) -+{ -+ LONG val, tmp; -+ for (val = *dest;; val = tmp) -+ { -+ if (!val || (tmp = InterlockedCompareExchange( dest, val + 1, val )) == val) -+ break; -+ } -+ return val; -+} -+ -+ -+static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) -+ return NULL; -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* this load needs acquire semantics [paired with the store in -+ * cache_inproc_sync_obj()] */ -+ if (!interlocked_inc_if_nonzero( &cache->refcount )) -+ return NULL; -+ -+ if (cache->closed) -+ { -+ /* The object is still being used, but "handle" has been closed. The -+ * handle value might have been reused for another object in the -+ * meantime, in which case we have to report that valid object, so -+ * force the caller to check the server. */ -+ release_inproc_sync_obj( cache ); -+ return NULL; -+ } -+ -+ return cache; -+} -+ -+ -+static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) -+{ -+ if (a == b) return TRUE; -+ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ return FALSE; -+} -+ -+ -+/* returns a pointer to a cache entry; if the object could not be cached, -+ * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, -+ ACCESS_MASK desired_access, -+ struct inproc_sync_cache_entry *stack_cache, -+ struct inproc_sync_cache_entry **ret_cache ) -+{ -+ struct inproc_sync_cache_entry *cache; -+ obj_handle_t inproc_sync_handle; -+ enum inproc_sync_type type; -+ unsigned int access; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ /* try to find it in the cache already */ -+ if ((cache = get_cached_inproc_sync_obj( handle ))) -+ { -+ *ret_cache = cache; -+ return STATUS_SUCCESS; -+ } -+ -+ /* try to retrieve it from the server */ -+ SERVER_START_REQ( get_linux_sync_obj ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ if (!(ret = wine_server_call( req ))) -+ { -+ inproc_sync_handle = reply->handle; -+ access = reply->access; -+ type = reply->type; -+ } -+ } -+ SERVER_END_REQ; -+ -+ if (ret) return ret; -+ -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), -+ 0, &fd, &needs_close, NULL, NULL ))) -+ return ret; -+ -+ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); -+ if (!cache) -+ { -+ cache = stack_cache; -+ cache->handle = inproc_sync_handle; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ cache->refcount = 1; -+ } -+ -+ *ret_cache = cache; -+ -+ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((cache->access & desired_access) != desired_access) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ -+ return STATUS_SUCCESS; -+} -+ -+ -+/* caller must hold fd_cache_mutex */ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); -+ -+ if (cache) -+ { -+ cache->closed = TRUE; -+ /* once for the reference we just grabbed, and once for the handle */ -+ release_inproc_sync_obj( cache ); -+ release_inproc_sync_obj( cache ); -+ } -+} -+ -+ -+static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count ) -+{ -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_semaphore_obj( int obj, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_sem_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->CurrentCount = args.count; -+ info->MaximumCount = args.max; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_semaphore_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_set_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_SET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_set_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_reset_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_RESET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_reset_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_pulse_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_PULSE, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_pulse_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_event_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; -+ info->EventState = args.signaled; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_event_obj( cache->fd, cache->type, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_release_mutex_obj( int obj, LONG *prev_count ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ args.owner = GetCurrentThreadId(); -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_UNLOCK, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_MUTANT_LIMIT_EXCEEDED; -+ else if (errno == EPERM) -+ return STATUS_MUTANT_NOT_OWNED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_mutex_obj( cache->fd, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_READ, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOWNERDEAD) -+ { -+ info->AbandonedState = TRUE; -+ info->OwnedByCaller = FALSE; -+ info->CurrentCount = 1; -+ return STATUS_SUCCESS; -+ } -+ else -+ return errno_to_status( errno ); -+ } -+ info->AbandonedState = FALSE; -+ info->OwnedByCaller = (args.owner == GetCurrentThreadId()); -+ info->CurrentCount = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_mutex_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+static void select_queue(void) -+{ -+ SERVER_START_REQ( select_inproc_queue ) -+ { -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static void unselect_queue( BOOL signaled ) -+{ -+ SERVER_START_REQ( unselect_inproc_queue ) -+ { -+ req->signaled = signaled; -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static int get_inproc_alert_obj(void) -+{ -+ struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ HANDLE alert_handle; -+ unsigned int ret; -+ -+ if (data->linux_alert_obj == -1) -+ { -+ SERVER_START_REQ( get_inproc_alert_event ) -+ { -+ if ((ret = wine_server_call( req ))) -+ ERR( "failed to get inproc alert event, status %#x\n", ret ); -+ alert_handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get inproc alert obj, status %#x\n", ret ); -+ data->linux_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. -+ * Manhandling the cache entry here is fine since we're the only thread -+ * that can access our own alert event. */ -+ cache->fd = -1; -+ release_inproc_sync_obj( cache ); -+ NtClose( alert_handle ); -+ } -+ -+ return data->linux_alert_obj; -+} -+ -+static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, -+ BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct ntsync_wait_args args = {0}; -+ unsigned long request; -+ struct timespec now; -+ int ret; -+ -+ if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) -+ { -+ args.timeout = ~(__u64)0; -+ } -+ else if (timeout->QuadPart <= 0) -+ { -+ clock_gettime( CLOCK_MONOTONIC, &now ); -+ args.timeout = (now.tv_sec * NSECPERSEC) + now.tv_nsec + (-timeout->QuadPart * 100); -+ } -+ else -+ { -+ args.timeout = (timeout->QuadPart * 100) - (SECS_1601_TO_1970 * NSECPERSEC); -+ args.flags |= NTSYNC_WAIT_REALTIME; -+ } -+ -+ args.objs = (uintptr_t)objs; -+ args.count = count; -+ args.owner = GetCurrentThreadId(); -+ args.index = ~0u; -+ -+ if (alertable) -+ args.alert = get_inproc_alert_obj(); -+ -+ if (wait_any || count == 1) -+ request = NTSYNC_IOC_WAIT_ANY; -+ else -+ request = NTSYNC_IOC_WAIT_ALL; -+ -+ do -+ { -+ ret = ioctl( device, request, &args ); -+ } while (ret < 0 && errno == EINTR); -+ -+ if (!ret) -+ { -+ if (args.index == count) -+ { -+ static const LARGE_INTEGER timeout; -+ -+ ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &timeout ); -+ assert( ret == STATUS_USER_APC ); -+ return ret; -+ } -+ -+ return wait_any ? args.index : 0; -+ } -+ else if (errno == EOWNERDEAD) -+ return STATUS_ABANDONED + (wait_any ? args.index : 0); -+ else if (errno == ETIMEDOUT) -+ return STATUS_TIMEOUT; -+ else -+ return errno_to_status( errno ); -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; -+ int device, objs[64]; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ DWORD i, j; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ for (i = 0; i < count; ++i) -+ { -+ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) -+ { -+ for (j = 0; j < i; ++j) -+ release_inproc_sync_obj( cache[j] ); -+ return ret; -+ } -+ if (cache[i]->type == INPROC_SYNC_QUEUE) -+ queue = handles[i]; -+ -+ objs[i] = cache[i]->fd; -+ } -+ -+ /* It's common to wait on the message queue alone. Some applications wait -+ * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through inproc_wait(), and since we only need -+ * to go through that path if we're waiting on other objects, just delegate -+ * to the server if we're only waiting on the message queue. */ -+ if (count == 1 && queue) -+ { -+ release_inproc_sync_obj( cache[0] ); -+ return server_wait_for_object( handles[0], alertable, timeout ); -+ } -+ -+ if (queue) select_queue(); -+ -+ ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); -+ -+ if (queue) unselect_queue( handles[ret] == queue ); -+ -+ for (i = 0; i < count; ++i) -+ release_inproc_sync_obj( cache[i] ); -+ -+ return ret; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ int device; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) -+ return ret; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ if (!(signal_cache->access & EVENT_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ break; -+ -+ default: -+ /* can't be signaled */ -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return ret; -+ } -+ -+ if (wait_cache->type == INPROC_SYNC_QUEUE) -+ queue = wait; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ ret = linux_set_event_obj( signal_cache->fd, NULL ); -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ ret = linux_release_mutex_obj( signal_cache->fd, NULL ); -+ break; -+ -+ default: -+ assert( 0 ); -+ break; -+ } -+ -+ if (!ret) -+ { -+ if (queue) select_queue(); -+ ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( !ret ); -+ } -+ -+ release_inproc_sync_obj( signal_cache ); -+ release_inproc_sync_obj( wait_cache ); -+ return ret; -+} -+ -+#else -+ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+} -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+#endif -+ -+ - /****************************************************************************** - * NtCreateSemaphore (NTDLL.@) - */ -@@ -311,6 +1214,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, initial %d, max %d\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)initial, (int)max ); -+ - *handle = 0; - if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -338,6 +1244,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -375,6 +1283,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - - if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -397,6 +1311,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous - { - unsigned int ret; - -+ TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); -+ -+ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( release_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -421,6 +1340,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u, state %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type, state ); -+ - *handle = 0; - if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -448,6 +1370,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -473,6 +1397,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -492,6 +1421,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -521,6 +1455,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -552,6 +1491,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, - - if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_event ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -577,6 +1522,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, owned %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", owned ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -602,6 +1550,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -627,6 +1577,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_count %p\n", handle, prev_count ); -+ -+ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( release_mutex ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -657,6 +1612,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, - - if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_mutex ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1426,6 +2387,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type ); -+ - *handle = 0; - if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1453,6 +2417,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1506,6 +2472,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) - { - unsigned int ret; - -+ TRACE( "handle %p, state %p\n", handle, state ); -+ - SERVER_START_REQ( cancel_timer ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1574,13 +2542,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO - { - union select_op select_op; - UINT i, flags = SELECT_INTERRUPTIBLE; -+ unsigned int ret; - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - -+ if (TRACE_ON(sync)) -+ { -+ TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); -+ for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); -+ TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); -+ } -+ -+ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ { -+ TRACE( "-> %#x\n", ret ); -+ return ret; -+ } -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; - for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); -- return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - -@@ -1601,9 +2585,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, - { - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS ret; -+ -+ TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) ); - - if (!signal) return STATUS_INVALID_HANDLE; - -+ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; - select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1836,6 +2826,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, flags %#x\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)flags ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -1860,6 +2853,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1886,6 +2881,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -1905,6 +2902,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -2049,7 +3048,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * - } - SERVER_END_REQ; - if (status != STATUS_PENDING) return status; -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) return status; - -@@ -2111,7 +3110,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM - assert( status == STATUS_USER_APC ); - goto done; - } -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) goto done; - -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index cec6b3cb106..74b4eb9673a 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -1801,7 +1801,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma - - if (ret == STATUS_PENDING) - { -- NtWaitForSingleObject( context_handle, FALSE, NULL ); -+ server_wait_for_object( context_handle, FALSE, NULL ); - - SERVER_START_REQ( get_thread_context ) - { -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index f840045f841..8201e2934f3 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -112,6 +112,7 @@ struct ntdll_thread_data - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ - void *jmp_buf; /* setjmp buffer for exception handling */ -+ int linux_alert_obj; /* fd for the linux in-process alert event */ - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -205,6 +206,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); - extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); - extern void start_server( BOOL debug ); - -+extern pthread_mutex_t fd_cache_mutex; -+ - extern unsigned int server_call_unlocked( void *req_ptr ); - extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); - extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -212,6 +215,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t - timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags, - const LARGE_INTEGER *timeout ); -+extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); - extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, - union apc_result *result ); - extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -378,6 +382,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); - - extern void dbg_init(void); - -+extern void close_inproc_sync_obj( HANDLE handle ); -+ - extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - PNTAPCFUNC func, NTSTATUS status ); - extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -386,6 +392,7 @@ extern void call_raise_user_exception_dispatcher(void); - #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ - - #define TICKSPERSEC 10000000 -+#define NSECPERSEC 1000000000 - #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) - - static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -451,7 +458,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio - - static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) - { -- return NtWaitForSingleObject( handle, alertable, NULL ); -+ return server_wait_for_object( handle, alertable, NULL ); - } - - static inline BOOL in_wow64_call(void) -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 0c0a12c394d..7567362a542 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3689,6 +3689,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ thread_data->linux_alert_obj = -1; - list_add_head( &teb_list, &thread_data->entry ); - return teb; - } -diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027fb86d..ddcf8964f23 100644 ---- a/dlls/webservices/tests/channel.c -+++ b/dlls/webservices/tests/channel.c -@@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { - static const char send_record_middle[] = { 0x01, 0x56, 0x0e, 0x42 }; - static const char send_record_end[] = { 0x08, 0x02, 0x6e, 0x73, 0x89, 0xff, 0x01, 0x01 }; - -+#pragma GCC diagnostic ignored "-Warray-bounds" -+#pragma GCC diagnostic ignored "-Wstringop-overflow" -+ - static BOOL send_dict_str( int sock, char *addr, const char *str, int dict_str_count ) - { - char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; -diff --git a/include/config.h.in b/include/config.h.in -index 6033d8674f3..7fb12090dfe 100644 ---- a/include/config.h.in -+++ b/include/config.h.in -@@ -189,6 +189,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_MAJOR_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_NTSYNC_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_PARAM_H - -diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index f524a3dc8b5..a6c74fa79e0 100644 ---- a/include/wine/server_protocol.h -+++ b/include/wine/server_protocol.h -@@ -5881,6 +5881,86 @@ struct set_keyboard_repeat_reply - }; - - -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+ -+struct get_linux_sync_device_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_linux_sync_device_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ -+ -+struct get_linux_sync_obj_request -+{ -+ struct request_header __header; -+ obj_handle_t handle; -+}; -+struct get_linux_sync_obj_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ int type; -+ unsigned int access; -+ char __pad_20[4]; -+}; -+ -+ -+ -+struct select_inproc_queue_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct select_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct unselect_inproc_queue_request -+{ -+ struct request_header __header; -+ int signaled; -+}; -+struct unselect_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct get_inproc_alert_event_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_inproc_alert_event_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ - enum request - { - REQ_new_process, -@@ -6175,6 +6255,11 @@ enum request - REQ_resume_process, - REQ_get_next_thread, - REQ_set_keyboard_repeat, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_select_inproc_queue, -+ REQ_unselect_inproc_queue, -+ REQ_get_inproc_alert_event, - REQ_NB_REQUESTS - }; - -@@ -6474,6 +6559,11 @@ union generic_request - struct resume_process_request resume_process_request; - struct get_next_thread_request get_next_thread_request; - struct set_keyboard_repeat_request set_keyboard_repeat_request; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct select_inproc_queue_request select_inproc_queue_request; -+ struct unselect_inproc_queue_request unselect_inproc_queue_request; -+ struct get_inproc_alert_event_request get_inproc_alert_event_request; - }; - union generic_reply - { -@@ -6771,8 +6861,13 @@ union generic_reply - struct resume_process_reply resume_process_reply; - struct get_next_thread_reply get_next_thread_reply; - struct set_keyboard_repeat_reply set_keyboard_repeat_reply; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct select_inproc_queue_reply select_inproc_queue_reply; -+ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; -+ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; - }; - --#define SERVER_PROTOCOL_VERSION 854 -+#define SERVER_PROTOCOL_VERSION 855 - - #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ -diff --git a/server/Makefile.in b/server/Makefile.in -index 7e571ac2ba6..91ec73dabc5 100644 ---- a/server/Makefile.in -+++ b/server/Makefile.in -@@ -16,6 +16,7 @@ SOURCES = \ - file.c \ - handle.c \ - hook.c \ -+ inproc_sync.c \ - mach.c \ - mailslot.c \ - main.c \ -diff --git a/server/async.c b/server/async.c -index d2d929c9709..e8b50a72f7e 100644 ---- a/server/async.c -+++ b/server/async.c -@@ -90,6 +90,7 @@ static const struct object_ops async_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - async_destroy /* destroy */ - }; -@@ -710,6 +711,7 @@ static const struct object_ops iosb_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - iosb_destroy /* destroy */ - }; -diff --git a/server/atom.c b/server/atom.c -index ff0799f5880..04951e628ba 100644 ---- a/server/atom.c -+++ b/server/atom.c -@@ -91,6 +91,7 @@ static const struct object_ops atom_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - atom_table_destroy /* destroy */ - }; -diff --git a/server/change.c b/server/change.c -index f42ce066340..92d321c8784 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -124,6 +124,7 @@ static const struct object_ops dir_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - dir_close_handle, /* close_handle */ - dir_destroy /* destroy */ - }; -diff --git a/server/clipboard.c b/server/clipboard.c -index 91f159bc7c9..a2258ae869d 100644 ---- a/server/clipboard.c -+++ b/server/clipboard.c -@@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - clipboard_destroy /* destroy */ - }; -diff --git a/server/completion.c b/server/completion.c -index 99680ae0680..529ed9d7956 100644 ---- a/server/completion.c -+++ b/server/completion.c -@@ -77,6 +77,7 @@ struct completion - struct list wait_queue; - unsigned int depth; - int closed; -+ struct inproc_sync *inproc_sync; - }; - - static void completion_wait_dump( struct object*, int ); -@@ -104,6 +105,7 @@ static const struct object_ops completion_wait_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - completion_wait_destroy /* destroy */ - }; -@@ -156,6 +158,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent - static void completion_dump( struct object*, int ); - static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); - static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); - static void completion_destroy( struct object * ); - - static const struct object_ops completion_ops = -@@ -178,6 +181,7 @@ static const struct object_ops completion_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_inproc_sync,/* get_inproc_sync */ - completion_close_handle, /* close_handle */ - completion_destroy /* destroy */ - }; -@@ -191,6 +195,7 @@ static void completion_destroy( struct object *obj) - { - free( tmp ); - } -+ if (completion->inproc_sync) release_object( completion->inproc_sync ); - } - - static void completion_dump( struct object *obj, int verbose ) -@@ -228,6 +233,7 @@ static int completion_close_handle( struct object *obj, struct process *process, - } - completion->closed = 1; - wake_up( obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); - return 1; - } - -@@ -261,6 +267,16 @@ static struct completion_wait *create_completion_wait( struct thread *thread ) - return wait; - } - -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) -+{ -+ struct completion *completion = (struct completion *)obj; -+ -+ if (!completion->inproc_sync) -+ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->inproc_sync) grab_object( completion->inproc_sync ); -+ return completion->inproc_sync; -+} -+ - static struct completion *create_completion( struct object *root, const struct unicode_str *name, - unsigned int attr, unsigned int concurrent, - const struct security_descriptor *sd ) -@@ -275,6 +291,7 @@ static struct completion *create_completion( struct object *root, const struct u - list_init( &completion->wait_queue ); - completion->depth = 0; - completion->closed = 0; -+ completion->inproc_sync = NULL; - } - } - -@@ -307,7 +324,11 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ - wake_up( &wait->obj, 1 ); - if (list_empty( &completion->queue )) return; - } -- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ if (!list_empty( &completion->queue )) -+ { -+ wake_up( &completion->obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); -+ } - } - - /* create a completion */ -@@ -408,6 +429,8 @@ DECL_HANDLER(remove_completion) - reply->information = msg->information; - free( msg ); - reply->wait_handle = 0; -+ if (list_empty( &completion->queue )) -+ reset_inproc_event( completion->inproc_sync ); - } - - release_object( completion ); -diff --git a/server/console.c b/server/console.c -index c3e7bf57e92..b4058f2d002 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -61,6 +61,7 @@ struct console - struct fd *fd; /* for bare console, attached input fd */ - struct async_queue ioctl_q; /* ioctl queue */ - struct async_queue read_q; /* read queue */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_dump( struct object *obj, int verbose ); -@@ -72,6 +73,7 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st - static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); - static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_ops = - { -@@ -93,6 +95,7 @@ static const struct object_ops console_ops = - NULL, /* unlink_name */ - console_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_destroy /* destroy */ - }; -@@ -139,6 +142,7 @@ struct console_server - unsigned int once_input : 1; /* flag if input thread has already been requested */ - int term_fd; /* UNIX terminal fd */ - struct termios termios; /* original termios */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_server_dump( struct object *obj, int verbose ); -@@ -149,6 +153,7 @@ static struct object *console_server_lookup_name( struct object *obj, struct uni - unsigned int attr, struct object *root ); - static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_server_ops = - { -@@ -170,6 +175,7 @@ static const struct object_ops console_server_ops = - NULL, /* unlink_name */ - console_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_server_destroy /* destroy */ - }; -@@ -218,6 +224,7 @@ static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *screen_buffer_get_fd( struct object *obj ); - static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); - - static const struct object_ops screen_buffer_ops = - { -@@ -239,6 +246,7 @@ static const struct object_ops screen_buffer_ops = - NULL, /* unlink_name */ - screen_buffer_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - screen_buffer_destroy /* destroy */ - }; -@@ -288,6 +296,7 @@ static const struct object_ops console_device_ops = - default_unlink_name, /* unlink_name */ - console_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -303,6 +312,7 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - unsigned int sharing, unsigned int options ); - static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); - static struct fd *console_input_get_fd( struct object *obj ); -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); - static void console_input_destroy( struct object *obj ); - - static const struct object_ops console_input_ops = -@@ -325,6 +335,7 @@ static const struct object_ops console_input_ops = - default_unlink_name, /* unlink_name */ - console_input_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_input_destroy /* destroy */ - }; -@@ -360,6 +371,7 @@ static int console_output_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *console_output_get_fd( struct object *obj ); - static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); - static void console_output_destroy( struct object *obj ); - - static const struct object_ops console_output_ops = -@@ -382,6 +394,7 @@ static const struct object_ops console_output_ops = - default_unlink_name, /* unlink_name */ - console_output_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_output_destroy /* destroy */ - }; -@@ -440,6 +453,7 @@ static const struct object_ops console_connection_ops = - default_unlink_name, /* unlink_name */ - console_connection_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - console_connection_close_handle, /* close_handle */ - console_connection_destroy /* destroy */ - }; -@@ -539,6 +553,7 @@ static struct object *create_console(void) - console->server = NULL; - console->fd = NULL; - console->last_id = 0; -+ console->inproc_sync = NULL; - init_async_queue( &console->ioctl_q ); - init_async_queue( &console->read_q ); - -@@ -578,6 +593,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u - } - list_add_tail( &server->queue, &ioctl->entry ); - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - if (async) set_error( STATUS_PENDING ); - return 1; - } -@@ -610,6 +626,7 @@ static void disconnect_console_server( struct console_server *server ) - server->console->server = NULL; - server->console = NULL; - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - } - } - -@@ -764,6 +781,8 @@ static void console_destroy( struct object *obj ) - free_async_queue( &console->read_q ); - if (console->fd) - release_object( console->fd ); -+ -+ if (console->inproc_sync) release_object( console->inproc_sync ); - } - - static struct object *create_console_connection( struct console *console ) -@@ -817,6 +836,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access - return grab_object( obj ); - } - -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ) -+{ -+ struct console *console = (struct console *)obj; -+ -+ if (!console->inproc_sync) -+ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->inproc_sync) grab_object( console->inproc_sync ); -+ return console->inproc_sync; -+} -+ - static void screen_buffer_dump( struct object *obj, int verbose ) - { - struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -866,6 +895,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) - return NULL; - } - -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) -+{ -+ struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -+ if (!screen_buffer->input) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( &screen_buffer->input->obj ); -+} -+ - static void console_server_dump( struct object *obj, int verbose ) - { - assert( obj->ops == &console_server_ops ); -@@ -878,6 +918,7 @@ static void console_server_destroy( struct object *obj ) - assert( obj->ops == &console_server_ops ); - disconnect_console_server( server ); - if (server->fd) release_object( server->fd ); -+ if (server->inproc_sync) release_object( server->inproc_sync ); - } - - static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -938,6 +979,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) -+{ -+ struct console_server *server = (struct console_server *)obj; -+ int signaled = !server->console || !list_empty( &server->queue ); -+ -+ if (!server->inproc_sync) -+ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (server->inproc_sync) grab_object( server->inproc_sync ); -+ return server->inproc_sync; -+} -+ - static struct object *create_console_server( void ) - { - struct console_server *server; -@@ -949,6 +1001,7 @@ static struct object *create_console_server( void ) - server->term_fd = -1; - list_init( &server->queue ); - list_init( &server->read_queue ); -+ server->inproc_sync = NULL; - server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); - if (!server->fd) - { -@@ -1414,6 +1467,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_input_destroy( struct object *obj ) - { - struct console_input *console_input = (struct console_input *)obj; -@@ -1486,6 +1549,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console || !current->process->console->active) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_output_destroy( struct object *obj ) - { - struct console_output *console_output = (struct console_output *)obj; -@@ -1543,11 +1616,16 @@ DECL_HANDLER(get_next_console_request) - - if (!server->console->renderer) server->console->renderer = current; - -- if (!req->signal) server->console->signaled = 0; -+ if (!req->signal) -+ { -+ server->console->signaled = 0; -+ reset_inproc_event( server->console->inproc_sync ); -+ } - else if (!server->console->signaled) - { - server->console->signaled = 1; - wake_up( &server->console->obj, 0 ); -+ set_inproc_event( server->console->inproc_sync ); - } - - if (req->read) -@@ -1569,6 +1647,8 @@ DECL_HANDLER(get_next_console_request) - /* set result of previous ioctl */ - ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); - list_remove( &ioctl->entry ); -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - } - - if (ioctl) -@@ -1655,5 +1735,8 @@ DECL_HANDLER(get_next_console_request) - set_error( STATUS_PENDING ); - } - -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); -+ - release_object( server ); - } -diff --git a/server/debugger.c b/server/debugger.c -index 39a740e07e5..35449172eaa 100644 ---- a/server/debugger.c -+++ b/server/debugger.c -@@ -71,6 +71,7 @@ struct debug_obj - struct object obj; /* object header */ - struct list event_queue; /* pending events queue */ - unsigned int flags; /* debug flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - -@@ -98,12 +99,14 @@ static const struct object_ops debug_event_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_event_destroy /* destroy */ - }; - - static void debug_obj_dump( struct object *obj, int verbose ); - static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); - static void debug_obj_destroy( struct object *obj ); - - static const struct object_ops debug_obj_ops = -@@ -126,6 +129,7 @@ static const struct object_ops debug_obj_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_obj_destroy /* destroy */ - }; -@@ -253,6 +257,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) - /* grab reference since debugger could be killed while trying to wake up */ - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -265,6 +270,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event - { - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -330,6 +336,17 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr - return find_event_to_send( debug_obj ) != NULL; - } - -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) -+{ -+ struct debug_obj *debug_obj = (struct debug_obj *)obj; -+ int signaled = find_event_to_send( debug_obj ) != NULL; -+ -+ if (!debug_obj->inproc_sync) -+ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); -+ return debug_obj->inproc_sync; -+} -+ - static void debug_obj_destroy( struct object *obj ) - { - struct list *ptr; -@@ -342,6 +359,8 @@ static void debug_obj_destroy( struct object *obj ) - /* free all pending events */ - while ((ptr = list_head( &debug_obj->event_queue ))) - unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); -+ -+ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); - } - - struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) -@@ -361,6 +380,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni - { - debug_obj->flags = flags; - list_init( &debug_obj->event_queue ); -+ debug_obj->inproc_sync = NULL; - } - } - return debug_obj; -@@ -569,6 +589,9 @@ DECL_HANDLER(wait_debug_event) - reply->tid = get_thread_id( event->sender ); - alloc_event_handles( event, current->process ); - set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); -+ -+ if (!find_event_to_send( debug_obj )) -+ reset_inproc_event( debug_obj->inproc_sync ); - } - else - { -diff --git a/server/device.c b/server/device.c -index cab09700d8c..72410c2da8b 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - irp_call_destroy /* destroy */ - }; -@@ -92,10 +93,12 @@ struct device_manager - struct list requests; /* list of pending irps across all devices */ - struct irp_call *current_call; /* call currently executed on client side */ - struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void device_manager_dump( struct object *obj, int verbose ); - static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); - static void device_manager_destroy( struct object *obj ); - - static const struct object_ops device_manager_ops = -@@ -118,6 +121,7 @@ static const struct object_ops device_manager_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_manager_destroy /* destroy */ - }; -@@ -175,6 +179,7 @@ static const struct object_ops device_ops = - default_unlink_name, /* unlink_name */ - device_open_file, /* open_file */ - device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -227,6 +232,7 @@ static const struct object_ops device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - device_file_close_handle, /* close_handle */ - device_file_destroy /* destroy */ - }; -@@ -418,7 +424,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i - irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; - if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); - list_add_tail( &manager->requests, &irp->mgr_entry ); -- if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ -+ if (list_head( &manager->requests ) == &irp->mgr_entry) -+ { -+ /* first one */ -+ wake_up( &manager->obj, 0 ); -+ set_inproc_event( manager->inproc_sync ); -+ } - } - - static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -752,6 +763,9 @@ static void delete_file( struct device_file *file ) - set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); - } - -+ if (list_empty( &file->device->manager->requests )) -+ reset_inproc_event( file->device->manager->inproc_sync ); -+ - release_object( file ); - } - -@@ -783,6 +797,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry - return !list_empty( &manager->requests ); - } - -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) -+{ -+ struct device_manager *manager = (struct device_manager *)obj; -+ -+ if (!manager->inproc_sync) -+ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->inproc_sync) grab_object( manager->inproc_sync ); -+ return manager->inproc_sync; -+} -+ - static void device_manager_destroy( struct object *obj ) - { - struct device_manager *manager = (struct device_manager *)obj; -@@ -817,6 +841,8 @@ static void device_manager_destroy( struct object *obj ) - assert( !irp->file && !irp->async ); - release_object( irp ); - } -+ -+ if (manager->inproc_sync) release_object( manager->inproc_sync ); - } - - static struct device_manager *create_device_manager(void) -@@ -826,6 +852,7 @@ static struct device_manager *create_device_manager(void) - if ((manager = alloc_object( &device_manager_ops ))) - { - manager->current_call = NULL; -+ manager->inproc_sync = NULL; - list_init( &manager->devices ); - list_init( &manager->requests ); - wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -@@ -1015,6 +1042,10 @@ DECL_HANDLER(get_next_device_request) - } - list_remove( &irp->mgr_entry ); - list_init( &irp->mgr_entry ); -+ -+ if (list_empty( &manager->requests )) -+ reset_inproc_event( manager->inproc_sync ); -+ - /* we already own the object if it's only on manager queue */ - if (irp->file) grab_object( irp ); - manager->current_call = irp; -diff --git a/server/directory.c b/server/directory.c -index fd689c561bc..40cb9b95999 100644 ---- a/server/directory.c -+++ b/server/directory.c -@@ -81,6 +81,7 @@ static const struct object_ops object_type_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -131,6 +132,7 @@ static const struct object_ops directory_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - directory_destroy /* destroy */ - }; -diff --git a/server/event.c b/server/event.c -index ad7c09acc99..4fb44d70039 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -56,6 +56,7 @@ struct event - struct list kernel_object; /* list of kernel object pointers */ - int manual_reset; /* is it a manual reset event? */ - int signaled; /* event has been signaled */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void event_dump( struct object *obj, int verbose ); -@@ -63,6 +64,8 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int event_signal( struct object *obj, unsigned int access); - static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ); -+static void event_destroy( struct object *obj ); - - static const struct object_ops event_ops = - { -@@ -84,8 +87,9 @@ static const struct object_ops event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ event_destroy /* destroy */ - }; - - -@@ -106,10 +110,13 @@ struct type_descr keyed_event_type = - struct keyed_event - { - struct object obj; /* object header */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void keyed_event_dump( struct object *obj, int verbose ); - static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); -+static void keyed_event_destroy( struct object *obj ); - - static const struct object_ops keyed_event_ops = - { -@@ -131,8 +138,9 @@ static const struct object_ops keyed_event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ keyed_event_destroy /* destroy */ - }; - - -@@ -150,6 +158,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; -+ event->inproc_sync = NULL; - } - } - return event; -@@ -173,11 +182,13 @@ void set_event( struct event *event ) - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); -+ set_inproc_event( event->inproc_sync ); - } - - void reset_event( struct event *event ) - { - event->signaled = 0; -+ reset_inproc_event( event->inproc_sync ); - } - - static void event_dump( struct object *obj, int verbose ) -@@ -223,6 +234,26 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) - return &event->kernel_object; - } - -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (!event->inproc_sync) -+ { -+ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; -+ event->inproc_sync = create_inproc_event( type, event->signaled ); -+ } -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void event_destroy( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, - unsigned int attr, const struct security_descriptor *sd ) - { -@@ -233,6 +264,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod - if (get_error() != STATUS_OBJECT_NAME_EXISTS) - { - /* initialize it if it didn't already exist */ -+ event->inproc_sync = NULL; - } - } - return event; -@@ -276,6 +308,23 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en - return 0; - } - -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (!event->inproc_sync) -+ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void keyed_event_destroy( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - /* create an event */ - DECL_HANDLER(create_event) - { -diff --git a/server/fd.c b/server/fd.c -index ce32e7f8397..77ac22b9655 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -154,6 +154,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -179,6 +180,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -220,6 +222,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -260,6 +263,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -302,6 +306,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1572,6 +1577,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -+ if (fd->inproc_sync) release_object( fd->inproc_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1690,6 +1696,7 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); - init_async_queue( &fd->wait_q ); -@@ -1730,6 +1737,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); -@@ -2140,7 +2148,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ set_inproc_event( fd->inproc_sync ); -+ } -+ else -+ { -+ reset_inproc_event( fd->inproc_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2166,6 +2182,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - -+struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) -+{ -+ struct fd *fd = get_obj_fd( obj ); -+ struct inproc_sync *ret; -+ -+ if (!fd->inproc_sync) -+ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->inproc_sync; -+ release_object( fd ); -+ if (ret) grab_object( ret ); -+ return ret; -+} -+ - int default_fd_get_poll_events( struct fd *fd ) - { - int events = 0; -diff --git a/server/file.c b/server/file.c -index 8f6566a0077..bab203b1914 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -106,6 +106,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index 4f5fc7b26f1..882976e9e02 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -109,6 +109,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -+extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); - 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 -index e65831b3b22..29b43789372 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index c2d2823cd61..c45900549fc 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -93,6 +93,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; -diff --git a/server/inproc_sync.c b/server/inproc_sync.c -new file mode 100644 -index 00000000000..6dd50d79bc0 ---- /dev/null -+++ b/server/inproc_sync.c -@@ -0,0 +1,437 @@ -+/* -+ * In-process synchronization primitives -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "ntstatus.h" -+#define WIN32_NO_STATUS -+#include "winternl.h" -+ -+#include "file.h" -+#include "handle.h" -+#include "request.h" -+#include "thread.h" -+ -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct linux_device -+{ -+ struct object obj; /* object header */ -+ struct fd *fd; /* fd for unix fd */ -+}; -+ -+static struct linux_device *linux_device_object; -+ -+static void linux_device_dump( struct object *obj, int verbose ); -+static struct fd *linux_device_get_fd( struct object *obj ); -+static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); -+ -+static const struct object_ops linux_device_ops = -+{ -+ sizeof(struct linux_device), /* size */ -+ &no_type, /* type */ -+ linux_device_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_device_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_device_destroy /* destroy */ -+}; -+ -+static const struct fd_ops inproc_sync_fd_ops = -+{ -+ default_fd_get_poll_events, /* get_poll_events */ -+ default_poll_event, /* poll_event */ -+ inproc_sync_get_fd_type, /* get_fd_type */ -+ no_fd_read, /* read */ -+ no_fd_write, /* write */ -+ no_fd_flush, /* flush */ -+ no_fd_get_file_info, /* get_file_info */ -+ no_fd_get_volume_info, /* get_volume_info */ -+ no_fd_ioctl, /* ioctl */ -+ default_fd_cancel_async, /* cancel_async */ -+ no_fd_queue_async, /* queue_async */ -+ default_fd_reselect_async /* reselect_async */ -+}; -+ -+static void linux_device_dump( struct object *obj, int verbose ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); -+} -+ -+static struct fd *linux_device_get_fd( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ return (struct fd *)grab_object( device->fd ); -+} -+ -+static void linux_device_destroy( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ if (device->fd) release_object( device->fd ); -+ linux_device_object = NULL; -+} -+ -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) -+{ -+ return FD_TYPE_FILE; -+} -+ -+static struct linux_device *get_linux_device(void) -+{ -+ struct linux_device *device; -+ static int initialized; -+ int unix_fd; -+ -+ if (initialized) -+ { -+ if (linux_device_object) -+ grab_object( linux_device_object ); -+ else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return linux_device_object; -+ } -+ -+ if (getenv( "WINE_DISABLE_FAST_SYNC" ) && atoi( getenv( "WINE_DISABLE_FAST_SYNC" ) )) -+ { -+ static int once; -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ if (!once++) fprintf(stderr, "ntsync is explicitly disabled.\n"); -+ initialized = 1; -+ return NULL; -+ } -+ -+ unix_fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY ); -+ if (unix_fd == -1) -+ { -+ static int once; -+ file_set_error(); -+ if (!once++) fprintf(stderr, "Cannot open /dev/ntsync: %s\n", strerror(errno)); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device = alloc_object( &linux_device_ops ))) -+ { -+ close( unix_fd ); -+ set_error( STATUS_NO_MEMORY ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) -+ { -+ release_object( device ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ fprintf( stderr, "wine: using fast synchronization.\n" ); -+ linux_device_object = device; -+ initialized = 1; -+ return device; -+} -+ -+struct inproc_sync -+{ -+ struct object obj; -+ enum inproc_sync_type type; -+ struct fd *fd; -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ); -+static void linux_obj_destroy( struct object *obj ); -+static struct fd *linux_obj_get_fd( struct object *obj ); -+ -+static const struct object_ops linux_obj_ops = -+{ -+ sizeof(struct inproc_sync), /* size */ -+ &no_type, /* type */ -+ linux_obj_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_obj_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_obj_destroy /* destroy */ -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); -+} -+ -+static void linux_obj_destroy( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ if (inproc_sync->fd) release_object( inproc_sync->fd ); -+} -+ -+static struct fd *linux_obj_get_fd( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( inproc_sync->fd ); -+} -+ -+static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) -+{ -+ struct inproc_sync *inproc_sync; -+ -+ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) -+ { -+ close( unix_fd ); -+ return NULL; -+ } -+ -+ inproc_sync->type = type; -+ -+ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) -+ { -+ release_object( inproc_sync ); -+ return NULL; -+ } -+ -+ return inproc_sync; -+} -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ struct ntsync_event_args args; -+ struct linux_device *device; -+ int event; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.signaled = signaled; -+ switch (type) -+ { -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_AUTO_SERVER: -+ args.manual = 0; -+ break; -+ -+ case INPROC_SYNC_MANUAL_EVENT: -+ case INPROC_SYNC_MANUAL_SERVER: -+ case INPROC_SYNC_QUEUE: -+ args.manual = 1; -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ case INPROC_SYNC_SEMAPHORE: -+ assert(0); -+ break; -+ } -+ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ release_object( device ); -+ -+ return create_inproc_sync( type, event ); -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ struct ntsync_sem_args args; -+ struct linux_device *device; -+ int semaphore; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.count = count; -+ args.max = max; -+ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ struct ntsync_mutex_args args; -+ struct linux_device *device; -+ int mutex; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.owner = owner; -+ args.count = count; -+ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); -+} -+ -+void reset_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); -+} -+ -+#else -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+} -+ -+void reset_inproc_event( struct inproc_sync *obj ) -+{ -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+} -+ -+#endif -+ -+DECL_HANDLER(get_linux_sync_device) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct linux_device *device; -+ -+ if ((device = get_linux_device())) -+ { -+ reply->handle = alloc_handle( current->process, device, 0, 0 ); -+ release_object( device ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -+ -+DECL_HANDLER(get_linux_sync_obj) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct object *obj; -+ -+ if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) -+ { -+ struct inproc_sync *inproc_sync; -+ -+ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) -+ { -+ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); -+ reply->type = inproc_sync->type; -+ reply->access = get_handle_access( current->process, req->handle ); -+ release_object( inproc_sync ); -+ } -+ release_object( obj ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -diff --git a/server/mailslot.c b/server/mailslot.c -index b14954ad6c3..701ac35f393 100644 ---- a/server/mailslot.c -+++ b/server/mailslot.c -@@ -93,6 +93,7 @@ static const struct object_ops mailslot_ops = - default_unlink_name, /* unlink_name */ - mailslot_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync,/* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_destroy /* destroy */ - }; -@@ -154,6 +155,7 @@ static const struct object_ops mail_writer_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mail_writer_destroy /* destroy */ - }; -@@ -219,6 +221,7 @@ static const struct object_ops mailslot_device_ops = - default_unlink_name, /* unlink_name */ - mailslot_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_destroy /* destroy */ - }; -@@ -249,6 +252,7 @@ static const struct object_ops mailslot_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_file_destroy /* destroy */ - }; -diff --git a/server/mapping.c b/server/mapping.c -index 4bdd7c5080a..7c715a87457 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -79,6 +79,7 @@ static const struct object_ops ranges_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ranges_destroy /* destroy */ - }; -@@ -115,6 +116,7 @@ static const struct object_ops shared_map_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - shared_map_destroy /* destroy */ - }; -@@ -188,6 +190,7 @@ static const struct object_ops mapping_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mapping_destroy /* destroy */ - }; -diff --git a/server/mutex.c b/server/mutex.c -index af0efe72132..a4374317760 100644 ---- a/server/mutex.c -+++ b/server/mutex.c -@@ -38,6 +38,8 @@ - - static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; - -+static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); -+ - struct type_descr mutex_type = - { - { mutex_name, sizeof(mutex_name) }, /* name */ -@@ -57,6 +59,8 @@ struct mutex - unsigned int count; /* recursion count */ - int abandoned; /* has it been abandoned? */ - struct list entry; /* entry in owner thread mutex list */ -+ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void mutex_dump( struct object *obj, int verbose ); -@@ -64,6 +68,7 @@ static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_destroy( struct object *obj ); - static int mutex_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); - - static const struct object_ops mutex_ops = - { -@@ -85,6 +90,7 @@ static const struct object_ops mutex_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mutex_destroy /* destroy */ - }; -@@ -127,6 +133,7 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - mutex->owner = NULL; - mutex->abandoned = 0; - if (owned) do_grab( mutex, current ); -+ mutex->inproc_sync = NULL; - } - } - return mutex; -@@ -134,16 +141,20 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - - void abandon_mutexes( struct thread *thread ) - { -+ struct mutex *mutex; - struct list *ptr; - - while ((ptr = list_head( &thread->mutex_list )) != NULL) - { -- struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry ); -+ mutex = LIST_ENTRY( ptr, struct mutex, entry ); - assert( mutex->owner == thread ); - mutex->count = 0; - mutex->abandoned = 1; - do_release( mutex ); - } -+ -+ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) -+ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); - } - - static void mutex_dump( struct object *obj, int verbose ) -@@ -189,14 +200,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) - return 1; - } - -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) -+{ -+ struct mutex *mutex = (struct mutex *)obj; -+ -+ if (!mutex->inproc_sync) -+ { -+ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); -+ } -+ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); -+ return mutex->inproc_sync; -+} -+ - static void mutex_destroy( struct object *obj ) - { - struct mutex *mutex = (struct mutex *)obj; - assert( obj->ops == &mutex_ops ); - -- if (!mutex->count) return; -- mutex->count = 0; -- do_release( mutex ); -+ if (mutex->count) -+ { -+ mutex->count = 0; -+ do_release( mutex ); -+ } -+ if (mutex->inproc_sync) -+ { -+ release_object( mutex->inproc_sync ); -+ list_remove( &mutex->inproc_mutexes_entry ); -+ } - } - - /* create a mutex */ -diff --git a/server/named_pipe.c b/server/named_pipe.c -index 59a90c36663..04e8f49fb79 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops = - default_unlink_name, /* unlink_name */ - named_pipe_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_destroy /* destroy */ - }; -@@ -179,6 +180,7 @@ static const struct object_ops pipe_server_ops = - NULL, /* unlink_name */ - pipe_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_server_destroy /* destroy */ - }; -@@ -223,6 +225,7 @@ static const struct object_ops pipe_client_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_end_destroy /* destroy */ - }; -@@ -270,6 +273,7 @@ static const struct object_ops named_pipe_device_ops = - default_unlink_name, /* unlink_name */ - named_pipe_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_destroy /* destroy */ - }; -@@ -301,6 +305,7 @@ static const struct object_ops named_pipe_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_file_destroy /* destroy */ - }; -@@ -351,6 +356,7 @@ static const struct object_ops named_pipe_dir_ops = - NULL, /* unlink_name */ - named_pipe_dir_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_dir_destroy /* destroy */ - }; -diff --git a/server/object.c b/server/object.c -index cd368ef724a..b07bc59bde1 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -120,6 +120,7 @@ static const struct object_ops apc_reserve_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -144,6 +145,7 @@ static const struct object_ops completion_reserve_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -639,6 +641,12 @@ struct fd *no_get_fd( struct object *obj ) - return NULL; - } - -+struct inproc_sync *no_get_inproc_sync( struct object *obj ) -+{ -+ set_error( STATUS_OBJECT_TYPE_MISMATCH ); -+ return NULL; -+} -+ - unsigned int default_map_access( struct object *obj, unsigned int access ) - { - return map_access( access, &obj->ops->type->mapping ); -diff --git a/server/object.h b/server/object.h -index 7555f564a08..b1612623b0f 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -42,6 +42,7 @@ struct async; - struct async_queue; - struct winstation; - struct object_type; -+struct inproc_sync; - - - struct unicode_str -@@ -103,6 +104,8 @@ struct object_ops - unsigned int options); - /* return list of kernel objects */ - struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable in-process synchronization handle to this object */ -+ struct inproc_sync *(*get_inproc_sync)(struct object *); - /* close a handle to this object */ - int (*close_handle)(struct object *,struct process *,obj_handle_t); - /* destroy on refcount == 0 */ -@@ -228,6 +231,17 @@ extern void reset_event( struct event *event ); - - extern void abandon_mutexes( struct thread *thread ); - -+/* in-process synchronization functions */ -+ -+extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); -+extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); -+extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); -+extern void set_inproc_event( struct inproc_sync *obj ); -+extern void reset_inproc_event( struct inproc_sync *obj ); -+extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); -+ -+extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); -+ - /* serial functions */ - - int get_serial_async_timeout(struct object *obj, int type, int count); -diff --git a/server/process.c b/server/process.c -index e06350f7311..fed2f95bd30 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -94,6 +94,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access - static struct security_descriptor *process_get_sd( struct object *obj ); - static void process_poll_event( struct fd *fd, int event ); - static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ); - static void process_destroy( struct object *obj ); - static void terminate_process( struct process *process, struct thread *skip, int exit_code ); - -@@ -117,6 +118,7 @@ static const struct object_ops process_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - process_destroy /* destroy */ - }; -@@ -168,6 +170,7 @@ static const struct object_ops startup_info_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - startup_info_destroy /* destroy */ - }; -@@ -190,6 +193,7 @@ struct type_descr job_type = - - static void job_dump( struct object *obj, int verbose ); - static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ); - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void job_destroy( struct object *obj ); - -@@ -207,6 +211,7 @@ struct job - struct job *parent; - struct list parent_job_entry; /* list entry for parent job */ - struct list child_job_list; /* list of child jobs */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static const struct object_ops job_ops = -@@ -229,6 +234,7 @@ static const struct object_ops job_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_inproc_sync, /* get_inproc_sync */ - job_close_handle, /* close_handle */ - job_destroy /* destroy */ - }; -@@ -253,6 +259,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_ - job->completion_port = NULL; - job->completion_key = 0; - job->parent = NULL; -+ job->inproc_sync = NULL; - } - } - return job; -@@ -409,6 +416,17 @@ static void terminate_job( struct job *job, int exit_code ) - job->terminating = 0; - job->signaled = 1; - wake_up( &job->obj, 0 ); -+ set_inproc_event( job->inproc_sync ); -+} -+ -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ) -+{ -+ struct job *job = (struct job *)obj; -+ -+ if (!job->inproc_sync) -+ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->inproc_sync) grab_object( job->inproc_sync ); -+ return job->inproc_sync; - } - - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) -@@ -439,6 +457,8 @@ static void job_destroy( struct object *obj ) - list_remove( &job->parent_job_entry ); - release_object( job->parent ); - } -+ -+ if (job->inproc_sync) release_object( job->inproc_sync ); - } - - static void job_dump( struct object *obj, int verbose ) -@@ -684,6 +704,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_device_count = 0; - process->rawinput_mouse = NULL; - process->rawinput_kbd = NULL; -+ process->inproc_sync = NULL; - memset( &process->image_info, 0, sizeof(process->image_info) ); - list_init( &process->rawinput_entry ); - list_init( &process->kernel_object ); -@@ -784,6 +805,8 @@ static void process_destroy( struct object *obj ) - free( process->rawinput_devices ); - free( process->dir_cache ); - free( process->image ); -+ -+ if (process->inproc_sync) release_object( process->inproc_sync ); - } - - /* dump a process on stdout for debugging purposes */ -@@ -817,6 +840,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) - return &process->kernel_object; - } - -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ) -+{ -+ struct process *process = (struct process *)obj; -+ -+ if (!process->inproc_sync) -+ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->inproc_sync) grab_object( process->inproc_sync ); -+ return process->inproc_sync; -+} -+ - static struct security_descriptor *process_get_sd( struct object *obj ) - { - static struct security_descriptor *process_default_sd; -@@ -981,6 +1014,7 @@ static void process_killed( struct process *process ) - release_job_process( process ); - start_sigkill_timer( process ); - wake_up( &process->obj, 0 ); -+ set_inproc_event( process->inproc_sync ); - } - - /* add a thread to a process running threads list */ -diff --git a/server/process.h b/server/process.h -index 96814ab7cf8..667e2506672 100644 ---- a/server/process.h -+++ b/server/process.h -@@ -86,6 +86,7 @@ struct process - struct list rawinput_entry; /* entry in the rawinput process list */ - struct list kernel_object; /* list of kernel object pointers */ - struct pe_image_info image_info; /* main exe image info */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - /* process functions */ -diff --git a/server/protocol.def b/server/protocol.def -index 4b9c4dc8e5c..85ab00ea704 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4076,3 +4076,50 @@ struct handle_info - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END -+ -+ -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+/* Obtain a handle to the ntsync device object */ -+@REQ(get_linux_sync_device) -+@REPLY -+ obj_handle_t handle; /* handle to the device */ -+@END -+ -+ -+/* Get the in-process synchronization object associated with the given handle */ -+@REQ(get_linux_sync_obj) -+ obj_handle_t handle; /* handle to the object */ -+@REPLY -+ obj_handle_t handle; /* handle to the fast synchronization object */ -+ int type; /* object type */ -+ unsigned int access; /* handle access rights */ -+@END -+ -+ -+/* Begin a client-side wait on a message queue */ -+@REQ(select_inproc_queue) -+@END -+ -+ -+/* End a client-side wait on a message queue */ -+@REQ(unselect_inproc_queue) -+ int signaled; /* was the queue signaled? */ -+@END -+ -+ -+/* Get an event handle to be used for thread alerts with in-process synchronization */ -+@REQ(get_inproc_alert_event) -+@REPLY -+ obj_handle_t handle; /* handle to the event */ -+@END -diff --git a/server/queue.c b/server/queue.c -index 47870884644..19a5e7aa9b8 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -133,6 +133,8 @@ struct msg_queue - timeout_t last_get_msg; /* time of last get message call */ - int keystate_lock; /* owns an input keystate lock */ - const queue_shm_t *shared; /* queue in session shared memory */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ int in_inproc_wait; /* are we in a client-side wait? */ - }; - - struct hotkey -@@ -150,6 +152,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent - static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ); - static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); - static void msg_queue_destroy( struct object *obj ); - static void msg_queue_poll_event( struct fd *fd, int event ); - static void thread_input_dump( struct object *obj, int verbose ); -@@ -176,6 +179,7 @@ static const struct object_ops msg_queue_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - msg_queue_destroy /* destroy */ - }; -@@ -213,6 +217,7 @@ static const struct object_ops thread_input_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_input_destroy /* destroy */ - }; -@@ -312,6 +317,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->hooks = NULL; - queue->last_get_msg = current_time; - queue->keystate_lock = 0; -+ queue->inproc_sync = NULL; -+ queue->in_inproc_wait = 0; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); -@@ -728,7 +735,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) - } - SHARED_WRITE_END; - -- if (is_signaled( queue )) wake_up( &queue->obj, 0 ); -+ if (is_signaled( queue )) -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } - } - - /* clear some queue bits */ -@@ -748,6 +759,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits - if (queue->keystate_lock) unlock_input_keystate( queue->input ); - queue->keystate_lock = 0; - } -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - - /* check if message is matched by the filter */ -@@ -1227,6 +1240,10 @@ static int is_queue_hung( struct msg_queue *queue ) - if (get_wait_queue_thread(entry)->queue == queue) - return 0; /* thread is waiting on queue -> not hung */ - } -+ -+ if (queue->in_inproc_wait) -+ return 0; /* thread is waiting on queue in absentia -> not hung */ -+ - return 1; - } - -@@ -1292,6 +1309,17 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en - shared->changed_mask = 0; - } - SHARED_WRITE_END; -+ reset_inproc_event( queue->inproc_sync ); -+} -+ -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) -+{ -+ struct msg_queue *queue = (struct msg_queue *)obj; -+ -+ if (!queue->inproc_sync) -+ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->inproc_sync) grab_object( queue->inproc_sync ); -+ return queue->inproc_sync; - } - - static void msg_queue_destroy( struct object *obj ) -@@ -1337,6 +1365,7 @@ static void msg_queue_destroy( struct object *obj ) - if (queue->hooks) release_object( queue->hooks ); - if (queue->fd) release_object( queue->fd ); - if (queue->shared) free_shared_object( queue->shared ); -+ if (queue->inproc_sync) release_object( queue->inproc_sync ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1347,6 +1376,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) - if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); - else set_fd_events( queue->fd, 0 ); - wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); - } - - static void thread_input_dump( struct object *obj, int verbose ) -@@ -3114,7 +3144,15 @@ DECL_HANDLER(set_queue_mask) - } - SHARED_WRITE_END; - } -- else wake_up( &queue->obj, 0 ); -+ else -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } -+ } -+ else -+ { -+ reset_inproc_event( queue->inproc_sync ); - } - } - } -@@ -3136,6 +3174,9 @@ DECL_HANDLER(get_queue_status) - shared->changed_bits &= ~req->clear_bits; - } - SHARED_WRITE_END; -+ -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - else reply->wake_bits = reply->changed_bits = 0; - } -@@ -3333,6 +3374,9 @@ DECL_HANDLER(get_message) - } - SHARED_WRITE_END; - -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); -+ - /* then check for posted messages */ - if ((filter & QS_POSTMESSAGE) && - get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3392,6 +3436,7 @@ DECL_HANDLER(get_message) - } - SHARED_WRITE_END; - -+ reset_inproc_event( queue->inproc_sync ); - set_error( STATUS_PENDING ); /* FIXME */ - } - -@@ -4183,3 +4228,42 @@ DECL_HANDLER(set_keyboard_repeat) - - release_object( desktop ); - } -+ -+DECL_HANDLER(select_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ check_thread_queue_idle( current ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_inproc_wait = 1; -+ } -+} -+ -+DECL_HANDLER(unselect_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (!queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_inproc_wait = 0; -+ } -+} -diff --git a/server/registry.c b/server/registry.c -index 3f02faaaefd..65beb11702d 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -192,6 +192,7 @@ static const struct object_ops key_ops = - key_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - key_close_handle, /* close_handle */ - key_destroy /* destroy */ - }; -diff --git a/server/request.c b/server/request.c -index 2254315b79e..24a4f779e68 100644 ---- a/server/request.c -+++ b/server/request.c -@@ -101,6 +101,7 @@ static const struct object_ops master_socket_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - master_socket_destroy /* destroy */ - }; -diff --git a/server/request_handlers.h b/server/request_handlers.h -index fb03e421562..1d88b63dff3 100644 ---- a/server/request_handlers.h -+++ b/server/request_handlers.h -@@ -299,6 +299,11 @@ DECL_HANDLER(suspend_process); - DECL_HANDLER(resume_process); - DECL_HANDLER(get_next_thread); - DECL_HANDLER(set_keyboard_repeat); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(select_inproc_queue); -+DECL_HANDLER(unselect_inproc_queue); -+DECL_HANDLER(get_inproc_alert_event); - - typedef void (*req_handler)( const void *req, void *reply ); - static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -595,6 +600,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = - (req_handler)req_resume_process, - (req_handler)req_get_next_thread, - (req_handler)req_set_keyboard_repeat, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_select_inproc_queue, -+ (req_handler)req_unselect_inproc_queue, -+ (req_handler)req_get_inproc_alert_event, - }; - - C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2268,3 +2278,18 @@ C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_request, handle) == 12 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, handle) == 8 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); -+C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); -+C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); -diff --git a/server/request_trace.h b/server/request_trace.h -index cf0aab07ca0..283f1c1774a 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -3339,6 +3339,45 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep - fprintf( stderr, " enable=%d", req->enable ); - } - -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) -+{ -+} -+ -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", type=%d", req->type ); -+ fprintf( stderr, ", access=%08x", req->access ); -+} -+ -+static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) -+{ -+} -+ -+static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) -+{ -+ fprintf( stderr, " signaled=%d", req->signaled ); -+} -+ -+static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) -+{ -+} -+ -+static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ - typedef void (*dump_func)( const void *req ); - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = -@@ -3635,6 +3674,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, - (dump_func)dump_set_keyboard_repeat_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_select_inproc_queue_request, -+ (dump_func)dump_unselect_inproc_queue_request, -+ (dump_func)dump_get_inproc_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = -@@ -3931,6 +3975,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = - NULL, - (dump_func)dump_get_next_thread_reply, - (dump_func)dump_set_keyboard_repeat_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, -+ NULL, -+ (dump_func)dump_get_inproc_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = -@@ -4227,6 +4276,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = - "resume_process", - "get_next_thread", - "set_keyboard_repeat", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "select_inproc_queue", -+ "unselect_inproc_queue", -+ "get_inproc_alert_event", - }; - - static const struct -diff --git a/server/semaphore.c b/server/semaphore.c -index 53b42a886df..bc7436b5673 100644 ---- a/server/semaphore.c -+++ b/server/semaphore.c -@@ -55,12 +55,15 @@ struct semaphore - struct object obj; /* object header */ - unsigned int count; /* current count */ - unsigned int max; /* maximum possible count */ -+ struct inproc_sync *inproc_sync; /* fast synchronization object */ - }; - - static void semaphore_dump( struct object *obj, int verbose ); - static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); -+static void semaphore_destroy( struct object *obj ); - - static const struct object_ops semaphore_ops = - { -@@ -82,8 +85,9 @@ static const struct object_ops semaphore_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ semaphore_destroy /* destroy */ - }; - - -@@ -105,6 +109,7 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni - /* initialize it if it didn't already exist */ - sem->count = initial; - sem->max = max; -+ sem->inproc_sync = NULL; - } - } - return sem; -@@ -167,6 +172,23 @@ static int semaphore_signal( struct object *obj, unsigned int access ) - return release_semaphore( sem, 1, NULL ); - } - -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (!semaphore->inproc_sync) -+ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); -+ return semaphore->inproc_sync; -+} -+ -+static void semaphore_destroy( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); -+} -+ - /* create a semaphore */ - DECL_HANDLER(create_semaphore) - { -diff --git a/server/serial.c b/server/serial.c -index 209f2e9174e..93753328d4d 100644 ---- a/server/serial.c -+++ b/server/serial.c -@@ -103,6 +103,7 @@ static const struct object_ops serial_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - serial_destroy /* destroy */ - }; -diff --git a/server/signal.c b/server/signal.c -index 19b76d44c16..85d16baa98c 100644 ---- a/server/signal.c -+++ b/server/signal.c -@@ -74,6 +74,7 @@ static const struct object_ops handler_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handler_destroy /* destroy */ - }; -diff --git a/server/sock.c b/server/sock.c -index 32d622aaebc..09366ea7dde 100644 ---- a/server/sock.c -+++ b/server/sock.c -@@ -483,6 +483,7 @@ static const struct object_ops sock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - sock_close_handle, /* close_handle */ - sock_destroy /* destroy */ - }; -@@ -3611,6 +3612,7 @@ static const struct object_ops ifchange_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ifchange_destroy /* destroy */ - }; -@@ -3832,6 +3834,7 @@ static const struct object_ops socket_device_ops = - default_unlink_name, /* unlink_name */ - socket_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -diff --git a/server/symlink.c b/server/symlink.c -index 74b60162c01..f0314f2ee90 100644 ---- a/server/symlink.c -+++ b/server/symlink.c -@@ -83,6 +83,7 @@ static const struct object_ops symlink_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - symlink_destroy /* destroy */ - }; -diff --git a/server/thread.c b/server/thread.c -index b3ce5d9ac95..a05a96d8728 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -108,6 +108,7 @@ static const struct object_ops thread_apc_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_apc_destroy /* destroy */ - }; -@@ -150,6 +151,7 @@ static const struct object_ops context_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -177,6 +179,7 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) - static unsigned int thread_map_access( struct object *obj, unsigned int access ); - static void thread_poll_event( struct fd *fd, int event ); - static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); - static void destroy_thread( struct object *obj ); - - static const struct object_ops thread_ops = -@@ -199,6 +202,7 @@ static const struct object_ops thread_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - destroy_thread /* destroy */ - }; -@@ -246,6 +250,8 @@ static inline void init_thread_structure( struct thread *thread ) - thread->token = NULL; - thread->desc = NULL; - thread->desc_len = 0; -+ thread->inproc_sync = NULL; -+ thread->inproc_alert_event = NULL; - - thread->creation_time = current_time; - thread->exit_time = 0; -@@ -397,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) - return &thread->kernel_object; - } - -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) -+{ -+ struct thread *thread = (struct thread *)obj; -+ -+ if (!thread->inproc_sync) -+ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->inproc_sync) grab_object( thread->inproc_sync ); -+ return thread->inproc_sync; -+} -+ - /* cleanup everything that is no longer needed by a dead thread */ - /* used by destroy_thread and kill_thread */ - static void cleanup_thread( struct thread *thread ) -@@ -452,6 +468,8 @@ static void destroy_thread( struct object *obj ) - release_object( thread->process ); - if (thread->id) free_ptid( thread->id ); - if (thread->token) release_object( thread->token ); -+ if (thread->inproc_sync) release_object( thread->inproc_sync ); -+ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); - } - - /* dump a thread on stdout for debugging purposes */ -@@ -1149,8 +1167,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr - grab_object( apc ); - list_add_tail( queue, &apc->entry ); - if (!list_prev( queue, &apc->entry )) /* first one */ -+ { - wake_thread( thread ); - -+ if (apc->call.type == APC_USER && thread->inproc_alert_event) -+ set_event( thread->inproc_alert_event ); -+ } -+ - return 1; - } - -@@ -1181,6 +1204,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty - apc->executed = 1; - wake_up( &apc->obj, 0 ); - release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - return; - } - } -@@ -1195,6 +1220,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system - { - apc = LIST_ENTRY( ptr, struct thread_apc, entry ); - list_remove( ptr ); -+ -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - } - return apc; - } -@@ -1292,6 +1320,7 @@ void kill_thread( struct thread *thread, int violent_death ) - kill_console_processes( thread, 0 ); - abandon_mutexes( thread ); - wake_up( &thread->obj, 0 ); -+ set_inproc_event( thread->inproc_sync ); - if (violent_death) send_thread_signal( thread, SIGQUIT ); - cleanup_thread( thread ); - remove_process_thread( thread->process, thread ); -@@ -2035,3 +2064,12 @@ DECL_HANDLER(get_next_thread) - set_error( STATUS_NO_MORE_ENTRIES ); - release_object( process ); - } -+ -+DECL_HANDLER(get_inproc_alert_event) -+{ -+ if (!current->inproc_alert_event) -+ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); -+ -+ if (current->inproc_alert_event) -+ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); -+} -diff --git a/server/thread.h b/server/thread.h -index 754e617b484..c75512ded87 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -93,6 +93,8 @@ struct thread - data_size_t desc_len; /* thread description length in bytes */ - WCHAR *desc; /* thread description string */ - struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ struct event *inproc_alert_event; /* in-process synchronization alert event */ - }; - - extern struct thread *current; -diff --git a/server/timer.c b/server/timer.c -index b0b6ec81535..08aa62292f0 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -52,20 +52,22 @@ struct type_descr timer_type = - - struct timer - { -- struct object obj; /* object header */ -- int manual; /* manual reset */ -- int signaled; /* current signaled state */ -- unsigned int period; /* timer period in ms */ -- abstime_t when; /* next expiration */ -- struct timeout_user *timeout; /* timeout user */ -- struct thread *thread; /* thread that set the APC function */ -- client_ptr_t callback; /* callback APC function */ -- client_ptr_t arg; /* callback argument */ -+ struct object obj; /* object header */ -+ int manual; /* manual reset */ -+ int signaled; /* current signaled state */ -+ unsigned int period; /* timer period in ms */ -+ abstime_t when; /* next expiration */ -+ struct timeout_user *timeout; /* timeout user */ -+ struct thread *thread; /* thread that set the APC function */ -+ client_ptr_t callback; /* callback APC function */ -+ client_ptr_t arg; /* callback argument */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void timer_dump( struct object *obj, int verbose ); - static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); - static void timer_destroy( struct object *obj ); - - static const struct object_ops timer_ops = -@@ -88,6 +90,7 @@ static const struct object_ops timer_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - timer_destroy /* destroy */ - }; -@@ -110,6 +113,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str - timer->period = 0; - timer->timeout = NULL; - timer->thread = NULL; -+ timer->inproc_sync = NULL; - } - } - return timer; -@@ -151,6 +155,7 @@ static void timer_callback( void *private ) - /* wake up waiters */ - timer->signaled = 1; - wake_up( &timer->obj, 0 ); -+ set_inproc_event( timer->inproc_sync ); - } - - /* cancel a running timer */ -@@ -181,6 +186,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period - { - period = 0; /* period doesn't make any sense for a manual timer */ - timer->signaled = 0; -+ reset_inproc_event( timer->inproc_sync ); - } - timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); - timer->period = period; -@@ -215,6 +221,19 @@ static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry - if (!timer->manual) timer->signaled = 0; - } - -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) -+{ -+ struct timer *timer = (struct timer *)obj; -+ -+ if (!timer->inproc_sync) -+ { -+ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; -+ timer->inproc_sync = create_inproc_event( type, timer->signaled ); -+ } -+ if (timer->inproc_sync) grab_object( timer->inproc_sync ); -+ return timer->inproc_sync; -+} -+ - static void timer_destroy( struct object *obj ) - { - struct timer *timer = (struct timer *)obj; -@@ -222,6 +241,7 @@ static void timer_destroy( struct object *obj ) - - if (timer->timeout) remove_timeout_user( timer->timeout ); - if (timer->thread) release_object( timer->thread ); -+ if (timer->inproc_sync) release_object( timer->inproc_sync ); - } - - /* create a timer */ -diff --git a/server/token.c b/server/token.c -index 7e20c670a16..844ad2814f4 100644 ---- a/server/token.c -+++ b/server/token.c -@@ -157,6 +157,7 @@ static const struct object_ops token_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - token_destroy /* destroy */ - }; -diff --git a/server/window.c b/server/window.c -index 2af70b09102..291aab520d7 100644 ---- a/server/window.c -+++ b/server/window.c -@@ -119,6 +119,7 @@ static const struct object_ops window_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - window_destroy /* destroy */ - }; -diff --git a/server/winstation.c b/server/winstation.c -index 8611c893cde..e3f0a870d02 100644 ---- a/server/winstation.c -+++ b/server/winstation.c -@@ -88,6 +88,7 @@ static const struct object_ops winstation_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - winstation_close_handle, /* close_handle */ - winstation_destroy /* destroy */ - }; -@@ -128,6 +129,7 @@ static const struct object_ops desktop_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - desktop_close_handle, /* close_handle */ - desktop_destroy /* destroy */ - }; --- -2.47.1 - diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-protonify.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-protonify.patch deleted file mode 100644 index 8fb2b81dc..000000000 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-protonify.patch +++ /dev/null @@ -1,4447 +0,0 @@ -From 0b446d37ae366bf9921bc7f99f313ffe1a7530b2 Mon Sep 17 00:00:00 2001 -From: Kirill Artemev -Date: Fri, 20 Dec 2024 21:54:47 +0500 -Subject: [PATCH] ntsync7-mainline - -Signed-off-by: Kirill Artemev ---- - configure | 6 + - configure.ac | 1 + - dlls/kernel32/tests/sync.c | 79 +++ - dlls/ntdll/unix/file.c | 2 +- - dlls/ntdll/unix/process.c | 2 +- - dlls/ntdll/unix/server.c | 28 +- - dlls/ntdll/unix/sync.c | 1007 +++++++++++++++++++++++++++++- - dlls/ntdll/unix/thread.c | 2 +- - dlls/ntdll/unix/unix_private.h | 9 +- - dlls/ntdll/unix/virtual.c | 1 + - dlls/webservices/tests/channel.c | 3 + - include/config.h.in | 3 + - include/wine/server_protocol.h | 97 ++- - server/Makefile.in | 1 + - server/async.c | 2 + - server/atom.c | 1 + - server/change.c | 1 + - server/clipboard.c | 1 + - server/completion.c | 25 +- - server/console.c | 85 ++- - server/debugger.c | 23 + - server/device.c | 33 +- - server/directory.c | 2 + - server/event.c | 53 +- - server/fd.c | 31 +- - server/file.c | 1 + - server/file.h | 1 + - server/handle.c | 1 + - server/hook.c | 1 + - server/inproc_sync.c | 437 +++++++++++++ - server/mailslot.c | 4 + - server/mapping.c | 3 + - server/mutex.c | 39 +- - server/named_pipe.c | 6 + - server/object.c | 8 + - server/object.h | 14 + - server/process.c | 34 + - server/process.h | 1 + - server/protocol.def | 47 ++ - server/queue.c | 88 ++- - server/registry.c | 1 + - server/request.c | 1 + - server/request_handlers.h | 25 + - server/request_trace.h | 54 ++ - server/semaphore.c | 24 +- - server/serial.c | 1 + - server/signal.c | 1 + - server/sock.c | 3 + - server/symlink.c | 1 + - server/thread.c | 38 ++ - server/thread.h | 2 + - server/timer.c | 38 +- - server/token.c | 1 + - server/window.c | 1 + - server/winstation.c | 2 + - 55 files changed, 2343 insertions(+), 33 deletions(-) - create mode 100644 server/inproc_sync.c - -diff --git a/configure b/configure -index beba1346b6a..da17410a661 100755 ---- a/configure -+++ b/configure -@@ -7734,6 +7734,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes - then : - printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h - -+fi -+ac_fn_c_check_header_compile "$LINENO" "linux/ntsync.h" "ac_cv_header_linux_ntsync_h" "$ac_includes_default" -+if test "x$ac_cv_header_linux_ntsync_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_LINUX_NTSYNC_H 1" >>confdefs.h -+ - fi - ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" - if test "x$ac_cv_header_linux_param_h" = xyes -diff --git a/configure.ac b/configure.ac -index 6596f653fb1..c3f925a55a5 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -383,6 +383,7 @@ AC_CHECK_HEADERS(\ - linux/input.h \ - linux/ioctl.h \ - linux/major.h \ -+ linux/ntsync.h \ - linux/param.h \ - linux/serial.h \ - linux/types.h \ -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 49420e4519f..2c69073db10 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -2904,6 +2904,84 @@ static void test_QueueUserAPC(void) - ok(apc_count == 1, "APC count %u\n", apc_count); - } - -+static int zigzag_state, zigzag_count[2], zigzag_stop; -+ -+static DWORD CALLBACK zigzag_event0(void *arg) -+{ -+ HANDLE *events = arg; -+ -+ while (!zigzag_stop) -+ { -+ WaitForSingleObject(events[0], INFINITE); -+ ResetEvent(events[0]); -+ ok(zigzag_state == 0, "got wrong state %d\n", zigzag_state); -+ zigzag_state++; -+ SetEvent(events[1]); -+ zigzag_count[0]++; -+ } -+ trace("thread 0 got done\n"); -+ return 0; -+} -+ -+static DWORD CALLBACK zigzag_event1(void *arg) -+{ -+ HANDLE *events = arg; -+ -+ while (!zigzag_stop) -+ { -+ WaitForSingleObject(events[1], INFINITE); -+ ResetEvent(events[1]); -+ ok(zigzag_state == 1, "got wrong state %d\n", zigzag_state); -+ zigzag_state--; -+ SetEvent(events[0]); -+ zigzag_count[1]++; -+ } -+ trace("thread 1 got done\n"); -+ return 0; -+} -+ -+static void test_zigzag_event(void) -+{ -+ /* The basic idea is to test SetEvent/Wait back and forth between two -+ * threads. Each thread clears their own event, sets some common data, -+ * signals the other's, then waits on their own. We make sure the common -+ * data is always in the right state. We also print performance data. */ -+ -+ HANDLE threads[2], events[2]; -+ BOOL ret; -+ -+ events[0] = CreateEventA(NULL, FALSE, FALSE, NULL); -+ events[1] = CreateEventA(NULL, FALSE, FALSE, NULL); -+ -+ threads[0] = CreateThread(NULL, 0, zigzag_event0, events, 0, NULL); -+ threads[1] = CreateThread(NULL, 0, zigzag_event1, events, 0, NULL); -+ -+ zigzag_state = 0; -+ zigzag_count[0] = zigzag_count[1] = 0; -+ zigzag_stop = 0; -+ -+ trace("starting zigzag test (events)\n"); -+ SetEvent(events[0]); -+ Sleep(2000); -+ zigzag_stop = 1; -+ ret = WaitForMultipleObjects(2, threads, FALSE, INFINITE); -+ trace("%d\n", ret); -+ ok(ret == 0 || ret == 1, "wait failed: %u\n", ret); -+ -+ ok(zigzag_count[0] == zigzag_count[1] || zigzag_count[0] == zigzag_count[1] + 1, -+ "count did not match: %d != %d\n", zigzag_count[0], zigzag_count[1]); -+ -+ /* signal the other thread to finish, if it didn't already -+ * (in theory they both would at the same time, but there's a slight race on teardown if we get -+ * thread 1 SetEvent -> thread 0 ResetEvent -> thread 0 Wait -> thread 1 exits */ -+ zigzag_state = 1-ret; -+ SetEvent(events[1-ret]); -+ ret = WaitForSingleObject(threads[1-ret], 1000); -+ ok(!ret, "wait failed: %u\n", ret); -+ -+ trace("count: %d\n", zigzag_count[0]); -+} -+ - START_TEST(sync) - { - char **argv; -@@ -2974,5 +3052,6 @@ START_TEST(sync) - test_srwlock_example(); - test_alertable_wait(); - test_apc_deadlock(); -+ test_zigzag_event(); - test_crit_section(); - } -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 8bc69557057..755a6e844a4 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -6451,7 +6451,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void - } - if (handle) - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - NtClose( handle ); - } - else /* Unix lock conflict, sleep a bit and retry */ -diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index c3a730379a4..db4d096acd1 100644 ---- a/dlls/ntdll/unix/process.c -+++ b/dlls/ntdll/unix/process.c -@@ -920,7 +920,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ - - /* wait for the new process info to be ready */ - -- NtWaitForSingleObject( process_info, FALSE, NULL ); -+ server_wait_for_object( process_info, FALSE, NULL ); - SERVER_START_REQ( get_new_process_info ) - { - req->info = wine_server_obj_handle( process_info ); -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index b40e7c2a1d7..3579e4f454d 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */ - static int fd_socket = -1; /* socket to exchange file descriptors with the server */ - static int initial_cwd = -1; - static pid_t server_pid; --static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER; -+pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER; - - /* atomically exchange a 64-bit value */ - static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val ) -@@ -789,6 +789,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI - } - - -+/* helper function to perform a server-side wait on an internal handle without -+ * using the fast synchronization path */ -+unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ) -+{ -+ union select_op select_op; -+ UINT flags = SELECT_INTERRUPTIBLE; -+ -+ if (alertable) flags |= SELECT_ALERTABLE; -+ -+ select_op.wait.op = SELECT_WAIT; -+ select_op.wait.handles[0] = wine_server_obj_handle( handle ); -+ return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); -+} -+ -+ - /*********************************************************************** - * NtContinue (NTDLL.@) - */ -@@ -865,7 +880,7 @@ unsigned int server_queue_process_apc( HANDLE process, const union apc_call *cal - } - else - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - - SERVER_START_REQ( get_apc_result ) - { -@@ -1793,12 +1808,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE - return result.dup_handle.status; - } - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - if (options & DUPLICATE_CLOSE_SOURCE) -+ { - fd = remove_fd_from_cache( source ); -+ close_inproc_sync_obj( source ); -+ } - - SERVER_START_REQ( dup_handle ) - { -@@ -1864,12 +1884,16 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) - if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) - return STATUS_SUCCESS; - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - fd = remove_fd_from_cache( handle ); - -+ close_inproc_sync_obj( handle ); -+ - SERVER_START_REQ( close_handle ) - { - req->handle = wine_server_obj_handle( handle ); -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index d486b50001d..c3203debc0b 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -30,9 +30,11 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #ifdef HAVE_SYS_SYSCALL_H - #include -@@ -48,6 +50,7 @@ - #endif - #include - #include -+#include - #include - #include - #include -@@ -57,6 +60,9 @@ - #ifdef HAVE_KQUEUE - # include - #endif -+#ifdef HAVE_LINUX_NTSYNC_H -+# include -+#endif - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -74,9 +80,11 @@ HANDLE keyed_event = 0; - static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - { - if (!timeout) return "(infinite)"; -- return wine_dbgstr_longlong( timeout->QuadPart ); -+ return wine_dbg_sprintf( "%lld.%07ld", (long long)(timeout->QuadPart / TICKSPERSEC), -+ (long)(timeout->QuadPart % TICKSPERSEC) ); - } - -+ - /* return a monotonic time counter, in Win32 ticks */ - static inline ULONGLONG monotonic_counter(void) - { -@@ -301,6 +309,901 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at - } - - -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+static int get_linux_sync_device(void) -+{ -+ static LONG device = -2; -+ -+ if (device == -2) -+ { -+ HANDLE handle; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ SERVER_START_REQ( get_linux_sync_device ) -+ { -+ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if (!ret) -+ { -+ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) -+ { -+ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) -+ { -+ /* someone beat us to it */ -+ if (needs_close) close( fd ); -+ NtClose( handle ); -+ } -+ /* otherwise don't close the device */ -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ NtClose( handle ); -+ } -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ } -+ } -+ return device; -+} -+ -+/* It's possible for synchronization primitives to remain alive even after being -+ * closed, because a thread is still waiting on them. It's rare in practice, and -+ * documented as being undefined behaviour by Microsoft, but it works, and some -+ * applications rely on it. This means we need to refcount handles, and defer -+ * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the in-process synchronization -+ * object, as well as a private refcount. When the client refcount reaches zero, -+ * it closes the handle; when all handles are closed, the server deletes the -+ * in-process synchronization object. -+ * -+ * We also need this for signal-and-wait. The signal and wait operations aren't -+ * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE -+ * for the wait—we need to either do both operations or neither. That means we -+ * need to grab references to both objects, and prevent them from being -+ * destroyed before we're done with them. -+ * -+ * We want lookup of objects from the cache to be very fast; ideally, it should -+ * be lock-free. We achieve this by using atomic modifications to "refcount", -+ * and guaranteeing that all other fields are valid and correct *as long as* -+ * refcount is nonzero, and we store the entire structure in memory which will -+ * never be freed. -+ * -+ * This means that acquiring the object can't use a simple atomic increment; it -+ * has to use a compare-and-swap loop to ensure that it doesn't try to increment -+ * an object with a zero refcount. That's still leagues better than a real lock, -+ * though, and release can be a single atomic decrement. -+ * -+ * It also means that threads modifying the cache need to take a lock, to -+ * prevent other threads from writing to it concurrently. -+ * -+ * It's possible for an object currently in use (by a waiter) to be closed and -+ * the same handle immediately reallocated to a different object. This should be -+ * a very rare situation, and in that case we simply don't cache the handle. -+ */ -+struct inproc_sync_cache_entry -+{ -+ LONG refcount; -+ int fd; -+ enum inproc_sync_type type; -+ unsigned int access; -+ BOOL closed; -+ /* handle to the underlying in-process sync object, stored as obj_handle_t -+ * to save space */ -+ obj_handle_t handle; -+}; -+ -+ -+static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) -+{ -+ /* save the handle and fd now; as soon as the refcount hits 0 we cannot -+ * access the cache anymore */ -+ HANDLE handle = wine_server_ptr_handle( cache->handle ); -+ int fd = cache->fd; -+ LONG refcount = InterlockedDecrement( &cache->refcount ); -+ -+ assert( refcount >= 0 ); -+ -+ if (!refcount) -+ { -+ NTSTATUS ret; -+ -+ /* we can't call NtClose here as we may be inside fd_cache_mutex */ -+ SERVER_START_REQ( close_handle ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ ret = wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+ -+ assert( !ret ); -+ close( fd ); -+ } -+} -+ -+ -+#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) -+#define INPROC_SYNC_CACHE_ENTRIES 128 -+ -+static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; -+static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; -+ -+static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) -+{ -+ unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; -+ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; -+} -+ -+ -+static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, -+ enum inproc_sync_type type, unsigned int access ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ sigset_t sigset; -+ int refcount; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES) -+ { -+ FIXME( "too many allocated handles, not caching %p\n", handle ); -+ return NULL; -+ } -+ -+ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ -+ { -+ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; -+ else -+ { -+ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); -+ void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); -+ if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) -+ munmap( ptr, size ); /* someone beat us to it */ -+ } -+ } -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same -+ * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_inproc_sync_obj() and close_handle. */ -+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) -+ { -+ /* We lost the race with another thread trying to cache this object, or -+ * the handle is currently being used for another object (i.e. it was -+ * closed and then reused). We have no way of knowing which, and in the -+ * latter case we can't cache this object until the old one is -+ * completely destroyed, so always return failure. */ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ return NULL; -+ } -+ -+ cache->handle = inproc_sync; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. -+ * Set the refcount to 2 (one for the handle, one for the caller). */ -+ refcount = InterlockedExchange( &cache->refcount, 2 ); -+ assert( !refcount ); -+ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ return cache; -+} -+ -+ -+/* returns the previous value */ -+static inline LONG interlocked_inc_if_nonzero( LONG *dest ) -+{ -+ LONG val, tmp; -+ for (val = *dest;; val = tmp) -+ { -+ if (!val || (tmp = InterlockedCompareExchange( dest, val + 1, val )) == val) -+ break; -+ } -+ return val; -+} -+ -+ -+static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) -+ return NULL; -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* this load needs acquire semantics [paired with the store in -+ * cache_inproc_sync_obj()] */ -+ if (!interlocked_inc_if_nonzero( &cache->refcount )) -+ return NULL; -+ -+ if (cache->closed) -+ { -+ /* The object is still being used, but "handle" has been closed. The -+ * handle value might have been reused for another object in the -+ * meantime, in which case we have to report that valid object, so -+ * force the caller to check the server. */ -+ release_inproc_sync_obj( cache ); -+ return NULL; -+ } -+ -+ return cache; -+} -+ -+ -+static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) -+{ -+ if (a == b) return TRUE; -+ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ return FALSE; -+} -+ -+ -+/* returns a pointer to a cache entry; if the object could not be cached, -+ * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, -+ ACCESS_MASK desired_access, -+ struct inproc_sync_cache_entry *stack_cache, -+ struct inproc_sync_cache_entry **ret_cache ) -+{ -+ struct inproc_sync_cache_entry *cache; -+ obj_handle_t inproc_sync_handle; -+ enum inproc_sync_type type; -+ unsigned int access; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ /* try to find it in the cache already */ -+ if ((cache = get_cached_inproc_sync_obj( handle ))) -+ { -+ *ret_cache = cache; -+ return STATUS_SUCCESS; -+ } -+ -+ /* try to retrieve it from the server */ -+ SERVER_START_REQ( get_linux_sync_obj ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ if (!(ret = wine_server_call( req ))) -+ { -+ inproc_sync_handle = reply->handle; -+ access = reply->access; -+ type = reply->type; -+ } -+ } -+ SERVER_END_REQ; -+ -+ if (ret) return ret; -+ -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), -+ 0, &fd, &needs_close, NULL, NULL ))) -+ return ret; -+ -+ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); -+ if (!cache) -+ { -+ cache = stack_cache; -+ cache->handle = inproc_sync_handle; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ cache->refcount = 1; -+ } -+ -+ *ret_cache = cache; -+ -+ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((cache->access & desired_access) != desired_access) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ -+ return STATUS_SUCCESS; -+} -+ -+ -+/* caller must hold fd_cache_mutex */ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); -+ -+ if (cache) -+ { -+ cache->closed = TRUE; -+ /* once for the reference we just grabbed, and once for the handle */ -+ release_inproc_sync_obj( cache ); -+ release_inproc_sync_obj( cache ); -+ } -+} -+ -+ -+static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count ) -+{ -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_semaphore_obj( int obj, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_sem_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->CurrentCount = args.count; -+ info->MaximumCount = args.max; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_semaphore_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_set_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_SET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_set_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_reset_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_RESET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_reset_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_pulse_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_PULSE, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_pulse_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_event_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; -+ info->EventState = args.signaled; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_event_obj( cache->fd, cache->type, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_release_mutex_obj( int obj, LONG *prev_count ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ args.owner = GetCurrentThreadId(); -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_UNLOCK, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_MUTANT_LIMIT_EXCEEDED; -+ else if (errno == EPERM) -+ return STATUS_MUTANT_NOT_OWNED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_mutex_obj( cache->fd, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_READ, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOWNERDEAD) -+ { -+ info->AbandonedState = TRUE; -+ info->OwnedByCaller = FALSE; -+ info->CurrentCount = 1; -+ return STATUS_SUCCESS; -+ } -+ else -+ return errno_to_status( errno ); -+ } -+ info->AbandonedState = FALSE; -+ info->OwnedByCaller = (args.owner == GetCurrentThreadId()); -+ info->CurrentCount = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_mutex_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+static void select_queue(void) -+{ -+ SERVER_START_REQ( select_inproc_queue ) -+ { -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static void unselect_queue( BOOL signaled ) -+{ -+ SERVER_START_REQ( unselect_inproc_queue ) -+ { -+ req->signaled = signaled; -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static int get_inproc_alert_obj(void) -+{ -+ struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ HANDLE alert_handle; -+ unsigned int ret; -+ -+ if (data->linux_alert_obj == -1) -+ { -+ SERVER_START_REQ( get_inproc_alert_event ) -+ { -+ if ((ret = wine_server_call( req ))) -+ ERR( "failed to get inproc alert event, status %#x\n", ret ); -+ alert_handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get inproc alert obj, status %#x\n", ret ); -+ data->linux_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. -+ * Manhandling the cache entry here is fine since we're the only thread -+ * that can access our own alert event. */ -+ cache->fd = -1; -+ release_inproc_sync_obj( cache ); -+ NtClose( alert_handle ); -+ } -+ -+ return data->linux_alert_obj; -+} -+ -+static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, -+ BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct ntsync_wait_args args = {0}; -+ unsigned long request; -+ struct timespec now; -+ int ret; -+ -+ if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) -+ { -+ args.timeout = ~(__u64)0; -+ } -+ else if (timeout->QuadPart <= 0) -+ { -+ clock_gettime( CLOCK_MONOTONIC, &now ); -+ args.timeout = (now.tv_sec * NSECPERSEC) + now.tv_nsec + (-timeout->QuadPart * 100); -+ } -+ else -+ { -+ args.timeout = (timeout->QuadPart * 100) - (SECS_1601_TO_1970 * NSECPERSEC); -+ args.flags |= NTSYNC_WAIT_REALTIME; -+ } -+ -+ args.objs = (uintptr_t)objs; -+ args.count = count; -+ args.owner = GetCurrentThreadId(); -+ args.index = ~0u; -+ -+ if (alertable) -+ args.alert = get_inproc_alert_obj(); -+ -+ if (wait_any || count == 1) -+ request = NTSYNC_IOC_WAIT_ANY; -+ else -+ request = NTSYNC_IOC_WAIT_ALL; -+ -+ do -+ { -+ ret = ioctl( device, request, &args ); -+ } while (ret < 0 && errno == EINTR); -+ -+ if (!ret) -+ { -+ if (args.index == count) -+ { -+ static const LARGE_INTEGER timeout; -+ -+ ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &timeout ); -+ assert( ret == STATUS_USER_APC ); -+ return ret; -+ } -+ -+ return wait_any ? args.index : 0; -+ } -+ else if (errno == EOWNERDEAD) -+ return STATUS_ABANDONED + (wait_any ? args.index : 0); -+ else if (errno == ETIMEDOUT) -+ return STATUS_TIMEOUT; -+ else -+ return errno_to_status( errno ); -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; -+ int device, objs[64]; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ DWORD i, j; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ for (i = 0; i < count; ++i) -+ { -+ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) -+ { -+ for (j = 0; j < i; ++j) -+ release_inproc_sync_obj( cache[j] ); -+ return ret; -+ } -+ if (cache[i]->type == INPROC_SYNC_QUEUE) -+ queue = handles[i]; -+ -+ objs[i] = cache[i]->fd; -+ } -+ -+ /* It's common to wait on the message queue alone. Some applications wait -+ * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through inproc_wait(), and since we only need -+ * to go through that path if we're waiting on other objects, just delegate -+ * to the server if we're only waiting on the message queue. */ -+ if (count == 1 && queue) -+ { -+ release_inproc_sync_obj( cache[0] ); -+ return server_wait_for_object( handles[0], alertable, timeout ); -+ } -+ -+ if (queue) select_queue(); -+ -+ ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); -+ -+ if (queue) unselect_queue( handles[ret] == queue ); -+ -+ for (i = 0; i < count; ++i) -+ release_inproc_sync_obj( cache[i] ); -+ -+ return ret; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ int device; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) -+ return ret; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ if (!(signal_cache->access & EVENT_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ break; -+ -+ default: -+ /* can't be signaled */ -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return ret; -+ } -+ -+ if (wait_cache->type == INPROC_SYNC_QUEUE) -+ queue = wait; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ ret = linux_set_event_obj( signal_cache->fd, NULL ); -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ ret = linux_release_mutex_obj( signal_cache->fd, NULL ); -+ break; -+ -+ default: -+ assert( 0 ); -+ break; -+ } -+ -+ if (!ret) -+ { -+ if (queue) select_queue(); -+ ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( !ret ); -+ } -+ -+ release_inproc_sync_obj( signal_cache ); -+ release_inproc_sync_obj( wait_cache ); -+ return ret; -+} -+ -+#else -+ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+} -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+#endif -+ -+ - /****************************************************************************** - * NtCreateSemaphore (NTDLL.@) - */ -@@ -311,6 +1214,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, initial %d, max %d\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)initial, (int)max ); -+ - *handle = 0; - if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -338,6 +1244,8 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -375,6 +1283,12 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - - if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -397,6 +1311,11 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous - { - unsigned int ret; - -+ TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); -+ -+ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( release_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -421,6 +1340,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u, state %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type, state ); -+ - *handle = 0; - if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -448,6 +1370,8 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -473,6 +1397,11 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -492,6 +1421,11 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -521,6 +1455,11 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -552,6 +1491,12 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, - - if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_event ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -577,6 +1522,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, owned %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", owned ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -602,6 +1550,8 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -627,6 +1577,11 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) - { - unsigned int ret; - -+ TRACE( "handle %p, prev_count %p\n", handle, prev_count ); -+ -+ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - SERVER_START_REQ( release_mutex ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -657,6 +1612,12 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, - - if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -+ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); -+ return ret; -+ } -+ - SERVER_START_REQ( query_mutex ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1426,6 +2387,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type ); -+ - *handle = 0; - if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1453,6 +2417,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1506,6 +2472,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) - { - unsigned int ret; - -+ TRACE( "handle %p, state %p\n", handle, state ); -+ - SERVER_START_REQ( cancel_timer ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1574,13 +2542,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO - { - union select_op select_op; - UINT i, flags = SELECT_INTERRUPTIBLE; -+ unsigned int ret; - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - -+ if (TRACE_ON(sync)) -+ { -+ TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); -+ for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); -+ TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); -+ } -+ -+ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ { -+ TRACE( "-> %#x\n", ret ); -+ return ret; -+ } -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; - for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); -- return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - -@@ -1601,9 +2585,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, - { - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS ret; -+ -+ TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) ); - - if (!signal) return STATUS_INVALID_HANDLE; - -+ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; - select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1836,6 +2826,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, flags %#x\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)flags ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -1860,6 +2853,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1886,6 +2881,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -1905,6 +2902,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -2049,7 +3048,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * - } - SERVER_END_REQ; - if (status != STATUS_PENDING) return status; -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) return status; - -@@ -2111,7 +3110,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM - assert( status == STATUS_USER_APC ); - goto done; - } -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) goto done; - -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index cec6b3cb106..74b4eb9673a 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -1801,7 +1801,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma - - if (ret == STATUS_PENDING) - { -- NtWaitForSingleObject( context_handle, FALSE, NULL ); -+ server_wait_for_object( context_handle, FALSE, NULL ); - - SERVER_START_REQ( get_thread_context ) - { -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index f840045f841..8201e2934f3 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -112,6 +112,7 @@ struct ntdll_thread_data - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ - void *jmp_buf; /* setjmp buffer for exception handling */ -+ int linux_alert_obj; /* fd for the linux in-process alert event */ - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -205,6 +206,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); - extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); - extern void start_server( BOOL debug ); - -+extern pthread_mutex_t fd_cache_mutex; -+ - extern unsigned int server_call_unlocked( void *req_ptr ); - extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); - extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -212,6 +215,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t - timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags, - const LARGE_INTEGER *timeout ); -+extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); - extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, - union apc_result *result ); - extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -378,6 +382,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); - - extern void dbg_init(void); - -+extern void close_inproc_sync_obj( HANDLE handle ); -+ - extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - PNTAPCFUNC func, NTSTATUS status ); - extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -386,6 +392,7 @@ extern void call_raise_user_exception_dispatcher(void); - #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ - - #define TICKSPERSEC 10000000 -+#define NSECPERSEC 1000000000 - #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) - - static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -451,7 +458,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio - - static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) - { -- return NtWaitForSingleObject( handle, alertable, NULL ); -+ return server_wait_for_object( handle, alertable, NULL ); - } - - static inline BOOL in_wow64_call(void) -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 0c0a12c394d..7567362a542 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3689,6 +3689,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ thread_data->linux_alert_obj = -1; - list_add_head( &teb_list, &thread_data->entry ); - return teb; - } -diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027fb86d..ddcf8964f23 100644 ---- a/dlls/webservices/tests/channel.c -+++ b/dlls/webservices/tests/channel.c -@@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { - static const char send_record_middle[] = { 0x01, 0x56, 0x0e, 0x42 }; - static const char send_record_end[] = { 0x08, 0x02, 0x6e, 0x73, 0x89, 0xff, 0x01, 0x01 }; - -+#pragma GCC diagnostic ignored "-Warray-bounds" -+#pragma GCC diagnostic ignored "-Wstringop-overflow" -+ - static BOOL send_dict_str( int sock, char *addr, const char *str, int dict_str_count ) - { - char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; -diff --git a/include/config.h.in b/include/config.h.in -index 6033d8674f3..7fb12090dfe 100644 ---- a/include/config.h.in -+++ b/include/config.h.in -@@ -189,6 +189,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_MAJOR_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_NTSYNC_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_PARAM_H - -diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index f524a3dc8b5..a6c74fa79e0 100644 ---- a/include/wine/server_protocol.h -+++ b/include/wine/server_protocol.h -@@ -5881,6 +5881,86 @@ struct set_keyboard_repeat_reply - }; - - -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+ -+struct get_linux_sync_device_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_linux_sync_device_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ -+ -+struct get_linux_sync_obj_request -+{ -+ struct request_header __header; -+ obj_handle_t handle; -+}; -+struct get_linux_sync_obj_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ int type; -+ unsigned int access; -+ char __pad_20[4]; -+}; -+ -+ -+ -+struct select_inproc_queue_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct select_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct unselect_inproc_queue_request -+{ -+ struct request_header __header; -+ int signaled; -+}; -+struct unselect_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct get_inproc_alert_event_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_inproc_alert_event_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ - enum request - { - REQ_new_process, -@@ -6175,6 +6255,11 @@ enum request - REQ_resume_process, - REQ_get_next_thread, - REQ_set_keyboard_repeat, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_select_inproc_queue, -+ REQ_unselect_inproc_queue, -+ REQ_get_inproc_alert_event, - REQ_NB_REQUESTS - }; - -@@ -6474,6 +6559,11 @@ union generic_request - struct resume_process_request resume_process_request; - struct get_next_thread_request get_next_thread_request; - struct set_keyboard_repeat_request set_keyboard_repeat_request; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct select_inproc_queue_request select_inproc_queue_request; -+ struct unselect_inproc_queue_request unselect_inproc_queue_request; -+ struct get_inproc_alert_event_request get_inproc_alert_event_request; - }; - union generic_reply - { -@@ -6771,8 +6861,13 @@ union generic_reply - struct resume_process_reply resume_process_reply; - struct get_next_thread_reply get_next_thread_reply; - struct set_keyboard_repeat_reply set_keyboard_repeat_reply; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct select_inproc_queue_reply select_inproc_queue_reply; -+ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; -+ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; - }; - --#define SERVER_PROTOCOL_VERSION 854 -+#define SERVER_PROTOCOL_VERSION 855 - - #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ -diff --git a/server/Makefile.in b/server/Makefile.in -index 7e571ac2ba6..91ec73dabc5 100644 ---- a/server/Makefile.in -+++ b/server/Makefile.in -@@ -16,6 +16,7 @@ SOURCES = \ - file.c \ - handle.c \ - hook.c \ -+ inproc_sync.c \ - mach.c \ - mailslot.c \ - main.c \ -diff --git a/server/async.c b/server/async.c -index d2d929c9709..e8b50a72f7e 100644 ---- a/server/async.c -+++ b/server/async.c -@@ -90,6 +90,7 @@ static const struct object_ops async_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - async_destroy /* destroy */ - }; -@@ -710,6 +711,7 @@ static const struct object_ops iosb_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - iosb_destroy /* destroy */ - }; -diff --git a/server/atom.c b/server/atom.c -index ff0799f5880..04951e628ba 100644 ---- a/server/atom.c -+++ b/server/atom.c -@@ -91,6 +91,7 @@ static const struct object_ops atom_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - atom_table_destroy /* destroy */ - }; -diff --git a/server/change.c b/server/change.c -index f42ce066340..92d321c8784 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -124,6 +124,7 @@ static const struct object_ops dir_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - dir_close_handle, /* close_handle */ - dir_destroy /* destroy */ - }; -diff --git a/server/clipboard.c b/server/clipboard.c -index 91f159bc7c9..a2258ae869d 100644 ---- a/server/clipboard.c -+++ b/server/clipboard.c -@@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - clipboard_destroy /* destroy */ - }; -diff --git a/server/completion.c b/server/completion.c -index 99680ae0680..529ed9d7956 100644 ---- a/server/completion.c -+++ b/server/completion.c -@@ -77,6 +77,7 @@ struct completion - struct list wait_queue; - unsigned int depth; - int closed; -+ struct inproc_sync *inproc_sync; - }; - - static void completion_wait_dump( struct object*, int ); -@@ -104,6 +105,7 @@ static const struct object_ops completion_wait_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - completion_wait_destroy /* destroy */ - }; -@@ -156,6 +158,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent - static void completion_dump( struct object*, int ); - static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); - static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); - static void completion_destroy( struct object * ); - - static const struct object_ops completion_ops = -@@ -178,6 +181,7 @@ static const struct object_ops completion_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_inproc_sync,/* get_inproc_sync */ - completion_close_handle, /* close_handle */ - completion_destroy /* destroy */ - }; -@@ -191,6 +195,7 @@ static void completion_destroy( struct object *obj) - { - free( tmp ); - } -+ if (completion->inproc_sync) release_object( completion->inproc_sync ); - } - - static void completion_dump( struct object *obj, int verbose ) -@@ -228,6 +233,7 @@ static int completion_close_handle( struct object *obj, struct process *process, - } - completion->closed = 1; - wake_up( obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); - return 1; - } - -@@ -261,6 +267,16 @@ static struct completion_wait *create_completion_wait( struct thread *thread ) - return wait; - } - -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) -+{ -+ struct completion *completion = (struct completion *)obj; -+ -+ if (!completion->inproc_sync) -+ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->inproc_sync) grab_object( completion->inproc_sync ); -+ return completion->inproc_sync; -+} -+ - static struct completion *create_completion( struct object *root, const struct unicode_str *name, - unsigned int attr, unsigned int concurrent, - const struct security_descriptor *sd ) -@@ -275,6 +291,7 @@ static struct completion *create_completion( struct object *root, const struct u - list_init( &completion->wait_queue ); - completion->depth = 0; - completion->closed = 0; -+ completion->inproc_sync = NULL; - } - } - -@@ -307,7 +324,11 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ - wake_up( &wait->obj, 1 ); - if (list_empty( &completion->queue )) return; - } -- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ if (!list_empty( &completion->queue )) -+ { -+ wake_up( &completion->obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); -+ } - } - - /* create a completion */ -@@ -408,6 +429,8 @@ DECL_HANDLER(remove_completion) - reply->information = msg->information; - free( msg ); - reply->wait_handle = 0; -+ if (list_empty( &completion->queue )) -+ reset_inproc_event( completion->inproc_sync ); - } - - release_object( completion ); -diff --git a/server/console.c b/server/console.c -index c3e7bf57e92..b4058f2d002 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -61,6 +61,7 @@ struct console - struct fd *fd; /* for bare console, attached input fd */ - struct async_queue ioctl_q; /* ioctl queue */ - struct async_queue read_q; /* read queue */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_dump( struct object *obj, int verbose ); -@@ -72,6 +73,7 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st - static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); - static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_ops = - { -@@ -93,6 +95,7 @@ static const struct object_ops console_ops = - NULL, /* unlink_name */ - console_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_destroy /* destroy */ - }; -@@ -139,6 +142,7 @@ struct console_server - unsigned int once_input : 1; /* flag if input thread has already been requested */ - int term_fd; /* UNIX terminal fd */ - struct termios termios; /* original termios */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_server_dump( struct object *obj, int verbose ); -@@ -149,6 +153,7 @@ static struct object *console_server_lookup_name( struct object *obj, struct uni - unsigned int attr, struct object *root ); - static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_server_ops = - { -@@ -170,6 +175,7 @@ static const struct object_ops console_server_ops = - NULL, /* unlink_name */ - console_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_server_destroy /* destroy */ - }; -@@ -218,6 +224,7 @@ static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *screen_buffer_get_fd( struct object *obj ); - static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); - - static const struct object_ops screen_buffer_ops = - { -@@ -239,6 +246,7 @@ static const struct object_ops screen_buffer_ops = - NULL, /* unlink_name */ - screen_buffer_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - screen_buffer_destroy /* destroy */ - }; -@@ -288,6 +296,7 @@ static const struct object_ops console_device_ops = - default_unlink_name, /* unlink_name */ - console_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -303,6 +312,7 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - unsigned int sharing, unsigned int options ); - static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); - static struct fd *console_input_get_fd( struct object *obj ); -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); - static void console_input_destroy( struct object *obj ); - - static const struct object_ops console_input_ops = -@@ -325,6 +335,7 @@ static const struct object_ops console_input_ops = - default_unlink_name, /* unlink_name */ - console_input_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_input_destroy /* destroy */ - }; -@@ -360,6 +371,7 @@ static int console_output_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *console_output_get_fd( struct object *obj ); - static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); - static void console_output_destroy( struct object *obj ); - - static const struct object_ops console_output_ops = -@@ -382,6 +394,7 @@ static const struct object_ops console_output_ops = - default_unlink_name, /* unlink_name */ - console_output_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_output_destroy /* destroy */ - }; -@@ -440,6 +453,7 @@ static const struct object_ops console_connection_ops = - default_unlink_name, /* unlink_name */ - console_connection_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - console_connection_close_handle, /* close_handle */ - console_connection_destroy /* destroy */ - }; -@@ -539,6 +553,7 @@ static struct object *create_console(void) - console->server = NULL; - console->fd = NULL; - console->last_id = 0; -+ console->inproc_sync = NULL; - init_async_queue( &console->ioctl_q ); - init_async_queue( &console->read_q ); - -@@ -578,6 +593,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u - } - list_add_tail( &server->queue, &ioctl->entry ); - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - if (async) set_error( STATUS_PENDING ); - return 1; - } -@@ -610,6 +626,7 @@ static void disconnect_console_server( struct console_server *server ) - server->console->server = NULL; - server->console = NULL; - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - } - } - -@@ -764,6 +781,8 @@ static void console_destroy( struct object *obj ) - free_async_queue( &console->read_q ); - if (console->fd) - release_object( console->fd ); -+ -+ if (console->inproc_sync) release_object( console->inproc_sync ); - } - - static struct object *create_console_connection( struct console *console ) -@@ -817,6 +836,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access - return grab_object( obj ); - } - -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ) -+{ -+ struct console *console = (struct console *)obj; -+ -+ if (!console->inproc_sync) -+ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->inproc_sync) grab_object( console->inproc_sync ); -+ return console->inproc_sync; -+} -+ - static void screen_buffer_dump( struct object *obj, int verbose ) - { - struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -866,6 +895,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) - return NULL; - } - -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) -+{ -+ struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -+ if (!screen_buffer->input) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( &screen_buffer->input->obj ); -+} -+ - static void console_server_dump( struct object *obj, int verbose ) - { - assert( obj->ops == &console_server_ops ); -@@ -878,6 +918,7 @@ static void console_server_destroy( struct object *obj ) - assert( obj->ops == &console_server_ops ); - disconnect_console_server( server ); - if (server->fd) release_object( server->fd ); -+ if (server->inproc_sync) release_object( server->inproc_sync ); - } - - static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -938,6 +979,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) -+{ -+ struct console_server *server = (struct console_server *)obj; -+ int signaled = !server->console || !list_empty( &server->queue ); -+ -+ if (!server->inproc_sync) -+ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (server->inproc_sync) grab_object( server->inproc_sync ); -+ return server->inproc_sync; -+} -+ - static struct object *create_console_server( void ) - { - struct console_server *server; -@@ -949,6 +1001,7 @@ static struct object *create_console_server( void ) - server->term_fd = -1; - list_init( &server->queue ); - list_init( &server->read_queue ); -+ server->inproc_sync = NULL; - server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); - if (!server->fd) - { -@@ -1414,6 +1467,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_input_destroy( struct object *obj ) - { - struct console_input *console_input = (struct console_input *)obj; -@@ -1486,6 +1549,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console || !current->process->console->active) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_output_destroy( struct object *obj ) - { - struct console_output *console_output = (struct console_output *)obj; -@@ -1543,11 +1616,16 @@ DECL_HANDLER(get_next_console_request) - - if (!server->console->renderer) server->console->renderer = current; - -- if (!req->signal) server->console->signaled = 0; -+ if (!req->signal) -+ { -+ server->console->signaled = 0; -+ reset_inproc_event( server->console->inproc_sync ); -+ } - else if (!server->console->signaled) - { - server->console->signaled = 1; - wake_up( &server->console->obj, 0 ); -+ set_inproc_event( server->console->inproc_sync ); - } - - if (req->read) -@@ -1569,6 +1647,8 @@ DECL_HANDLER(get_next_console_request) - /* set result of previous ioctl */ - ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); - list_remove( &ioctl->entry ); -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - } - - if (ioctl) -@@ -1655,5 +1735,8 @@ DECL_HANDLER(get_next_console_request) - set_error( STATUS_PENDING ); - } - -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); -+ - release_object( server ); - } -diff --git a/server/debugger.c b/server/debugger.c -index 39a740e07e5..35449172eaa 100644 ---- a/server/debugger.c -+++ b/server/debugger.c -@@ -71,6 +71,7 @@ struct debug_obj - struct object obj; /* object header */ - struct list event_queue; /* pending events queue */ - unsigned int flags; /* debug flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - -@@ -98,12 +99,14 @@ static const struct object_ops debug_event_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_event_destroy /* destroy */ - }; - - static void debug_obj_dump( struct object *obj, int verbose ); - static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); - static void debug_obj_destroy( struct object *obj ); - - static const struct object_ops debug_obj_ops = -@@ -126,6 +129,7 @@ static const struct object_ops debug_obj_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_obj_destroy /* destroy */ - }; -@@ -253,6 +257,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) - /* grab reference since debugger could be killed while trying to wake up */ - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -265,6 +270,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event - { - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -330,6 +336,17 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr - return find_event_to_send( debug_obj ) != NULL; - } - -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) -+{ -+ struct debug_obj *debug_obj = (struct debug_obj *)obj; -+ int signaled = find_event_to_send( debug_obj ) != NULL; -+ -+ if (!debug_obj->inproc_sync) -+ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); -+ return debug_obj->inproc_sync; -+} -+ - static void debug_obj_destroy( struct object *obj ) - { - struct list *ptr; -@@ -342,6 +359,8 @@ static void debug_obj_destroy( struct object *obj ) - /* free all pending events */ - while ((ptr = list_head( &debug_obj->event_queue ))) - unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); -+ -+ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); - } - - struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) -@@ -361,6 +380,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni - { - debug_obj->flags = flags; - list_init( &debug_obj->event_queue ); -+ debug_obj->inproc_sync = NULL; - } - } - return debug_obj; -@@ -569,6 +589,9 @@ DECL_HANDLER(wait_debug_event) - reply->tid = get_thread_id( event->sender ); - alloc_event_handles( event, current->process ); - set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); -+ -+ if (!find_event_to_send( debug_obj )) -+ reset_inproc_event( debug_obj->inproc_sync ); - } - else - { -diff --git a/server/device.c b/server/device.c -index cab09700d8c..72410c2da8b 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - irp_call_destroy /* destroy */ - }; -@@ -92,10 +93,12 @@ struct device_manager - struct list requests; /* list of pending irps across all devices */ - struct irp_call *current_call; /* call currently executed on client side */ - struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void device_manager_dump( struct object *obj, int verbose ); - static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); - static void device_manager_destroy( struct object *obj ); - - static const struct object_ops device_manager_ops = -@@ -118,6 +121,7 @@ static const struct object_ops device_manager_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_manager_destroy /* destroy */ - }; -@@ -175,6 +179,7 @@ static const struct object_ops device_ops = - default_unlink_name, /* unlink_name */ - device_open_file, /* open_file */ - device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -227,6 +232,7 @@ static const struct object_ops device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - device_file_close_handle, /* close_handle */ - device_file_destroy /* destroy */ - }; -@@ -418,7 +424,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i - irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; - if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); - list_add_tail( &manager->requests, &irp->mgr_entry ); -- if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ -+ if (list_head( &manager->requests ) == &irp->mgr_entry) -+ { -+ /* first one */ -+ wake_up( &manager->obj, 0 ); -+ set_inproc_event( manager->inproc_sync ); -+ } - } - - static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -752,6 +763,9 @@ static void delete_file( struct device_file *file ) - set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); - } - -+ if (list_empty( &file->device->manager->requests )) -+ reset_inproc_event( file->device->manager->inproc_sync ); -+ - release_object( file ); - } - -@@ -783,6 +797,16 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry - return !list_empty( &manager->requests ); - } - -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) -+{ -+ struct device_manager *manager = (struct device_manager *)obj; -+ -+ if (!manager->inproc_sync) -+ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->inproc_sync) grab_object( manager->inproc_sync ); -+ return manager->inproc_sync; -+} -+ - static void device_manager_destroy( struct object *obj ) - { - struct device_manager *manager = (struct device_manager *)obj; -@@ -817,6 +841,8 @@ static void device_manager_destroy( struct object *obj ) - assert( !irp->file && !irp->async ); - release_object( irp ); - } -+ -+ if (manager->inproc_sync) release_object( manager->inproc_sync ); - } - - static struct device_manager *create_device_manager(void) -@@ -826,6 +852,7 @@ static struct device_manager *create_device_manager(void) - if ((manager = alloc_object( &device_manager_ops ))) - { - manager->current_call = NULL; -+ manager->inproc_sync = NULL; - list_init( &manager->devices ); - list_init( &manager->requests ); - wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -@@ -1015,6 +1042,10 @@ DECL_HANDLER(get_next_device_request) - } - list_remove( &irp->mgr_entry ); - list_init( &irp->mgr_entry ); -+ -+ if (list_empty( &manager->requests )) -+ reset_inproc_event( manager->inproc_sync ); -+ - /* we already own the object if it's only on manager queue */ - if (irp->file) grab_object( irp ); - manager->current_call = irp; -diff --git a/server/directory.c b/server/directory.c -index fd689c561bc..40cb9b95999 100644 ---- a/server/directory.c -+++ b/server/directory.c -@@ -81,6 +81,7 @@ static const struct object_ops object_type_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -131,6 +132,7 @@ static const struct object_ops directory_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - directory_destroy /* destroy */ - }; -diff --git a/server/event.c b/server/event.c -index ad7c09acc99..4fb44d70039 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -56,6 +56,7 @@ struct event - struct list kernel_object; /* list of kernel object pointers */ - int manual_reset; /* is it a manual reset event? */ - int signaled; /* event has been signaled */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void event_dump( struct object *obj, int verbose ); -@@ -63,6 +64,8 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int event_signal( struct object *obj, unsigned int access); - static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ); -+static void event_destroy( struct object *obj ); - - static const struct object_ops event_ops = - { -@@ -84,8 +87,9 @@ static const struct object_ops event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ event_destroy /* destroy */ - }; - - -@@ -106,10 +110,13 @@ struct type_descr keyed_event_type = - struct keyed_event - { - struct object obj; /* object header */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void keyed_event_dump( struct object *obj, int verbose ); - static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); -+static void keyed_event_destroy( struct object *obj ); - - static const struct object_ops keyed_event_ops = - { -@@ -131,8 +138,9 @@ static const struct object_ops keyed_event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ keyed_event_destroy /* destroy */ - }; - - -@@ -150,6 +158,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; -+ event->inproc_sync = NULL; - } - } - return event; -@@ -173,11 +182,13 @@ void set_event( struct event *event ) - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); -+ set_inproc_event( event->inproc_sync ); - } - - void reset_event( struct event *event ) - { - event->signaled = 0; -+ reset_inproc_event( event->inproc_sync ); - } - - static void event_dump( struct object *obj, int verbose ) -@@ -223,6 +234,26 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) - return &event->kernel_object; - } - -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (!event->inproc_sync) -+ { -+ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; -+ event->inproc_sync = create_inproc_event( type, event->signaled ); -+ } -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void event_destroy( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, - unsigned int attr, const struct security_descriptor *sd ) - { -@@ -233,6 +264,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod - if (get_error() != STATUS_OBJECT_NAME_EXISTS) - { - /* initialize it if it didn't already exist */ -+ event->inproc_sync = NULL; - } - } - return event; -@@ -276,6 +308,23 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en - return 0; - } - -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (!event->inproc_sync) -+ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void keyed_event_destroy( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - /* create an event */ - DECL_HANDLER(create_event) - { -diff --git a/server/fd.c b/server/fd.c -index ce32e7f8397..77ac22b9655 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -154,6 +154,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -179,6 +180,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -220,6 +222,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -260,6 +263,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -302,6 +306,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1572,6 +1577,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -+ if (fd->inproc_sync) release_object( fd->inproc_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1690,6 +1696,7 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); - init_async_queue( &fd->wait_q ); -@@ -1730,6 +1737,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); -@@ -2140,7 +2148,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ set_inproc_event( fd->inproc_sync ); -+ } -+ else -+ { -+ reset_inproc_event( fd->inproc_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2166,6 +2182,19 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - -+struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) -+{ -+ struct fd *fd = get_obj_fd( obj ); -+ struct inproc_sync *ret; -+ -+ if (!fd->inproc_sync) -+ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->inproc_sync; -+ release_object( fd ); -+ if (ret) grab_object( ret ); -+ return ret; -+} -+ - int default_fd_get_poll_events( struct fd *fd ) - { - int events = 0; -diff --git a/server/file.c b/server/file.c -index 8f6566a0077..bab203b1914 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -106,6 +106,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index 4f5fc7b26f1..882976e9e02 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -109,6 +109,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); -+extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); - 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 -index e65831b3b22..29b43789372 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index c2d2823cd61..c45900549fc 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -93,6 +93,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; -diff --git a/server/inproc_sync.c b/server/inproc_sync.c -new file mode 100644 -index 00000000000..6dd50d79bc0 ---- /dev/null -+++ b/server/inproc_sync.c -@@ -0,0 +1,437 @@ -+/* -+ * In-process synchronization primitives -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "ntstatus.h" -+#define WIN32_NO_STATUS -+#include "winternl.h" -+ -+#include "file.h" -+#include "handle.h" -+#include "request.h" -+#include "thread.h" -+ -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct linux_device -+{ -+ struct object obj; /* object header */ -+ struct fd *fd; /* fd for unix fd */ -+}; -+ -+static struct linux_device *linux_device_object; -+ -+static void linux_device_dump( struct object *obj, int verbose ); -+static struct fd *linux_device_get_fd( struct object *obj ); -+static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); -+ -+static const struct object_ops linux_device_ops = -+{ -+ sizeof(struct linux_device), /* size */ -+ &no_type, /* type */ -+ linux_device_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_device_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_device_destroy /* destroy */ -+}; -+ -+static const struct fd_ops inproc_sync_fd_ops = -+{ -+ default_fd_get_poll_events, /* get_poll_events */ -+ default_poll_event, /* poll_event */ -+ inproc_sync_get_fd_type, /* get_fd_type */ -+ no_fd_read, /* read */ -+ no_fd_write, /* write */ -+ no_fd_flush, /* flush */ -+ no_fd_get_file_info, /* get_file_info */ -+ no_fd_get_volume_info, /* get_volume_info */ -+ no_fd_ioctl, /* ioctl */ -+ default_fd_cancel_async, /* cancel_async */ -+ no_fd_queue_async, /* queue_async */ -+ default_fd_reselect_async /* reselect_async */ -+}; -+ -+static void linux_device_dump( struct object *obj, int verbose ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); -+} -+ -+static struct fd *linux_device_get_fd( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ return (struct fd *)grab_object( device->fd ); -+} -+ -+static void linux_device_destroy( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ if (device->fd) release_object( device->fd ); -+ linux_device_object = NULL; -+} -+ -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) -+{ -+ return FD_TYPE_FILE; -+} -+ -+static struct linux_device *get_linux_device(void) -+{ -+ struct linux_device *device; -+ static int initialized; -+ int unix_fd; -+ -+ if (initialized) -+ { -+ if (linux_device_object) -+ grab_object( linux_device_object ); -+ else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return linux_device_object; -+ } -+ -+ if (getenv( "WINE_DISABLE_FAST_SYNC" ) && atoi( getenv( "WINE_DISABLE_FAST_SYNC" ) )) -+ { -+ static int once; -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ if (!once++) fprintf(stderr, "ntsync is explicitly disabled.\n"); -+ initialized = 1; -+ return NULL; -+ } -+ -+ unix_fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY ); -+ if (unix_fd == -1) -+ { -+ static int once; -+ file_set_error(); -+ if (!once++) fprintf(stderr, "Cannot open /dev/ntsync: %s\n", strerror(errno)); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device = alloc_object( &linux_device_ops ))) -+ { -+ close( unix_fd ); -+ set_error( STATUS_NO_MEMORY ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) -+ { -+ release_object( device ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ fprintf( stderr, "wine: using fast synchronization.\n" ); -+ linux_device_object = device; -+ initialized = 1; -+ return device; -+} -+ -+struct inproc_sync -+{ -+ struct object obj; -+ enum inproc_sync_type type; -+ struct fd *fd; -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ); -+static void linux_obj_destroy( struct object *obj ); -+static struct fd *linux_obj_get_fd( struct object *obj ); -+ -+static const struct object_ops linux_obj_ops = -+{ -+ sizeof(struct inproc_sync), /* size */ -+ &no_type, /* type */ -+ linux_obj_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_obj_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_obj_destroy /* destroy */ -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); -+} -+ -+static void linux_obj_destroy( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ if (inproc_sync->fd) release_object( inproc_sync->fd ); -+} -+ -+static struct fd *linux_obj_get_fd( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( inproc_sync->fd ); -+} -+ -+static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) -+{ -+ struct inproc_sync *inproc_sync; -+ -+ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) -+ { -+ close( unix_fd ); -+ return NULL; -+ } -+ -+ inproc_sync->type = type; -+ -+ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) -+ { -+ release_object( inproc_sync ); -+ return NULL; -+ } -+ -+ return inproc_sync; -+} -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ struct ntsync_event_args args; -+ struct linux_device *device; -+ int event; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.signaled = signaled; -+ switch (type) -+ { -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_AUTO_SERVER: -+ args.manual = 0; -+ break; -+ -+ case INPROC_SYNC_MANUAL_EVENT: -+ case INPROC_SYNC_MANUAL_SERVER: -+ case INPROC_SYNC_QUEUE: -+ args.manual = 1; -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ case INPROC_SYNC_SEMAPHORE: -+ assert(0); -+ break; -+ } -+ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ release_object( device ); -+ -+ return create_inproc_sync( type, event ); -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ struct ntsync_sem_args args; -+ struct linux_device *device; -+ int semaphore; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.count = count; -+ args.max = max; -+ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ struct ntsync_mutex_args args; -+ struct linux_device *device; -+ int mutex; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.owner = owner; -+ args.count = count; -+ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); -+} -+ -+void reset_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); -+} -+ -+#else -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+} -+ -+void reset_inproc_event( struct inproc_sync *obj ) -+{ -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+} -+ -+#endif -+ -+DECL_HANDLER(get_linux_sync_device) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct linux_device *device; -+ -+ if ((device = get_linux_device())) -+ { -+ reply->handle = alloc_handle( current->process, device, 0, 0 ); -+ release_object( device ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -+ -+DECL_HANDLER(get_linux_sync_obj) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct object *obj; -+ -+ if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) -+ { -+ struct inproc_sync *inproc_sync; -+ -+ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) -+ { -+ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); -+ reply->type = inproc_sync->type; -+ reply->access = get_handle_access( current->process, req->handle ); -+ release_object( inproc_sync ); -+ } -+ release_object( obj ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -diff --git a/server/mailslot.c b/server/mailslot.c -index b14954ad6c3..701ac35f393 100644 ---- a/server/mailslot.c -+++ b/server/mailslot.c -@@ -93,6 +93,7 @@ static const struct object_ops mailslot_ops = - default_unlink_name, /* unlink_name */ - mailslot_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync,/* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_destroy /* destroy */ - }; -@@ -154,6 +155,7 @@ static const struct object_ops mail_writer_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mail_writer_destroy /* destroy */ - }; -@@ -219,6 +221,7 @@ static const struct object_ops mailslot_device_ops = - default_unlink_name, /* unlink_name */ - mailslot_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_destroy /* destroy */ - }; -@@ -249,6 +252,7 @@ static const struct object_ops mailslot_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_file_destroy /* destroy */ - }; -diff --git a/server/mapping.c b/server/mapping.c -index 4bdd7c5080a..7c715a87457 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -79,6 +79,7 @@ static const struct object_ops ranges_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ranges_destroy /* destroy */ - }; -@@ -115,6 +116,7 @@ static const struct object_ops shared_map_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - shared_map_destroy /* destroy */ - }; -@@ -188,6 +190,7 @@ static const struct object_ops mapping_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mapping_destroy /* destroy */ - }; -diff --git a/server/mutex.c b/server/mutex.c -index af0efe72132..a4374317760 100644 ---- a/server/mutex.c -+++ b/server/mutex.c -@@ -38,6 +38,8 @@ - - static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; - -+static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); -+ - struct type_descr mutex_type = - { - { mutex_name, sizeof(mutex_name) }, /* name */ -@@ -57,6 +59,8 @@ struct mutex - unsigned int count; /* recursion count */ - int abandoned; /* has it been abandoned? */ - struct list entry; /* entry in owner thread mutex list */ -+ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void mutex_dump( struct object *obj, int verbose ); -@@ -64,6 +68,7 @@ static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_destroy( struct object *obj ); - static int mutex_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); - - static const struct object_ops mutex_ops = - { -@@ -85,6 +90,7 @@ static const struct object_ops mutex_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mutex_destroy /* destroy */ - }; -@@ -127,6 +133,7 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - mutex->owner = NULL; - mutex->abandoned = 0; - if (owned) do_grab( mutex, current ); -+ mutex->inproc_sync = NULL; - } - } - return mutex; -@@ -134,16 +141,20 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - - void abandon_mutexes( struct thread *thread ) - { -+ struct mutex *mutex; - struct list *ptr; - - while ((ptr = list_head( &thread->mutex_list )) != NULL) - { -- struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry ); -+ mutex = LIST_ENTRY( ptr, struct mutex, entry ); - assert( mutex->owner == thread ); - mutex->count = 0; - mutex->abandoned = 1; - do_release( mutex ); - } -+ -+ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) -+ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); - } - - static void mutex_dump( struct object *obj, int verbose ) -@@ -189,14 +200,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) - return 1; - } - -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) -+{ -+ struct mutex *mutex = (struct mutex *)obj; -+ -+ if (!mutex->inproc_sync) -+ { -+ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); -+ } -+ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); -+ return mutex->inproc_sync; -+} -+ - static void mutex_destroy( struct object *obj ) - { - struct mutex *mutex = (struct mutex *)obj; - assert( obj->ops == &mutex_ops ); - -- if (!mutex->count) return; -- mutex->count = 0; -- do_release( mutex ); -+ if (mutex->count) -+ { -+ mutex->count = 0; -+ do_release( mutex ); -+ } -+ if (mutex->inproc_sync) -+ { -+ release_object( mutex->inproc_sync ); -+ list_remove( &mutex->inproc_mutexes_entry ); -+ } - } - - /* create a mutex */ -diff --git a/server/named_pipe.c b/server/named_pipe.c -index 59a90c36663..04e8f49fb79 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops = - default_unlink_name, /* unlink_name */ - named_pipe_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_destroy /* destroy */ - }; -@@ -179,6 +180,7 @@ static const struct object_ops pipe_server_ops = - NULL, /* unlink_name */ - pipe_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_server_destroy /* destroy */ - }; -@@ -223,6 +225,7 @@ static const struct object_ops pipe_client_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_end_destroy /* destroy */ - }; -@@ -270,6 +273,7 @@ static const struct object_ops named_pipe_device_ops = - default_unlink_name, /* unlink_name */ - named_pipe_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_destroy /* destroy */ - }; -@@ -301,6 +305,7 @@ static const struct object_ops named_pipe_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_file_destroy /* destroy */ - }; -@@ -351,6 +356,7 @@ static const struct object_ops named_pipe_dir_ops = - NULL, /* unlink_name */ - named_pipe_dir_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_dir_destroy /* destroy */ - }; -diff --git a/server/object.c b/server/object.c -index cd368ef724a..b07bc59bde1 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -120,6 +120,7 @@ static const struct object_ops apc_reserve_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -144,6 +145,7 @@ static const struct object_ops completion_reserve_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -639,6 +641,12 @@ struct fd *no_get_fd( struct object *obj ) - return NULL; - } - -+struct inproc_sync *no_get_inproc_sync( struct object *obj ) -+{ -+ set_error( STATUS_OBJECT_TYPE_MISMATCH ); -+ return NULL; -+} -+ - unsigned int default_map_access( struct object *obj, unsigned int access ) - { - return map_access( access, &obj->ops->type->mapping ); -diff --git a/server/object.h b/server/object.h -index 7555f564a08..b1612623b0f 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -42,6 +42,7 @@ struct async; - struct async_queue; - struct winstation; - struct object_type; -+struct inproc_sync; - - - struct unicode_str -@@ -103,6 +104,8 @@ struct object_ops - unsigned int options); - /* return list of kernel objects */ - struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable in-process synchronization handle to this object */ -+ struct inproc_sync *(*get_inproc_sync)(struct object *); - /* close a handle to this object */ - int (*close_handle)(struct object *,struct process *,obj_handle_t); - /* destroy on refcount == 0 */ -@@ -228,6 +231,17 @@ extern void reset_event( struct event *event ); - - extern void abandon_mutexes( struct thread *thread ); - -+/* in-process synchronization functions */ -+ -+extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); -+extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); -+extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); -+extern void set_inproc_event( struct inproc_sync *obj ); -+extern void reset_inproc_event( struct inproc_sync *obj ); -+extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); -+ -+extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); -+ - /* serial functions */ - - int get_serial_async_timeout(struct object *obj, int type, int count); -diff --git a/server/process.c b/server/process.c -index e06350f7311..fed2f95bd30 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -94,6 +94,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access - static struct security_descriptor *process_get_sd( struct object *obj ); - static void process_poll_event( struct fd *fd, int event ); - static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ); - static void process_destroy( struct object *obj ); - static void terminate_process( struct process *process, struct thread *skip, int exit_code ); - -@@ -117,6 +118,7 @@ static const struct object_ops process_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - process_destroy /* destroy */ - }; -@@ -168,6 +170,7 @@ static const struct object_ops startup_info_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - startup_info_destroy /* destroy */ - }; -@@ -190,6 +193,7 @@ struct type_descr job_type = - - static void job_dump( struct object *obj, int verbose ); - static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ); - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void job_destroy( struct object *obj ); - -@@ -207,6 +211,7 @@ struct job - struct job *parent; - struct list parent_job_entry; /* list entry for parent job */ - struct list child_job_list; /* list of child jobs */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static const struct object_ops job_ops = -@@ -229,6 +234,7 @@ static const struct object_ops job_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_inproc_sync, /* get_inproc_sync */ - job_close_handle, /* close_handle */ - job_destroy /* destroy */ - }; -@@ -253,6 +259,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_ - job->completion_port = NULL; - job->completion_key = 0; - job->parent = NULL; -+ job->inproc_sync = NULL; - } - } - return job; -@@ -409,6 +416,17 @@ static void terminate_job( struct job *job, int exit_code ) - job->terminating = 0; - job->signaled = 1; - wake_up( &job->obj, 0 ); -+ set_inproc_event( job->inproc_sync ); -+} -+ -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ) -+{ -+ struct job *job = (struct job *)obj; -+ -+ if (!job->inproc_sync) -+ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->inproc_sync) grab_object( job->inproc_sync ); -+ return job->inproc_sync; - } - - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) -@@ -439,6 +457,8 @@ static void job_destroy( struct object *obj ) - list_remove( &job->parent_job_entry ); - release_object( job->parent ); - } -+ -+ if (job->inproc_sync) release_object( job->inproc_sync ); - } - - static void job_dump( struct object *obj, int verbose ) -@@ -684,6 +704,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_device_count = 0; - process->rawinput_mouse = NULL; - process->rawinput_kbd = NULL; -+ process->inproc_sync = NULL; - memset( &process->image_info, 0, sizeof(process->image_info) ); - list_init( &process->rawinput_entry ); - list_init( &process->kernel_object ); -@@ -784,6 +805,8 @@ static void process_destroy( struct object *obj ) - free( process->rawinput_devices ); - free( process->dir_cache ); - free( process->image ); -+ -+ if (process->inproc_sync) release_object( process->inproc_sync ); - } - - /* dump a process on stdout for debugging purposes */ -@@ -817,6 +840,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) - return &process->kernel_object; - } - -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ) -+{ -+ struct process *process = (struct process *)obj; -+ -+ if (!process->inproc_sync) -+ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->inproc_sync) grab_object( process->inproc_sync ); -+ return process->inproc_sync; -+} -+ - static struct security_descriptor *process_get_sd( struct object *obj ) - { - static struct security_descriptor *process_default_sd; -@@ -981,6 +1014,7 @@ static void process_killed( struct process *process ) - release_job_process( process ); - start_sigkill_timer( process ); - wake_up( &process->obj, 0 ); -+ set_inproc_event( process->inproc_sync ); - } - - /* add a thread to a process running threads list */ -diff --git a/server/process.h b/server/process.h -index 96814ab7cf8..667e2506672 100644 ---- a/server/process.h -+++ b/server/process.h -@@ -86,6 +86,7 @@ struct process - struct list rawinput_entry; /* entry in the rawinput process list */ - struct list kernel_object; /* list of kernel object pointers */ - struct pe_image_info image_info; /* main exe image info */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - /* process functions */ -diff --git a/server/protocol.def b/server/protocol.def -index 4b9c4dc8e5c..85ab00ea704 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4076,3 +4076,50 @@ struct handle_info - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END -+ -+ -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+/* Obtain a handle to the ntsync device object */ -+@REQ(get_linux_sync_device) -+@REPLY -+ obj_handle_t handle; /* handle to the device */ -+@END -+ -+ -+/* Get the in-process synchronization object associated with the given handle */ -+@REQ(get_linux_sync_obj) -+ obj_handle_t handle; /* handle to the object */ -+@REPLY -+ obj_handle_t handle; /* handle to the fast synchronization object */ -+ int type; /* object type */ -+ unsigned int access; /* handle access rights */ -+@END -+ -+ -+/* Begin a client-side wait on a message queue */ -+@REQ(select_inproc_queue) -+@END -+ -+ -+/* End a client-side wait on a message queue */ -+@REQ(unselect_inproc_queue) -+ int signaled; /* was the queue signaled? */ -+@END -+ -+ -+/* Get an event handle to be used for thread alerts with in-process synchronization */ -+@REQ(get_inproc_alert_event) -+@REPLY -+ obj_handle_t handle; /* handle to the event */ -+@END -diff --git a/server/queue.c b/server/queue.c -index 47870884644..19a5e7aa9b8 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -133,6 +133,8 @@ struct msg_queue - timeout_t last_get_msg; /* time of last get message call */ - int keystate_lock; /* owns an input keystate lock */ - const queue_shm_t *shared; /* queue in session shared memory */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ int in_inproc_wait; /* are we in a client-side wait? */ - }; - - struct hotkey -@@ -150,6 +152,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent - static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ); - static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); - static void msg_queue_destroy( struct object *obj ); - static void msg_queue_poll_event( struct fd *fd, int event ); - static void thread_input_dump( struct object *obj, int verbose ); -@@ -176,6 +179,7 @@ static const struct object_ops msg_queue_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - msg_queue_destroy /* destroy */ - }; -@@ -213,6 +217,7 @@ static const struct object_ops thread_input_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_input_destroy /* destroy */ - }; -@@ -312,6 +317,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->hooks = NULL; - queue->last_get_msg = current_time; - queue->keystate_lock = 0; -+ queue->inproc_sync = NULL; -+ queue->in_inproc_wait = 0; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); -@@ -728,7 +735,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) - } - SHARED_WRITE_END; - -- if (is_signaled( queue )) wake_up( &queue->obj, 0 ); -+ if (is_signaled( queue )) -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } - } - - /* clear some queue bits */ -@@ -748,6 +759,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits - if (queue->keystate_lock) unlock_input_keystate( queue->input ); - queue->keystate_lock = 0; - } -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - - /* check if message is matched by the filter */ -@@ -1227,6 +1240,10 @@ static int is_queue_hung( struct msg_queue *queue ) - if (get_wait_queue_thread(entry)->queue == queue) - return 0; /* thread is waiting on queue -> not hung */ - } -+ -+ if (queue->in_inproc_wait) -+ return 0; /* thread is waiting on queue in absentia -> not hung */ -+ - return 1; - } - -@@ -1292,6 +1309,17 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en - shared->changed_mask = 0; - } - SHARED_WRITE_END; -+ reset_inproc_event( queue->inproc_sync ); -+} -+ -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) -+{ -+ struct msg_queue *queue = (struct msg_queue *)obj; -+ -+ if (!queue->inproc_sync) -+ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->inproc_sync) grab_object( queue->inproc_sync ); -+ return queue->inproc_sync; - } - - static void msg_queue_destroy( struct object *obj ) -@@ -1337,6 +1365,7 @@ static void msg_queue_destroy( struct object *obj ) - if (queue->hooks) release_object( queue->hooks ); - if (queue->fd) release_object( queue->fd ); - if (queue->shared) free_shared_object( queue->shared ); -+ if (queue->inproc_sync) release_object( queue->inproc_sync ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1347,6 +1376,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) - if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); - else set_fd_events( queue->fd, 0 ); - wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); - } - - static void thread_input_dump( struct object *obj, int verbose ) -@@ -3114,7 +3144,15 @@ DECL_HANDLER(set_queue_mask) - } - SHARED_WRITE_END; - } -- else wake_up( &queue->obj, 0 ); -+ else -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } -+ } -+ else -+ { -+ reset_inproc_event( queue->inproc_sync ); - } - } - } -@@ -3136,6 +3174,9 @@ DECL_HANDLER(get_queue_status) - shared->changed_bits &= ~req->clear_bits; - } - SHARED_WRITE_END; -+ -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - else reply->wake_bits = reply->changed_bits = 0; - } -@@ -3333,6 +3374,9 @@ DECL_HANDLER(get_message) - } - SHARED_WRITE_END; - -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); -+ - /* then check for posted messages */ - if ((filter & QS_POSTMESSAGE) && - get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3392,6 +3436,7 @@ DECL_HANDLER(get_message) - } - SHARED_WRITE_END; - -+ reset_inproc_event( queue->inproc_sync ); - set_error( STATUS_PENDING ); /* FIXME */ - } - -@@ -4183,3 +4228,42 @@ DECL_HANDLER(set_keyboard_repeat) - - release_object( desktop ); - } -+ -+DECL_HANDLER(select_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ check_thread_queue_idle( current ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_inproc_wait = 1; -+ } -+} -+ -+DECL_HANDLER(unselect_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (!queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_inproc_wait = 0; -+ } -+} -diff --git a/server/registry.c b/server/registry.c -index 3f02faaaefd..65beb11702d 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -192,6 +192,7 @@ static const struct object_ops key_ops = - key_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - key_close_handle, /* close_handle */ - key_destroy /* destroy */ - }; -diff --git a/server/request.c b/server/request.c -index 2254315b79e..24a4f779e68 100644 ---- a/server/request.c -+++ b/server/request.c -@@ -101,6 +101,7 @@ static const struct object_ops master_socket_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - master_socket_destroy /* destroy */ - }; -diff --git a/server/request_handlers.h b/server/request_handlers.h -index fb03e421562..1d88b63dff3 100644 ---- a/server/request_handlers.h -+++ b/server/request_handlers.h -@@ -299,6 +299,11 @@ DECL_HANDLER(suspend_process); - DECL_HANDLER(resume_process); - DECL_HANDLER(get_next_thread); - DECL_HANDLER(set_keyboard_repeat); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(select_inproc_queue); -+DECL_HANDLER(unselect_inproc_queue); -+DECL_HANDLER(get_inproc_alert_event); - - typedef void (*req_handler)( const void *req, void *reply ); - static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -595,6 +600,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = - (req_handler)req_resume_process, - (req_handler)req_get_next_thread, - (req_handler)req_set_keyboard_repeat, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_select_inproc_queue, -+ (req_handler)req_unselect_inproc_queue, -+ (req_handler)req_get_inproc_alert_event, - }; - - C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2268,3 +2278,18 @@ C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_request, handle) == 12 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, handle) == 8 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); -+C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); -+C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); -diff --git a/server/request_trace.h b/server/request_trace.h -index cf0aab07ca0..283f1c1774a 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -3339,6 +3339,45 @@ static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_rep - fprintf( stderr, " enable=%d", req->enable ); - } - -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) -+{ -+} -+ -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+ fprintf( stderr, ", type=%d", req->type ); -+ fprintf( stderr, ", access=%08x", req->access ); -+} -+ -+static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) -+{ -+} -+ -+static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) -+{ -+ fprintf( stderr, " signaled=%d", req->signaled ); -+} -+ -+static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) -+{ -+} -+ -+static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) -+{ -+ fprintf( stderr, " handle=%04x", req->handle ); -+} -+ - typedef void (*dump_func)( const void *req ); - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = -@@ -3635,6 +3674,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, - (dump_func)dump_set_keyboard_repeat_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_select_inproc_queue_request, -+ (dump_func)dump_unselect_inproc_queue_request, -+ (dump_func)dump_get_inproc_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = -@@ -3931,6 +3975,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = - NULL, - (dump_func)dump_get_next_thread_reply, - (dump_func)dump_set_keyboard_repeat_reply, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, -+ NULL, -+ (dump_func)dump_get_inproc_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = -@@ -4227,6 +4276,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = - "resume_process", - "get_next_thread", - "set_keyboard_repeat", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "select_inproc_queue", -+ "unselect_inproc_queue", -+ "get_inproc_alert_event", - }; - - static const struct -diff --git a/server/semaphore.c b/server/semaphore.c -index 53b42a886df..bc7436b5673 100644 ---- a/server/semaphore.c -+++ b/server/semaphore.c -@@ -55,12 +55,15 @@ struct semaphore - struct object obj; /* object header */ - unsigned int count; /* current count */ - unsigned int max; /* maximum possible count */ -+ struct inproc_sync *inproc_sync; /* fast synchronization object */ - }; - - static void semaphore_dump( struct object *obj, int verbose ); - static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); -+static void semaphore_destroy( struct object *obj ); - - static const struct object_ops semaphore_ops = - { -@@ -82,8 +85,9 @@ static const struct object_ops semaphore_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ semaphore_destroy /* destroy */ - }; - - -@@ -105,6 +109,7 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni - /* initialize it if it didn't already exist */ - sem->count = initial; - sem->max = max; -+ sem->inproc_sync = NULL; - } - } - return sem; -@@ -167,6 +172,23 @@ static int semaphore_signal( struct object *obj, unsigned int access ) - return release_semaphore( sem, 1, NULL ); - } - -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (!semaphore->inproc_sync) -+ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); -+ return semaphore->inproc_sync; -+} -+ -+static void semaphore_destroy( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); -+} -+ - /* create a semaphore */ - DECL_HANDLER(create_semaphore) - { -diff --git a/server/serial.c b/server/serial.c -index 209f2e9174e..93753328d4d 100644 ---- a/server/serial.c -+++ b/server/serial.c -@@ -103,6 +103,7 @@ static const struct object_ops serial_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - serial_destroy /* destroy */ - }; -diff --git a/server/signal.c b/server/signal.c -index 19b76d44c16..85d16baa98c 100644 ---- a/server/signal.c -+++ b/server/signal.c -@@ -74,6 +74,7 @@ static const struct object_ops handler_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handler_destroy /* destroy */ - }; -diff --git a/server/sock.c b/server/sock.c -index 32d622aaebc..09366ea7dde 100644 ---- a/server/sock.c -+++ b/server/sock.c -@@ -483,6 +483,7 @@ static const struct object_ops sock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - sock_close_handle, /* close_handle */ - sock_destroy /* destroy */ - }; -@@ -3611,6 +3612,7 @@ static const struct object_ops ifchange_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ifchange_destroy /* destroy */ - }; -@@ -3832,6 +3834,7 @@ static const struct object_ops socket_device_ops = - default_unlink_name, /* unlink_name */ - socket_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -diff --git a/server/symlink.c b/server/symlink.c -index 74b60162c01..f0314f2ee90 100644 ---- a/server/symlink.c -+++ b/server/symlink.c -@@ -83,6 +83,7 @@ static const struct object_ops symlink_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - symlink_destroy /* destroy */ - }; -diff --git a/server/thread.c b/server/thread.c -index b3ce5d9ac95..a05a96d8728 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -108,6 +108,7 @@ static const struct object_ops thread_apc_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_apc_destroy /* destroy */ - }; -@@ -150,6 +151,7 @@ static const struct object_ops context_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -177,6 +179,7 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) - static unsigned int thread_map_access( struct object *obj, unsigned int access ); - static void thread_poll_event( struct fd *fd, int event ); - static struct list *thread_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); - static void destroy_thread( struct object *obj ); - - static const struct object_ops thread_ops = -@@ -199,6 +202,7 @@ static const struct object_ops thread_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - destroy_thread /* destroy */ - }; -@@ -246,6 +250,8 @@ static inline void init_thread_structure( struct thread *thread ) - thread->token = NULL; - thread->desc = NULL; - thread->desc_len = 0; -+ thread->inproc_sync = NULL; -+ thread->inproc_alert_event = NULL; - - thread->creation_time = current_time; - thread->exit_time = 0; -@@ -397,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) - return &thread->kernel_object; - } - -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) -+{ -+ struct thread *thread = (struct thread *)obj; -+ -+ if (!thread->inproc_sync) -+ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->inproc_sync) grab_object( thread->inproc_sync ); -+ return thread->inproc_sync; -+} -+ - /* cleanup everything that is no longer needed by a dead thread */ - /* used by destroy_thread and kill_thread */ - static void cleanup_thread( struct thread *thread ) -@@ -452,6 +468,8 @@ static void destroy_thread( struct object *obj ) - release_object( thread->process ); - if (thread->id) free_ptid( thread->id ); - if (thread->token) release_object( thread->token ); -+ if (thread->inproc_sync) release_object( thread->inproc_sync ); -+ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); - } - - /* dump a thread on stdout for debugging purposes */ -@@ -1149,8 +1167,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr - grab_object( apc ); - list_add_tail( queue, &apc->entry ); - if (!list_prev( queue, &apc->entry )) /* first one */ -+ { - wake_thread( thread ); - -+ if (apc->call.type == APC_USER && thread->inproc_alert_event) -+ set_event( thread->inproc_alert_event ); -+ } -+ - return 1; - } - -@@ -1181,6 +1204,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty - apc->executed = 1; - wake_up( &apc->obj, 0 ); - release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - return; - } - } -@@ -1195,6 +1220,9 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system - { - apc = LIST_ENTRY( ptr, struct thread_apc, entry ); - list_remove( ptr ); -+ -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - } - return apc; - } -@@ -1292,6 +1320,7 @@ void kill_thread( struct thread *thread, int violent_death ) - kill_console_processes( thread, 0 ); - abandon_mutexes( thread ); - wake_up( &thread->obj, 0 ); -+ set_inproc_event( thread->inproc_sync ); - if (violent_death) send_thread_signal( thread, SIGQUIT ); - cleanup_thread( thread ); - remove_process_thread( thread->process, thread ); -@@ -2035,3 +2064,12 @@ DECL_HANDLER(get_next_thread) - set_error( STATUS_NO_MORE_ENTRIES ); - release_object( process ); - } -+ -+DECL_HANDLER(get_inproc_alert_event) -+{ -+ if (!current->inproc_alert_event) -+ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); -+ -+ if (current->inproc_alert_event) -+ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); -+} -diff --git a/server/thread.h b/server/thread.h -index 754e617b484..c75512ded87 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -93,6 +93,8 @@ struct thread - data_size_t desc_len; /* thread description length in bytes */ - WCHAR *desc; /* thread description string */ - struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ struct event *inproc_alert_event; /* in-process synchronization alert event */ - }; - - extern struct thread *current; -diff --git a/server/timer.c b/server/timer.c -index b0b6ec81535..08aa62292f0 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -52,20 +52,22 @@ struct type_descr timer_type = - - struct timer - { -- struct object obj; /* object header */ -- int manual; /* manual reset */ -- int signaled; /* current signaled state */ -- unsigned int period; /* timer period in ms */ -- abstime_t when; /* next expiration */ -- struct timeout_user *timeout; /* timeout user */ -- struct thread *thread; /* thread that set the APC function */ -- client_ptr_t callback; /* callback APC function */ -- client_ptr_t arg; /* callback argument */ -+ struct object obj; /* object header */ -+ int manual; /* manual reset */ -+ int signaled; /* current signaled state */ -+ unsigned int period; /* timer period in ms */ -+ abstime_t when; /* next expiration */ -+ struct timeout_user *timeout; /* timeout user */ -+ struct thread *thread; /* thread that set the APC function */ -+ client_ptr_t callback; /* callback APC function */ -+ client_ptr_t arg; /* callback argument */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void timer_dump( struct object *obj, int verbose ); - static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); - static void timer_destroy( struct object *obj ); - - static const struct object_ops timer_ops = -@@ -88,6 +90,7 @@ static const struct object_ops timer_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - timer_destroy /* destroy */ - }; -@@ -110,6 +113,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str - timer->period = 0; - timer->timeout = NULL; - timer->thread = NULL; -+ timer->inproc_sync = NULL; - } - } - return timer; -@@ -151,6 +155,7 @@ static void timer_callback( void *private ) - /* wake up waiters */ - timer->signaled = 1; - wake_up( &timer->obj, 0 ); -+ set_inproc_event( timer->inproc_sync ); - } - - /* cancel a running timer */ -@@ -181,6 +186,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period - { - period = 0; /* period doesn't make any sense for a manual timer */ - timer->signaled = 0; -+ reset_inproc_event( timer->inproc_sync ); - } - timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); - timer->period = period; -@@ -215,6 +221,19 @@ static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry - if (!timer->manual) timer->signaled = 0; - } - -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) -+{ -+ struct timer *timer = (struct timer *)obj; -+ -+ if (!timer->inproc_sync) -+ { -+ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; -+ timer->inproc_sync = create_inproc_event( type, timer->signaled ); -+ } -+ if (timer->inproc_sync) grab_object( timer->inproc_sync ); -+ return timer->inproc_sync; -+} -+ - static void timer_destroy( struct object *obj ) - { - struct timer *timer = (struct timer *)obj; -@@ -222,6 +241,7 @@ static void timer_destroy( struct object *obj ) - - if (timer->timeout) remove_timeout_user( timer->timeout ); - if (timer->thread) release_object( timer->thread ); -+ if (timer->inproc_sync) release_object( timer->inproc_sync ); - } - - /* create a timer */ -diff --git a/server/token.c b/server/token.c -index 7e20c670a16..844ad2814f4 100644 ---- a/server/token.c -+++ b/server/token.c -@@ -157,6 +157,7 @@ static const struct object_ops token_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - token_destroy /* destroy */ - }; -diff --git a/server/window.c b/server/window.c -index 2af70b09102..291aab520d7 100644 ---- a/server/window.c -+++ b/server/window.c -@@ -119,6 +119,7 @@ static const struct object_ops window_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - window_destroy /* destroy */ - }; -diff --git a/server/winstation.c b/server/winstation.c -index 8611c893cde..e3f0a870d02 100644 ---- a/server/winstation.c -+++ b/server/winstation.c -@@ -88,6 +88,7 @@ static const struct object_ops winstation_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - winstation_close_handle, /* close_handle */ - winstation_destroy /* destroy */ - }; -@@ -128,6 +129,7 @@ static const struct object_ops desktop_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - desktop_close_handle, /* close_handle */ - desktop_destroy /* destroy */ - }; --- -2.47.1 - diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging-protonify.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging-protonify.patch deleted file mode 100644 index 884a267d0..000000000 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging-protonify.patch +++ /dev/null @@ -1,8376 +0,0 @@ -diff --git a/README.esync b/README.esync -deleted file mode 100644 -index 11d8656..0000000 ---- a/README.esync -+++ /dev/null -@@ -1,196 +0,0 @@ --This is eventfd-based synchronization, or 'esync' for short. Turn it on with --WINEESYNC=1; debug it with +esync. -- --== BUGS AND LIMITATIONS == -- --Please let me know if you find any bugs. If you can, also attach a log with --+seh,+pid,+esync,+server,+timestamp. -- --If you get something like "eventfd: Too many open files" and then things start --crashing, you've probably run out of file descriptors. esync creates one --eventfd descriptor for each synchronization object, and some games may use a --large number of these. Linux by default limits a process to 4096 file --descriptors, which probably was reasonable back in the nineties but isn't --really anymore. (Fortunately Debian and derivatives [Ubuntu, Mint] already --have a reasonable limit.) To raise the limit you'll want to edit --/etc/security/limits.conf and add a line like -- --* hard nofile 1048576 -- --then restart your session. -- --On distributions using systemd, the settings in `/etc/security/limits.conf` --will be overridden by systemd's own settings. If you run `ulimit -Hn` and it --returns a lower number than the one you've previously set, then you can set -- --DefaultLimitNOFILE=1048576 -- --in both `/etc/systemd/system.conf` and `/etc/systemd/user.conf`. You can then --execute `sudo systemctl daemon-reexec` and restart your session. Check again --with `ulimit -Hn` that the limit is correct. -- --Also note that if the wineserver has esync active, all clients also must, and --vice versa. Otherwise things will probably crash quite badly. -- --== EXPLANATION == -- --The aim is to execute all synchronization operations in "user-space", that is, --without going through wineserver. We do this using Linux's eventfd --facility. The main impetus to using eventfd is so that we can poll multiple --objects at once; in particular we can't do this with futexes, or pthread --semaphores, or the like. The only way I know of to wait on any of multiple --objects is to use select/poll/epoll to wait on multiple fds, and eventfd gives --us those fds in a quite usable way. -- --Whenever a semaphore, event, or mutex is created, we have the server, instead --of creating a traditional server-side event/semaphore/mutex, instead create an --'esync' primitive. These live in esync.c and are very slim objects; in fact, --they don't even know what type of primitive they are. The server is involved --at all because we still need a way of creating named objects, passing handles --to another process, etc. -- --The server creates an eventfd file descriptor with the requested parameters --and passes it back to ntdll. ntdll creates an object of the appropriate type, --then caches it in a table. This table is copied almost wholesale from the fd --cache code in server.c. -- --Specific operations follow quite straightforwardly from eventfd: -- --* To release an object, or set an event, we simply write() to it. --* An object is signalled if read() succeeds on it. Notably, we create all -- eventfd descriptors with O_NONBLOCK, so that we can atomically check if an -- object is signalled and grab it if it is. This also lets us reset events. --* For objects whose state should not be reset upon waiting—e.g. manual-reset -- events—we simply check for the POLLIN flag instead of reading. --* Semaphores are handled by the EFD_SEMAPHORE flag. This matches up quite well -- (although with some difficulties; see below). --* Mutexes store their owner thread locally. This isn't reliable information if -- a different process's thread owns the mutex, but this doesn't matter—a -- thread should only care whether it owns the mutex, so it knows whether to -- try waiting on it or simply to increase the recursion count. -- --The interesting part about esync is that (almost) all waits happen in ntdll, --including those on server-bound objects. The idea here is that on the server --side, for any waitable object, we create an eventfd file descriptor (not an --esync primitive), and then pass it to ntdll if the program tries to wait on --it. These are cached too, so only the first wait will require a round trip to --the server. Then the server signals the file descriptor as appropriate, and --thereby wakes up the client. So far this is implemented for processes, --threads, message queues (difficult; see below), and device managers (necessary --for drivers to work). All of these are necessarily server-bound, so we --wouldn't really gain anything by signalling on the client side instead. Of --course, except possibly for message queues, it's not likely that any program --(cutting-edge D3D game or not) is going to be causing a great wineserver load --by waiting on any of these objects; the motivation was rather to provide a way --to wait on ntdll-bound and server-bound objects at the same time. -- --Some cases are still passed to the server, and there's probably no reason not --to keep them that way. Those that I noticed while testing include: async --objects, which are internal to the file APIs and never exposed to userspace, --startup_info objects, which are internal to the loader and signalled when a --process starts, and keyed events, which are exposed through an ntdll API --(although not through kernel32) but can't be mixed with other objects (you --have to use NtWaitForKeyedEvent()). Other cases include: named pipes, debug --events, sockets, and timers. It's unlikely we'll want to optimize debug events --or sockets (or any of the other, rather rare, objects), but it is possible --we'll want to optimize named pipes or timers. -- --There were two sort of complications when working out the above. The first one --was events. The trouble is that (1) the server actually creates some events by --itself and (2) the server sometimes manipulates events passed by the --client. Resolving the first case was easy enough, and merely entailed creating --eventfd descriptors for the events the same way as for processes and threads --(note that we don't really lose anything this way; the events include --"LowMemoryCondition" and the event that signals system processes to shut --down). For the second case I basically had to hook the server-side event --functions to redirect to esync versions if the event was actually an esync --primitive. -- --The second complication was message queues. The difficulty here is that X11 --signals events by writing into a pipe (at least I think it's a pipe?), and so --as a result wineserver has to poll on that descriptor. In theory we could just --let wineserver do so and then signal us as appropriate, except that wineserver --only polls on the pipe when the thread is waiting for events (otherwise we'd --get e.g. keyboard input while the thread is doing something else, and spin --forever trying to wake up a thread that doesn't care). The obvious solution is --just to poll on that fd ourselves, and that's what I did—it's just that --getting the fd from wineserver was kind of ugly, and the code for waiting was --also kind of ugly basically because we have to wait on both X11's fd and the --"normal" process/thread-style wineserver fd that we use to signal sent --messages. The upshot about the whole thing was that races are basically --impossible, since a thread can only wait on its own queue. -- --System APCs already work, since the server will forcibly suspend a thread if --it's not already waiting, and so we just need to check for EINTR from --poll(). User APCs and alertable waits are implemented in a similar style to --message queues (well, sort of): whenever someone executes an alertable wait, --we add an additional eventfd to the list, which the server signals when an APC --arrives. If that eventfd gets signaled, we hand it off to the server to take --care of, and return STATUS_USER_APC. -- --Originally I kept the volatile state of semaphores and mutexes inside a --variable local to the handle, with the knowledge that this would break if --someone tried to open the handle elsewhere or duplicate it. It did, and so now --this state is stored inside shared memory. This is of the POSIX variety, is --allocated by the server (but never mapped there) and lives under the path --"/wine-esync". -- --There are a couple things that this infrastructure can't handle, although --surprisingly there aren't that many. In particular: --* Implementing wait-all, i.e. WaitForMultipleObjects(..., TRUE, ...), is not -- exactly possible the way we'd like it to be possible. In theory that -- function should wait until it knows all objects are available, then grab -- them all at once atomically. The server (like the kernel) can do this -- because the server is single-threaded and can't race with itself. We can't -- do this in ntdll, though. The approach I've taken I've laid out in great -- detail in the relevant patch, but for a quick summary we poll on each object -- until it's signaled (but don't grab it), check them all again, and if -- they're all signaled we try to grab them all at once in a tight loop, and if -- we fail on any of them we reset the count on whatever we shouldn't have -- consumed. Such a blip would necessarily be very quick. --* The whole patchset only works on Linux, where eventfd is available. However, -- it should be possible to make it work on a Mac, since eventfd is just a -- quicker, easier way to use pipes (i.e. instead of writing 1 to the fd you'd -- write 1 byte; instead of reading a 64-bit value from the fd you'd read as -- many bytes as you can carry, which is admittedly less than 2**64 but -- can probably be something reasonable.) It's also possible, although I -- haven't yet looked, to use some different kind of synchronization -- primitives, but pipes would be easiest to tack onto this framework. --* PulseEvent() can't work the way it's supposed to work. Fortunately it's rare -- and deprecated. It's also explicitly mentioned on MSDN that a thread can -- miss the notification for a kernel APC, so in a sense we're not necessarily -- doing anything wrong. -- --There are some things that are perfectly implementable but that I just haven't --done yet: --* Other synchronizable server primitives. It's unlikely we'll need any of -- these, except perhaps named pipes (which would honestly be rather difficult) -- and (maybe) timers. --* Access masks. We'd need to store these inside ntdll, and validate them when -- someone tries to execute esync operations. -- --This patchset was inspired by Daniel Santos' "hybrid synchronization" --patchset. My idea was to create a framework whereby even contended waits could --be executed in userspace, eliminating a lot of the complexity that his --synchronization primitives used. I do however owe some significant gratitude --toward him for setting me on the right path. -- --I've tried to maximize code separation, both to make any potential rebases --easier and to ensure that esync is only active when configured. All code in --existing source files is guarded with "if (do_esync())", and generally that --condition is followed by "return esync_version_of_this_method(...);", where --the latter lives in esync.c and is declared in esync.h. I've also tried to --make the patchset very clear and readable—to write it as if I were going to --submit it upstream. (Some intermediate patches do break things, which Wine is --generally against, but I think it's for the better in this case.) I have cut --some corners, though; there is some error checking missing, or implicit --assumptions that the program is behaving correctly. -- --I've tried to be careful about races. There are a lot of comments whose --purpose are basically to assure me that races are impossible. In most cases we --don't have to worry about races since all of the low-level synchronization is --done by the kernel. -- --Anyway, yeah, this is esync. Use it if you like. -- ----Zebediah Figura -diff --git a/configure b/configure -index 4d13060..58291ba 100755 ---- a/configure -+++ b/configure -@@ -8110,6 +8110,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes - then : - printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h - -+fi -+ac_fn_c_check_header_compile "$LINENO" "linux/ntsync.h" "ac_cv_header_linux_ntsync_h" "$ac_includes_default" -+if test "x$ac_cv_header_linux_ntsync_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_LINUX_NTSYNC_H 1" >>confdefs.h -+ - fi - ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" - if test "x$ac_cv_header_linux_param_h" = xyes -diff --git a/configure.ac b/configure.ac -index a3c414d..5af9132 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -403,6 +403,7 @@ AC_CHECK_HEADERS(\ - linux/input.h \ - linux/ioctl.h \ - linux/major.h \ -+ linux/ntsync.h \ - linux/param.h \ - linux/seccomp.h \ - linux/serial.h \ -@@ -433,7 +434,6 @@ AC_CHECK_HEADERS(\ - sys/cdio.h \ - sys/epoll.h \ - sys/event.h \ -- sys/eventfd.h \ - sys/extattr.h \ - sys/filio.h \ - sys/ipc.h \ -@@ -2094,7 +2094,6 @@ AC_CHECK_FUNCS(\ - port_create \ - posix_fadvise \ - posix_fallocate \ -- ppoll \ - prctl \ - proc_pidinfo \ - sched_yield \ -@@ -2120,12 +2119,6 @@ case $host_os in - ;; - esac - --ac_save_LIBS=$LIBS --AC_SEARCH_LIBS(shm_open, rt, -- [AC_DEFINE(HAVE_SHM_OPEN, 1, [Define to 1 if you have the `shm_open' function.]) -- test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) --LIBS=$ac_save_LIBS -- - AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [[#include ]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 424cbe2..50e81aa 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -57,7 +57,6 @@ static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); - - static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); - static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); --static NTSTATUS (WINAPI *pNtQuerySystemTime)(LARGE_INTEGER *); - static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); - static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); - static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, -@@ -228,23 +227,8 @@ static void test_temporary_objects(void) - ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError()); - } - --static HANDLE mutex, mutex2, mutices[2]; -- --static DWORD WINAPI mutex_thread( void *param ) --{ -- DWORD expect = (DWORD)(DWORD_PTR)param; -- DWORD ret; -- -- ret = WaitForSingleObject( mutex, 0 ); -- ok(ret == expect, "expected %lu, got %lu\n", expect, ret); -- -- if (!ret) ReleaseMutex( mutex ); -- return 0; --} -- - static void test_mutex(void) - { -- HANDLE thread; - DWORD wait_ret; - BOOL ret; - HANDLE hCreated; -@@ -284,8 +268,7 @@ static void test_mutex(void) - SetLastError(0xdeadbeef); - hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); - ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError()); -- wait_ret = WaitForSingleObject(hOpened, 0); --todo_wine_if(getenv("WINEESYNC")) /* XFAIL: validation is not implemented */ -+ wait_ret = WaitForSingleObject(hOpened, INFINITE); - ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); - CloseHandle(hOpened); - -@@ -316,7 +299,6 @@ todo_wine_if(getenv("WINEESYNC")) /* XFAIL: validation is not implemented */ - - SetLastError(0xdeadbeef); - ret = ReleaseMutex(hCreated); --todo_wine_if(getenv("WINEESYNC")) /* XFAIL: due to the above */ - ok(!ret && (GetLastError() == ERROR_NOT_OWNER), - "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %ld\n", GetLastError()); - -@@ -355,85 +337,6 @@ todo_wine_if(getenv("WINEESYNC")) /* XFAIL: due to the above */ - CloseHandle(hOpened); - - CloseHandle(hCreated); -- -- mutex = CreateMutexA( NULL, FALSE, NULL ); -- ok(!!mutex, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- for (i = 0; i < 100; i++) -- { -- ret = WaitForSingleObject( mutex, 0 ); -- ok(ret == 0, "got %u\n", ret); -- } -- -- for (i = 0; i < 100; i++) -- { -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- } -- -- ret = ReleaseMutex( mutex ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)0, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- WaitForSingleObject( mutex, 0 ); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)WAIT_TIMEOUT, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)0, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- mutex2 = CreateMutexA( NULL, TRUE, NULL ); -- ok(!!mutex2, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- mutices[0] = mutex; -- mutices[1] = mutex2; -- -- ret = WaitForMultipleObjects( 2, mutices, FALSE, 0 ); -- ok(ret == 0, "got %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- ret = WaitForMultipleObjects( 2, mutices, TRUE, 0 ); -- ok(ret == 0, "got %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- - } - - static void test_slist(void) -@@ -609,13 +512,12 @@ static void test_slist(void) - - static void test_event(void) - { -- HANDLE handle, handle2, handles[2]; -+ HANDLE handle, handle2; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - ACL acl; - DWORD ret; - BOOL val; -- int i; - - /* no sd */ - handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); -@@ -719,130 +621,11 @@ static void test_event(void) - ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() ); - ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); - CloseHandle( handle ); -- -- handle = CreateEventA( NULL, TRUE, FALSE, NULL ); -- ok(!!handle, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = SetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = SetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- for (i = 0; i < 100; i++) -- { -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = ResetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handle2 = CreateEventA( NULL, FALSE, TRUE, NULL ); -- ok(!!handle2, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = SetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = SetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handles[0] = handle; -- handles[1] = handle2; -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ResetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle2 ); -- ResetEvent( handle ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- handles[0] = handle2; -- handles[1] = handle; -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = CloseHandle( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); - } - - static void test_semaphore(void) - { -- HANDLE handle, handle2, handles[2]; -- DWORD ret; -- LONG prev; -- int i; -+ HANDLE handle, handle2; - - /* test case sensitivity */ - -@@ -884,99 +667,6 @@ static void test_semaphore(void) - ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); - - CloseHandle( handle ); -- -- handle = CreateSemaphoreA( NULL, 0, 5, NULL ); -- ok(!!handle, "CreateSemaphore failed: %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 0, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 1, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 5, &prev ); -- ok(!ret, "got %ld\n", ret); -- ok(GetLastError() == ERROR_TOO_MANY_POSTS, "got error %lu\n", GetLastError()); -- ok(prev == 1, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 2, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 2, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 4, "got prev %ld\n", prev); -- -- for (i = 0; i < 5; i++) -- { -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handle2 = CreateSemaphoreA( NULL, 3, 5, NULL ); -- ok(!!handle2, "CreateSemaphore failed: %lu\n", GetLastError()); -- -- ret = ReleaseSemaphore( handle2, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 3, "got prev %ld\n", prev); -- -- for (i = 0; i < 4; i++) -- { -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handles[0] = handle; -- handles[1] = handle2; -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- ReleaseSemaphore( handle2, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- ReleaseSemaphore( handle2, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = CloseHandle( handle ); -- ok(ret, "got error %lu\n", ret); -- -- ret = CloseHandle( handle2 ); -- ok(ret, "got error %lu\n", ret); - } - - static void test_waitable_timer(void) -@@ -1531,15 +1221,11 @@ static HANDLE modify_handle(HANDLE handle, DWORD modify) - return ULongToHandle(tmp); - } - --#define TIMEOUT_INFINITE (((LONGLONG)0x7fffffff) << 32 | 0xffffffff) -- - static void test_WaitForSingleObject(void) - { - HANDLE signaled, nonsignaled, invalid; -- LARGE_INTEGER ntnow, ntthen; - LARGE_INTEGER timeout; - NTSTATUS status; -- DWORD now, then; - DWORD ret; - - signaled = CreateEventW(NULL, TRUE, TRUE, NULL); -@@ -1624,68 +1310,6 @@ static void test_WaitForSingleObject(void) - status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); - ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status); - -- ret = WaitForSingleObject( signaled, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( nonsignaled, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- /* test that a timed wait actually does wait */ -- now = GetTickCount(); -- ret = WaitForSingleObject( nonsignaled, 100 ); -- then = GetTickCount(); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- ok(abs((then - now) - 100) < 5, "got %lu ms\n", then - now); -- -- now = GetTickCount(); -- ret = WaitForSingleObject( signaled, 100 ); -- then = GetTickCount(); -- ok(ret == 0, "got %lu\n", ret); -- ok(abs(then - now) < 5, "got %lu ms\n", then - now); -- -- ret = WaitForSingleObject( signaled, INFINITE ); -- ok(ret == 0, "got %lu\n", ret); -- -- /* test NT timeouts */ -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart + 100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs(((ntthen.QuadPart - ntnow.QuadPart) / 10000) - 100) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = -100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs(((ntthen.QuadPart - ntnow.QuadPart) / 10000) - 100) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- status = pNtWaitForSingleObject( signaled, FALSE, NULL ); -- ok(status == 0, "got %#lx\n", status); -- -- timeout.QuadPart = TIMEOUT_INFINITE; -- status = pNtWaitForSingleObject( signaled, FALSE, &timeout ); -- ok(status == 0, "got %#lx\n", status); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs((ntthen.QuadPart - ntnow.QuadPart) / 10000) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart - 100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs((ntthen.QuadPart - ntnow.QuadPart) / 10000) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- - CloseHandle(signaled); - CloseHandle(nonsignaled); - } -@@ -3351,7 +2975,6 @@ START_TEST(sync) - pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); - pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); - pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); -- pNtQuerySystemTime = (void *)GetProcAddress(hntdll, "NtQuerySystemTime"); - pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); - pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); - pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); -diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in -index 4629457..f71f79b 100644 ---- a/dlls/ntdll/Makefile.in -+++ b/dlls/ntdll/Makefile.in -@@ -48,7 +48,6 @@ SOURCES = \ - unix/cdrom.c \ - unix/debug.c \ - unix/env.c \ -- unix/esync.c \ - unix/file.c \ - unix/loader.c \ - unix/loadorder.c \ -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -deleted file mode 100644 -index edfeb03..0000000 ---- a/dlls/ntdll/unix/esync.c -+++ /dev/null -@@ -1,1337 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#if 0 --#pragma makedep unix --#endif -- --#include "config.h" -- --#ifndef _GNU_SOURCE --#define _GNU_SOURCE --#endif -- --#include --#include --#include --#include --#include --#include --#include --#ifdef HAVE_SYS_STAT_H --# include --#endif --#include --#include --#include -- --#include "ntstatus.h" --#define WIN32_NO_STATUS --#include "windef.h" --#include "winternl.h" --#include "wine/server.h" --#include "wine/debug.h" -- --#include "unix_private.h" --#include "esync.h" -- --WINE_DEFAULT_DEBUG_CHANNEL(esync); -- --int do_esync(void) --{ --#ifdef HAVE_SYS_EVENTFD_H -- static int do_esync_cached = -1; -- -- if (do_esync_cached == -1) -- do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); -- -- return do_esync_cached; --#else -- static int once; -- if (!once++) -- FIXME("eventfd not supported on this platform.\n"); -- return 0; --#endif --} -- --struct esync --{ -- LONG type; -- int fd; -- void *shm; --}; -- --struct semaphore --{ -- LONG max; -- LONG count; --}; --C_ASSERT(sizeof(struct semaphore) == 8); -- --struct mutex --{ -- LONG tid; -- LONG count; /* recursion count */ --}; --C_ASSERT(sizeof(struct mutex) == 8); -- --struct event --{ -- LONG signaled; -- LONG locked; --}; --C_ASSERT(sizeof(struct event) == 8); -- --static char shm_name[29]; --static int shm_fd; --static void **shm_addrs; --static int shm_addrs_size; /* length of the allocated shm_addrs array */ --static long pagesize; -- --static pthread_mutex_t shm_addrs_mutex = PTHREAD_MUTEX_INITIALIZER; -- --static void *get_shm( unsigned int idx ) --{ -- int entry = (idx * 8) / pagesize; -- int offset = (idx * 8) % pagesize; -- void *ret; -- -- pthread_mutex_lock( &shm_addrs_mutex ); -- -- if (entry >= shm_addrs_size) -- { -- int new_size = max(shm_addrs_size * 2, entry + 1); -- -- if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) ))) -- ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_size); -- memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) ); -- shm_addrs_size = new_size; -- } -- -- if (!shm_addrs[entry]) -- { -- void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize ); -- if (addr == (void *)-1) -- ERR("Failed to map page %d (offset %#lx).\n", entry, entry * pagesize); -- -- TRACE("Mapping page %d at %p.\n", entry, addr); -- -- if (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 )) -- munmap( addr, pagesize ); /* someone beat us to it */ -- } -- -- ret = (void *)((unsigned long)shm_addrs[entry] + offset); -- -- pthread_mutex_unlock( &shm_addrs_mutex ); -- -- return ret; --} -- --/* We'd like lookup to be fast. To that end, we use a static list indexed by handle. -- * This is copied and adapted from the fd cache code. */ -- --#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync)) --#define ESYNC_LIST_ENTRIES 256 -- --static struct esync *esync_list[ESYNC_LIST_ENTRIES]; --static struct esync esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE]; -- --static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry ) --{ -- UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1; -- *entry = idx / ESYNC_LIST_BLOCK_SIZE; -- return idx % ESYNC_LIST_BLOCK_SIZE; --} -- --static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, void *shm ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- if (entry >= ESYNC_LIST_ENTRIES) -- { -- FIXME( "too many allocated handles, not caching %p\n", handle ); -- return FALSE; -- } -- -- if (!esync_list[entry]) /* do we need to allocate a new block of entries? */ -- { -- if (!entry) esync_list[0] = esync_list_initial_block; -- else -- { -- void *ptr = anon_mmap_alloc( ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync), -- PROT_READ | PROT_WRITE ); -- if (ptr == MAP_FAILED) return FALSE; -- esync_list[entry] = ptr; -- } -- } -- -- if (!InterlockedCompareExchange( &esync_list[entry][idx].type, type, 0 )) -- { -- esync_list[entry][idx].fd = fd; -- esync_list[entry][idx].shm = shm; -- } -- return &esync_list[entry][idx]; --} -- --static struct esync *get_cached_object( HANDLE handle ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL; -- if (!esync_list[entry][idx].type) return NULL; -- -- return &esync_list[entry][idx]; --} -- --/* Gets an object. This is either a proper esync object (i.e. an event, -- * semaphore, etc. created using create_esync) or a generic synchronizable -- * server-side object which the server will signal (e.g. a process, thread, -- * message queue, etc.) */ --static NTSTATUS get_object( HANDLE handle, struct esync **obj ) --{ -- int ret = STATUS_SUCCESS; -- enum esync_type type = 0; -- unsigned int shm_idx = 0; -- obj_handle_t fd_handle; -- sigset_t sigset; -- int fd = -1; -- -- if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS; -- -- if ((INT_PTR)handle < 0) -- { -- /* We can deal with pseudo-handles, but it's just easier this way */ -- return STATUS_NOT_IMPLEMENTED; -- } -- -- if (!handle) -- { -- /* Shadow of the Tomb Raider really likes passing in NULL handles to -- * various functions. Concerning, but let's avoid a server call. */ -- return STATUS_INVALID_HANDLE; -- } -- -- /* We need to try grabbing it from the server. */ -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- if (!(*obj = get_cached_object( handle ))) -- { -- SERVER_START_REQ( get_esync_fd ) -- { -- req->handle = wine_server_obj_handle( handle ); -- if (!(ret = wine_server_call( req ))) -- { -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == handle ); -- } -- } -- SERVER_END_REQ; -- } -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (*obj) -- { -- /* We managed to grab it while in the CS; return it. */ -- return STATUS_SUCCESS; -- } -- -- if (ret) -- { -- WARN("Failed to retrieve fd for handle %p, status %#x.\n", handle, ret); -- *obj = NULL; -- return ret; -- } -- -- TRACE("Got fd %d for handle %p.\n", fd, handle); -- -- *obj = add_to_list( handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- return ret; --} -- --NTSTATUS esync_close( HANDLE handle ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- TRACE("%p.\n", handle); -- -- if (entry < ESYNC_LIST_ENTRIES && esync_list[entry]) -- { -- if (InterlockedExchange(&esync_list[entry][idx].type, 0)) -- { -- close( esync_list[entry][idx].fd ); -- return STATUS_SUCCESS; -- } -- } -- -- return STATUS_INVALID_HANDLE; --} -- --static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initval, int max ) --{ -- NTSTATUS ret; -- data_size_t len; -- struct object_attributes *objattr; -- obj_handle_t fd_handle; -- unsigned int shm_idx; -- sigset_t sigset; -- int fd; -- -- if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -- -- /* We have to synchronize on the fd cache CS so that our calls to -- * receive_fd don't race with theirs. */ -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( create_esync ) -- { -- req->access = access; -- req->initval = initval; -- req->type = type; -- req->max = max; -- wine_server_add_data( req, objattr, len ); -- ret = wine_server_call( req ); -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -- { -- *handle = wine_server_ptr_handle( reply->handle ); -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == *handle ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -- { -- add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- TRACE("-> handle %p, fd %d.\n", *handle, fd); -- } -- -- free( objattr ); -- return ret; --} -- --static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) --{ -- NTSTATUS ret; -- obj_handle_t fd_handle; -- unsigned int shm_idx; -- sigset_t sigset; -- int fd; -- -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( open_esync ) -- { -- req->access = access; -- req->attributes = attr->Attributes; -- req->rootdir = wine_server_obj_handle( attr->RootDirectory ); -- req->type = type; -- if (attr->ObjectName) -- wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); -- if (!(ret = wine_server_call( req ))) -- { -- *handle = wine_server_ptr_handle( reply->handle ); -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == *handle ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (!ret) -- { -- add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- -- TRACE("-> handle %p, fd %d.\n", *handle, fd); -- } -- return ret; --} -- --extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initial, int max) --{ -- TRACE("name %s, initial %d, max %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", initial, max); -- -- return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max ); --} -- --NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); --} -- --NTSTATUS esync_release_semaphore( HANDLE handle, unsigned int count, ULONG *prev ) --{ -- struct esync *obj; -- struct semaphore *semaphore; -- uint64_t count64 = count; -- ULONG current; -- NTSTATUS ret; -- -- TRACE("%p, %d, %p.\n", handle, count, prev); -- -- if ((ret = get_object( handle, &obj))) return ret; -- semaphore = obj->shm; -- -- do -- { -- current = semaphore->count; -- -- if (count + current > semaphore->max) -- return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -- } while (InterlockedCompareExchange( &semaphore->count, count + current, current ) != current); -- -- if (prev) *prev = current; -- -- /* We don't have to worry about a race between increasing the count and -- * write(). The fact that we were able to increase the count means that we -- * have permission to actually write that many releases to the semaphore. */ -- -- if (write( obj->fd, &count64, sizeof(count64) ) == -1) -- return errno_to_status( errno ); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_semaphore( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- struct semaphore *semaphore; -- SEMAPHORE_BASIC_INFORMATION *out = info; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- semaphore = obj->shm; -- -- out->CurrentCount = semaphore->count; -- out->MaximumCount = semaphore->max; -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, EVENT_TYPE event_type, BOOLEAN initial ) --{ -- enum esync_type type = (event_type == SynchronizationEvent ? ESYNC_AUTO_EVENT : ESYNC_MANUAL_EVENT); -- -- TRACE("name %s, %s-reset, initial %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", -- event_type == NotificationEvent ? "manual" : "auto", initial); -- -- return create_esync( type, handle, access, attr, initial, 0 ); --} -- --NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ --} -- --static inline void small_pause(void) --{ --#ifdef __i386__ -- __asm__ __volatile__( "rep;nop" : : : "memory" ); --#else -- __asm__ __volatile__( "" : : : "memory" ); --#endif --} -- --/* Manual-reset events are actually racier than other objects in terms of shm -- * state. With other objects, races don't matter, because we only treat the shm -- * state as a hint that lets us skip poll()—we still have to read(). But with -- * manual-reset events we don't, which means that the shm state can be out of -- * sync with the actual state. -- * -- * In general we shouldn't have to worry about races between modifying the -- * event and waiting on it. If the state changes while we're waiting, it's -- * equally plausible that we caught it before or after the state changed. -- * However, we can have races between SetEvent() and ResetEvent(), so that the -- * event has inconsistent internal state. -- * -- * To solve this we have to use the other field to lock the event. Currently -- * this is implemented as a spinlock, but I'm not sure if a futex might be -- * better. I'm also not sure if it's possible to obviate locking by arranging -- * writes and reads in a certain way. -- * -- * Note that we don't have to worry about locking in esync_wait_objects(). -- * There's only two general patterns: -- * -- * WaitFor() SetEvent() -- * ------------------------- -- * read() -- * signaled = 0 -- * signaled = 1 -- * write() -- * ------------------------- -- * read() -- * signaled = 1 -- * signaled = 0 -- * -- * ------------------------- -- * -- * That is, if SetEvent() tries to signal the event before WaitFor() resets its -- * signaled state, it won't bother trying to write(), and then the signaled -- * state will be reset, so the result is a consistent non-signaled event. -- * There's several variations to this pattern but all of them are protected in -- * the same way. Note however this is why we have to use interlocked_xchg() -- * event inside of the lock. -- */ -- --/* Removing this spinlock is harder than it looks. esync_wait_objects() can -- * deal with inconsistent state well enough, and a race between SetEvent() and -- * ResetEvent() gives us license to yield either result as long as we act -- * consistently, but that's not enough. Notably, esync_wait_objects() should -- * probably act like a fence, so that the second half of esync_set_event() does -- * not seep past a subsequent reset. That's one problem, but no guarantee there -- * aren't others. */ -- --NTSTATUS esync_set_event( HANDLE handle ) --{ -- static const uint64_t value = 1; -- struct esync *obj; -- struct event *event; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- event = obj->shm; -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -- } -- -- /* For manual-reset events, as long as we're in a lock, we can take the -- * optimization of only calling write() if the event wasn't already -- * signaled. -- * -- * For auto-reset events, esync_wait_objects() must grab the kernel object. -- * Thus if we got into a race so that the shm state is signaled but the -- * eventfd is unsignaled (i.e. reset shm, set shm, set fd, reset fd), we -- * *must* signal the fd now, or any waiting threads will never wake up. */ -- -- if (!InterlockedExchange( &event->signaled, 1 ) || obj->type == ESYNC_AUTO_EVENT) -- { -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- ERR("write: %s\n", strerror(errno)); -- } -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_reset_event( HANDLE handle ) --{ -- uint64_t value; -- struct esync *obj; -- struct event *event; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- event = obj->shm; -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -- } -- -- /* For manual-reset events, as long as we're in a lock, we can take the -- * optimization of only calling read() if the event was already signaled. -- * -- * For auto-reset events, we have no guarantee that the previous "signaled" -- * state is actually correct. We need to leave both states unsignaled after -- * leaving this function, so we always have to read(). */ -- if (InterlockedExchange( &event->signaled, 0 ) || obj->type == ESYNC_AUTO_EVENT) -- { -- if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) -- { -- ERR("read: %s\n", strerror(errno)); -- } -- } -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_pulse_event( HANDLE handle ) --{ -- uint64_t value = 1; -- struct esync *obj; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- -- /* This isn't really correct; an application could miss the write. -- * Unfortunately we can't really do much better. Fortunately this is rarely -- * used (and publicly deprecated). */ -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return errno_to_status( errno ); -- -- /* Try to give other threads a chance to wake up. Hopefully erring on this -- * side is the better thing to do... */ -- NtYieldExecution(); -- -- read( obj->fd, &value, sizeof(value) ); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- EVENT_BASIC_INFORMATION *out = info; -- struct pollfd fd; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- -- fd.fd = obj->fd; -- fd.events = POLLIN; -- out->EventState = poll( &fd, 1, 0 ); -- out->EventType = (obj->type == ESYNC_AUTO_EVENT ? SynchronizationEvent : NotificationEvent); -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) --{ -- TRACE("name %s, initial %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", initial); -- -- return create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); --} -- --NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_MUTEX, handle, access, attr ); --} -- --NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) --{ -- struct esync *obj; -- struct mutex *mutex; -- static const uint64_t value = 1; -- NTSTATUS ret; -- -- TRACE("%p, %p.\n", handle, prev); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- mutex = obj->shm; -- -- /* This is thread-safe, because the only thread that can change the tid to -- * or from our tid is ours. */ -- if (mutex->tid != GetCurrentThreadId()) return STATUS_MUTANT_NOT_OWNED; -- -- if (prev) *prev = mutex->count; -- -- mutex->count--; -- -- if (!mutex->count) -- { -- /* This is also thread-safe, as long as signaling the file is the last -- * thing we do. Other threads don't care about the tid if it isn't -- * theirs. */ -- mutex->tid = 0; -- -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return errno_to_status( errno ); -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- struct mutex *mutex; -- MUTANT_BASIC_INFORMATION *out = info; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- mutex = obj->shm; -- -- out->CurrentCount = 1 - mutex->count; -- out->OwnedByCaller = (mutex->tid == GetCurrentThreadId()); -- out->AbandonedState = (mutex->tid == ~0); -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --#define TICKSPERSEC 10000000 --#define TICKSPERMSEC 10000 -- --static LONGLONG update_timeout( ULONGLONG end ) --{ -- LARGE_INTEGER now; -- LONGLONG timeleft; -- -- NtQuerySystemTime( &now ); -- timeleft = end - now.QuadPart; -- if (timeleft < 0) timeleft = 0; -- return timeleft; --} -- --static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) --{ -- int ret; -- -- do -- { -- if (end) -- { -- LONGLONG timeleft = update_timeout( *end ); -- --#ifdef HAVE_PPOLL -- /* We use ppoll() if available since the time granularity is better. */ -- struct timespec tmo_p; -- tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; -- tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100; -- ret = ppoll( fds, nfds, &tmo_p, NULL ); --#else -- ret = poll( fds, nfds, timeleft / TICKSPERMSEC ); --#endif -- } -- else -- ret = poll( fds, nfds, -1 ); -- -- /* If we receive EINTR we were probably suspended (SIGUSR1), possibly for a -- * system APC. The right thing to do is just try again. */ -- } while (ret < 0 && errno == EINTR); -- -- return ret; --} -- --/* Return TRUE if abandoned. */ --static BOOL update_grabbed_object( struct esync *obj ) --{ -- BOOL ret = FALSE; -- -- if (obj->type == ESYNC_MUTEX) -- { -- struct mutex *mutex = obj->shm; -- /* We don't have to worry about a race between this and read(); the -- * fact that we grabbed it means the count is now zero, so nobody else -- * can (and the only thread that can release it is us). */ -- if (mutex->tid == ~0) -- ret = TRUE; -- mutex->tid = GetCurrentThreadId(); -- mutex->count++; -- } -- else if (obj->type == ESYNC_SEMAPHORE) -- { -- struct semaphore *semaphore = obj->shm; -- /* We don't have to worry about a race between this and read(); the -- * fact that we were able to grab it at all means the count is nonzero, -- * and if someone else grabbed it then the count must have been >= 2, -- * etc. */ -- InterlockedExchangeAdd( &semaphore->count, -1 ); -- } -- else if (obj->type == ESYNC_AUTO_EVENT) -- { -- struct event *event = obj->shm; -- /* We don't have to worry about a race between this and read(), since -- * this is just a hint, and the real state is in the kernel object. -- * This might already be 0, but that's okay! */ -- event->signaled = 0; -- } -- -- return ret; --} -- --/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we -- * need to delegate to server_select(). */ --static NTSTATUS __esync_wait_objects( unsigned int count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ) --{ -- static const LARGE_INTEGER zero; -- -- struct esync *objs[MAXIMUM_WAIT_OBJECTS]; -- struct pollfd fds[MAXIMUM_WAIT_OBJECTS + 1]; -- int has_esync = 0, has_server = 0; -- BOOL msgwait = FALSE; -- LONGLONG timeleft; -- LARGE_INTEGER now; -- DWORD pollcount; -- ULONGLONG end; -- int64_t value; -- ssize_t size; -- int i, j, ret; -- -- /* Grab the APC fd if we don't already have it. */ -- if (alertable && ntdll_get_thread_data()->esync_apc_fd == -1) -- { -- obj_handle_t fd_handle; -- sigset_t sigset; -- int fd = -1; -- -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( get_esync_apc_fd ) -- { -- if (!(ret = wine_server_call( req ))) -- { -- fd = receive_fd( &fd_handle ); -- assert( fd_handle == GetCurrentThreadId() ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- ntdll_get_thread_data()->esync_apc_fd = fd; -- } -- -- NtQuerySystemTime( &now ); -- if (timeout) -- { -- if (timeout->QuadPart == TIMEOUT_INFINITE) -- timeout = NULL; -- else if (timeout->QuadPart >= 0) -- end = timeout->QuadPart; -- else -- end = now.QuadPart - timeout->QuadPart; -- } -- -- for (i = 0; i < count; i++) -- { -- ret = get_object( handles[i], &objs[i] ); -- if (ret == STATUS_SUCCESS) -- has_esync = 1; -- else if (ret == STATUS_NOT_IMPLEMENTED) -- has_server = 1; -- else -- return ret; -- } -- -- if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE) -- msgwait = TRUE; -- -- if (has_esync && has_server) -- FIXME("Can't wait on esync and server objects at the same time!\n"); -- else if (has_server) -- return STATUS_NOT_IMPLEMENTED; -- -- if (TRACE_ON(esync)) -- { -- TRACE("Waiting for %s of %d handles:", wait_any ? "any" : "all", count); -- for (i = 0; i < count; i++) -- TRACE(" %p", handles[i]); -- -- if (msgwait) -- TRACE(" or driver events"); -- if (alertable) -- TRACE(", alertable"); -- -- if (!timeout) -- TRACE(", timeout = INFINITE.\n"); -- else -- { -- timeleft = update_timeout( end ); -- TRACE(", timeout = %ld.%07ld sec.\n", -- (long) timeleft / TICKSPERSEC, (long) timeleft % TICKSPERSEC); -- } -- } -- -- if (wait_any || count == 1) -- { -- /* Try to check objects now, so we can obviate poll() at least. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- if (obj) -- { -- switch (obj->type) -- { -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = obj->shm; -- -- if (mutex->tid == GetCurrentThreadId()) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- mutex->count++; -- return i; -- } -- else if (!mutex->count) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- if (mutex->tid == ~0) -- { -- TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i); -- i += STATUS_ABANDONED_WAIT_0; -- } -- else -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- mutex->tid = GetCurrentThreadId(); -- mutex->count++; -- return i; -- } -- } -- break; -- } -- case ESYNC_SEMAPHORE: -- { -- struct semaphore *semaphore = obj->shm; -- -- if (semaphore->count) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- InterlockedDecrement( &semaphore->count ); -- return i; -- } -- } -- break; -- } -- case ESYNC_AUTO_EVENT: -- { -- struct event *event = obj->shm; -- -- if (event->signaled) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- event->signaled = 0; -- return i; -- } -- } -- break; -- } -- case ESYNC_MANUAL_EVENT: -- { -- struct event *event = obj->shm; -- -- if (event->signaled) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- return i; -- } -- break; -- } -- case ESYNC_AUTO_SERVER: -- case ESYNC_MANUAL_SERVER: -- case ESYNC_QUEUE: -- /* We can't wait on any of these. Fortunately I don't think -- * they'll ever be uncontended anyway (at least, they won't be -- * performance-critical). */ -- break; -- } -- } -- -- fds[i].fd = obj ? obj->fd : -1; -- fds[i].events = POLLIN; -- } -- if (alertable) -- { -- fds[i].fd = ntdll_get_thread_data()->esync_apc_fd; -- fds[i].events = POLLIN; -- i++; -- } -- pollcount = i; -- -- while (1) -- { -- ret = do_poll( fds, pollcount, timeout ? &end : NULL ); -- if (ret > 0) -- { -- /* We must check this first! The server may set an event that -- * we're waiting on, but we need to return STATUS_USER_APC. */ -- if (alertable) -- { -- if (fds[pollcount - 1].revents & POLLIN) -- goto userapc; -- } -- -- /* Find out which object triggered the wait. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) -- { -- ERR("Polling on fd %d returned %#x.\n", fds[i].fd, fds[i].revents); -- return STATUS_INVALID_HANDLE; -- } -- -- if (obj) -- { -- if (obj->type == ESYNC_MANUAL_EVENT -- || obj->type == ESYNC_MANUAL_SERVER -- || obj->type == ESYNC_QUEUE) -- { -- /* Don't grab the object, just check if it's signaled. */ -- if (fds[i].revents & POLLIN) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- return i; -- } -- } -- else -- { -- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value)) -- { -- /* We found our object. */ -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- if (update_grabbed_object( obj )) -- return STATUS_ABANDONED_WAIT_0 + i; -- return i; -- } -- } -- } -- } -- -- /* If we got here, someone else stole (or reset, etc.) whatever -- * we were waiting for. So keep waiting. */ -- NtQuerySystemTime( &now ); -- } -- else -- goto err; -- } -- } -- else -- { -- /* Wait-all is a little trickier to implement correctly. Fortunately, -- * it's not as common. -- * -- * The idea is basically just to wait in sequence on every object in the -- * set. Then when we're done, try to grab them all in a tight loop. If -- * that fails, release any resources we've grabbed (and yes, we can -- * reliably do this—it's just mutexes and semaphores that we have to -- * put back, and in both cases we just put back 1), and if any of that -- * fails we start over. -- * -- * What makes this inherently bad is that we might temporarily grab a -- * resource incorrectly. Hopefully it'll be quick (and hey, it won't -- * block on wineserver) so nobody will notice. Besides, consider: if -- * object A becomes signaled but someone grabs it before we can grab it -- * and everything else, then they could just as well have grabbed it -- * before it became signaled. Similarly if object A was signaled and we -- * were blocking on object B, then B becomes available and someone grabs -- * A before we can, then they might have grabbed A before B became -- * signaled. In either case anyone who tries to wait on A or B will be -- * waiting for an instant while we put things back. */ -- -- while (1) -- { --tryagain: -- /* First step: try to poll on each object in sequence. */ -- fds[0].events = POLLIN; -- pollcount = 1; -- if (alertable) -- { -- /* We also need to wait on APCs. */ -- fds[1].fd = ntdll_get_thread_data()->esync_apc_fd; -- fds[1].events = POLLIN; -- pollcount++; -- } -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- fds[0].fd = obj ? obj->fd : -1; -- -- if (obj && obj->type == ESYNC_MUTEX) -- { -- /* It might be ours. */ -- struct mutex *mutex = obj->shm; -- -- if (mutex->tid == GetCurrentThreadId()) -- continue; -- } -- -- ret = do_poll( fds, pollcount, timeout ? &end : NULL ); -- if (ret <= 0) -- goto err; -- else if (alertable && (fds[1].revents & POLLIN)) -- goto userapc; -- -- if (fds[0].revents & (POLLHUP | POLLERR | POLLNVAL)) -- { -- ERR("Polling on fd %d returned %#x.\n", fds[0].fd, fds[0].revents); -- return STATUS_INVALID_HANDLE; -- } -- } -- -- /* If we got here and we haven't timed out, that means all of the -- * handles were signaled. Check to make sure they still are. */ -- for (i = 0; i < count; i++) -- { -- fds[i].fd = objs[i] ? objs[i]->fd : -1; -- fds[i].events = POLLIN; -- } -- /* There's no reason to check for APCs here. */ -- pollcount = i; -- -- /* Poll everything to see if they're still signaled. */ -- ret = poll( fds, pollcount, 0 ); -- if (ret == pollcount) -- { -- BOOL abandoned = FALSE; -- -- /* Quick, grab everything. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- switch (obj->type) -- { -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = obj->shm; -- if (mutex->tid == GetCurrentThreadId()) -- break; -- /* otherwise fall through */ -- } -- case ESYNC_SEMAPHORE: -- case ESYNC_AUTO_EVENT: -- if ((size = read( fds[i].fd, &value, sizeof(value) )) != sizeof(value)) -- { -- /* We were too slow. Put everything back. */ -- value = 1; -- for (j = i - 1; j >= 0; j--) -- { -- struct esync *obj = objs[j]; -- -- if (obj->type == ESYNC_MUTEX) -- { -- struct mutex *mutex = obj->shm; -- -- if (mutex->tid == GetCurrentThreadId()) -- continue; -- } -- if (write( fds[j].fd, &value, sizeof(value) ) == -1) -- { -- ERR("write failed.\n"); -- return errno_to_status( errno ); -- } -- } -- -- goto tryagain; /* break out of two loops and a switch */ -- } -- break; -- default: -- /* If a manual-reset event changed between there and -- * here, it's shouldn't be a problem. */ -- break; -- } -- } -- -- /* If we got here, we successfully waited on every object. */ -- /* Make sure to let ourselves know that we grabbed the mutexes -- * and semaphores. */ -- for (i = 0; i < count; i++) -- abandoned |= update_grabbed_object( objs[i] ); -- -- if (abandoned) -- { -- TRACE("Wait successful, but some object(s) were abandoned.\n"); -- return STATUS_ABANDONED; -- } -- TRACE("Wait successful.\n"); -- return STATUS_SUCCESS; -- } -- -- /* If we got here, ppoll() returned less than all of our objects. -- * So loop back to the beginning and try again. */ -- } /* while(1) */ -- } /* else (wait-all) */ -- --err: -- /* We should only get here if poll() failed. */ -- -- if (ret == 0) -- { -- TRACE("Wait timed out.\n"); -- return STATUS_TIMEOUT; -- } -- else -- { -- ERR("ppoll failed: %s\n", strerror(errno)); -- return errno_to_status( errno ); -- } -- --userapc: -- TRACE("Woken up by user APC.\n"); -- -- /* We have to make a server call anyway to get the APC to execute, so just -- * delegate down to server_select(). */ -- ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &zero ); -- -- /* This can happen if we received a system APC, and the APC fd was woken up -- * before we got SIGUSR1. poll() doesn't return EINTR in that case. The -- * right thing to do seems to be to return STATUS_USER_APC anyway. */ -- if (ret == STATUS_TIMEOUT) ret = STATUS_USER_APC; -- return ret; --} -- --/* We need to let the server know when we are doing a message wait, and when we -- * are done with one, so that all of the code surrounding hung queues works. -- * We also need this for WaitForInputIdle(). */ --static void server_set_msgwait( int in_msgwait ) --{ -- SERVER_START_REQ( esync_msgwait ) -- { -- req->in_msgwait = in_msgwait; -- wine_server_call( req ); -- } -- SERVER_END_REQ; --} -- --/* This is a very thin wrapper around the proper implementation above. The -- * purpose is to make sure the server knows when we are doing a message wait. -- * This is separated into a wrapper function since there are at least a dozen -- * exit paths from esync_wait_objects(). */ --NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ) --{ -- BOOL msgwait = FALSE; -- struct esync *obj; -- NTSTATUS ret; -- -- if (count && !get_object( handles[count - 1], &obj ) && obj->type == ESYNC_QUEUE) -- { -- msgwait = TRUE; -- server_set_msgwait( 1 ); -- } -- -- ret = __esync_wait_objects( count, handles, wait_any, alertable, timeout ); -- -- if (msgwait) -- server_set_msgwait( 0 ); -- -- return ret; --} -- --NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -- const LARGE_INTEGER *timeout ) --{ -- struct esync *obj; -- NTSTATUS ret; -- -- if ((ret = get_object( signal, &obj ))) return ret; -- -- switch (obj->type) -- { -- case ESYNC_SEMAPHORE: -- ret = esync_release_semaphore( signal, 1, NULL ); -- break; -- case ESYNC_AUTO_EVENT: -- case ESYNC_MANUAL_EVENT: -- ret = esync_set_event( signal ); -- break; -- case ESYNC_MUTEX: -- ret = esync_release_mutex( signal, NULL ); -- break; -- default: -- return STATUS_OBJECT_TYPE_MISMATCH; -- } -- if (ret) return ret; -- -- return esync_wait_objects( 1, &wait, TRUE, alertable, timeout ); --} -- --void esync_init(void) --{ -- struct stat st; -- -- if (!do_esync()) -- { -- /* make sure the server isn't running with WINEESYNC */ -- HANDLE handle; -- NTSTATUS ret; -- -- ret = create_esync( 0, &handle, 0, NULL, 0, 0 ); -- if (ret != STATUS_NOT_IMPLEMENTED) -- { -- ERR("Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.\n"); -- exit(1); -- } -- -- return; -- } -- -- if (stat( config_dir, &st ) == -1) -- ERR("Cannot stat %s\n", config_dir); -- -- if (st.st_ino != (unsigned long)st.st_ino) -- sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino ); -- else -- sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino ); -- -- if ((shm_fd = shm_open( shm_name, O_RDWR, 0644 )) == -1) -- { -- /* probably the server isn't running with WINEESYNC, tell the user and bail */ -- if (errno == ENOENT) -- ERR("Failed to open esync shared memory file; make sure no stale wineserver instances are running without WINEESYNC.\n"); -- else -- ERR("Failed to initialize shared memory: %s\n", strerror( errno )); -- exit(1); -- } -- -- pagesize = sysconf( _SC_PAGESIZE ); -- -- shm_addrs = calloc( 128, sizeof(shm_addrs[0]) ); -- shm_addrs_size = 128; --} -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -deleted file mode 100644 -index 59f8809..0000000 ---- a/dlls/ntdll/unix/esync.h -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --extern int do_esync(void); --extern void esync_init(void); --extern NTSTATUS esync_close( HANDLE handle ); -- --extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initial, int max); --extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_query_semaphore( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_release_semaphore( HANDLE handle, unsigned int count, ULONG *prev ); -- --extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ); --extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_pulse_event( HANDLE handle ); --extern NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_reset_event( HANDLE handle ); --extern NTSTATUS esync_set_event( HANDLE handle ); -- --extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ); --extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ); -- --extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ); --extern NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -- const LARGE_INTEGER *timeout ); -- -- --/* We have to synchronize on the fd cache mutex so that our calls to receive_fd -- * don't race with theirs. It looks weird, I know. -- * -- * If we weren't trying to avoid touching the code I'd rename the mutex to -- * "server_fd_mutex" or something similar. */ --extern pthread_mutex_t fd_cache_mutex; -- --extern int receive_fd( obj_handle_t *handle ); -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 2bfb9b7..81564d7 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -7507,7 +7507,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void - } - if (handle) - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - NtClose( handle ); - } - else /* Unix lock conflict, sleep a bit and retry */ -diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index 50d9e27..f163492 100644 ---- a/dlls/ntdll/unix/loader.c -+++ b/dlls/ntdll/unix/loader.c -@@ -88,7 +88,6 @@ extern char **environ; - #include "winioctl.h" - #include "winternl.h" - #include "unix_private.h" --#include "esync.h" - #include "wine/list.h" - #include "ntsyscalls.h" - #include "wine/debug.h" -@@ -1853,7 +1852,6 @@ static void start_main_thread(void) - signal_alloc_thread( teb ); - dbg_init(); - startup_info_size = server_init_process(); -- esync_init(); - virtual_map_user_shared_data(); - init_cpu_info(); - init_files(); -diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index 3591a3e..b744517 100644 ---- a/dlls/ntdll/unix/process.c -+++ b/dlls/ntdll/unix/process.c -@@ -921,7 +921,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ - - /* wait for the new process info to be ready */ - -- NtWaitForSingleObject( process_info, FALSE, NULL ); -+ server_wait_for_object( process_info, FALSE, NULL ); - SERVER_START_REQ( get_new_process_info ) - { - req->info = wine_server_obj_handle( process_info ); -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index 0d4b320..dba7645 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -83,7 +83,6 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" --#include "esync.h" - #include "ddk/wdm.h" - - WINE_DEFAULT_DEBUG_CHANNEL(server); -@@ -814,6 +813,21 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f - } - - -+/* helper function to perform a server-side wait on an internal handle without -+ * using the fast synchronization path */ -+unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ) -+{ -+ union select_op select_op; -+ UINT flags = SELECT_INTERRUPTIBLE; -+ -+ if (alertable) flags |= SELECT_ALERTABLE; -+ -+ select_op.wait.op = SELECT_WAIT; -+ select_op.wait.handles[0] = wine_server_obj_handle( handle ); -+ return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); -+} -+ -+ - /*********************************************************************** - * NtContinue (NTDLL.@) - */ -@@ -875,7 +889,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a - } - else - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - - SERVER_START_REQ( get_apc_result ) - { -@@ -947,7 +961,7 @@ void wine_server_send_fd( int fd ) - * - * Receive a file descriptor passed from the server. - */ --int receive_fd( obj_handle_t *handle ) -+static int receive_fd( obj_handle_t *handle ) - { - struct iovec vec; - struct msghdr msghdr; -@@ -1826,12 +1840,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE - return result.dup_handle.status; - } - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - if (options & DUPLICATE_CLOSE_SOURCE) -+ { - fd = remove_fd_from_cache( source ); -+ close_inproc_sync_obj( source ); -+ } - - SERVER_START_REQ( dup_handle ) - { -@@ -1897,14 +1916,15 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) - if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) - return STATUS_SUCCESS; - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - fd = remove_fd_from_cache( handle ); - -- if (do_esync()) -- esync_close( handle ); -+ close_inproc_sync_obj( handle ); - - SERVER_START_REQ( close_handle ) - { -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 1072265..a9a0a2c 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -30,9 +30,11 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #ifdef HAVE_SYS_SYSCALL_H - #include -@@ -45,6 +47,7 @@ - #endif - #include - #include -+#include - #include - #include - #include -@@ -54,6 +57,9 @@ - #ifdef HAVE_KQUEUE - # include - #endif -+#ifdef HAVE_LINUX_NTSYNC_H -+# include -+#endif - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -63,7 +69,6 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" --#include "esync.h" - - WINE_DEFAULT_DEBUG_CHANNEL(sync); - -@@ -72,9 +77,11 @@ HANDLE keyed_event = 0; - static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - { - if (!timeout) return "(infinite)"; -- return wine_dbgstr_longlong( timeout->QuadPart ); -+ return wine_dbg_sprintf( "%lld.%07ld", (long long)(timeout->QuadPart / TICKSPERSEC), -+ (long)(timeout->QuadPart % TICKSPERSEC) ); - } - -+ - /* return a monotonic time counter, in Win32 ticks */ - static inline ULONGLONG monotonic_counter(void) - { -@@ -301,6 +309,901 @@ - } - - -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+static int get_linux_sync_device(void) -+{ -+ static LONG device = -2; -+ -+ if (device == -2) -+ { -+ HANDLE handle; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ SERVER_START_REQ( get_linux_sync_device ) -+ { -+ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if (!ret) -+ { -+ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) -+ { -+ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) -+ { -+ /* someone beat us to it */ -+ if (needs_close) close( fd ); -+ NtClose( handle ); -+ } -+ /* otherwise don't close the device */ -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ NtClose( handle ); -+ } -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ } -+ } -+ return device; -+} -+ -+/* It's possible for synchronization primitives to remain alive even after being -+ * closed, because a thread is still waiting on them. It's rare in practice, and -+ * documented as being undefined behaviour by Microsoft, but it works, and some -+ * applications rely on it. This means we need to refcount handles, and defer -+ * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the in-process synchronization -+ * object, as well as a private refcount. When the client refcount reaches zero, -+ * it closes the handle; when all handles are closed, the server deletes the -+ * in-process synchronization object. -+ * -+ * We also need this for signal-and-wait. The signal and wait operations aren't -+ * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE -+ * for the wait—we need to either do both operations or neither. That means we -+ * need to grab references to both objects, and prevent them from being -+ * destroyed before we're done with them. -+ * -+ * We want lookup of objects from the cache to be very fast; ideally, it should -+ * be lock-free. We achieve this by using atomic modifications to "refcount", -+ * and guaranteeing that all other fields are valid and correct *as long as* -+ * refcount is nonzero, and we store the entire structure in memory which will -+ * never be freed. -+ * -+ * This means that acquiring the object can't use a simple atomic increment; it -+ * has to use a compare-and-swap loop to ensure that it doesn't try to increment -+ * an object with a zero refcount. That's still leagues better than a real lock, -+ * though, and release can be a single atomic decrement. -+ * -+ * It also means that threads modifying the cache need to take a lock, to -+ * prevent other threads from writing to it concurrently. -+ * -+ * It's possible for an object currently in use (by a waiter) to be closed and -+ * the same handle immediately reallocated to a different object. This should be -+ * a very rare situation, and in that case we simply don't cache the handle. -+ */ -+struct inproc_sync_cache_entry -+{ -+ LONG refcount; -+ int fd; -+ enum inproc_sync_type type; -+ unsigned int access; -+ BOOL closed; -+ /* handle to the underlying in-process sync object, stored as obj_handle_t -+ * to save space */ -+ obj_handle_t handle; -+}; -+ -+ -+static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) -+{ -+ /* save the handle and fd now; as soon as the refcount hits 0 we cannot -+ * access the cache anymore */ -+ HANDLE handle = wine_server_ptr_handle( cache->handle ); -+ int fd = cache->fd; -+ LONG refcount = InterlockedDecrement( &cache->refcount ); -+ -+ assert( refcount >= 0 ); -+ -+ if (!refcount) -+ { -+ NTSTATUS ret; -+ -+ /* we can't call NtClose here as we may be inside fd_cache_mutex */ -+ SERVER_START_REQ( close_handle ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ ret = wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+ -+ assert( !ret ); -+ close( fd ); -+ } -+} -+ -+ -+#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) -+#define INPROC_SYNC_CACHE_ENTRIES 128 -+ -+static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; -+static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; -+ -+static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) -+{ -+ unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; -+ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; -+} -+ -+ -+static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, -+ enum inproc_sync_type type, unsigned int access ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ sigset_t sigset; -+ int refcount; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES) -+ { -+ FIXME( "too many allocated handles, not caching %p\n", handle ); -+ return NULL; -+ } -+ -+ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ -+ { -+ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; -+ else -+ { -+ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); -+ void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); -+ if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) -+ munmap( ptr, size ); /* someone beat us to it */ -+ } -+ } -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same -+ * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_inproc_sync_obj() and close_handle. */ -+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) -+ { -+ /* We lost the race with another thread trying to cache this object, or -+ * the handle is currently being used for another object (i.e. it was -+ * closed and then reused). We have no way of knowing which, and in the -+ * latter case we can't cache this object until the old one is -+ * completely destroyed, so always return failure. */ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ return NULL; -+ } -+ -+ cache->handle = inproc_sync; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. -+ * Set the refcount to 2 (one for the handle, one for the caller). */ -+ refcount = InterlockedExchange( &cache->refcount, 2 ); -+ assert( !refcount ); -+ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ return cache; -+} -+ -+ -+/* returns the previous value */ -+static inline LONG interlocked_inc_if_nonzero( LONG *dest ) -+{ -+ LONG val, tmp; -+ for (val = *dest;; val = tmp) -+ { -+ if (!val || (tmp = InterlockedCompareExchange( dest, val + 1, val )) == val) -+ break; -+ } -+ return val; -+} -+ -+ -+static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) -+ return NULL; -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* this load needs acquire semantics [paired with the store in -+ * cache_inproc_sync_obj()] */ -+ if (!interlocked_inc_if_nonzero( &cache->refcount )) -+ return NULL; -+ -+ if (cache->closed) -+ { -+ /* The object is still being used, but "handle" has been closed. The -+ * handle value might have been reused for another object in the -+ * meantime, in which case we have to report that valid object, so -+ * force the caller to check the server. */ -+ release_inproc_sync_obj( cache ); -+ return NULL; -+ } -+ -+ return cache; -+} -+ -+ -+static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) -+{ -+ if (a == b) return TRUE; -+ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ return FALSE; -+} -+ -+ -+/* returns a pointer to a cache entry; if the object could not be cached, -+ * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, -+ ACCESS_MASK desired_access, -+ struct inproc_sync_cache_entry *stack_cache, -+ struct inproc_sync_cache_entry **ret_cache ) -+{ -+ struct inproc_sync_cache_entry *cache; -+ obj_handle_t inproc_sync_handle; -+ enum inproc_sync_type type; -+ unsigned int access; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ /* try to find it in the cache already */ -+ if ((cache = get_cached_inproc_sync_obj( handle ))) -+ { -+ *ret_cache = cache; -+ return STATUS_SUCCESS; -+ } -+ -+ /* try to retrieve it from the server */ -+ SERVER_START_REQ( get_linux_sync_obj ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ if (!(ret = wine_server_call( req ))) -+ { -+ inproc_sync_handle = reply->handle; -+ access = reply->access; -+ type = reply->type; -+ } -+ } -+ SERVER_END_REQ; -+ -+ if (ret) return ret; -+ -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), -+ 0, &fd, &needs_close, NULL, NULL ))) -+ return ret; -+ -+ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); -+ if (!cache) -+ { -+ cache = stack_cache; -+ cache->handle = inproc_sync_handle; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ cache->refcount = 1; -+ } -+ -+ *ret_cache = cache; -+ -+ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((cache->access & desired_access) != desired_access) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ -+ return STATUS_SUCCESS; -+} -+ -+ -+/* caller must hold fd_cache_mutex */ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); -+ -+ if (cache) -+ { -+ cache->closed = TRUE; -+ /* once for the reference we just grabbed, and once for the handle */ -+ release_inproc_sync_obj( cache ); -+ release_inproc_sync_obj( cache ); -+ } -+} -+ -+ -+static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count ) -+{ -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_semaphore_obj( int obj, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_sem_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->CurrentCount = args.count; -+ info->MaximumCount = args.max; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_semaphore_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_set_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_SET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_set_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_reset_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_RESET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_reset_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_pulse_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_PULSE, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_pulse_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_event_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; -+ info->EventState = args.signaled; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_event_obj( cache->fd, cache->type, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_release_mutex_obj( int obj, LONG *prev_count ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ args.owner = GetCurrentThreadId(); -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_UNLOCK, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_MUTANT_LIMIT_EXCEEDED; -+ else if (errno == EPERM) -+ return STATUS_MUTANT_NOT_OWNED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_mutex_obj( cache->fd, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_READ, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOWNERDEAD) -+ { -+ info->AbandonedState = TRUE; -+ info->OwnedByCaller = FALSE; -+ info->CurrentCount = 1; -+ return STATUS_SUCCESS; -+ } -+ else -+ return errno_to_status( errno ); -+ } -+ info->AbandonedState = FALSE; -+ info->OwnedByCaller = (args.owner == GetCurrentThreadId()); -+ info->CurrentCount = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_mutex_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+static void select_queue(void) -+{ -+ SERVER_START_REQ( select_inproc_queue ) -+ { -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static void unselect_queue( BOOL signaled ) -+{ -+ SERVER_START_REQ( unselect_inproc_queue ) -+ { -+ req->signaled = signaled; -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static int get_inproc_alert_obj(void) -+{ -+ struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ HANDLE alert_handle; -+ unsigned int ret; -+ -+ if (data->linux_alert_obj == -1) -+ { -+ SERVER_START_REQ( get_inproc_alert_event ) -+ { -+ if ((ret = wine_server_call( req ))) -+ ERR( "failed to get inproc alert event, status %#x\n", ret ); -+ alert_handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get inproc alert obj, status %#x\n", ret ); -+ data->linux_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. -+ * Manhandling the cache entry here is fine since we're the only thread -+ * that can access our own alert event. */ -+ cache->fd = -1; -+ release_inproc_sync_obj( cache ); -+ NtClose( alert_handle ); -+ } -+ -+ return data->linux_alert_obj; -+} -+ -+static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, -+ BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct ntsync_wait_args args = {0}; -+ unsigned long request; -+ struct timespec now; -+ int ret; -+ -+ if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) -+ { -+ args.timeout = ~(__u64)0; -+ } -+ else if (timeout->QuadPart <= 0) -+ { -+ clock_gettime( CLOCK_MONOTONIC, &now ); -+ args.timeout = (now.tv_sec * NSECPERSEC) + now.tv_nsec + (-timeout->QuadPart * 100); -+ } -+ else -+ { -+ args.timeout = (timeout->QuadPart * 100) - (SECS_1601_TO_1970 * NSECPERSEC); -+ args.flags |= NTSYNC_WAIT_REALTIME; -+ } -+ -+ args.objs = (uintptr_t)objs; -+ args.count = count; -+ args.owner = GetCurrentThreadId(); -+ args.index = ~0u; -+ -+ if (alertable) -+ args.alert = get_inproc_alert_obj(); -+ -+ if (wait_any || count == 1) -+ request = NTSYNC_IOC_WAIT_ANY; -+ else -+ request = NTSYNC_IOC_WAIT_ALL; -+ -+ do -+ { -+ ret = ioctl( device, request, &args ); -+ } while (ret < 0 && errno == EINTR); -+ -+ if (!ret) -+ { -+ if (args.index == count) -+ { -+ static const LARGE_INTEGER timeout; -+ -+ ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &timeout ); -+ assert( ret == STATUS_USER_APC ); -+ return ret; -+ } -+ -+ return wait_any ? args.index : 0; -+ } -+ else if (errno == EOWNERDEAD) -+ return STATUS_ABANDONED + (wait_any ? args.index : 0); -+ else if (errno == ETIMEDOUT) -+ return STATUS_TIMEOUT; -+ else -+ return errno_to_status( errno ); -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; -+ int device, objs[64]; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ DWORD i, j; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ for (i = 0; i < count; ++i) -+ { -+ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) -+ { -+ for (j = 0; j < i; ++j) -+ release_inproc_sync_obj( cache[j] ); -+ return ret; -+ } -+ if (cache[i]->type == INPROC_SYNC_QUEUE) -+ queue = handles[i]; -+ -+ objs[i] = cache[i]->fd; -+ } -+ -+ /* It's common to wait on the message queue alone. Some applications wait -+ * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through inproc_wait(), and since we only need -+ * to go through that path if we're waiting on other objects, just delegate -+ * to the server if we're only waiting on the message queue. */ -+ if (count == 1 && queue) -+ { -+ release_inproc_sync_obj( cache[0] ); -+ return server_wait_for_object( handles[0], alertable, timeout ); -+ } -+ -+ if (queue) select_queue(); -+ -+ ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); -+ -+ if (queue) unselect_queue( handles[ret] == queue ); -+ -+ for (i = 0; i < count; ++i) -+ release_inproc_sync_obj( cache[i] ); -+ -+ return ret; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ int device; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) -+ return ret; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ if (!(signal_cache->access & EVENT_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ break; -+ -+ default: -+ /* can't be signaled */ -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return ret; -+ } -+ -+ if (wait_cache->type == INPROC_SYNC_QUEUE) -+ queue = wait; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ ret = linux_set_event_obj( signal_cache->fd, NULL ); -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ ret = linux_release_mutex_obj( signal_cache->fd, NULL ); -+ break; -+ -+ default: -+ assert( 0 ); -+ break; -+ } -+ -+ if (!ret) -+ { -+ if (queue) select_queue(); -+ ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( !ret ); -+ } -+ -+ release_inproc_sync_obj( signal_cache ); -+ release_inproc_sync_obj( wait_cache ); -+ return ret; -+} -+ -+#else -+ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+} -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+#endif -+ -+ - /****************************************************************************** - * NtCreateSemaphore (NTDLL.@) - */ -@@ -249,13 +1152,13 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, initial %d, max %d\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)initial, (int)max ); -+ - *handle = 0; - if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -- if (do_esync()) -- return esync_create_semaphore( handle, access, attr, initial, max ); -- - SERVER_START_REQ( create_semaphore ) - { - req->access = access; -@@ -279,11 +1182,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC - { - unsigned int ret; - -- *handle = 0; -- -- if (do_esync()) -- return esync_open_semaphore( handle, access, attr ); -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); - -+ *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - - SERVER_START_REQ( open_semaphore ) -@@ -320,8 +1221,11 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - - if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_semaphore( handle, info, ret_len ); -+ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_semaphore ) - { -@@ -345,8 +1249,10 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous - { - unsigned int ret; - -- if (do_esync()) -- return esync_release_semaphore( handle, count, previous ); -+ TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); -+ -+ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( release_semaphore ) - { -@@ -372,12 +1278,11 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u, state %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type, state ); -+ - *handle = 0; - if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; -- -- if (do_esync()) -- return esync_create_event( handle, access, attr, type, state ); -- - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_event ) -@@ -403,12 +1308,11 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -- if (do_esync()) -- return esync_open_event( handle, access, attr ); -- - SERVER_START_REQ( open_event ) - { - req->access = access; -@@ -429,11 +1333,12 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - */ - NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - { -- /* This comment is a dummy to make sure this patch applies in the right place. */ - unsigned int ret; - -- if (do_esync()) -- return esync_set_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -452,12 +1357,12 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - */ - NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) - { -- /* This comment is a dummy to make sure this patch applies in the right place. */ - unsigned int ret; - -- if (do_esync()) -- return esync_reset_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); - -+ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -488,8 +1393,10 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -- if (do_esync()) -- return esync_pulse_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -522,8 +1429,11 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, - - if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_event( handle, info, ret_len ); -+ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_event ) - { -@@ -550,11 +1460,10 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT - data_size_t len; - struct object_attributes *objattr; - -- *handle = 0; -- -- if (do_esync()) -- return esync_create_mutex( handle, access, attr, owned ); -+ TRACE( "access %#x, name %s, owned %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", owned ); - -+ *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_mutex ) -@@ -579,12 +1488,11 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -- if (do_esync()) -- return esync_open_mutex( handle, access, attr ); -- - SERVER_START_REQ( open_mutex ) - { - req->access = access; -@@ -607,8 +1515,10 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) - { - unsigned int ret; - -- if (do_esync()) -- return esync_release_mutex( handle, prev_count ); -+ TRACE( "handle %p, prev_count %p\n", handle, prev_count ); -+ -+ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( release_mutex ) - { -@@ -640,8 +1550,11 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, - - if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_mutex( handle, info, ret_len ); -+ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_mutex ) - { -@@ -1350,6 +2263,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type ); -+ - *handle = 0; - if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1377,6 +2293,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1430,6 +2348,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) - { - unsigned int ret; - -+ TRACE( "handle %p, state %p\n", handle, state ); -+ - SERVER_START_REQ( cancel_timer ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1498,20 +2418,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO - { - union select_op select_op; - UINT i, flags = SELECT_INTERRUPTIBLE; -+ unsigned int ret; - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - -- if (do_esync()) -+ if (TRACE_ON(sync)) - { -- NTSTATUS ret = esync_wait_objects( count, handles, wait_any, alertable, timeout ); -- if (ret != STATUS_NOT_IMPLEMENTED) -- return ret; -+ TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); -+ for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); -+ TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); -+ } -+ -+ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ { -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; - for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); -- return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - -@@ -1532,12 +2461,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, - { - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS ret; - -- if (do_esync()) -- return esync_signal_and_wait( signal, wait, alertable, timeout ); -+ TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) ); - - if (!signal) return STATUS_INVALID_HANDLE; - -+ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; - select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1760,6 +2692,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, flags %#x\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)flags ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -1784,6 +2719,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1810,6 +2747,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -1829,6 +2768,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -2019,7 +2019,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * - } - SERVER_END_REQ; - if (status != STATUS_PENDING) return status; -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) return status; - -@@ -2081,7 +2081,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM - assert( status == STATUS_USER_APC ); - goto done; - } -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) goto done; - -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 7f2f1b9..3f706f4 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -1776,7 +1776,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma - - if (ret == STATUS_PENDING) - { -- NtWaitForSingleObject( context_handle, FALSE, NULL ); -+ server_wait_for_object( context_handle, FALSE, NULL ); - - SERVER_START_REQ( get_thread_context ) - { -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 4e5b282..fc5b259 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -93,7 +93,6 @@ struct ntdll_thread_data - { - void *cpu_data[16]; /* reserved for CPU-specific data */ - void *kernel_stack; /* stack for thread startup and kernel syscalls */ -- int esync_apc_fd; /* fd to wait on for user APCs */ - 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 */ -@@ -102,6 +101,7 @@ struct ntdll_thread_data - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ - void *jmp_buf; /* setjmp buffer for exception handling */ -+ int linux_alert_obj; /* fd for the linux in-process alert event */ - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -196,6 +196,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); - extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); - extern void start_server( BOOL debug ); - -+extern pthread_mutex_t fd_cache_mutex; -+ - extern unsigned int server_call_unlocked( void *req_ptr ); - extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); - extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -203,6 +205,7 @@ extern unsigned int server_select( const select_op_t *select_op, data_size_t siz - timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, - const LARGE_INTEGER *timeout ); -+extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); - extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, - union apc_result *result ); - extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -353,6 +356,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); - - extern void dbg_init(void); - -+extern void close_inproc_sync_obj( HANDLE handle ); -+ - extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - PNTAPCFUNC func, NTSTATUS status ); - extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -361,6 +366,7 @@ extern void call_raise_user_exception_dispatcher(void); - #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ - - #define TICKSPERSEC 10000000 -+#define NSECPERSEC 1000000000 - #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) - - static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -419,7 +425,7 @@ static inline async_data_t server_async( HANDLE handle, struct async_fileio *use - - static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) - { -- return NtWaitForSingleObject( handle, alertable, NULL ); -+ return server_wait_for_object( handle, alertable, NULL ); - } - - static inline BOOL in_wow64_call(void) -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 1e1af8c..a54ac45 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3712,11 +3712,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) - teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; - teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); - thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; -- thread_data->esync_apc_fd = -1; - thread_data->request_fd = -1; - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ thread_data->linux_alert_obj = -1; - list_add_head( &teb_list, &thread_data->entry ); - return teb; - } -diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027f..ddcf896 100644 ---- a/dlls/webservices/tests/channel.c -+++ b/dlls/webservices/tests/channel.c -@@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { - static const char send_record_middle[] = { 0x01, 0x56, 0x0e, 0x42 }; - static const char send_record_end[] = { 0x08, 0x02, 0x6e, 0x73, 0x89, 0xff, 0x01, 0x01 }; - -+#pragma GCC diagnostic ignored "-Warray-bounds" -+#pragma GCC diagnostic ignored "-Wstringop-overflow" -+ - static BOOL send_dict_str( int sock, char *addr, const char *str, int dict_str_count ) - { - char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; -diff --git a/include/config.h.in b/include/config.h.in -index a53870f..ba0bdbd 100644 ---- a/include/config.h.in -+++ b/include/config.h.in -@@ -177,6 +177,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_MAJOR_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_NTSYNC_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_PARAM_H - -@@ -522,9 +519,6 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_EPOLL_H - --/* Define to 1 if you have the header file. */ --#undef HAVE_SYS_EVENTFD_H -- - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_EVENT_H - -diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index 34655d1..1f8e10a 100644 ---- a/include/wine/server_protocol.h -+++ b/include/wine/server_protocol.h -@@ -5881,6 +5881,86 @@ - }; - - -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+ -+struct get_linux_sync_device_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_linux_sync_device_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ -+ -+struct get_linux_sync_obj_request -+{ -+ struct request_header __header; -+ obj_handle_t handle; -+}; -+struct get_linux_sync_obj_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ int type; -+ unsigned int access; -+ char __pad_20[4]; -+}; -+ -+ -+ -+struct select_inproc_queue_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct select_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct unselect_inproc_queue_request -+{ -+ struct request_header __header; -+ int signaled; -+}; -+struct unselect_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct get_inproc_alert_event_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_inproc_alert_event_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ - enum request - { - REQ_new_process, -@@ -5921,12 +6003,12 @@ enum request - REQ_suspend_process, - REQ_resume_process, - REQ_get_next_thread, -- REQ_create_esync, -- REQ_open_esync, -- REQ_get_esync_fd, -- REQ_esync_msgwait, - REQ_set_keyboard_repeat, -- REQ_get_esync_apc_fd, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_select_inproc_queue, -+ REQ_unselect_inproc_queue, -+ REQ_get_inproc_alert_event, - REQ_NB_REQUESTS - }; - -@@ -6213,12 +6300,12 @@ union generic_request - struct suspend_process_request suspend_process_request; - struct resume_process_request resume_process_request; - struct get_next_thread_request get_next_thread_request; -- struct create_esync_request create_esync_request; -- struct open_esync_request open_esync_request; -- struct get_esync_fd_request get_esync_fd_request; -- 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; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct select_inproc_queue_request select_inproc_queue_request; -+ struct unselect_inproc_queue_request unselect_inproc_queue_request; -+ struct get_inproc_alert_event_request get_inproc_alert_event_request; - }; - union generic_reply - { -@@ -6503,12 +6595,12 @@ union generic_reply - struct suspend_process_reply suspend_process_reply; - struct resume_process_reply resume_process_reply; - struct get_next_thread_reply get_next_thread_reply; -- struct create_esync_reply create_esync_reply; -- struct open_esync_reply open_esync_reply; -- struct get_esync_fd_reply get_esync_fd_reply; -- 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; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct select_inproc_queue_reply select_inproc_queue_reply; -+ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; -+ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; - }; - - /* ### protocol_version begin ### */ -diff --git a/server/Makefile.in b/server/Makefile.in -index b164193..b30df66 100644 ---- a/server/Makefile.in -+++ b/server/Makefile.in -@@ -11,8 +11,8 @@ SOURCES = \ - debugger.c \ - device.c \ - directory.c \ -- esync.c \ - event.c \ -+ inproc_sync.c \ - fd.c \ - file.c \ - handle.c \ -diff --git a/server/async.c b/server/async.c -index b0f9fe4..02fb966 100644 ---- a/server/async.c -+++ b/server/async.c -@@ -77,7 +77,6 @@ static const struct object_ops async_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - async_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - async_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -90,6 +89,7 @@ static const struct object_ops async_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - async_destroy /* destroy */ - }; -@@ -687,7 +687,6 @@ static const struct object_ops iosb_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -700,6 +699,7 @@ static const struct object_ops iosb_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - iosb_destroy /* destroy */ - }; -diff --git a/server/atom.c b/server/atom.c -index d9824de..ba320c4 100644 ---- a/server/atom.c -+++ b/server/atom.c -@@ -79,7 +79,6 @@ static const struct object_ops atom_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -92,6 +91,7 @@ static const struct object_ops atom_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - atom_table_destroy /* destroy */ - }; -diff --git a/server/change.c b/server/change.c -index ec61711..dafa7e8 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -112,7 +112,6 @@ static const struct object_ops dir_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - dir_get_fd, /* get_fd */ -@@ -125,6 +124,7 @@ static const struct object_ops dir_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - dir_close_handle, /* close_handle */ - dir_destroy /* destroy */ - }; -diff --git a/server/clipboard.c b/server/clipboard.c -index 8b265f2..de9f84f 100644 ---- a/server/clipboard.c -+++ b/server/clipboard.c -@@ -76,7 +76,6 @@ static const struct object_ops clipboard_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +88,7 @@ static const struct object_ops clipboard_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - clipboard_destroy /* destroy */ - }; -diff --git a/server/completion.c b/server/completion.c -index 3d4be86..5ec6d20 100644 ---- a/server/completion.c -+++ b/server/completion.c -@@ -77,6 +77,7 @@ - struct list wait_queue; - unsigned int depth; - int closed; -+ struct inproc_sync *inproc_sync; - }; - - static void completion_wait_dump( struct object*, int ); -@@ -92,7 +93,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - completion_wait_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - completion_wait_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -105,6 +105,7 @@ - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - completion_wait_destroy /* destroy */ - }; -@@ -156,6 +157,7 @@ - - static void completion_dump( struct object*, int ); - static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); - static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void completion_destroy( struct object * ); - -@@ -167,7 +169,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - completion_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -180,6 +181,7 @@ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_inproc_sync,/* get_inproc_sync */ - completion_close_handle, /* close_handle */ - completion_destroy /* destroy */ - }; -@@ -193,6 +195,7 @@ - { - free( tmp ); - } -+ if (completion->inproc_sync) release_object( completion->inproc_sync ); - } - - static void completion_dump( struct object *obj, int verbose ) -@@ -230,6 +233,7 @@ - } - completion->closed = 1; - wake_up( obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); - return 1; - } - -@@ -263,6 +267,16 @@ - return wait; - } - -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) -+{ -+ struct completion *completion = (struct completion *)obj; -+ -+ if (!completion->inproc_sync) -+ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->inproc_sync) grab_object( completion->inproc_sync ); -+ return completion->inproc_sync; -+} -+ - static struct completion *create_completion( struct object *root, const struct unicode_str *name, - unsigned int attr, unsigned int concurrent, - const struct security_descriptor *sd ) -@@ -277,6 +291,7 @@ - list_init( &completion->wait_queue ); - completion->depth = 0; - completion->closed = 0; -+ completion->inproc_sync = NULL; - } - } - -@@ -309,7 +324,11 @@ - wake_up( &wait->obj, 1 ); - if (list_empty( &completion->queue )) return; - } -- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ if (!list_empty( &completion->queue )) -+ { -+ wake_up( &completion->obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); -+ } - } - - /* create a completion */ -@@ -410,6 +429,8 @@ - reply->information = msg->information; - free( msg ); - reply->wait_handle = 0; -+ if (list_empty( &completion->queue )) -+ reset_inproc_event( completion->inproc_sync ); - } - - release_object( completion ); -diff --git a/server/console.c b/server/console.c -index dbd4a97..17708df 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -41,7 +41,6 @@ - #include "wincon.h" - #include "winternl.h" - #include "wine/condrv.h" --#include "esync.h" - - struct screen_buffer; - -@@ -62,6 +61,7 @@ struct console - struct fd *fd; /* for bare console, attached input fd */ - struct async_queue ioctl_q; /* ioctl queue */ - struct async_queue read_q; /* read queue */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_dump( struct object *obj, int verbose ); -@@ -73,6 +73,7 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st - static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); - static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_ops = - { -@@ -82,7 +83,6 @@ static const struct object_ops console_ops = - console_add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_get_fd, /* get_fd */ -@@ -95,6 +95,7 @@ static const struct object_ops console_ops = - NULL, /* unlink_name */ - console_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_destroy /* destroy */ - }; -@@ -132,27 +133,27 @@ struct console_host_ioctl - - struct console_server - { -- struct object obj; /* object header */ -- struct fd *fd; /* pseudo-fd for ioctls */ -- struct console *console; /* attached console */ -- struct list queue; /* ioctl queue */ -- struct list read_queue; /* blocking read queue */ -+ struct object obj; /* object header */ -+ struct fd *fd; /* pseudo-fd for ioctls */ -+ struct console *console; /* attached console */ -+ struct list queue; /* ioctl queue */ -+ struct list read_queue; /* blocking read queue */ - unsigned int busy : 1; /* flag if server processing an ioctl */ - unsigned int once_input : 1; /* flag if input thread has already been requested */ -- int term_fd; /* UNIX terminal fd */ -- struct termios termios; /* original termios */ -- int esync_fd; -+ int term_fd; /* UNIX terminal fd */ -+ struct termios termios; /* original termios */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_server_dump( struct object *obj, int verbose ); - static void console_server_destroy( struct object *obj ); - static int console_server_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int console_server_get_esync_fd( struct object *obj, enum esync_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 ); - static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_server_ops = - { -@@ -162,7 +163,6 @@ static const struct object_ops console_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_server_signaled, /* signaled */ -- console_server_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_server_get_fd, /* get_fd */ -@@ -175,6 +175,7 @@ static const struct object_ops console_server_ops = - NULL, /* unlink_name */ - console_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_server_destroy /* destroy */ - }; -@@ -223,6 +224,7 @@ static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *screen_buffer_get_fd( struct object *obj ); - static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); - - static const struct object_ops screen_buffer_ops = - { -@@ -232,7 +234,6 @@ static const struct object_ops screen_buffer_ops = - screen_buffer_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - screen_buffer_get_fd, /* get_fd */ -@@ -245,6 +246,7 @@ static const struct object_ops screen_buffer_ops = - NULL, /* unlink_name */ - screen_buffer_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - screen_buffer_destroy /* destroy */ - }; -@@ -282,7 +284,6 @@ static const struct object_ops console_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -295,6 +296,7 @@ static const struct object_ops console_device_ops = - default_unlink_name, /* unlink_name */ - console_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -310,6 +312,7 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - unsigned int sharing, unsigned int options ); - static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); - static struct fd *console_input_get_fd( struct object *obj ); -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); - static void console_input_destroy( struct object *obj ); - - static const struct object_ops console_input_ops = -@@ -320,7 +323,6 @@ static const struct object_ops console_input_ops = - console_input_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_input_get_fd, /* get_fd */ -@@ -333,6 +335,7 @@ static const struct object_ops console_input_ops = - default_unlink_name, /* unlink_name */ - console_input_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_input_destroy /* destroy */ - }; -@@ -368,6 +371,7 @@ static int console_output_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *console_output_get_fd( struct object *obj ); - static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); - static void console_output_destroy( struct object *obj ); - - static const struct object_ops console_output_ops = -@@ -378,7 +382,6 @@ static const struct object_ops console_output_ops = - console_output_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_output_get_fd, /* get_fd */ -@@ -391,6 +394,7 @@ static const struct object_ops console_output_ops = - default_unlink_name, /* unlink_name */ - console_output_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_output_destroy /* destroy */ - }; -@@ -437,7 +441,6 @@ static const struct object_ops console_connection_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_connection_get_fd, /* get_fd */ -@@ -450,6 +453,7 @@ static const struct object_ops console_connection_ops = - default_unlink_name, /* unlink_name */ - console_connection_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - console_connection_close_handle, /* close_handle */ - console_connection_destroy /* destroy */ - }; -@@ -549,6 +553,7 @@ static struct object *create_console(void) - console->server = NULL; - console->fd = NULL; - console->last_id = 0; -+ console->inproc_sync = NULL; - init_async_queue( &console->ioctl_q ); - init_async_queue( &console->read_q ); - -@@ -588,6 +593,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u - } - list_add_tail( &server->queue, &ioctl->entry ); - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - if (async) set_error( STATUS_PENDING ); - return 1; - } -@@ -600,8 +606,6 @@ static void disconnect_console_server( struct console_server *server ) - list_remove( &call->entry ); - console_host_ioctl_terminate( call, STATUS_CANCELLED ); - } -- if (do_esync()) -- esync_clear( server->esync_fd ); - while (!list_empty( &server->read_queue )) - { - struct console_host_ioctl *call = LIST_ENTRY( list_head( &server->read_queue ), struct console_host_ioctl, entry ); -@@ -622,6 +626,7 @@ static void disconnect_console_server( struct console_server *server ) - server->console->server = NULL; - server->console = NULL; - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - } - } - -@@ -776,6 +781,8 @@ static void console_destroy( struct object *obj ) - free_async_queue( &console->read_q ); - if (console->fd) - release_object( console->fd ); -+ -+ if (console->inproc_sync) release_object( console->inproc_sync ); - } - - static struct object *create_console_connection( struct console *console ) -@@ -823,6 +830,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access - return grab_object( obj ); - } - -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ) -+{ -+ struct console *console = (struct console *)obj; -+ -+ if (!console->inproc_sync) -+ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->inproc_sync) grab_object( console->inproc_sync ); -+ return console->inproc_sync; -+} -+ - static void screen_buffer_dump( struct object *obj, int verbose ) - { - struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -872,6 +889,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) - return NULL; - } - -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) -+{ -+ struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -+ if (!screen_buffer->input) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( &screen_buffer->input->obj ); -+} -+ - static void console_server_dump( struct object *obj, int verbose ) - { - assert( obj->ops == &console_server_ops ); -@@ -884,7 +912,7 @@ static void console_server_destroy( struct object *obj ) - assert( obj->ops == &console_server_ops ); - disconnect_console_server( server ); - if (server->fd) release_object( server->fd ); -- if (do_esync()) close( server->esync_fd ); -+ if (server->inproc_sync) release_object( server->inproc_sync ); - } - - static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -926,13 +954,6 @@ static int console_server_signaled( struct object *obj, struct wait_queue_entry - return !server->console || !list_empty( &server->queue ); - } - --static int console_server_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct console_server *server = (struct console_server*)obj; -- *type = ESYNC_MANUAL_SERVER; -- return server->esync_fd; --} -- - static struct fd *console_server_get_fd( struct object* obj ) - { - struct console_server *server = (struct console_server*)obj; -@@ -946,6 +967,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) -+{ -+ struct console_server *server = (struct console_server *)obj; -+ int signaled = !server->console || !list_empty( &server->queue ); -+ -+ if (!server->inproc_sync) -+ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (server->inproc_sync) grab_object( server->inproc_sync ); -+ return server->inproc_sync; -+} -+ - static struct object *create_console_server( void ) - { - struct console_server *server; -@@ -957,6 +989,7 @@ static struct object *create_console_server( void ) - server->term_fd = -1; - list_init( &server->queue ); - list_init( &server->read_queue ); -+ server->inproc_sync = NULL; - server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); - if (!server->fd) - { -@@ -964,10 +997,6 @@ static struct object *create_console_server( void ) - return NULL; - } - allow_fd_caching(server->fd); -- server->esync_fd = -1; -- -- if (do_esync()) -- server->esync_fd = esync_create_fd( 0, 0 ); - - return &server->obj; - } -@@ -1426,6 +1455,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_input_destroy( struct object *obj ) - { - struct console_input *console_input = (struct console_input *)obj; -@@ -1498,6 +1537,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console || !current->process->console->active) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_output_destroy( struct object *obj ) - { - struct console_output *console_output = (struct console_output *)obj; -@@ -1555,11 +1604,16 @@ DECL_HANDLER(get_next_console_request) - - if (!server->console->renderer) server->console->renderer = current; - -- if (!req->signal) server->console->signaled = 0; -+ if (!req->signal) -+ { -+ server->console->signaled = 0; -+ reset_inproc_event( server->console->inproc_sync ); -+ } - else if (!server->console->signaled) - { - server->console->signaled = 1; - wake_up( &server->console->obj, 0 ); -+ set_inproc_event( server->console->inproc_sync ); - } - - if (req->read) -@@ -1581,8 +1635,8 @@ DECL_HANDLER(get_next_console_request) - /* set result of previous ioctl */ - ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); - list_remove( &ioctl->entry ); -- if (do_esync() && list_empty( &server->queue )) -- esync_clear( server->esync_fd ); -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - } - - if (ioctl) -@@ -1668,8 +1722,9 @@ DECL_HANDLER(get_next_console_request) - { - set_error( STATUS_PENDING ); - } -- if (do_esync() && list_empty( &server->queue )) -- esync_clear( server->esync_fd ); -+ -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - - release_object( server ); - } -diff --git a/server/debugger.c b/server/debugger.c -index ca04d4c..7975fc4 100644 ---- a/server/debugger.c -+++ b/server/debugger.c -@@ -71,6 +71,7 @@ struct debug_obj - struct object obj; /* object header */ - struct list event_queue; /* pending events queue */ - unsigned int flags; /* debug flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - -@@ -86,7 +87,6 @@ static const struct object_ops debug_event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_event_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -99,12 +99,14 @@ static const struct object_ops debug_event_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_event_destroy /* destroy */ - }; - - static void debug_obj_dump( struct object *obj, int verbose ); - static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); - static void debug_obj_destroy( struct object *obj ); - - static const struct object_ops debug_obj_ops = -@@ -115,7 +117,6 @@ static const struct object_ops debug_obj_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_obj_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -128,6 +129,7 @@ static const struct object_ops debug_obj_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_obj_destroy /* destroy */ - }; -@@ -255,6 +257,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) - /* grab reference since debugger could be killed while trying to wake up */ - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -267,6 +270,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event - { - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -332,6 +336,17 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr - return find_event_to_send( debug_obj ) != NULL; - } - -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) -+{ -+ struct debug_obj *debug_obj = (struct debug_obj *)obj; -+ int signaled = find_event_to_send( debug_obj ) != NULL; -+ -+ if (!debug_obj->inproc_sync) -+ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); -+ return debug_obj->inproc_sync; -+} -+ - static void debug_obj_destroy( struct object *obj ) - { - struct list *ptr; -@@ -344,6 +359,8 @@ static void debug_obj_destroy( struct object *obj ) - /* free all pending events */ - while ((ptr = list_head( &debug_obj->event_queue ))) - unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); -+ -+ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); - } - - struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) -@@ -363,6 +380,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni - { - debug_obj->flags = flags; - list_init( &debug_obj->event_queue ); -+ debug_obj->inproc_sync = NULL; - } - } - return debug_obj; -@@ -571,6 +589,9 @@ DECL_HANDLER(wait_debug_event) - reply->tid = get_thread_id( event->sender ); - alloc_event_handles( event, current->process ); - set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); -+ -+ if (!find_event_to_send( debug_obj )) -+ reset_inproc_event( debug_obj->inproc_sync ); - } - else - { -diff --git a/server/device.c b/server/device.c -index c45d010..698fee6 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -38,7 +38,6 @@ - #include "handle.h" - #include "request.h" - #include "process.h" --#include "esync.h" - - /* IRP object */ - -@@ -67,7 +66,6 @@ static const struct object_ops irp_call_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -80,6 +78,7 @@ static const struct object_ops irp_call_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - irp_call_destroy /* destroy */ - }; -@@ -94,12 +93,12 @@ struct device_manager - struct list requests; /* list of pending irps across all devices */ - struct irp_call *current_call; /* call currently executed on client side */ - struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void device_manager_dump( struct object *obj, int verbose ); - static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ); -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); - static void device_manager_destroy( struct object *obj ); - - static const struct object_ops device_manager_ops = -@@ -110,7 +109,6 @@ static const struct object_ops device_manager_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - device_manager_signaled, /* signaled */ -- device_manager_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -123,6 +121,7 @@ static const struct object_ops device_manager_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_manager_destroy /* destroy */ - }; -@@ -168,7 +167,6 @@ static const struct object_ops device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -181,6 +179,7 @@ static const struct object_ops device_ops = - default_unlink_name, /* unlink_name */ - device_open_file, /* open_file */ - device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -221,7 +220,6 @@ static const struct object_ops device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - device_file_get_fd, /* get_fd */ -@@ -234,6 +232,7 @@ static const struct object_ops device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - device_file_close_handle, /* close_handle */ - device_file_destroy /* destroy */ - }; -@@ -424,7 +423,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i - irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; - if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); - list_add_tail( &manager->requests, &irp->mgr_entry ); -- if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ -+ if (list_head( &manager->requests ) == &irp->mgr_entry) -+ { -+ /* first one */ -+ wake_up( &manager->obj, 0 ); -+ set_inproc_event( manager->inproc_sync ); -+ } - } - - static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -754,13 +758,13 @@ static void delete_file( struct device_file *file ) - /* terminate all pending requests */ - LIST_FOR_EACH_ENTRY_SAFE( irp, next, &file->requests, struct irp_call, dev_entry ) - { -- if (do_esync() && file->device->manager && list_empty( &file->device->manager->requests )) -- esync_clear( file->device->manager->esync_fd ); -- - list_remove( &irp->mgr_entry ); - set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); - } - -+ if (list_empty( &file->device->manager->requests )) -+ reset_inproc_event( file->device->manager->inproc_sync ); -+ - release_object( file ); - } - -@@ -792,11 +796,14 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry - return !list_empty( &manager->requests ); - } - --static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ) -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) - { - struct device_manager *manager = (struct device_manager *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return manager->esync_fd; -+ -+ if (!manager->inproc_sync) -+ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->inproc_sync) grab_object( manager->inproc_sync ); -+ return manager->inproc_sync; - } - - static void device_manager_destroy( struct object *obj ) -@@ -834,8 +841,7 @@ static void device_manager_destroy( struct object *obj ) - release_object( irp ); - } - -- if (do_esync()) -- close( manager->esync_fd ); -+ if (manager->inproc_sync) release_object( manager->inproc_sync ); - } - - static struct device_manager *create_device_manager(void) -@@ -845,12 +851,10 @@ static struct device_manager *create_device_manager(void) - if ((manager = alloc_object( &device_manager_ops ))) - { - manager->current_call = NULL; -+ manager->inproc_sync = NULL; - list_init( &manager->devices ); - list_init( &manager->requests ); - wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -- -- if (do_esync()) -- manager->esync_fd = esync_create_fd( 0, 0 ); - } - return manager; - } -@@ -1037,12 +1041,13 @@ DECL_HANDLER(get_next_device_request) - } - list_remove( &irp->mgr_entry ); - list_init( &irp->mgr_entry ); -+ -+ if (list_empty( &manager->requests )) -+ reset_inproc_event( manager->inproc_sync ); -+ - /* we already own the object if it's only on manager queue */ - if (irp->file) grab_object( irp ); - manager->current_call = irp; -- -- if (do_esync() && list_empty( &manager->requests )) -- esync_clear( manager->esync_fd ); - } - else close_handle( current->process, reply->next ); - } -diff --git a/server/directory.c b/server/directory.c -index bc161b9..8e32abb 100644 ---- a/server/directory.c -+++ b/server/directory.c -@@ -69,7 +69,6 @@ static const struct object_ops object_type_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -82,6 +81,7 @@ static const struct object_ops object_type_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -120,7 +120,6 @@ static const struct object_ops directory_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -133,6 +132,7 @@ static const struct object_ops directory_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - directory_destroy /* destroy */ - }; -diff --git a/server/esync.c b/server/esync.c -deleted file mode 100644 -index e193f61..0000000 ---- a/server/esync.c -+++ /dev/null -@@ -1,588 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#include "config.h" -- -- --#include --#include --#include --#ifdef HAVE_SYS_EVENTFD_H --# include --#endif --#include --#ifdef HAVE_SYS_STAT_H --# include --#endif --#include -- --#include "ntstatus.h" --#define WIN32_NO_STATUS --#include "windef.h" --#include "winternl.h" -- --#include "handle.h" --#include "request.h" --#include "file.h" --#include "esync.h" -- --int do_esync(void) --{ --#ifdef HAVE_SYS_EVENTFD_H -- static int do_esync_cached = -1; -- -- if (do_esync_cached == -1) -- do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); -- -- return do_esync_cached; --#else -- return 0; --#endif --} -- --static char shm_name[29]; --static int shm_fd; --static off_t shm_size; --static void **shm_addrs; --static int shm_addrs_size; /* length of the allocated shm_addrs array */ --static long pagesize; -- --static void shm_cleanup(void) --{ -- close( shm_fd ); -- if (shm_unlink( shm_name ) == -1) -- perror( "shm_unlink" ); --} -- --void esync_init(void) --{ -- struct stat st; -- -- if (fstat( config_dir_fd, &st ) == -1) -- fatal_error( "cannot stat config dir\n" ); -- -- if (st.st_ino != (unsigned long)st.st_ino) -- sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino ); -- else -- sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino ); -- -- shm_unlink( shm_name ); -- -- shm_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 ); -- if (shm_fd == -1) -- perror( "shm_open" ); -- -- pagesize = sysconf( _SC_PAGESIZE ); -- -- shm_addrs = calloc( 128, sizeof(shm_addrs[0]) ); -- shm_addrs_size = 128; -- -- shm_size = pagesize; -- if (ftruncate( shm_fd, shm_size ) == -1) -- perror( "ftruncate" ); -- -- fprintf( stderr, "esync: up and running.\n" ); -- -- atexit( shm_cleanup ); --} -- --static struct list mutex_list = LIST_INIT(mutex_list); -- --struct esync --{ -- struct object obj; /* object header */ -- int fd; /* eventfd file descriptor */ -- enum esync_type type; -- unsigned int shm_idx; /* index into the shared memory section */ -- struct list mutex_entry; /* entry in the mutex list (if applicable) */ --}; -- --static void esync_dump( struct object *obj, int verbose ); --static int esync_get_esync_fd( struct object *obj, enum esync_type *type ); --static unsigned int esync_map_access( struct object *obj, unsigned int access ); --static void esync_destroy( struct object *obj ); -- --const struct object_ops esync_ops = --{ -- sizeof(struct esync), /* size */ -- &no_type, /* type */ -- esync_dump, /* dump */ -- no_add_queue, /* add_queue */ -- NULL, /* remove_queue */ -- NULL, /* signaled */ -- esync_get_esync_fd, /* get_esync_fd */ -- NULL, /* satisfied */ -- no_signal, /* signal */ -- no_get_fd, /* get_fd */ -- esync_map_access, /* map_access */ -- default_get_sd, /* get_sd */ -- default_set_sd, /* set_sd */ -- default_get_full_name, /* get_full_name */ -- no_lookup_name, /* lookup_name */ -- directory_link_name, /* link_name */ -- default_unlink_name, /* unlink_name */ -- no_open_file, /* open_file */ -- no_kernel_obj_list, /* get_kernel_obj_list */ -- no_close_handle, /* close_handle */ -- esync_destroy /* destroy */ --}; -- --static void esync_dump( struct object *obj, int verbose ) --{ -- struct esync *esync = (struct esync *)obj; -- assert( obj->ops == &esync_ops ); -- fprintf( stderr, "esync fd=%d\n", esync->fd ); --} -- --static int esync_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct esync *esync = (struct esync *)obj; -- *type = esync->type; -- return esync->fd; --} -- --static unsigned int esync_map_access( struct object *obj, unsigned int access ) --{ -- /* Sync objects have the same flags. */ -- if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | EVENT_QUERY_STATE; -- if (access & GENERIC_WRITE) access |= STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE; -- if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE; -- if (access & GENERIC_ALL) access |= STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE; -- return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); --} -- --static void esync_destroy( struct object *obj ) --{ -- struct esync *esync = (struct esync *)obj; -- if (esync->type == ESYNC_MUTEX) -- list_remove( &esync->mutex_entry ); -- close( esync->fd ); --} -- --static int type_matches( enum esync_type type1, enum esync_type type2 ) --{ -- return (type1 == type2) || -- ((type1 == ESYNC_AUTO_EVENT || type1 == ESYNC_MANUAL_EVENT) && -- (type2 == ESYNC_AUTO_EVENT || type2 == ESYNC_MANUAL_EVENT)); --} -- --static void *get_shm( unsigned int idx ) --{ -- int entry = (idx * 8) / pagesize; -- int offset = (idx * 8) % pagesize; -- -- if (entry >= shm_addrs_size) -- { -- int new_size = max(shm_addrs_size * 2, entry + 1); -- -- if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) ))) -- fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 ); -- -- memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) ); -- -- shm_addrs_size = new_size; -- } -- -- if (!shm_addrs[entry]) -- { -- void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize ); -- if (addr == (void *)-1) -- { -- fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize ); -- perror( "mmap" ); -- } -- -- if (debug_level) -- fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr ); -- -- if (__sync_val_compare_and_swap( &shm_addrs[entry], 0, addr )) -- munmap( addr, pagesize ); /* someone beat us to it */ -- } -- -- return (void *)((unsigned long)shm_addrs[entry] + offset); --} -- --struct semaphore --{ -- int max; -- int count; --}; --C_ASSERT(sizeof(struct semaphore) == 8); -- --struct mutex --{ -- DWORD tid; -- int count; /* recursion count */ --}; --C_ASSERT(sizeof(struct mutex) == 8); -- --struct event --{ -- int signaled; -- int locked; --}; --C_ASSERT(sizeof(struct event) == 8); -- --struct esync *create_esync( struct object *root, const struct unicode_str *name, -- unsigned int attr, int initval, int max, enum esync_type type, -- const struct security_descriptor *sd ) --{ --#ifdef HAVE_SYS_EVENTFD_H -- struct esync *esync; -- -- if ((esync = create_named_object( root, &esync_ops, name, attr, sd ))) -- { -- if (get_error() != STATUS_OBJECT_NAME_EXISTS) -- { -- int flags = EFD_CLOEXEC | EFD_NONBLOCK; -- -- if (type == ESYNC_SEMAPHORE) -- flags |= EFD_SEMAPHORE; -- -- /* initialize it if it didn't already exist */ -- esync->fd = eventfd( initval, flags ); -- if (esync->fd == -1) -- { -- perror( "eventfd" ); -- file_set_error(); -- release_object( esync ); -- return NULL; -- } -- esync->type = type; -- -- /* Use the fd as index, since that'll be unique across all -- * processes, but should hopefully end up also allowing reuse. */ -- esync->shm_idx = esync->fd + 1; /* we keep index 0 reserved */ -- while (esync->shm_idx * 8 >= shm_size) -- { -- /* Better expand the shm section. */ -- shm_size += pagesize; -- if (ftruncate( shm_fd, shm_size ) == -1) -- { -- fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -- shm_name, (long)shm_size ); -- perror( "ftruncate" ); -- } -- } -- -- /* Initialize the shared memory portion. We want to do this on the -- * server side to avoid a potential though unlikely race whereby -- * the same object is opened and used between the time it's created -- * and the time its shared memory portion is initialized. */ -- switch (type) -- { -- case ESYNC_SEMAPHORE: -- { -- struct semaphore *semaphore = get_shm( esync->shm_idx ); -- semaphore->max = max; -- semaphore->count = initval; -- break; -- } -- case ESYNC_AUTO_EVENT: -- case ESYNC_MANUAL_EVENT: -- { -- struct event *event = get_shm( esync->shm_idx ); -- event->signaled = initval ? 1 : 0; -- event->locked = 0; -- break; -- } -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = get_shm( esync->shm_idx ); -- mutex->tid = initval ? 0 : current->id; -- mutex->count = initval ? 0 : 1; -- list_add_tail( &mutex_list, &esync->mutex_entry ); -- break; -- } -- default: -- assert( 0 ); -- } -- } -- else -- { -- /* validate the type */ -- if (!type_matches( type, esync->type )) -- { -- release_object( &esync->obj ); -- set_error( STATUS_OBJECT_TYPE_MISMATCH ); -- return NULL; -- } -- } -- } -- return esync; --#else -- /* FIXME: Provide a fallback implementation using pipe(). */ -- set_error( STATUS_NOT_IMPLEMENTED ); -- return NULL; --#endif --} -- --/* Create a file descriptor for an existing handle. -- * Caller must close the handle when it's done; it's not linked to an esync -- * server object in any way. */ --int esync_create_fd( int initval, int flags ) --{ --#ifdef HAVE_SYS_EVENTFD_H -- int fd; -- -- fd = eventfd( initval, flags | EFD_CLOEXEC | EFD_NONBLOCK ); -- if (fd == -1) -- perror( "eventfd" ); -- -- return fd; --#else -- return -1; --#endif --} -- --/* Wake up a specific fd. */ --void esync_wake_fd( int fd ) --{ -- static const uint64_t value = 1; -- -- if (write( fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); --} -- --/* Wake up a server-side esync object. */ --void esync_wake_up( struct object *obj ) --{ -- enum esync_type dummy; -- int fd; -- -- if (obj->ops->get_esync_fd) -- { -- fd = obj->ops->get_esync_fd( obj, &dummy ); -- esync_wake_fd( fd ); -- } --} -- --void esync_clear( int fd ) --{ -- uint64_t value; -- -- /* we don't care about the return value */ -- read( fd, &value, sizeof(value) ); --} -- --static inline void small_pause(void) --{ --#ifdef __i386__ -- __asm__ __volatile__( "rep;nop" : : : "memory" ); --#else -- __asm__ __volatile__( "" : : : "memory" ); --#endif --} -- --/* Server-side event support. */ --void esync_set_event( struct esync *esync ) --{ -- static const uint64_t value = 1; -- struct event *event = get_shm( esync->shm_idx ); -- -- assert( esync->obj.ops == &esync_ops ); -- assert( event != NULL ); -- -- if (debug_level) -- fprintf( stderr, "esync_set_event() fd=%d\n", esync->fd ); -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (__sync_val_compare_and_swap( &event->locked, 0, 1 )) -- small_pause(); -- } -- -- if (!__atomic_exchange_n( &event->signaled, 1, __ATOMIC_SEQ_CST )) -- { -- if (write( esync->fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); -- } -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } --} -- --void esync_reset_event( struct esync *esync ) --{ -- static uint64_t value = 1; -- struct event *event = get_shm( esync->shm_idx ); -- -- assert( esync->obj.ops == &esync_ops ); -- assert( event != NULL ); -- -- if (debug_level) -- fprintf( stderr, "esync_reset_event() fd=%d\n", esync->fd ); -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (__sync_val_compare_and_swap( &event->locked, 0, 1 )) -- small_pause(); -- } -- -- /* Only bother signaling the fd if we weren't already signaled. */ -- if (__atomic_exchange_n( &event->signaled, 0, __ATOMIC_SEQ_CST )) -- { -- /* we don't care about the return value */ -- read( esync->fd, &value, sizeof(value) ); -- } -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } --} -- --void esync_abandon_mutexes( struct thread *thread ) --{ -- struct esync *esync; -- -- LIST_FOR_EACH_ENTRY( esync, &mutex_list, struct esync, mutex_entry ) -- { -- struct mutex *mutex = get_shm( esync->shm_idx ); -- -- if (mutex->tid == thread->id) -- { -- if (debug_level) -- fprintf( stderr, "esync_abandon_mutexes() fd=%d\n", esync->fd ); -- mutex->tid = ~0; -- mutex->count = 0; -- esync_wake_fd( esync->fd ); -- } -- } --} -- --DECL_HANDLER(create_esync) --{ -- struct esync *esync; -- struct unicode_str name; -- struct object *root; -- const struct security_descriptor *sd; -- const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root ); -- -- if (!do_esync()) -- { -- set_error( STATUS_NOT_IMPLEMENTED ); -- return; -- } -- -- if (!req->type) -- { -- set_error( STATUS_INVALID_PARAMETER ); -- return; -- } -- -- if (!objattr) return; -- -- if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->max, req->type, sd ))) -- { -- if (get_error() == STATUS_OBJECT_NAME_EXISTS) -- reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes ); -- else -- reply->handle = alloc_handle_no_access_check( current->process, esync, -- req->access, objattr->attributes ); -- -- reply->type = esync->type; -- reply->shm_idx = esync->shm_idx; -- send_client_fd( current->process, esync->fd, reply->handle ); -- release_object( esync ); -- } -- -- if (root) release_object( root ); --} -- --DECL_HANDLER(open_esync) --{ -- struct unicode_str name = get_req_unicode_str(); -- -- reply->handle = open_object( current->process, req->rootdir, req->access, -- &esync_ops, &name, req->attributes ); -- -- /* send over the fd */ -- if (reply->handle) -- { -- struct esync *esync; -- -- if (!(esync = (struct esync *)get_handle_obj( current->process, reply->handle, -- 0, &esync_ops ))) -- return; -- -- if (!type_matches( req->type, esync->type )) -- { -- set_error( STATUS_OBJECT_TYPE_MISMATCH ); -- release_object( esync ); -- return; -- } -- -- reply->type = esync->type; -- reply->shm_idx = esync->shm_idx; -- -- send_client_fd( current->process, esync->fd, reply->handle ); -- release_object( esync ); -- } --} -- --/* Retrieve a file descriptor for an esync object which will be signaled by the -- * server. The client should only read from (i.e. wait on) this object. */ --DECL_HANDLER(get_esync_fd) --{ -- struct object *obj; -- enum esync_type type; -- int fd; -- -- if (!(obj = get_handle_obj( current->process, req->handle, SYNCHRONIZE, NULL ))) -- return; -- -- if (obj->ops->get_esync_fd) -- { -- fd = obj->ops->get_esync_fd( obj, &type ); -- reply->type = type; -- if (obj->ops == &esync_ops) -- { -- struct esync *esync = (struct esync *)obj; -- reply->shm_idx = esync->shm_idx; -- } -- else -- reply->shm_idx = 0; -- send_client_fd( current->process, fd, req->handle ); -- } -- else -- { -- if (debug_level) -- { -- fprintf( stderr, "%04x: esync: can't wait on object: ", current->id ); -- obj->ops->dump( obj, 0 ); -- } -- set_error( STATUS_NOT_IMPLEMENTED ); -- } -- -- release_object( obj ); --} -- --/* Return the fd used for waiting on user APCs. */ --DECL_HANDLER(get_esync_apc_fd) --{ -- send_client_fd( current->process, current->esync_apc_fd, current->id ); --} -diff --git a/server/esync.h b/server/esync.h -deleted file mode 100644 -index d39f4ef..0000000 ---- a/server/esync.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#include -- --extern int do_esync(void); --void esync_init(void); --int esync_create_fd( int initval, int flags ); --void esync_wake_fd( int fd ); --void esync_wake_up( struct object *obj ); --void esync_clear( int fd ); -- --struct esync; -- --extern const struct object_ops esync_ops; --void esync_set_event( struct esync *esync ); --void esync_reset_event( struct esync *esync ); --void esync_abandon_mutexes( struct thread *thread ); -diff --git a/server/event.c b/server/event.c -index f4ca3e4..b750a22 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -35,7 +35,6 @@ - #include "thread.h" - #include "request.h" - #include "security.h" --#include "esync.h" - - static const WCHAR event_name[] = {'E','v','e','n','t'}; - -@@ -57,15 +56,15 @@ struct event - struct list kernel_object; /* list of kernel object pointers */ - int manual_reset; /* is it a manual reset event? */ - int signaled; /* event has been signaled */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - 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 ); --static int event_get_esync_fd( struct object *obj, enum esync_type *type ); - static int event_signal( struct object *obj, unsigned int access); - static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ); - static void event_destroy( struct object *obj ); - - static const struct object_ops event_ops = -@@ -76,7 +75,6 @@ static const struct object_ops event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - event_signaled, /* signaled */ -- event_get_esync_fd, /* get_esync_fd */ - event_satisfied, /* satisfied */ - event_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +87,7 @@ static const struct object_ops event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - event_destroy /* destroy */ - }; -@@ -111,10 +110,13 @@ struct type_descr keyed_event_type = - struct keyed_event - { - struct object obj; /* object header */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void keyed_event_dump( struct object *obj, int verbose ); - static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); -+static void keyed_event_destroy( struct object *obj ); - - static const struct object_ops keyed_event_ops = - { -@@ -124,7 +126,6 @@ static const struct object_ops keyed_event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - keyed_event_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -137,8 +138,9 @@ static const struct object_ops keyed_event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ keyed_event_destroy /* destroy */ - }; - - -@@ -156,9 +158,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; -- -- if (do_esync()) -- event->esync_fd = esync_create_fd( initial_state, 0 ); -+ event->inproc_sync = NULL; - } - } - return event; -@@ -166,10 +166,6 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - - struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access ) - { -- struct object *obj; -- if (do_esync() && (obj = get_handle_obj( process, handle, access, &esync_ops))) -- return (struct event *)obj; /* even though it's not an event */ -- - return (struct event *)get_handle_obj( process, handle, access, &event_ops ); - } - -@@ -183,28 +179,16 @@ static void pulse_event( struct event *event ) - - void set_event( struct event *event ) - { -- if (do_esync() && event->obj.ops == &esync_ops) -- { -- esync_set_event( (struct esync *)event ); -- return; -- } -- - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); -+ set_inproc_event( event->inproc_sync ); - } - - void reset_event( struct event *event ) - { -- if (do_esync() && event->obj.ops == &esync_ops) -- { -- esync_reset_event( (struct esync *)event ); -- return; -- } - event->signaled = 0; -- -- if (do_esync()) -- esync_clear( event->esync_fd ); -+ reset_inproc_event( event->inproc_sync ); - } - - static void event_dump( struct object *obj, int verbose ) -@@ -222,13 +206,6 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) - return event->signaled; - } - --static int event_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct event *event = (struct event *)obj; -- *type = event->manual_reset ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER; -- return event->esync_fd; --} -- - static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct event *event = (struct event *)obj; -@@ -257,12 +234,24 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) - return &event->kernel_object; - } - -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (!event->inproc_sync) -+ { -+ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; -+ event->inproc_sync = create_inproc_event( type, event->signaled ); -+ } -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ - static void event_destroy( struct object *obj ) - { - struct event *event = (struct event *)obj; - -- if (do_esync()) -- close( event->esync_fd ); -+ if (event->inproc_sync) release_object( event->inproc_sync ); - } - - struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, -@@ -275,6 +264,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod - if (get_error() != STATUS_OBJECT_NAME_EXISTS) - { - /* initialize it if it didn't already exist */ -+ event->inproc_sync = NULL; - } - } - return event; -@@ -318,6 +308,23 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en - return 0; - } - -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (!event->inproc_sync) -+ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void keyed_event_destroy( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - /* create an event */ - DECL_HANDLER(create_event) - { -diff --git a/server/inproc_sync.c b/server/inproc_sync.c -new file mode 100644 -index 0000000..fed6eb9 ---- /dev/null -+++ b/server/inproc_sync.c -@@ -0,0 +1,437 @@ -+/* -+ * In-process synchronization primitives -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "ntstatus.h" -+#define WIN32_NO_STATUS -+#include "winternl.h" -+ -+#include "file.h" -+#include "handle.h" -+#include "request.h" -+#include "thread.h" -+ -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct linux_device -+{ -+ struct object obj; /* object header */ -+ struct fd *fd; /* fd for unix fd */ -+}; -+ -+static struct linux_device *linux_device_object; -+ -+static void linux_device_dump( struct object *obj, int verbose ); -+static struct fd *linux_device_get_fd( struct object *obj ); -+static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); -+ -+static const struct object_ops linux_device_ops = -+{ -+ sizeof(struct linux_device), /* size */ -+ &no_type, /* type */ -+ linux_device_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_device_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_device_destroy /* destroy */ -+}; -+ -+static const struct fd_ops inproc_sync_fd_ops = -+{ -+ default_fd_get_poll_events, /* get_poll_events */ -+ default_poll_event, /* poll_event */ -+ inproc_sync_get_fd_type, /* get_fd_type */ -+ no_fd_read, /* read */ -+ no_fd_write, /* write */ -+ no_fd_flush, /* flush */ -+ no_fd_get_file_info, /* get_file_info */ -+ no_fd_get_volume_info, /* get_volume_info */ -+ no_fd_ioctl, /* ioctl */ -+ default_fd_cancel_async, /* cancel_async */ -+ no_fd_queue_async, /* queue_async */ -+ default_fd_reselect_async /* reselect_async */ -+}; -+ -+static void linux_device_dump( struct object *obj, int verbose ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); -+} -+ -+static struct fd *linux_device_get_fd( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ return (struct fd *)grab_object( device->fd ); -+} -+ -+static void linux_device_destroy( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ if (device->fd) release_object( device->fd ); -+ linux_device_object = NULL; -+} -+ -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) -+{ -+ return FD_TYPE_FILE; -+} -+ -+static struct linux_device *get_linux_device(void) -+{ -+ struct linux_device *device; -+ static int initialized; -+ int unix_fd; -+ -+ if (initialized) -+ { -+ if (linux_device_object) -+ grab_object( linux_device_object ); -+ else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return linux_device_object; -+ } -+ -+ if (getenv( "WINE_DISABLE_FAST_SYNC" ) && atoi( getenv( "WINE_DISABLE_FAST_SYNC" ) )) -+ { -+ static int once; -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ if (!once++) fprintf(stderr, "ntsync is explicitly disabled.\n"); -+ initialized = 1; -+ return NULL; -+ } -+ -+ unix_fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY ); -+ if (unix_fd == -1) -+ { -+ static int once; -+ file_set_error(); -+ if (!once++) fprintf(stderr, "Cannot open /dev/ntsync: %s\n", strerror(errno)); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device = alloc_object( &linux_device_ops ))) -+ { -+ close( unix_fd ); -+ set_error( STATUS_NO_MEMORY ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) -+ { -+ release_object( device ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ fprintf( stderr, "wine: using fast synchronization.\n" ); -+ linux_device_object = device; -+ initialized = 1; -+ return device; -+} -+ -+struct inproc_sync -+{ -+ struct object obj; -+ enum inproc_sync_type type; -+ struct fd *fd; -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ); -+static void linux_obj_destroy( struct object *obj ); -+static struct fd *linux_obj_get_fd( struct object *obj ); -+ -+static const struct object_ops linux_obj_ops = -+{ -+ sizeof(struct inproc_sync), /* size */ -+ &no_type, /* type */ -+ linux_obj_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_obj_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_obj_destroy /* destroy */ -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); -+} -+ -+static void linux_obj_destroy( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ if (inproc_sync->fd) release_object( inproc_sync->fd ); -+} -+ -+static struct fd *linux_obj_get_fd( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( inproc_sync->fd ); -+} -+ -+static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) -+{ -+ struct inproc_sync *inproc_sync; -+ -+ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) -+ { -+ close( unix_fd ); -+ return NULL; -+ } -+ -+ inproc_sync->type = type; -+ -+ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) -+ { -+ release_object( inproc_sync ); -+ return NULL; -+ } -+ -+ return inproc_sync; -+} -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ struct ntsync_event_args args; -+ struct linux_device *device; -+ int event; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.signaled = signaled; -+ switch (type) -+ { -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_AUTO_SERVER: -+ args.manual = 0; -+ break; -+ -+ case INPROC_SYNC_MANUAL_EVENT: -+ case INPROC_SYNC_MANUAL_SERVER: -+ case INPROC_SYNC_QUEUE: -+ args.manual = 1; -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ case INPROC_SYNC_SEMAPHORE: -+ assert(0); -+ break; -+ } -+ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ release_object( device ); -+ -+ return create_inproc_sync( type, event ); -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ struct ntsync_sem_args args; -+ struct linux_device *device; -+ int semaphore; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.count = count; -+ args.max = max; -+ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ struct ntsync_mutex_args args; -+ struct linux_device *device; -+ int mutex; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.owner = owner; -+ args.count = count; -+ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); -+} -+ -+void reset_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); -+} -+ -+#else -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+} -+ -+void reset_inproc_event( struct inproc_sync *obj ) -+{ -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+} -+ -+#endif -+ -+DECL_HANDLER(get_linux_sync_device) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct linux_device *device; -+ -+ if ((device = get_linux_device())) -+ { -+ reply->handle = alloc_handle( current->process, device, 0, 0 ); -+ release_object( device ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -+ -+DECL_HANDLER(get_linux_sync_obj) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct object *obj; -+ -+ if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) -+ { -+ struct inproc_sync *inproc_sync; -+ -+ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) -+ { -+ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); -+ reply->type = inproc_sync->type; -+ reply->access = get_handle_access( current->process, req->handle ); -+ release_object( inproc_sync ); -+ } -+ release_object( obj ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -diff --git a/server/fd.c b/server/fd.c -index a6782b0..f00e22d 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -97,7 +97,6 @@ - #include "handle.h" - #include "process.h" - #include "request.h" --#include "esync.h" - - #include "winternl.h" - #include "winioctl.h" -@@ -162,7 +161,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -176,7 +175,6 @@ static const struct object_ops fd_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -189,6 +187,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -218,7 +217,6 @@ static const struct object_ops device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -231,6 +229,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -259,7 +258,6 @@ static const struct object_ops inode_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -272,6 +270,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -302,7 +301,6 @@ static const struct object_ops file_lock_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - file_lock_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -315,6 +313,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1651,9 +1650,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -- -- if (do_esync()) -- close( fd->esync_fd ); -+ if (fd->inproc_sync) release_object( fd->inproc_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1772,16 +1769,13 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -- fd->esync_fd = -1; -+ fd->inproc_sync = NULL; - 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 ); - -- if (do_esync()) -- fd->esync_fd = esync_create_fd( 1, 0 ); -- - if ((fd->poll_index = add_poll_user( fd )) == -1) - { - release_object( fd ); -@@ -1816,16 +1810,13 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; -- fd->esync_fd = -1; - 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 ); -- -- if (do_esync()) -- fd->esync_fd = esync_create_fd( 0, 0 ); - return fd; - } - -@@ -2282,10 +2273,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -- -- if (do_esync() && !signaled) -- esync_clear( fd->esync_fd ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ set_inproc_event( fd->inproc_sync ); -+ } -+ else -+ { -+ reset_inproc_event( fd->inproc_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2311,12 +2307,16 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - --int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ) -+struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) - { - struct fd *fd = get_obj_fd( obj ); -- int ret = fd->esync_fd; -- *type = ESYNC_MANUAL_SERVER; -+ struct inproc_sync *ret; -+ -+ if (!fd->inproc_sync) -+ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->inproc_sync; - release_object( fd ); -+ if (ret) grab_object( ret ); - return ret; - } - -diff --git a/server/file.c b/server/file.c -index 828a21c..c6bdbef 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -123,7 +123,6 @@ static const struct object_ops file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - file_get_fd, /* get_fd */ -@@ -136,6 +135,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index abad355..6b4fa51 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -108,7 +108,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); --extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ); -+extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); - 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 -index cf6afe4..e07f32c 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -126,7 +126,6 @@ static const struct object_ops handle_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -139,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index da351d6..5a00699 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -80,7 +80,6 @@ static const struct object_ops hook_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -93,6 +92,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; -diff --git a/server/mailslot.c b/server/mailslot.c -index 4cf9b73..d9807b4 100644 ---- a/server/mailslot.c -+++ b/server/mailslot.c -@@ -74,7 +74,6 @@ static const struct object_ops mailslot_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - mailslot_get_fd, /* get_fd */ -@@ -87,6 +86,7 @@ static const struct object_ops mailslot_ops = - default_unlink_name, /* unlink_name */ - mailslot_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync,/* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_destroy /* destroy */ - }; -@@ -134,7 +134,6 @@ static const struct object_ops mail_writer_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - mail_writer_get_fd, /* get_fd */ -@@ -147,6 +146,7 @@ static const struct object_ops mail_writer_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mail_writer_destroy /* destroy */ - }; -@@ -198,7 +198,6 @@ static const struct object_ops mailslot_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -211,6 +210,7 @@ static const struct object_ops mailslot_device_ops = - default_unlink_name, /* unlink_name */ - mailslot_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_destroy /* destroy */ - }; -@@ -229,7 +229,6 @@ static const struct object_ops mailslot_device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - mailslot_device_file_get_fd, /* get_fd */ -@@ -242,6 +241,7 @@ static const struct object_ops mailslot_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_file_destroy /* destroy */ - }; -diff --git a/server/main.c b/server/main.c -index 5062d09..ddda5f4 100644 ---- a/server/main.c -+++ b/server/main.c -@@ -34,7 +34,6 @@ - #include "thread.h" - #include "request.h" - #include "unicode.h" --#include "esync.h" - - /* command-line options */ - int debug_level = 0; -@@ -230,9 +229,6 @@ int main( int argc, char *argv[] ) - sock_init(); - open_master_socket(); - -- if (do_esync()) -- esync_init(); -- - if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); - set_current_time(); - init_scheduler(); -diff --git a/server/mapping.c b/server/mapping.c -index 88de806..c3cba90 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -67,7 +67,6 @@ static const struct object_ops ranges_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -80,6 +79,7 @@ static const struct object_ops ranges_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ranges_destroy /* destroy */ - }; -@@ -104,7 +104,6 @@ static const struct object_ops shared_map_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -117,6 +116,7 @@ static const struct object_ops shared_map_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - shared_map_destroy /* destroy */ - }; -@@ -178,7 +178,6 @@ static const struct object_ops mapping_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - mapping_get_fd, /* get_fd */ -@@ -191,6 +190,7 @@ static const struct object_ops mapping_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mapping_destroy /* destroy */ - }; -diff --git a/server/mutex.c b/server/mutex.c -index 4785a83..167c236 100644 ---- a/server/mutex.c -+++ b/server/mutex.c -@@ -38,6 +38,8 @@ - - static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; - -+static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); -+ - struct type_descr mutex_type = - { - { mutex_name, sizeof(mutex_name) }, /* name */ -@@ -57,6 +59,8 @@ struct mutex - unsigned int count; /* recursion count */ - int abandoned; /* has it been abandoned? */ - struct list entry; /* entry in owner thread mutex list */ -+ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void mutex_dump( struct object *obj, int verbose ); -@@ -64,6 +68,7 @@ static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_destroy( struct object *obj ); - static int mutex_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); - - static const struct object_ops mutex_ops = - { -@@ -73,7 +78,6 @@ static const struct object_ops mutex_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - mutex_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - mutex_satisfied, /* satisfied */ - mutex_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -86,6 +90,7 @@ static const struct object_ops mutex_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mutex_destroy /* destroy */ - }; -@@ -128,6 +133,7 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - mutex->owner = NULL; - mutex->abandoned = 0; - if (owned) do_grab( mutex, current ); -+ mutex->inproc_sync = NULL; - } - } - return mutex; -@@ -135,16 +141,22 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - - void abandon_mutexes( struct thread *thread ) - { -+ struct mutex *mutex; - struct list *ptr; - - while ((ptr = list_head( &thread->mutex_list )) != NULL) - { -- struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry ); -+ mutex = LIST_ENTRY( ptr, struct mutex, entry ); - assert( mutex->owner == thread ); - mutex->count = 0; - mutex->abandoned = 1; - do_release( mutex ); - } -+ -+ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) -+ { -+ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); -+ } - } - - static void mutex_dump( struct object *obj, int verbose ) -@@ -190,14 +202,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) - return 1; - } - -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) -+{ -+ struct mutex *mutex = (struct mutex *)obj; -+ -+ if (!mutex->inproc_sync) -+ { -+ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); -+ } -+ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); -+ return mutex->inproc_sync; -+} -+ - static void mutex_destroy( struct object *obj ) - { - struct mutex *mutex = (struct mutex *)obj; - assert( obj->ops == &mutex_ops ); - -- if (!mutex->count) return; -- mutex->count = 0; -- do_release( mutex ); -+ if (mutex->count) -+ { -+ mutex->count = 0; -+ do_release( mutex ); -+ } -+ if (mutex->inproc_sync) -+ { -+ release_object( mutex->inproc_sync ); -+ list_remove( &mutex->inproc_mutexes_entry ); -+ } - } - - /* create a mutex */ -diff --git a/server/named_pipe.c b/server/named_pipe.c -index a90ec60..6d8cb3e 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -119,7 +119,6 @@ static const struct object_ops named_pipe_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -132,6 +131,7 @@ static const struct object_ops named_pipe_ops = - default_unlink_name, /* unlink_name */ - named_pipe_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_destroy /* destroy */ - }; -@@ -168,7 +168,6 @@ static const struct object_ops pipe_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -181,6 +180,7 @@ static const struct object_ops pipe_server_ops = - NULL, /* unlink_name */ - pipe_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_server_destroy /* destroy */ - }; -@@ -213,7 +213,6 @@ static const struct object_ops pipe_client_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -226,6 +225,7 @@ static const struct object_ops pipe_client_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_end_destroy /* destroy */ - }; -@@ -261,7 +261,6 @@ static const struct object_ops named_pipe_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -274,6 +273,7 @@ static const struct object_ops named_pipe_device_ops = - default_unlink_name, /* unlink_name */ - named_pipe_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_destroy /* destroy */ - }; -@@ -293,7 +293,6 @@ static const struct object_ops named_pipe_device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - named_pipe_device_file_get_fd, /* get_fd */ -@@ -306,6 +305,7 @@ static const struct object_ops named_pipe_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_file_destroy /* destroy */ - }; -@@ -344,7 +344,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - named_pipe_dir_get_fd, /* get_fd */ -@@ -357,6 +356,7 @@ - NULL, /* unlink_name */ - named_pipe_dir_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_dir_destroy /* destroy */ - }; -diff --git a/server/object.c b/server/object.c -index 29f1ea9..33fc18c 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -120,19 +120,19 @@ static const struct object_ops apc_reserve_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - directory_link_name, /* link_name */ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -144,19 +145,19 @@ static const struct object_ops completion_reserve_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - directory_link_name, /* link_name */ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -538,6 +538,12 @@ struct fd *no_get_fd( struct object *obj ) - return NULL; - } - -+struct inproc_sync *no_get_inproc_sync( struct object *obj ) -+{ -+ set_error( STATUS_OBJECT_TYPE_MISMATCH ); -+ return NULL; -+} -+ - unsigned int default_map_access( struct object *obj, unsigned int access ) - { - return map_access( access, &obj->ops->type->mapping ); -diff --git a/server/object.h b/server/object.h -index 6f4bca8..f028a8e 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -42,6 +42,7 @@ struct async; - struct async_queue; - struct winstation; - struct object_type; -+struct inproc_sync; - - - struct unicode_str -@@ -78,8 +79,6 @@ struct object_ops - void (*remove_queue)(struct object *,struct wait_queue_entry *); - /* is object signaled? */ - int (*signaled)(struct object *,struct wait_queue_entry *); -- /* return the esync fd for this object */ -- int (*get_esync_fd)(struct object *, enum esync_type *type); - /* wait satisfied */ - void (*satisfied)(struct object *,struct wait_queue_entry *); - /* signal an object */ -@@ -105,6 +104,8 @@ struct object_ops - unsigned int options); - /* return list of kernel objects */ - struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable in-process synchronization handle to this object */ -+ struct inproc_sync *(*get_inproc_sync)(struct object *); - /* close a handle to this object */ - int (*close_handle)(struct object *,struct process *,obj_handle_t); - /* destroy on refcount == 0 */ -@@ -224,6 +225,17 @@ extern void reset_event( struct event *event ); - - extern void abandon_mutexes( struct thread *thread ); - -+/* in-process synchronization functions */ -+ -+extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); -+extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); -+extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); -+extern void set_inproc_event( struct inproc_sync *obj ); -+extern void reset_inproc_event( struct inproc_sync *obj ); -+extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); -+ -+extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); -+ - /* serial functions */ - - int get_serial_async_timeout(struct object *obj, int type, int count); -diff --git a/server/process.c b/server/process.c -index 6d66a7c..34451c1 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -63,7 +63,6 @@ - #include "request.h" - #include "user.h" - #include "security.h" --#include "esync.h" - - /* process object */ - -@@ -95,8 +94,8 @@ static unsigned int process_map_access( struct object *obj, unsigned int access - static struct security_descriptor *process_get_sd( struct object *obj ); - static void process_poll_event( struct fd *fd, int event ); - static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ); - static void process_destroy( struct object *obj ); --static int process_get_esync_fd( struct object *obj, enum esync_type *type ); - static void terminate_process( struct process *process, struct thread *skip, int exit_code ); - - static const struct object_ops process_ops = -@@ -107,7 +106,6 @@ static const struct object_ops process_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - process_signaled, /* signaled */ -- process_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -120,6 +118,7 @@ static const struct object_ops process_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - process_destroy /* destroy */ - }; -@@ -159,7 +158,6 @@ static const struct object_ops startup_info_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - startup_info_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -172,6 +170,7 @@ static const struct object_ops startup_info_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - startup_info_destroy /* destroy */ - }; -@@ -194,6 +193,7 @@ struct type_descr job_type = - - static void job_dump( struct object *obj, int verbose ); - static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ); - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void job_destroy( struct object *obj ); - -@@ -211,6 +211,7 @@ struct job - struct job *parent; - struct list parent_job_entry; /* list entry for parent job */ - struct list child_job_list; /* list of child jobs */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static const struct object_ops job_ops = -@@ -221,7 +222,6 @@ static const struct object_ops job_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - job_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -234,6 +234,7 @@ static const struct object_ops job_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_inproc_sync, /* get_inproc_sync */ - job_close_handle, /* close_handle */ - job_destroy /* destroy */ - }; -@@ -258,6 +259,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_ - job->completion_port = NULL; - job->completion_key = 0; - job->parent = NULL; -+ job->inproc_sync = NULL; - } - } - return job; -@@ -414,6 +416,17 @@ static void terminate_job( struct job *job, int exit_code ) - job->terminating = 0; - job->signaled = 1; - wake_up( &job->obj, 0 ); -+ set_inproc_event( job->inproc_sync ); -+} -+ -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ) -+{ -+ struct job *job = (struct job *)obj; -+ -+ if (!job->inproc_sync) -+ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->inproc_sync) grab_object( job->inproc_sync ); -+ return job->inproc_sync; - } - - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) -@@ -444,6 +457,8 @@ static void job_destroy( struct object *obj ) - list_remove( &job->parent_job_entry ); - release_object( job->parent ); - } -+ -+ if (job->inproc_sync) release_object( job->inproc_sync ); - } - - static void job_dump( struct object *obj, int verbose ) -@@ -688,9 +703,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_device_count = 0; - process->rawinput_mouse = NULL; - process->rawinput_kbd = NULL; -+ process->inproc_sync = NULL; - memset( &process->image_info, 0, sizeof(process->image_info) ); - list_init( &process->rawinput_entry ); -- process->esync_fd = -1; - list_init( &process->kernel_object ); - list_init( &process->thread_list ); - list_init( &process->locks ); -@@ -747,9 +762,6 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - if (!token_assign_label( process->token, &high_label_sid )) - goto error; - -- if (do_esync()) -- process->esync_fd = esync_create_fd( 0, 0 ); -- - set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ - return process; - -@@ -798,7 +810,8 @@ static void process_destroy( struct object *obj ) - free( process->rawinput_devices ); - free( process->dir_cache ); - free( process->image ); -- if (do_esync()) close( process->esync_fd ); -+ -+ if (process->inproc_sync) release_object( process->inproc_sync ); - } - - /* dump a process on stdout for debugging purposes */ -@@ -816,13 +829,6 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry - return !process->running_threads; - } - --static int process_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct process *process = (struct process *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return process->esync_fd; --} -- - static unsigned int process_map_access( struct object *obj, unsigned int access ) - { - access = default_map_access( obj, access ); -@@ -837,6 +843,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) - return &process->kernel_object; - } - -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ) -+{ -+ struct process *process = (struct process *)obj; -+ -+ if (!process->inproc_sync) -+ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->inproc_sync) grab_object( process->inproc_sync ); -+ return process->inproc_sync; -+} -+ - static struct security_descriptor *process_get_sd( struct object *obj ) - { - static struct security_descriptor *process_default_sd; -@@ -1001,6 +1017,7 @@ static void process_killed( struct process *process ) - release_job_process( process ); - start_sigkill_timer( process ); - wake_up( &process->obj, 0 ); -+ set_inproc_event( process->inproc_sync ); - } - - /* add a thread to a process running threads list */ -diff --git a/server/process.h b/server/process.h -index bedd8bb..2140427 100644 ---- a/server/process.h -+++ b/server/process.h -@@ -86,7 +86,7 @@ struct process - struct list rawinput_entry; /* entry in the rawinput process list */ - struct list kernel_object; /* list of kernel object pointers */ - struct pe_image_info image_info; /* main exe image info */ -- int esync_fd; /* esync file descriptor (signaled on exit) */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - /* process functions */ -diff --git a/server/protocol.def b/server/protocol.def -index 4983691..7bc4208 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -3887,6 +3887,7 @@ struct handle_info - obj_handle_t handle; /* process handle */ - @END - -+ - /* Iterate thread list for process */ - @REQ(get_next_thread) - obj_handle_t process; /* process handle */ -@@ -3898,63 +3899,58 @@ struct handle_info - obj_handle_t handle; /* next thread handle */ - @END - --enum esync_type -+ -+enum inproc_sync_type - { -- ESYNC_SEMAPHORE = 1, -- ESYNC_AUTO_EVENT, -- ESYNC_MANUAL_EVENT, -- ESYNC_MUTEX, -- ESYNC_AUTO_SERVER, -- ESYNC_MANUAL_SERVER, -- ESYNC_QUEUE, -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, - }; - --/* Create a new eventfd-based synchronization object */ --@REQ(create_esync) -- unsigned int access; /* wanted access rights */ -- int initval; /* initial value */ -- int type; /* type of esync object */ -- int max; /* maximum count on a semaphore */ -- VARARG(objattr,object_attributes); /* object attributes */ -+ -+/* Obtain a handle to the fast synchronization device object */ -+@REQ(get_linux_sync_device) - @REPLY -- obj_handle_t handle; /* handle to the object */ -- int type; /* actual type (may be different for events) */ -- unsigned int shm_idx; -+ obj_handle_t handle; /* handle to the device */ - @END - --@REQ(open_esync) -- unsigned int access; /* wanted access rights */ -- unsigned int attributes; /* object attributes */ -- obj_handle_t rootdir; /* root directory */ -- int type; /* type of esync object (above) */ -- VARARG(name,unicode_str); /* object name */ -+ -+/* Get the in-process synchronization object associated with the given handle */ -+@REQ(get_linux_sync_obj) -+ obj_handle_t handle; /* handle to the object */ - @REPLY -- obj_handle_t handle; /* handle to the event */ -- int type; /* type of esync object (above) */ -- unsigned int shm_idx; /* this object's index into the shm section */ -+ obj_handle_t handle; /* handle to the fast synchronization object */ -+ int type; /* object type */ -+ unsigned int access; /* handle access rights */ - @END - --/* Retrieve the esync fd for an object. */ --@REQ(get_esync_fd) -- obj_handle_t handle; /* handle to the object */ --@REPLY -- int type; -- unsigned int shm_idx; -+ -+/* Begin a client-side wait on a message queue */ -+@REQ(select_inproc_queue) - @END - --@REQ(esync_msgwait) -- int in_msgwait; /* are we in a message wait? */ -+ -+/* End a client-side wait on a message queue */ -+@REQ(unselect_inproc_queue) -+ int signaled; /* was the queue signaled? */ - @END - - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ - int delay; /* auto-repeat delay in ms */ - int period; /* auto-repeat period in ms */ - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END - --/* Retrieve the fd to wait on for user APCs. */ --@REQ(get_esync_apc_fd) -+ -+/* Get an event handle to be used for thread alerts with in-process synchronization */ -+@REQ(get_inproc_alert_event) -+@REPLY -+ obj_handle_t handle; /* handle to the event */ - @END -diff --git a/server/queue.c b/server/queue.c -index fee3a8d..287a56e 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -43,7 +43,6 @@ - #include "process.h" - #include "request.h" - #include "user.h" --#include "esync.h" - - #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE - #define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST)) -@@ -147,8 +146,8 @@ struct msg_queue - timeout_t last_get_msg; /* time of last get message call */ - int keystate_lock; /* owns an input keystate lock */ - 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 */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ int in_inproc_wait; /* are we in a client-side wait? */ - }; - - struct hotkey -@@ -165,8 +164,8 @@ static void msg_queue_dump( struct object *obj, int verbose ); - static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ); - 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 ); - static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); - static void msg_queue_destroy( struct object *obj ); - static void msg_queue_poll_event( struct fd *fd, int event ); - static void thread_input_dump( struct object *obj, int verbose ); -@@ -181,7 +180,6 @@ static const struct object_ops msg_queue_ops = - msg_queue_add_queue, /* add_queue */ - msg_queue_remove_queue, /* remove_queue */ - msg_queue_signaled, /* signaled */ -- msg_queue_get_esync_fd, /* get_esync_fd */ - msg_queue_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -194,6 +192,7 @@ static const struct object_ops msg_queue_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - msg_queue_destroy /* destroy */ - }; -@@ -219,7 +218,6 @@ static const struct object_ops thread_input_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -232,6 +230,7 @@ static const struct object_ops thread_input_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_input_destroy /* destroy */ - }; -@@ -321,33 +320,30 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->last_get_msg = current_time; - queue->keystate_lock = 0; - queue->ignore_post_msg = 0; -- queue->esync_fd = -1; -- queue->esync_in_msgwait = 0; -+ queue->inproc_sync = NULL; -+ queue->in_inproc_wait = 0; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); - list_init( &queue->expired_timers ); - for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] ); - - if (!(queue->shared = alloc_shared_object())) - { - release_object( queue ); - return NULL; - } - - SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) - { - memset( (void *)shared->hooks_count, 0, sizeof(shared->hooks_count) ); - shared->wake_mask = 0; - shared->wake_bits = 0; - shared->changed_mask = 0; - shared->changed_bits = 0; - } - SHARED_WRITE_END; - -- if (do_esync()) -- queue->esync_fd = esync_create_fd( 0, 0 ); -- - thread->queue = queue; - } - -@@ -606,7 +602,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) - } - SHARED_WRITE_END; - -- if (is_signaled( queue )) wake_up( &queue->obj, 0 ); -+ if (is_signaled( queue )) -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } - } - - /* clear some queue bits */ -@@ -620,9 +620,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits - if (queue->keystate_lock) unlock_input_keystate( queue->input ); - queue->keystate_lock = 0; - } -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - - /* check if message is matched by the filter */ -@@ -1112,8 +1111,8 @@ static int is_queue_hung( struct msg_queue *queue ) - return 0; /* thread is waiting on queue -> not hung */ - } - -- if (do_esync() && queue->esync_in_msgwait) -- return 0; /* thread is waiting on queue in absentia -> not hung */ -+ if (queue->in_inproc_wait) -+ return 0; /* thread is waiting on queue in absentia -> not hung */ - - return 1; - } -@@ -1168,24 +1167,29 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr - return ret || is_signaled( queue ); - } - --static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type ) -+static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct msg_queue *queue = (struct msg_queue *)obj; -- *type = ESYNC_QUEUE; -- return queue->esync_fd; -+ const queue_shm_t *queue_shm = queue->shared; -+ -+ SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) -+ { -+ shared->wake_mask = 0; -+ shared->changed_mask = 0; -+ } -+ SHARED_WRITE_END; -+ -+ reset_inproc_event( queue->inproc_sync ); - } - --static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) - { - struct msg_queue *queue = (struct msg_queue *)obj; -- const queue_shm_t *queue_shm = queue->shared; - -- SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) -- { -- shared->wake_mask = 0; -- shared->changed_mask = 0; -- } -- SHARED_WRITE_END; -+ if (!queue->inproc_sync) -+ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->inproc_sync) grab_object( queue->inproc_sync ); -+ return queue->inproc_sync; - } - - static void msg_queue_destroy( struct object *obj ) -@@ -1221,7 +1224,7 @@ static void msg_queue_destroy( struct object *obj ) - if (queue->hooks) release_object( queue->hooks ); - if (queue->fd) release_object( queue->fd ); - if (queue->shared) free_shared_object( queue->shared ); -- if (do_esync()) close( queue->esync_fd ); -+ if (queue->inproc_sync) release_object( queue->inproc_sync ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1232,6 +1235,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) - if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); - else set_fd_events( queue->fd, 0 ); - wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); - } - - static void thread_input_dump( struct object *obj, int verbose ) -@@ -2982,10 +2982,15 @@ DECL_HANDLER(set_queue_mask) - } - SHARED_WRITE_END; -+ } -+ else -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } -+ } -+ else -+ { -+ reset_inproc_event( queue->inproc_sync ); -- } -- else wake_up( &queue->obj, 0 ); - } -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); - } - } -@@ -2867,8 +2880,8 @@ DECL_HANDLER(get_queue_status) - } - SHARED_WRITE_END; - -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - else reply->wake_bits = reply->changed_bits = 0; - } -@@ -3049,6 +3061,9 @@ DECL_HANDLER(get_message) - if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT; - if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; - -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); -+ - /* then check for posted messages */ - if ((filter & QS_POSTMESSAGE) && - get_posted_message( queue, queue->ignore_post_msg, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3119,11 +3134,8 @@ DECL_HANDLER(get_message) - shared->changed_mask = req->changed_mask; - } - SHARED_WRITE_END; - -+ reset_inproc_event( queue->inproc_sync ); - set_error( STATUS_PENDING ); /* FIXME */ -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -- - return; - - found_msg: -diff --git a/server/registry.c b/server/registry.c -index 4454de3..dd5c556 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -180,7 +180,6 @@ static const struct object_ops key_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -193,6 +192,7 @@ static const struct object_ops key_ops = - key_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - key_close_handle, /* close_handle */ - key_destroy /* destroy */ - }; -diff --git a/server/request.c b/server/request.c -index ca83fdb..8c50f99 100644 ---- a/server/request.c -+++ b/server/request.c -@@ -90,7 +90,6 @@ static const struct object_ops master_socket_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -103,6 +102,7 @@ static const struct object_ops master_socket_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - master_socket_destroy /* destroy */ - }; -diff --git a/server/request_handlers.h b/server/request_handlers.h -index eb6b8f4..1636e98 100644 ---- a/server/request_handlers.h 2024-11-18 18:02:30.072599085 +0500 -+++ b/server/request_handlers.h 2024-11-18 18:14:42.357268807 +0500 -@@ -298,12 +298,12 @@ - DECL_HANDLER(suspend_process); - DECL_HANDLER(resume_process); - DECL_HANDLER(get_next_thread); --DECL_HANDLER(create_esync); --DECL_HANDLER(open_esync); --DECL_HANDLER(get_esync_fd); --DECL_HANDLER(esync_msgwait); - DECL_HANDLER(set_keyboard_repeat); --DECL_HANDLER(get_esync_apc_fd); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(select_inproc_queue); -+DECL_HANDLER(unselect_inproc_queue); -+DECL_HANDLER(get_inproc_alert_event); - - typedef void (*req_handler)( const void *req, void *reply ); - static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -599,12 +599,12 @@ - (req_handler)req_suspend_process, - (req_handler)req_resume_process, - (req_handler)req_get_next_thread, -- (req_handler)req_create_esync, -- (req_handler)req_open_esync, -- (req_handler)req_get_esync_fd, -- (req_handler)req_esync_msgwait, - (req_handler)req_set_keyboard_repeat, -- (req_handler)req_get_esync_apc_fd, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_select_inproc_queue, -+ (req_handler)req_unselect_inproc_queue, -+ (req_handler)req_get_inproc_alert_event, - }; - - C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,35 +2276,24 @@ - C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); - C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); - C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); --C_ASSERT( offsetof(struct create_esync_request, access) == 12 ); --C_ASSERT( offsetof(struct create_esync_request, initval) == 16 ); --C_ASSERT( offsetof(struct create_esync_request, type) == 20 ); --C_ASSERT( offsetof(struct create_esync_request, max) == 24 ); --C_ASSERT( sizeof(struct create_esync_request) == 32 ); --C_ASSERT( offsetof(struct create_esync_reply, handle) == 8 ); --C_ASSERT( offsetof(struct create_esync_reply, type) == 12 ); --C_ASSERT( offsetof(struct create_esync_reply, shm_idx) == 16 ); --C_ASSERT( sizeof(struct create_esync_reply) == 24 ); --C_ASSERT( offsetof(struct open_esync_request, access) == 12 ); --C_ASSERT( offsetof(struct open_esync_request, attributes) == 16 ); --C_ASSERT( offsetof(struct open_esync_request, rootdir) == 20 ); --C_ASSERT( offsetof(struct open_esync_request, type) == 24 ); --C_ASSERT( sizeof(struct open_esync_request) == 32 ); --C_ASSERT( offsetof(struct open_esync_reply, handle) == 8 ); --C_ASSERT( offsetof(struct open_esync_reply, type) == 12 ); --C_ASSERT( offsetof(struct open_esync_reply, shm_idx) == 16 ); --C_ASSERT( sizeof(struct open_esync_reply) == 24 ); --C_ASSERT( offsetof(struct get_esync_fd_request, handle) == 12 ); --C_ASSERT( sizeof(struct get_esync_fd_request) == 16 ); --C_ASSERT( offsetof(struct get_esync_fd_reply, type) == 8 ); --C_ASSERT( offsetof(struct get_esync_fd_reply, shm_idx) == 12 ); --C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 ); --C_ASSERT( offsetof(struct esync_msgwait_request, in_msgwait) == 12 ); --C_ASSERT( sizeof(struct esync_msgwait_request) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); --C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_request, handle) == 12 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, handle) == 8 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); -+C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); -+C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); -diff --git a/server/semaphore.c b/server/semaphore.c -index e3889f2..9940919 100644 ---- a/server/semaphore.c -+++ b/server/semaphore.c -@@ -55,12 +55,15 @@ struct semaphore - struct object obj; /* object header */ - unsigned int count; /* current count */ - unsigned int max; /* maximum possible count */ -+ struct inproc_sync *inproc_sync; /* fast synchronization object */ - }; - - static void semaphore_dump( struct object *obj, int verbose ); - static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); -+static void semaphore_destroy( struct object *obj ); - - static const struct object_ops semaphore_ops = - { -@@ -70,7 +73,6 @@ static const struct object_ops semaphore_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - semaphore_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - semaphore_satisfied, /* satisfied */ - semaphore_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -83,8 +85,9 @@ static const struct object_ops semaphore_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ semaphore_destroy /* destroy */ - }; - - -@@ -106,6 +109,7 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni - /* initialize it if it didn't already exist */ - sem->count = initial; - sem->max = max; -+ sem->inproc_sync = NULL; - } - } - return sem; -@@ -168,6 +172,23 @@ static int semaphore_signal( struct object *obj, unsigned int access ) - return release_semaphore( sem, 1, NULL ); - } - -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (!semaphore->inproc_sync) -+ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); -+ return semaphore->inproc_sync; -+} -+ -+static void semaphore_destroy( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); -+} -+ - /* create a semaphore */ - DECL_HANDLER(create_semaphore) - { -diff --git a/server/serial.c b/server/serial.c -index 11e204e..5c210d1 100644 ---- a/server/serial.c -+++ b/server/serial.c -@@ -85,7 +85,6 @@ static const struct object_ops serial_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - serial_get_fd, /* get_fd */ -@@ -98,6 +97,7 @@ static const struct object_ops serial_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - serial_destroy /* destroy */ - }; -diff --git a/server/signal.c b/server/signal.c -index 55cd6aa..e5def3d 100644 ---- a/server/signal.c -+++ b/server/signal.c -@@ -62,7 +62,6 @@ static const struct object_ops handler_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -75,6 +74,7 @@ static const struct object_ops handler_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handler_destroy /* destroy */ - }; -diff --git a/server/sock.c b/server/sock.c -index 104321b..3fb2e29 100644 ---- a/server/sock.c -+++ b/server/sock.c -@@ -453,7 +453,6 @@ static const struct object_ops sock_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - sock_get_fd, /* get_fd */ -@@ -466,6 +465,7 @@ static const struct object_ops sock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - sock_close_handle, /* close_handle */ - sock_destroy /* destroy */ - }; -@@ -3555,7 +3555,6 @@ static const struct object_ops ifchange_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - ifchange_get_fd, /* get_fd */ -@@ -3568,6 +3567,7 @@ static const struct object_ops ifchange_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ifchange_destroy /* destroy */ - }; -@@ -3777,7 +3777,6 @@ static const struct object_ops socket_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -3790,6 +3789,7 @@ static const struct object_ops socket_device_ops = - default_unlink_name, /* unlink_name */ - socket_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -diff --git a/server/symlink.c b/server/symlink.c -index c7f3441..4a7cf68 100644 ---- a/server/symlink.c -+++ b/server/symlink.c -@@ -71,7 +71,6 @@ static const struct object_ops symlink_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -84,6 +83,7 @@ static const struct object_ops symlink_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - symlink_destroy /* destroy */ - }; -diff --git a/server/thread.c b/server/thread.c -index 2ce94b4..8f603fc 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -50,7 +50,6 @@ - #include "request.h" - #include "user.h" - #include "security.h" --#include "esync.h" - - - /* thread queues */ -@@ -97,7 +96,6 @@ static const struct object_ops thread_apc_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_apc_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -110,6 +108,7 @@ static const struct object_ops thread_apc_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_apc_destroy /* destroy */ - }; -@@ -140,7 +139,6 @@ static const struct object_ops context_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - context_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -153,6 +151,7 @@ static const struct object_ops context_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -177,10 +176,10 @@ struct type_descr thread_type = - - static void dump_thread( struct object *obj, int verbose ); - static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int thread_get_esync_fd( struct object *obj, enum esync_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 ); -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); - static void destroy_thread( struct object *obj ); - - static const struct object_ops thread_ops = -@@ -191,7 +190,6 @@ static const struct object_ops thread_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_signaled, /* signaled */ -- thread_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -204,6 +202,7 @@ static const struct object_ops thread_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - destroy_thread /* destroy */ - }; -@@ -231,8 +230,6 @@ static inline void init_thread_structure( struct thread *thread ) - thread->context = NULL; - thread->teb = 0; - thread->entry_point = 0; -- thread->esync_fd = -1; -- thread->esync_apc_fd = -1; - thread->system_regs = 0; - thread->queue = NULL; - thread->wait = NULL; -@@ -253,6 +250,7 @@ static inline void init_thread_structure( struct thread *thread ) - thread->token = NULL; - thread->desc = NULL; - thread->desc_len = 0; -+ thread->inproc_sync = NULL; -+ thread->inproc_alert_event = NULL; -- thread->exit_poll = NULL; - - thread->creation_time = current_time; -@@ -380,12 +379,6 @@ struct thread *create_thread( int fd, struct process *process, const struct secu - } - } - -- if (do_esync()) -- { -- thread->esync_fd = esync_create_fd( 0, 0 ); -- thread->esync_apc_fd = esync_create_fd( 0, 0 ); -- } -- - set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */ - add_process_thread( thread->process, thread ); - return thread; -@@ -410,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) - return &thread->kernel_object; - } - -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) -+{ -+ struct thread *thread = (struct thread *)obj; -+ -+ if (!thread->inproc_sync) -+ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->inproc_sync) grab_object( thread->inproc_sync ); -+ return thread->inproc_sync; -+} -+ - /* cleanup everything that is no longer needed by a dead thread */ - /* used by destroy_thread and kill_thread */ - static void cleanup_thread( struct thread *thread ) -@@ -465,9 +468,7 @@ static void destroy_thread( struct object *obj ) -- if (thread->exit_poll) remove_timeout_user( thread->exit_poll ); - if (thread->id) free_ptid( thread->id ); - if (thread->token) release_object( thread->token ); -- -- if (do_esync()) -- close( thread->esync_fd ); -+ if (thread->inproc_sync) release_object( thread->inproc_sync ); -+ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); - } - - /* dump a thread on stdout for debugging purposes */ -@@ -486,13 +488,6 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) -- return mythread->state == TERMINATED && !mythread->exit_poll; -+ return (mythread->state == TERMINATED); - } - --static int thread_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct thread *thread = (struct thread *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return thread->esync_fd; --} -- - static unsigned int thread_map_access( struct object *obj, unsigned int access ) - { - access = default_map_access( obj, access ); -@@ -1087,9 +1082,6 @@ void wake_up( struct object *obj, int max ) - struct list *ptr; - int ret; - -- if (do_esync()) -- esync_wake_up( obj ); -- - LIST_FOR_EACH( ptr, &obj->wait_queue ) - { - struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry ); -@@ -1177,8 +1169,8 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr - { - wake_thread( thread ); - -- if (do_esync() && queue == &thread->user_apc) -- esync_wake_fd( thread->esync_apc_fd ); -+ if (apc->call.type == APC_USER && thread->inproc_alert_event) -+ set_event( thread->inproc_alert_event ); - } - - return 1; -@@ -1211,6 +1203,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty - apc->executed = 1; - wake_up( &apc->obj, 0 ); - release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - return; - } - } -@@ -1225,11 +1219,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system - { - apc = LIST_ENTRY( ptr, struct thread_apc, entry ); - list_remove( ptr ); -- } -- -- if (do_esync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc )) -- esync_clear( thread->esync_apc_fd ); - -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); -+ } - return apc; - } - -@@ -1305,26 +1302,6 @@ - return -1; - } - --static void check_terminated( void *arg ) --{ -- struct thread *thread = arg; -- assert( thread->obj.ops == &thread_ops ); -- assert( thread->state == TERMINATED ); -- -- /* don't wake up until the thread is really dead, to avoid race conditions */ -- if (thread->unix_tid != -1 && !kill( thread->unix_tid, 0 )) -- { -- thread->exit_poll = add_timeout_user( -TICKS_PER_SEC / 1000, check_terminated, thread ); -- return; -- } -- -- /* grab reference since object can be destroyed while trying to wake up */ -- grab_object( &thread->obj ); -- thread->exit_poll = NULL; -- wake_up( &thread->obj, 0 ); -- release_object( &thread->obj ); --} -- - /* kill a thread on the spot */ - void kill_thread( struct thread *thread, int violent_death ) - { -@@ -1345,14 +1338,9 @@ void kill_thread( struct thread *thread, int violent_death ) - } - kill_console_processes( thread, 0 ); - abandon_mutexes( thread ); -- if (do_esync()) -- esync_abandon_mutexes( thread ); -+ wake_up( &thread->obj, 0 ); -+ set_inproc_event( thread->inproc_sync ); -+ if (violent_death) send_thread_signal( thread, SIGQUIT ); -- if (violent_death) -- { -- send_thread_signal( thread, SIGQUIT ); -- check_terminated( thread ); -- } -- else wake_up( &thread->obj, 0 ); - cleanup_thread( thread ); - remove_process_thread( thread->process, thread ); - release_object( thread ); -@@ -2094,3 +2086,12 @@ DECL_HANDLER(get_next_thread) - set_error( STATUS_NO_MORE_ENTRIES ); - release_object( process ); - } -+ -+DECL_HANDLER(get_inproc_alert_event) -+{ -+ if (!current->inproc_alert_event) -+ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); -+ -+ if (current->inproc_alert_event) -+ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); -+} -diff --git a/server/thread.h b/server/thread.h -index 10e9e28..cb4643a 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -55,8 +55,6 @@ struct thread - struct process *process; - thread_id_t id; /* thread id */ - struct list mutex_list; /* list of currently owned mutexes */ -- int esync_fd; /* esync file descriptor (signalled on exit) */ -- int esync_apc_fd; /* esync apc fd (signalled when APCs are present) */ - 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 */ -@@ -94,6 +92,7 @@ struct thread - WCHAR *desc; /* thread description string */ - struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -- struct timeout_user *exit_poll; /* poll if the thread/process has exited already */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ struct event *inproc_alert_event; /* in-process synchronization alert event */ - }; - - extern struct thread *current; -diff --git a/server/timer.c b/server/timer.c -index 36645a2..854a8e1 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -35,7 +35,6 @@ - #include "file.h" - #include "handle.h" - #include "request.h" --#include "esync.h" - - static const WCHAR timer_name[] = {'T','i','m','e','r'}; - -@@ -62,13 +61,13 @@ struct timer - struct thread *thread; /* thread that set the APC function */ - client_ptr_t callback; /* callback APC function */ - client_ptr_t arg; /* callback argument */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void timer_dump( struct object *obj, int verbose ); - static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int timer_get_esync_fd( struct object *obj, enum esync_type *type ); - static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); - static void timer_destroy( struct object *obj ); - - static const struct object_ops timer_ops = -@@ -79,7 +78,6 @@ static const struct object_ops timer_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - timer_signaled, /* signaled */ -- timer_get_esync_fd, /* get_esync_fd */ - timer_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -92,6 +90,7 @@ static const struct object_ops timer_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - timer_destroy /* destroy */ - }; -@@ -114,10 +113,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str - timer->period = 0; - timer->timeout = NULL; - timer->thread = NULL; -- timer->esync_fd = -1; -- -- if (do_esync()) -- timer->esync_fd = esync_create_fd( 0, 0 ); -+ timer->inproc_sync = NULL; - } - } - return timer; -@@ -159,6 +155,7 @@ static void timer_callback( void *private ) - /* wake up waiters */ - timer->signaled = 1; - wake_up( &timer->obj, 0 ); -+ set_inproc_event( timer->inproc_sync ); - } - - /* cancel a running timer */ -@@ -189,9 +186,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period - { - period = 0; /* period doesn't make any sense for a manual timer */ - timer->signaled = 0; -- -- if (do_esync()) -- esync_clear( timer->esync_fd ); -+ reset_inproc_event( timer->inproc_sync ); - } - timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); - timer->period = period; -@@ -219,18 +214,24 @@ static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) - return timer->signaled; - } - --static int timer_get_esync_fd( struct object *obj, enum esync_type *type ) -+static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct timer *timer = (struct timer *)obj; -- *type = timer->manual ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER; -- return timer->esync_fd; -+ assert( obj->ops == &timer_ops ); -+ if (!timer->manual) timer->signaled = 0; - } - --static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) - { - struct timer *timer = (struct timer *)obj; -- assert( obj->ops == &timer_ops ); -- if (!timer->manual) timer->signaled = 0; -+ -+ if (!timer->inproc_sync) -+ { -+ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; -+ timer->inproc_sync = create_inproc_event( type, timer->signaled ); -+ } -+ if (timer->inproc_sync) grab_object( timer->inproc_sync ); -+ return timer->inproc_sync; - } - - static void timer_destroy( struct object *obj ) -@@ -240,7 +241,7 @@ static void timer_destroy( struct object *obj ) - - if (timer->timeout) remove_timeout_user( timer->timeout ); - if (timer->thread) release_object( timer->thread ); -- if (do_esync()) close( timer->esync_fd ); -+ if (timer->inproc_sync) release_object( timer->inproc_sync ); - } - - /* create a timer */ -diff --git a/server/token.c b/server/token.c -index 8b4d2f0..42562fd 100644 ---- a/server/token.c -+++ b/server/token.c -@@ -143,7 +143,6 @@ static const struct object_ops token_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -156,6 +155,7 @@ static const struct object_ops token_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - token_destroy /* destroy */ - }; -diff --git a/server/request_trace.h b/server/request_trace.h -index af96565..c027f4b 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -4619,67 +4619,54 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req - fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_create_esync_request( const struct create_esync_request *req ) -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) - { -- fprintf( stderr, " access=%08x", req->access ); -- fprintf( stderr, ", initval=%d", req->initval ); -- fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", max=%d", req->max ); -- dump_varargs_object_attributes( ", objattr=", cur_size ); - } - --static void dump_create_esync_reply( const struct create_esync_reply *req ) -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); -- fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); - } - --static void dump_open_esync_request( const struct open_esync_request *req ) -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) - { -- fprintf( stderr, " access=%08x", req->access ); -- fprintf( stderr, ", attributes=%08x", req->attributes ); -- fprintf( stderr, ", rootdir=%04x", req->rootdir ); -- fprintf( stderr, ", type=%d", req->type ); -- dump_varargs_unicode_str( ", name=", cur_size ); -+ fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_open_esync_reply( const struct open_esync_reply *req ) -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); - fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, ", access=%08x", req->access ); - } - --static void dump_get_esync_fd_request( const struct get_esync_fd_request *req ) -+static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) - { -- fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req ) -+static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) - { -- fprintf( stderr, " type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, ", signaled=%d", req->signaled ); - } - --static void dump_esync_msgwait_request( const struct esync_msgwait_request *req ) -+static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) - { -- fprintf( stderr, " in_msgwait=%d", req->in_msgwait ); - } - - static void dump_set_keyboard_repeat_request( const struct set_keyboard_repeat_request *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - fprintf( stderr, ", delay=%d", req->delay ); - fprintf( stderr, ", period=%d", req->period ); - } - - static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_reply *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - } - --static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request *req ) -+static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) - { -+ fprintf( stderr, " handle=%04x", req->handle ); - } - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = { -@@ -4959,11 +4948,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_suspend_process_request, - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, -- (dump_func)dump_create_esync_request, -- (dump_func)dump_open_esync_request, -- (dump_func)dump_get_esync_fd_request, -- (dump_func)dump_esync_msgwait_request, -- (dump_func)dump_get_esync_apc_fd_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_select_inproc_queue_request, -+ (dump_func)dump_unselect_inproc_queue_request, -+ (dump_func)dump_get_inproc_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { -@@ -5254,12 +5243,12 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { - NULL, - NULL, - (dump_func)dump_get_next_thread_reply, -- (dump_func)dump_create_esync_reply, -- (dump_func)dump_open_esync_reply, -- (dump_func)dump_get_esync_fd_reply, - NULL, - (dump_func)dump_set_keyboard_repeat_reply, - NULL, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, -+ NULL, -+ (dump_func)dump_get_inproc_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = { -@@ -5549,11 +5538,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = { - "suspend_process", - "resume_process", - "get_next_thread", -- "create_esync", -- "open_esync", -- "get_esync_fd", -- "esync_msgwait", - "set_keyboard_repeat", -- "get_esync_apc_fd", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "select_inproc_queue", -+ "unselect_inproc_queue", -+ "get_inproc_alert_event", - }; - - static const struct -diff --git a/server/window.c b/server/window.c -index feac54e..f52e118 100644 ---- a/server/window.c -+++ b/server/window.c -@@ -108,7 +108,6 @@ static const struct object_ops window_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -121,6 +120,7 @@ static const struct object_ops window_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - window_destroy /* destroy */ - }; -diff --git a/server/winstation.c b/server/winstation.c -index 4ef21d9..2719c9e 100644 ---- a/server/winstation.c -+++ b/server/winstation.c -@@ -76,7 +76,6 @@ static const struct object_ops winstation_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +88,7 @@ static const struct object_ops winstation_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - winstation_close_handle, /* close_handle */ - winstation_destroy /* destroy */ - }; -@@ -117,7 +117,6 @@ static const struct object_ops desktop_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -130,6 +129,7 @@ static const struct object_ops desktop_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - desktop_close_handle, /* close_handle */ - desktop_destroy /* destroy */ - }; ---- a/server/queue.c 2024-12-20 20:01:39.879368500 +0500 -+++ b/server/queue.c 2024-12-20 20:03:11.782212833 +0500 -@@ -4252,23 +4252,6 @@ - } - } - --DECL_HANDLER(esync_msgwait) --{ -- struct msg_queue *queue = get_current_queue(); -- const queue_shm_t *queue_shm; -- -- if (!queue) return; -- queue_shm = queue->shared; -- queue->esync_in_msgwait = req->in_msgwait; -- -- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -- set_event( current->process->idle_event ); -- -- /* and start/stop waiting on the driver */ -- if (queue->fd) -- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); --} -- - DECL_HANDLER(set_keyboard_repeat) - { - struct desktop *desktop; -@@ -4288,3 +4271,41 @@ - release_object( desktop ); - } - -+DECL_HANDLER(select_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ check_thread_queue_idle( current ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_inproc_wait = 1; -+ } -+} -+ -+DECL_HANDLER(unselect_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (!queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_inproc_wait = 0; -+ } -+} diff --git a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging.patch b/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging.patch deleted file mode 100644 index f6488c417..000000000 --- a/wine-tkg-git/wine-tkg-patches/misc/fastsync/ntsync7-staging.patch +++ /dev/null @@ -1,8364 +0,0 @@ -diff --git a/README.esync b/README.esync -deleted file mode 100644 -index 11d8656..0000000 ---- a/README.esync -+++ /dev/null -@@ -1,196 +0,0 @@ --This is eventfd-based synchronization, or 'esync' for short. Turn it on with --WINEESYNC=1; debug it with +esync. -- --== BUGS AND LIMITATIONS == -- --Please let me know if you find any bugs. If you can, also attach a log with --+seh,+pid,+esync,+server,+timestamp. -- --If you get something like "eventfd: Too many open files" and then things start --crashing, you've probably run out of file descriptors. esync creates one --eventfd descriptor for each synchronization object, and some games may use a --large number of these. Linux by default limits a process to 4096 file --descriptors, which probably was reasonable back in the nineties but isn't --really anymore. (Fortunately Debian and derivatives [Ubuntu, Mint] already --have a reasonable limit.) To raise the limit you'll want to edit --/etc/security/limits.conf and add a line like -- --* hard nofile 1048576 -- --then restart your session. -- --On distributions using systemd, the settings in `/etc/security/limits.conf` --will be overridden by systemd's own settings. If you run `ulimit -Hn` and it --returns a lower number than the one you've previously set, then you can set -- --DefaultLimitNOFILE=1048576 -- --in both `/etc/systemd/system.conf` and `/etc/systemd/user.conf`. You can then --execute `sudo systemctl daemon-reexec` and restart your session. Check again --with `ulimit -Hn` that the limit is correct. -- --Also note that if the wineserver has esync active, all clients also must, and --vice versa. Otherwise things will probably crash quite badly. -- --== EXPLANATION == -- --The aim is to execute all synchronization operations in "user-space", that is, --without going through wineserver. We do this using Linux's eventfd --facility. The main impetus to using eventfd is so that we can poll multiple --objects at once; in particular we can't do this with futexes, or pthread --semaphores, or the like. The only way I know of to wait on any of multiple --objects is to use select/poll/epoll to wait on multiple fds, and eventfd gives --us those fds in a quite usable way. -- --Whenever a semaphore, event, or mutex is created, we have the server, instead --of creating a traditional server-side event/semaphore/mutex, instead create an --'esync' primitive. These live in esync.c and are very slim objects; in fact, --they don't even know what type of primitive they are. The server is involved --at all because we still need a way of creating named objects, passing handles --to another process, etc. -- --The server creates an eventfd file descriptor with the requested parameters --and passes it back to ntdll. ntdll creates an object of the appropriate type, --then caches it in a table. This table is copied almost wholesale from the fd --cache code in server.c. -- --Specific operations follow quite straightforwardly from eventfd: -- --* To release an object, or set an event, we simply write() to it. --* An object is signalled if read() succeeds on it. Notably, we create all -- eventfd descriptors with O_NONBLOCK, so that we can atomically check if an -- object is signalled and grab it if it is. This also lets us reset events. --* For objects whose state should not be reset upon waiting—e.g. manual-reset -- events—we simply check for the POLLIN flag instead of reading. --* Semaphores are handled by the EFD_SEMAPHORE flag. This matches up quite well -- (although with some difficulties; see below). --* Mutexes store their owner thread locally. This isn't reliable information if -- a different process's thread owns the mutex, but this doesn't matter—a -- thread should only care whether it owns the mutex, so it knows whether to -- try waiting on it or simply to increase the recursion count. -- --The interesting part about esync is that (almost) all waits happen in ntdll, --including those on server-bound objects. The idea here is that on the server --side, for any waitable object, we create an eventfd file descriptor (not an --esync primitive), and then pass it to ntdll if the program tries to wait on --it. These are cached too, so only the first wait will require a round trip to --the server. Then the server signals the file descriptor as appropriate, and --thereby wakes up the client. So far this is implemented for processes, --threads, message queues (difficult; see below), and device managers (necessary --for drivers to work). All of these are necessarily server-bound, so we --wouldn't really gain anything by signalling on the client side instead. Of --course, except possibly for message queues, it's not likely that any program --(cutting-edge D3D game or not) is going to be causing a great wineserver load --by waiting on any of these objects; the motivation was rather to provide a way --to wait on ntdll-bound and server-bound objects at the same time. -- --Some cases are still passed to the server, and there's probably no reason not --to keep them that way. Those that I noticed while testing include: async --objects, which are internal to the file APIs and never exposed to userspace, --startup_info objects, which are internal to the loader and signalled when a --process starts, and keyed events, which are exposed through an ntdll API --(although not through kernel32) but can't be mixed with other objects (you --have to use NtWaitForKeyedEvent()). Other cases include: named pipes, debug --events, sockets, and timers. It's unlikely we'll want to optimize debug events --or sockets (or any of the other, rather rare, objects), but it is possible --we'll want to optimize named pipes or timers. -- --There were two sort of complications when working out the above. The first one --was events. The trouble is that (1) the server actually creates some events by --itself and (2) the server sometimes manipulates events passed by the --client. Resolving the first case was easy enough, and merely entailed creating --eventfd descriptors for the events the same way as for processes and threads --(note that we don't really lose anything this way; the events include --"LowMemoryCondition" and the event that signals system processes to shut --down). For the second case I basically had to hook the server-side event --functions to redirect to esync versions if the event was actually an esync --primitive. -- --The second complication was message queues. The difficulty here is that X11 --signals events by writing into a pipe (at least I think it's a pipe?), and so --as a result wineserver has to poll on that descriptor. In theory we could just --let wineserver do so and then signal us as appropriate, except that wineserver --only polls on the pipe when the thread is waiting for events (otherwise we'd --get e.g. keyboard input while the thread is doing something else, and spin --forever trying to wake up a thread that doesn't care). The obvious solution is --just to poll on that fd ourselves, and that's what I did—it's just that --getting the fd from wineserver was kind of ugly, and the code for waiting was --also kind of ugly basically because we have to wait on both X11's fd and the --"normal" process/thread-style wineserver fd that we use to signal sent --messages. The upshot about the whole thing was that races are basically --impossible, since a thread can only wait on its own queue. -- --System APCs already work, since the server will forcibly suspend a thread if --it's not already waiting, and so we just need to check for EINTR from --poll(). User APCs and alertable waits are implemented in a similar style to --message queues (well, sort of): whenever someone executes an alertable wait, --we add an additional eventfd to the list, which the server signals when an APC --arrives. If that eventfd gets signaled, we hand it off to the server to take --care of, and return STATUS_USER_APC. -- --Originally I kept the volatile state of semaphores and mutexes inside a --variable local to the handle, with the knowledge that this would break if --someone tried to open the handle elsewhere or duplicate it. It did, and so now --this state is stored inside shared memory. This is of the POSIX variety, is --allocated by the server (but never mapped there) and lives under the path --"/wine-esync". -- --There are a couple things that this infrastructure can't handle, although --surprisingly there aren't that many. In particular: --* Implementing wait-all, i.e. WaitForMultipleObjects(..., TRUE, ...), is not -- exactly possible the way we'd like it to be possible. In theory that -- function should wait until it knows all objects are available, then grab -- them all at once atomically. The server (like the kernel) can do this -- because the server is single-threaded and can't race with itself. We can't -- do this in ntdll, though. The approach I've taken I've laid out in great -- detail in the relevant patch, but for a quick summary we poll on each object -- until it's signaled (but don't grab it), check them all again, and if -- they're all signaled we try to grab them all at once in a tight loop, and if -- we fail on any of them we reset the count on whatever we shouldn't have -- consumed. Such a blip would necessarily be very quick. --* The whole patchset only works on Linux, where eventfd is available. However, -- it should be possible to make it work on a Mac, since eventfd is just a -- quicker, easier way to use pipes (i.e. instead of writing 1 to the fd you'd -- write 1 byte; instead of reading a 64-bit value from the fd you'd read as -- many bytes as you can carry, which is admittedly less than 2**64 but -- can probably be something reasonable.) It's also possible, although I -- haven't yet looked, to use some different kind of synchronization -- primitives, but pipes would be easiest to tack onto this framework. --* PulseEvent() can't work the way it's supposed to work. Fortunately it's rare -- and deprecated. It's also explicitly mentioned on MSDN that a thread can -- miss the notification for a kernel APC, so in a sense we're not necessarily -- doing anything wrong. -- --There are some things that are perfectly implementable but that I just haven't --done yet: --* Other synchronizable server primitives. It's unlikely we'll need any of -- these, except perhaps named pipes (which would honestly be rather difficult) -- and (maybe) timers. --* Access masks. We'd need to store these inside ntdll, and validate them when -- someone tries to execute esync operations. -- --This patchset was inspired by Daniel Santos' "hybrid synchronization" --patchset. My idea was to create a framework whereby even contended waits could --be executed in userspace, eliminating a lot of the complexity that his --synchronization primitives used. I do however owe some significant gratitude --toward him for setting me on the right path. -- --I've tried to maximize code separation, both to make any potential rebases --easier and to ensure that esync is only active when configured. All code in --existing source files is guarded with "if (do_esync())", and generally that --condition is followed by "return esync_version_of_this_method(...);", where --the latter lives in esync.c and is declared in esync.h. I've also tried to --make the patchset very clear and readable—to write it as if I were going to --submit it upstream. (Some intermediate patches do break things, which Wine is --generally against, but I think it's for the better in this case.) I have cut --some corners, though; there is some error checking missing, or implicit --assumptions that the program is behaving correctly. -- --I've tried to be careful about races. There are a lot of comments whose --purpose are basically to assure me that races are impossible. In most cases we --don't have to worry about races since all of the low-level synchronization is --done by the kernel. -- --Anyway, yeah, this is esync. Use it if you like. -- ----Zebediah Figura -diff --git a/configure b/configure -index 4d13060..58291ba 100755 ---- a/configure -+++ b/configure -@@ -8110,6 +8110,12 @@ if test "x$ac_cv_header_linux_major_h" = xyes - then : - printf "%s\n" "#define HAVE_LINUX_MAJOR_H 1" >>confdefs.h - -+fi -+ac_fn_c_check_header_compile "$LINENO" "linux/ntsync.h" "ac_cv_header_linux_ntsync_h" "$ac_includes_default" -+if test "x$ac_cv_header_linux_ntsync_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_LINUX_NTSYNC_H 1" >>confdefs.h -+ - fi - ac_fn_c_check_header_compile "$LINENO" "linux/param.h" "ac_cv_header_linux_param_h" "$ac_includes_default" - if test "x$ac_cv_header_linux_param_h" = xyes -diff --git a/configure.ac b/configure.ac -index a3c414d..5af9132 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -403,6 +403,7 @@ AC_CHECK_HEADERS(\ - linux/input.h \ - linux/ioctl.h \ - linux/major.h \ -+ linux/ntsync.h \ - linux/param.h \ - linux/seccomp.h \ - linux/serial.h \ -@@ -433,7 +434,6 @@ AC_CHECK_HEADERS(\ - sys/cdio.h \ - sys/epoll.h \ - sys/event.h \ -- sys/eventfd.h \ - sys/extattr.h \ - sys/filio.h \ - sys/ipc.h \ -@@ -2094,7 +2094,6 @@ AC_CHECK_FUNCS(\ - port_create \ - posix_fadvise \ - posix_fallocate \ -- ppoll \ - prctl \ - proc_pidinfo \ - sched_yield \ -@@ -2120,12 +2119,6 @@ case $host_os in - ;; - esac - --ac_save_LIBS=$LIBS --AC_SEARCH_LIBS(shm_open, rt, -- [AC_DEFINE(HAVE_SHM_OPEN, 1, [Define to 1 if you have the `shm_open' function.]) -- test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) --LIBS=$ac_save_LIBS -- - AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity, - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [[#include ]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no])) -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 424cbe2..50e81aa 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -57,7 +57,6 @@ static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); - - static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); - static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); --static NTSTATUS (WINAPI *pNtQuerySystemTime)(LARGE_INTEGER *); - static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); - static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); - static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, -@@ -228,23 +227,8 @@ static void test_temporary_objects(void) - ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError()); - } - --static HANDLE mutex, mutex2, mutices[2]; -- --static DWORD WINAPI mutex_thread( void *param ) --{ -- DWORD expect = (DWORD)(DWORD_PTR)param; -- DWORD ret; -- -- ret = WaitForSingleObject( mutex, 0 ); -- ok(ret == expect, "expected %lu, got %lu\n", expect, ret); -- -- if (!ret) ReleaseMutex( mutex ); -- return 0; --} -- - static void test_mutex(void) - { -- HANDLE thread; - DWORD wait_ret; - BOOL ret; - HANDLE hCreated; -@@ -284,8 +268,7 @@ static void test_mutex(void) - SetLastError(0xdeadbeef); - hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); - ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError()); -- wait_ret = WaitForSingleObject(hOpened, 0); --todo_wine_if(getenv("WINEESYNC")) /* XFAIL: validation is not implemented */ -+ wait_ret = WaitForSingleObject(hOpened, INFINITE); - ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); - CloseHandle(hOpened); - -@@ -316,7 +299,6 @@ todo_wine_if(getenv("WINEESYNC")) /* XFAIL: validation is not implemented */ - - SetLastError(0xdeadbeef); - ret = ReleaseMutex(hCreated); --todo_wine_if(getenv("WINEESYNC")) /* XFAIL: due to the above */ - ok(!ret && (GetLastError() == ERROR_NOT_OWNER), - "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %ld\n", GetLastError()); - -@@ -355,85 +337,6 @@ todo_wine_if(getenv("WINEESYNC")) /* XFAIL: due to the above */ - CloseHandle(hOpened); - - CloseHandle(hCreated); -- -- mutex = CreateMutexA( NULL, FALSE, NULL ); -- ok(!!mutex, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- for (i = 0; i < 100; i++) -- { -- ret = WaitForSingleObject( mutex, 0 ); -- ok(ret == 0, "got %u\n", ret); -- } -- -- for (i = 0; i < 100; i++) -- { -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- } -- -- ret = ReleaseMutex( mutex ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)0, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- WaitForSingleObject( mutex, 0 ); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)WAIT_TIMEOUT, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- thread = CreateThread( NULL, 0, mutex_thread, (void *)0, 0, NULL ); -- ret = WaitForSingleObject( thread, 2000 ); -- ok(ret == 0, "wait failed: %u\n", ret); -- -- mutex2 = CreateMutexA( NULL, TRUE, NULL ); -- ok(!!mutex2, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- mutices[0] = mutex; -- mutices[1] = mutex2; -- -- ret = WaitForMultipleObjects( 2, mutices, FALSE, 0 ); -- ok(ret == 0, "got %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(!ret, "got %d\n", ret); -- ok(GetLastError() == ERROR_NOT_OWNER, "got error %lu\n", GetLastError()); -- -- ret = WaitForMultipleObjects( 2, mutices, TRUE, 0 ); -- ok(ret == 0, "got %u\n", ret); -- -- ret = ReleaseMutex( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ReleaseMutex( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( mutex ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( mutex2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- - } - - static void test_slist(void) -@@ -609,13 +512,12 @@ static void test_slist(void) - - static void test_event(void) - { -- HANDLE handle, handle2, handles[2]; -+ HANDLE handle, handle2; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - ACL acl; - DWORD ret; - BOOL val; -- int i; - - /* no sd */ - handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); -@@ -719,130 +621,11 @@ static void test_event(void) - ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() ); - ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); - CloseHandle( handle ); -- -- handle = CreateEventA( NULL, TRUE, FALSE, NULL ); -- ok(!!handle, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = SetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = SetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- for (i = 0; i < 100; i++) -- { -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = ResetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handle2 = CreateEventA( NULL, FALSE, TRUE, NULL ); -- ok(!!handle2, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = SetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = SetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = ResetEvent( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handles[0] = handle; -- handles[1] = handle2; -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ResetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- SetEvent( handle2 ); -- ResetEvent( handle ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- handles[0] = handle2; -- handles[1] = handle; -- SetEvent( handle ); -- SetEvent( handle2 ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = CloseHandle( handle ); -- ok(ret, "got error %lu\n", GetLastError()); -- -- ret = CloseHandle( handle2 ); -- ok(ret, "got error %lu\n", GetLastError()); - } - - static void test_semaphore(void) - { -- HANDLE handle, handle2, handles[2]; -- DWORD ret; -- LONG prev; -- int i; -+ HANDLE handle, handle2; - - /* test case sensitivity */ - -@@ -884,99 +667,6 @@ static void test_semaphore(void) - ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); - - CloseHandle( handle ); -- -- handle = CreateSemaphoreA( NULL, 0, 5, NULL ); -- ok(!!handle, "CreateSemaphore failed: %lu\n", GetLastError()); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 0, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 1, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 5, &prev ); -- ok(!ret, "got %ld\n", ret); -- ok(GetLastError() == ERROR_TOO_MANY_POSTS, "got error %lu\n", GetLastError()); -- ok(prev == 1, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 2, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 2, "got prev %ld\n", prev); -- -- ret = ReleaseSemaphore( handle, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 4, "got prev %ld\n", prev); -- -- for (i = 0; i < 5; i++) -- { -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handle2 = CreateSemaphoreA( NULL, 3, 5, NULL ); -- ok(!!handle2, "CreateSemaphore failed: %lu\n", GetLastError()); -- -- ret = ReleaseSemaphore( handle2, 1, &prev ); -- ok(ret, "got error %lu\n", GetLastError()); -- ok(prev == 3, "got prev %ld\n", prev); -- -- for (i = 0; i < 4; i++) -- { -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- } -- -- ret = WaitForSingleObject( handle2, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- handles[0] = handle; -- handles[1] = handle2; -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- ReleaseSemaphore( handle2, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == 1, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- ReleaseSemaphore( handle2, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForMultipleObjects( 2, handles, FALSE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ReleaseSemaphore( handle, 1, NULL ); -- -- ret = WaitForMultipleObjects( 2, handles, TRUE, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- ret = WaitForSingleObject( handle, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = CloseHandle( handle ); -- ok(ret, "got error %lu\n", ret); -- -- ret = CloseHandle( handle2 ); -- ok(ret, "got error %lu\n", ret); - } - - static void test_waitable_timer(void) -@@ -1531,15 +1221,11 @@ static HANDLE modify_handle(HANDLE handle, DWORD modify) - return ULongToHandle(tmp); - } - --#define TIMEOUT_INFINITE (((LONGLONG)0x7fffffff) << 32 | 0xffffffff) -- - static void test_WaitForSingleObject(void) - { - HANDLE signaled, nonsignaled, invalid; -- LARGE_INTEGER ntnow, ntthen; - LARGE_INTEGER timeout; - NTSTATUS status; -- DWORD now, then; - DWORD ret; - - signaled = CreateEventW(NULL, TRUE, TRUE, NULL); -@@ -1624,68 +1310,6 @@ static void test_WaitForSingleObject(void) - status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); - ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status); - -- ret = WaitForSingleObject( signaled, 0 ); -- ok(ret == 0, "got %lu\n", ret); -- -- ret = WaitForSingleObject( nonsignaled, 0 ); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- -- /* test that a timed wait actually does wait */ -- now = GetTickCount(); -- ret = WaitForSingleObject( nonsignaled, 100 ); -- then = GetTickCount(); -- ok(ret == WAIT_TIMEOUT, "got %lu\n", ret); -- ok(abs((then - now) - 100) < 5, "got %lu ms\n", then - now); -- -- now = GetTickCount(); -- ret = WaitForSingleObject( signaled, 100 ); -- then = GetTickCount(); -- ok(ret == 0, "got %lu\n", ret); -- ok(abs(then - now) < 5, "got %lu ms\n", then - now); -- -- ret = WaitForSingleObject( signaled, INFINITE ); -- ok(ret == 0, "got %lu\n", ret); -- -- /* test NT timeouts */ -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart + 100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs(((ntthen.QuadPart - ntnow.QuadPart) / 10000) - 100) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = -100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs(((ntthen.QuadPart - ntnow.QuadPart) / 10000) - 100) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- status = pNtWaitForSingleObject( signaled, FALSE, NULL ); -- ok(status == 0, "got %#lx\n", status); -- -- timeout.QuadPart = TIMEOUT_INFINITE; -- status = pNtWaitForSingleObject( signaled, FALSE, &timeout ); -- ok(status == 0, "got %#lx\n", status); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs((ntthen.QuadPart - ntnow.QuadPart) / 10000) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- -- pNtQuerySystemTime( &ntnow ); -- timeout.QuadPart = ntnow.QuadPart - 100 * 10000; -- status = pNtWaitForSingleObject( nonsignaled, FALSE, &timeout ); -- pNtQuerySystemTime( &ntthen ); -- ok(status == STATUS_TIMEOUT, "got %#lx\n", status); -- ok(abs((ntthen.QuadPart - ntnow.QuadPart) / 10000) < 5, "got %s ns\n", -- wine_dbgstr_longlong((ntthen.QuadPart - ntnow.QuadPart) * 100)); -- - CloseHandle(signaled); - CloseHandle(nonsignaled); - } -@@ -3351,7 +2975,6 @@ START_TEST(sync) - pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); - pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); - pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); -- pNtQuerySystemTime = (void *)GetProcAddress(hntdll, "NtQuerySystemTime"); - pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); - pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); - pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); -diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in -index 4629457..f71f79b 100644 ---- a/dlls/ntdll/Makefile.in -+++ b/dlls/ntdll/Makefile.in -@@ -48,7 +48,6 @@ SOURCES = \ - unix/cdrom.c \ - unix/debug.c \ - unix/env.c \ -- unix/esync.c \ - unix/file.c \ - unix/loader.c \ - unix/loadorder.c \ -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -deleted file mode 100644 -index edfeb03..0000000 ---- a/dlls/ntdll/unix/esync.c -+++ /dev/null -@@ -1,1325 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#if 0 --#pragma makedep unix --#endif -- --#include "config.h" -- --#ifndef _GNU_SOURCE --#define _GNU_SOURCE --#endif -- --#include --#include --#include --#include --#include --#include --#include --#ifdef HAVE_SYS_STAT_H --# include --#endif --#include --#include --#include -- --#include "ntstatus.h" --#define WIN32_NO_STATUS --#include "windef.h" --#include "winternl.h" --#include "wine/server.h" --#include "wine/debug.h" -- --#include "unix_private.h" --#include "esync.h" -- --WINE_DEFAULT_DEBUG_CHANNEL(esync); -- --int do_esync(void) --{ --#ifdef HAVE_SYS_EVENTFD_H -- static int do_esync_cached = -1; -- -- if (do_esync_cached == -1) -- do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); -- -- return do_esync_cached; --#else -- static int once; -- if (!once++) -- FIXME("eventfd not supported on this platform.\n"); -- return 0; --#endif --} -- --struct esync --{ -- LONG type; -- int fd; -- void *shm; --}; -- --struct semaphore --{ -- LONG max; -- LONG count; --}; --C_ASSERT(sizeof(struct semaphore) == 8); -- --struct mutex --{ -- LONG tid; -- LONG count; /* recursion count */ --}; --C_ASSERT(sizeof(struct mutex) == 8); -- --struct event --{ -- LONG signaled; -- LONG locked; --}; --C_ASSERT(sizeof(struct event) == 8); -- --static char shm_name[29]; --static int shm_fd; --static void **shm_addrs; --static int shm_addrs_size; /* length of the allocated shm_addrs array */ --static long pagesize; -- --static pthread_mutex_t shm_addrs_mutex = PTHREAD_MUTEX_INITIALIZER; -- --static void *get_shm( unsigned int idx ) --{ -- int entry = (idx * 8) / pagesize; -- int offset = (idx * 8) % pagesize; -- void *ret; -- -- pthread_mutex_lock( &shm_addrs_mutex ); -- -- if (entry >= shm_addrs_size) -- { -- int new_size = max(shm_addrs_size * 2, entry + 1); -- -- if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) ))) -- ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_size); -- memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) ); -- shm_addrs_size = new_size; -- } -- -- if (!shm_addrs[entry]) -- { -- void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize ); -- if (addr == (void *)-1) -- ERR("Failed to map page %d (offset %#lx).\n", entry, entry * pagesize); -- -- TRACE("Mapping page %d at %p.\n", entry, addr); -- -- if (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 )) -- munmap( addr, pagesize ); /* someone beat us to it */ -- } -- -- ret = (void *)((unsigned long)shm_addrs[entry] + offset); -- -- pthread_mutex_unlock( &shm_addrs_mutex ); -- -- return ret; --} -- --/* We'd like lookup to be fast. To that end, we use a static list indexed by handle. -- * This is copied and adapted from the fd cache code. */ -- --#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync)) --#define ESYNC_LIST_ENTRIES 256 -- --static struct esync *esync_list[ESYNC_LIST_ENTRIES]; --static struct esync esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE]; -- --static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry ) --{ -- UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1; -- *entry = idx / ESYNC_LIST_BLOCK_SIZE; -- return idx % ESYNC_LIST_BLOCK_SIZE; --} -- --static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, void *shm ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- if (entry >= ESYNC_LIST_ENTRIES) -- { -- FIXME( "too many allocated handles, not caching %p\n", handle ); -- return FALSE; -- } -- -- if (!esync_list[entry]) /* do we need to allocate a new block of entries? */ -- { -- if (!entry) esync_list[0] = esync_list_initial_block; -- else -- { -- void *ptr = anon_mmap_alloc( ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync), -- PROT_READ | PROT_WRITE ); -- if (ptr == MAP_FAILED) return FALSE; -- esync_list[entry] = ptr; -- } -- } -- -- if (!InterlockedCompareExchange( &esync_list[entry][idx].type, type, 0 )) -- { -- esync_list[entry][idx].fd = fd; -- esync_list[entry][idx].shm = shm; -- } -- return &esync_list[entry][idx]; --} -- --static struct esync *get_cached_object( HANDLE handle ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL; -- if (!esync_list[entry][idx].type) return NULL; -- -- return &esync_list[entry][idx]; --} -- --/* Gets an object. This is either a proper esync object (i.e. an event, -- * semaphore, etc. created using create_esync) or a generic synchronizable -- * server-side object which the server will signal (e.g. a process, thread, -- * message queue, etc.) */ --static NTSTATUS get_object( HANDLE handle, struct esync **obj ) --{ -- int ret = STATUS_SUCCESS; -- enum esync_type type = 0; -- unsigned int shm_idx = 0; -- obj_handle_t fd_handle; -- sigset_t sigset; -- int fd = -1; -- -- if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS; -- -- if ((INT_PTR)handle < 0) -- { -- /* We can deal with pseudo-handles, but it's just easier this way */ -- return STATUS_NOT_IMPLEMENTED; -- } -- -- if (!handle) -- { -- /* Shadow of the Tomb Raider really likes passing in NULL handles to -- * various functions. Concerning, but let's avoid a server call. */ -- return STATUS_INVALID_HANDLE; -- } -- -- /* We need to try grabbing it from the server. */ -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- if (!(*obj = get_cached_object( handle ))) -- { -- SERVER_START_REQ( get_esync_fd ) -- { -- req->handle = wine_server_obj_handle( handle ); -- if (!(ret = wine_server_call( req ))) -- { -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == handle ); -- } -- } -- SERVER_END_REQ; -- } -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (*obj) -- { -- /* We managed to grab it while in the CS; return it. */ -- return STATUS_SUCCESS; -- } -- -- if (ret) -- { -- WARN("Failed to retrieve fd for handle %p, status %#x.\n", handle, ret); -- *obj = NULL; -- return ret; -- } -- -- TRACE("Got fd %d for handle %p.\n", fd, handle); -- -- *obj = add_to_list( handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- return ret; --} -- --NTSTATUS esync_close( HANDLE handle ) --{ -- UINT_PTR entry, idx = handle_to_index( handle, &entry ); -- -- TRACE("%p.\n", handle); -- -- if (entry < ESYNC_LIST_ENTRIES && esync_list[entry]) -- { -- if (InterlockedExchange(&esync_list[entry][idx].type, 0)) -- { -- close( esync_list[entry][idx].fd ); -- return STATUS_SUCCESS; -- } -- } -- -- return STATUS_INVALID_HANDLE; --} -- --static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initval, int max ) --{ -- NTSTATUS ret; -- data_size_t len; -- struct object_attributes *objattr; -- obj_handle_t fd_handle; -- unsigned int shm_idx; -- sigset_t sigset; -- int fd; -- -- if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -- -- /* We have to synchronize on the fd cache CS so that our calls to -- * receive_fd don't race with theirs. */ -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( create_esync ) -- { -- req->access = access; -- req->initval = initval; -- req->type = type; -- req->max = max; -- wine_server_add_data( req, objattr, len ); -- ret = wine_server_call( req ); -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -- { -- *handle = wine_server_ptr_handle( reply->handle ); -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == *handle ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -- { -- add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- TRACE("-> handle %p, fd %d.\n", *handle, fd); -- } -- -- free( objattr ); -- return ret; --} -- --static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) --{ -- NTSTATUS ret; -- obj_handle_t fd_handle; -- unsigned int shm_idx; -- sigset_t sigset; -- int fd; -- -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( open_esync ) -- { -- req->access = access; -- req->attributes = attr->Attributes; -- req->rootdir = wine_server_obj_handle( attr->RootDirectory ); -- req->type = type; -- if (attr->ObjectName) -- wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); -- if (!(ret = wine_server_call( req ))) -- { -- *handle = wine_server_ptr_handle( reply->handle ); -- type = reply->type; -- shm_idx = reply->shm_idx; -- fd = receive_fd( &fd_handle ); -- assert( wine_server_ptr_handle(fd_handle) == *handle ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- if (!ret) -- { -- add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); -- -- TRACE("-> handle %p, fd %d.\n", *handle, fd); -- } -- return ret; --} -- --extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initial, int max) --{ -- TRACE("name %s, initial %d, max %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", initial, max); -- -- return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max ); --} -- --NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); --} -- --NTSTATUS esync_release_semaphore( HANDLE handle, unsigned int count, ULONG *prev ) --{ -- struct esync *obj; -- struct semaphore *semaphore; -- uint64_t count64 = count; -- ULONG current; -- NTSTATUS ret; -- -- TRACE("%p, %d, %p.\n", handle, count, prev); -- -- if ((ret = get_object( handle, &obj))) return ret; -- semaphore = obj->shm; -- -- do -- { -- current = semaphore->count; -- -- if (count + current > semaphore->max) -- return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -- } while (InterlockedCompareExchange( &semaphore->count, count + current, current ) != current); -- -- if (prev) *prev = current; -- -- /* We don't have to worry about a race between increasing the count and -- * write(). The fact that we were able to increase the count means that we -- * have permission to actually write that many releases to the semaphore. */ -- -- if (write( obj->fd, &count64, sizeof(count64) ) == -1) -- return errno_to_status( errno ); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_semaphore( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- struct semaphore *semaphore; -- SEMAPHORE_BASIC_INFORMATION *out = info; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- semaphore = obj->shm; -- -- out->CurrentCount = semaphore->count; -- out->MaximumCount = semaphore->max; -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, EVENT_TYPE event_type, BOOLEAN initial ) --{ -- enum esync_type type = (event_type == SynchronizationEvent ? ESYNC_AUTO_EVENT : ESYNC_MANUAL_EVENT); -- -- TRACE("name %s, %s-reset, initial %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", -- event_type == NotificationEvent ? "manual" : "auto", initial); -- -- return create_esync( type, handle, access, attr, initial, 0 ); --} -- --NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ --} -- --static inline void small_pause(void) --{ --#ifdef __i386__ -- __asm__ __volatile__( "rep;nop" : : : "memory" ); --#else -- __asm__ __volatile__( "" : : : "memory" ); --#endif --} -- --/* Manual-reset events are actually racier than other objects in terms of shm -- * state. With other objects, races don't matter, because we only treat the shm -- * state as a hint that lets us skip poll()—we still have to read(). But with -- * manual-reset events we don't, which means that the shm state can be out of -- * sync with the actual state. -- * -- * In general we shouldn't have to worry about races between modifying the -- * event and waiting on it. If the state changes while we're waiting, it's -- * equally plausible that we caught it before or after the state changed. -- * However, we can have races between SetEvent() and ResetEvent(), so that the -- * event has inconsistent internal state. -- * -- * To solve this we have to use the other field to lock the event. Currently -- * this is implemented as a spinlock, but I'm not sure if a futex might be -- * better. I'm also not sure if it's possible to obviate locking by arranging -- * writes and reads in a certain way. -- * -- * Note that we don't have to worry about locking in esync_wait_objects(). -- * There's only two general patterns: -- * -- * WaitFor() SetEvent() -- * ------------------------- -- * read() -- * signaled = 0 -- * signaled = 1 -- * write() -- * ------------------------- -- * read() -- * signaled = 1 -- * signaled = 0 -- * -- * ------------------------- -- * -- * That is, if SetEvent() tries to signal the event before WaitFor() resets its -- * signaled state, it won't bother trying to write(), and then the signaled -- * state will be reset, so the result is a consistent non-signaled event. -- * There's several variations to this pattern but all of them are protected in -- * the same way. Note however this is why we have to use interlocked_xchg() -- * event inside of the lock. -- */ -- --/* Removing this spinlock is harder than it looks. esync_wait_objects() can -- * deal with inconsistent state well enough, and a race between SetEvent() and -- * ResetEvent() gives us license to yield either result as long as we act -- * consistently, but that's not enough. Notably, esync_wait_objects() should -- * probably act like a fence, so that the second half of esync_set_event() does -- * not seep past a subsequent reset. That's one problem, but no guarantee there -- * aren't others. */ -- --NTSTATUS esync_set_event( HANDLE handle ) --{ -- static const uint64_t value = 1; -- struct esync *obj; -- struct event *event; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- event = obj->shm; -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -- } -- -- /* For manual-reset events, as long as we're in a lock, we can take the -- * optimization of only calling write() if the event wasn't already -- * signaled. -- * -- * For auto-reset events, esync_wait_objects() must grab the kernel object. -- * Thus if we got into a race so that the shm state is signaled but the -- * eventfd is unsignaled (i.e. reset shm, set shm, set fd, reset fd), we -- * *must* signal the fd now, or any waiting threads will never wake up. */ -- -- if (!InterlockedExchange( &event->signaled, 1 ) || obj->type == ESYNC_AUTO_EVENT) -- { -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- ERR("write: %s\n", strerror(errno)); -- } -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_reset_event( HANDLE handle ) --{ -- uint64_t value; -- struct esync *obj; -- struct event *event; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- event = obj->shm; -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -- } -- -- /* For manual-reset events, as long as we're in a lock, we can take the -- * optimization of only calling read() if the event was already signaled. -- * -- * For auto-reset events, we have no guarantee that the previous "signaled" -- * state is actually correct. We need to leave both states unsignaled after -- * leaving this function, so we always have to read(). */ -- if (InterlockedExchange( &event->signaled, 0 ) || obj->type == ESYNC_AUTO_EVENT) -- { -- if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) -- { -- ERR("read: %s\n", strerror(errno)); -- } -- } -- -- if (obj->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_pulse_event( HANDLE handle ) --{ -- uint64_t value = 1; -- struct esync *obj; -- NTSTATUS ret; -- -- TRACE("%p.\n", handle); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- -- /* This isn't really correct; an application could miss the write. -- * Unfortunately we can't really do much better. Fortunately this is rarely -- * used (and publicly deprecated). */ -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return errno_to_status( errno ); -- -- /* Try to give other threads a chance to wake up. Hopefully erring on this -- * side is the better thing to do... */ -- NtYieldExecution(); -- -- read( obj->fd, &value, sizeof(value) ); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- EVENT_BASIC_INFORMATION *out = info; -- struct pollfd fd; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- -- fd.fd = obj->fd; -- fd.events = POLLIN; -- out->EventState = poll( &fd, 1, 0 ); -- out->EventType = (obj->type == ESYNC_AUTO_EVENT ? SynchronizationEvent : NotificationEvent); -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) --{ -- TRACE("name %s, initial %d.\n", -- attr ? debugstr_us(attr->ObjectName) : "", initial); -- -- return create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); --} -- --NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ) --{ -- TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -- -- return open_esync( ESYNC_MUTEX, handle, access, attr ); --} -- --NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) --{ -- struct esync *obj; -- struct mutex *mutex; -- static const uint64_t value = 1; -- NTSTATUS ret; -- -- TRACE("%p, %p.\n", handle, prev); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- mutex = obj->shm; -- -- /* This is thread-safe, because the only thread that can change the tid to -- * or from our tid is ours. */ -- if (mutex->tid != GetCurrentThreadId()) return STATUS_MUTANT_NOT_OWNED; -- -- if (prev) *prev = mutex->count; -- -- mutex->count--; -- -- if (!mutex->count) -- { -- /* This is also thread-safe, as long as signaling the file is the last -- * thing we do. Other threads don't care about the tid if it isn't -- * theirs. */ -- mutex->tid = 0; -- -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return errno_to_status( errno ); -- } -- -- return STATUS_SUCCESS; --} -- --NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ) --{ -- struct esync *obj; -- struct mutex *mutex; -- MUTANT_BASIC_INFORMATION *out = info; -- NTSTATUS ret; -- -- TRACE("handle %p, info %p, ret_len %p.\n", handle, info, ret_len); -- -- if ((ret = get_object( handle, &obj ))) return ret; -- mutex = obj->shm; -- -- out->CurrentCount = 1 - mutex->count; -- out->OwnedByCaller = (mutex->tid == GetCurrentThreadId()); -- out->AbandonedState = (mutex->tid == ~0); -- if (ret_len) *ret_len = sizeof(*out); -- -- return STATUS_SUCCESS; --} -- --#define TICKSPERSEC 10000000 --#define TICKSPERMSEC 10000 -- --static LONGLONG update_timeout( ULONGLONG end ) --{ -- LARGE_INTEGER now; -- LONGLONG timeleft; -- -- NtQuerySystemTime( &now ); -- timeleft = end - now.QuadPart; -- if (timeleft < 0) timeleft = 0; -- return timeleft; --} -- --static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) --{ -- int ret; -- -- do -- { -- if (end) -- { -- LONGLONG timeleft = update_timeout( *end ); -- --#ifdef HAVE_PPOLL -- /* We use ppoll() if available since the time granularity is better. */ -- struct timespec tmo_p; -- tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC; -- tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100; -- ret = ppoll( fds, nfds, &tmo_p, NULL ); --#else -- ret = poll( fds, nfds, timeleft / TICKSPERMSEC ); --#endif -- } -- else -- ret = poll( fds, nfds, -1 ); -- -- /* If we receive EINTR we were probably suspended (SIGUSR1), possibly for a -- * system APC. The right thing to do is just try again. */ -- } while (ret < 0 && errno == EINTR); -- -- return ret; --} -- --/* Return TRUE if abandoned. */ --static BOOL update_grabbed_object( struct esync *obj ) --{ -- BOOL ret = FALSE; -- -- if (obj->type == ESYNC_MUTEX) -- { -- struct mutex *mutex = obj->shm; -- /* We don't have to worry about a race between this and read(); the -- * fact that we grabbed it means the count is now zero, so nobody else -- * can (and the only thread that can release it is us). */ -- if (mutex->tid == ~0) -- ret = TRUE; -- mutex->tid = GetCurrentThreadId(); -- mutex->count++; -- } -- else if (obj->type == ESYNC_SEMAPHORE) -- { -- struct semaphore *semaphore = obj->shm; -- /* We don't have to worry about a race between this and read(); the -- * fact that we were able to grab it at all means the count is nonzero, -- * and if someone else grabbed it then the count must have been >= 2, -- * etc. */ -- InterlockedExchangeAdd( &semaphore->count, -1 ); -- } -- else if (obj->type == ESYNC_AUTO_EVENT) -- { -- struct event *event = obj->shm; -- /* We don't have to worry about a race between this and read(), since -- * this is just a hint, and the real state is in the kernel object. -- * This might already be 0, but that's okay! */ -- event->signaled = 0; -- } -- -- return ret; --} -- --/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we -- * need to delegate to server_select(). */ --static NTSTATUS __esync_wait_objects( unsigned int count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ) --{ -- static const LARGE_INTEGER zero; -- -- struct esync *objs[MAXIMUM_WAIT_OBJECTS]; -- struct pollfd fds[MAXIMUM_WAIT_OBJECTS + 1]; -- int has_esync = 0, has_server = 0; -- BOOL msgwait = FALSE; -- LONGLONG timeleft; -- LARGE_INTEGER now; -- DWORD pollcount; -- ULONGLONG end; -- int64_t value; -- ssize_t size; -- int i, j, ret; -- -- /* Grab the APC fd if we don't already have it. */ -- if (alertable && ntdll_get_thread_data()->esync_apc_fd == -1) -- { -- obj_handle_t fd_handle; -- sigset_t sigset; -- int fd = -1; -- -- server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -- SERVER_START_REQ( get_esync_apc_fd ) -- { -- if (!(ret = wine_server_call( req ))) -- { -- fd = receive_fd( &fd_handle ); -- assert( fd_handle == GetCurrentThreadId() ); -- } -- } -- SERVER_END_REQ; -- server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -- -- ntdll_get_thread_data()->esync_apc_fd = fd; -- } -- -- NtQuerySystemTime( &now ); -- if (timeout) -- { -- if (timeout->QuadPart == TIMEOUT_INFINITE) -- timeout = NULL; -- else if (timeout->QuadPart >= 0) -- end = timeout->QuadPart; -- else -- end = now.QuadPart - timeout->QuadPart; -- } -- -- for (i = 0; i < count; i++) -- { -- ret = get_object( handles[i], &objs[i] ); -- if (ret == STATUS_SUCCESS) -- has_esync = 1; -- else if (ret == STATUS_NOT_IMPLEMENTED) -- has_server = 1; -- else -- return ret; -- } -- -- if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE) -- msgwait = TRUE; -- -- if (has_esync && has_server) -- FIXME("Can't wait on esync and server objects at the same time!\n"); -- else if (has_server) -- return STATUS_NOT_IMPLEMENTED; -- -- if (TRACE_ON(esync)) -- { -- TRACE("Waiting for %s of %d handles:", wait_any ? "any" : "all", count); -- for (i = 0; i < count; i++) -- TRACE(" %p", handles[i]); -- -- if (msgwait) -- TRACE(" or driver events"); -- if (alertable) -- TRACE(", alertable"); -- -- if (!timeout) -- TRACE(", timeout = INFINITE.\n"); -- else -- { -- timeleft = update_timeout( end ); -- TRACE(", timeout = %ld.%07ld sec.\n", -- (long) timeleft / TICKSPERSEC, (long) timeleft % TICKSPERSEC); -- } -- } -- -- if (wait_any || count == 1) -- { -- /* Try to check objects now, so we can obviate poll() at least. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- if (obj) -- { -- switch (obj->type) -- { -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = obj->shm; -- -- if (mutex->tid == GetCurrentThreadId()) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- mutex->count++; -- return i; -- } -- else if (!mutex->count) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- if (mutex->tid == ~0) -- { -- TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i); -- i += STATUS_ABANDONED_WAIT_0; -- } -- else -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- mutex->tid = GetCurrentThreadId(); -- mutex->count++; -- return i; -- } -- } -- break; -- } -- case ESYNC_SEMAPHORE: -- { -- struct semaphore *semaphore = obj->shm; -- -- if (semaphore->count) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- InterlockedDecrement( &semaphore->count ); -- return i; -- } -- } -- break; -- } -- case ESYNC_AUTO_EVENT: -- { -- struct event *event = obj->shm; -- -- if (event->signaled) -- { -- if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- event->signaled = 0; -- return i; -- } -- } -- break; -- } -- case ESYNC_MANUAL_EVENT: -- { -- struct event *event = obj->shm; -- -- if (event->signaled) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- return i; -- } -- break; -- } -- case ESYNC_AUTO_SERVER: -- case ESYNC_MANUAL_SERVER: -- case ESYNC_QUEUE: -- /* We can't wait on any of these. Fortunately I don't think -- * they'll ever be uncontended anyway (at least, they won't be -- * performance-critical). */ -- break; -- } -- } -- -- fds[i].fd = obj ? obj->fd : -1; -- fds[i].events = POLLIN; -- } -- if (alertable) -- { -- fds[i].fd = ntdll_get_thread_data()->esync_apc_fd; -- fds[i].events = POLLIN; -- i++; -- } -- pollcount = i; -- -- while (1) -- { -- ret = do_poll( fds, pollcount, timeout ? &end : NULL ); -- if (ret > 0) -- { -- /* We must check this first! The server may set an event that -- * we're waiting on, but we need to return STATUS_USER_APC. */ -- if (alertable) -- { -- if (fds[pollcount - 1].revents & POLLIN) -- goto userapc; -- } -- -- /* Find out which object triggered the wait. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) -- { -- ERR("Polling on fd %d returned %#x.\n", fds[i].fd, fds[i].revents); -- return STATUS_INVALID_HANDLE; -- } -- -- if (obj) -- { -- if (obj->type == ESYNC_MANUAL_EVENT -- || obj->type == ESYNC_MANUAL_SERVER -- || obj->type == ESYNC_QUEUE) -- { -- /* Don't grab the object, just check if it's signaled. */ -- if (fds[i].revents & POLLIN) -- { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- return i; -- } -- } -- else -- { -- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value)) -- { -- /* We found our object. */ -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- if (update_grabbed_object( obj )) -- return STATUS_ABANDONED_WAIT_0 + i; -- return i; -- } -- } -- } -- } -- -- /* If we got here, someone else stole (or reset, etc.) whatever -- * we were waiting for. So keep waiting. */ -- NtQuerySystemTime( &now ); -- } -- else -- goto err; -- } -- } -- else -- { -- /* Wait-all is a little trickier to implement correctly. Fortunately, -- * it's not as common. -- * -- * The idea is basically just to wait in sequence on every object in the -- * set. Then when we're done, try to grab them all in a tight loop. If -- * that fails, release any resources we've grabbed (and yes, we can -- * reliably do this—it's just mutexes and semaphores that we have to -- * put back, and in both cases we just put back 1), and if any of that -- * fails we start over. -- * -- * What makes this inherently bad is that we might temporarily grab a -- * resource incorrectly. Hopefully it'll be quick (and hey, it won't -- * block on wineserver) so nobody will notice. Besides, consider: if -- * object A becomes signaled but someone grabs it before we can grab it -- * and everything else, then they could just as well have grabbed it -- * before it became signaled. Similarly if object A was signaled and we -- * were blocking on object B, then B becomes available and someone grabs -- * A before we can, then they might have grabbed A before B became -- * signaled. In either case anyone who tries to wait on A or B will be -- * waiting for an instant while we put things back. */ -- -- while (1) -- { --tryagain: -- /* First step: try to poll on each object in sequence. */ -- fds[0].events = POLLIN; -- pollcount = 1; -- if (alertable) -- { -- /* We also need to wait on APCs. */ -- fds[1].fd = ntdll_get_thread_data()->esync_apc_fd; -- fds[1].events = POLLIN; -- pollcount++; -- } -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- fds[0].fd = obj ? obj->fd : -1; -- -- if (obj && obj->type == ESYNC_MUTEX) -- { -- /* It might be ours. */ -- struct mutex *mutex = obj->shm; -- -- if (mutex->tid == GetCurrentThreadId()) -- continue; -- } -- -- ret = do_poll( fds, pollcount, timeout ? &end : NULL ); -- if (ret <= 0) -- goto err; -- else if (alertable && (fds[1].revents & POLLIN)) -- goto userapc; -- -- if (fds[0].revents & (POLLHUP | POLLERR | POLLNVAL)) -- { -- ERR("Polling on fd %d returned %#x.\n", fds[0].fd, fds[0].revents); -- return STATUS_INVALID_HANDLE; -- } -- } -- -- /* If we got here and we haven't timed out, that means all of the -- * handles were signaled. Check to make sure they still are. */ -- for (i = 0; i < count; i++) -- { -- fds[i].fd = objs[i] ? objs[i]->fd : -1; -- fds[i].events = POLLIN; -- } -- /* There's no reason to check for APCs here. */ -- pollcount = i; -- -- /* Poll everything to see if they're still signaled. */ -- ret = poll( fds, pollcount, 0 ); -- if (ret == pollcount) -- { -- BOOL abandoned = FALSE; -- -- /* Quick, grab everything. */ -- for (i = 0; i < count; i++) -- { -- struct esync *obj = objs[i]; -- -- switch (obj->type) -- { -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = obj->shm; -- if (mutex->tid == GetCurrentThreadId()) -- break; -- /* otherwise fall through */ -- } -- case ESYNC_SEMAPHORE: -- case ESYNC_AUTO_EVENT: -- if ((size = read( fds[i].fd, &value, sizeof(value) )) != sizeof(value)) -- { -- /* We were too slow. Put everything back. */ -- value = 1; -- for (j = i; j >= 0; j--) -- { -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return errno_to_status( errno ); -- } -- -- goto tryagain; /* break out of two loops and a switch */ -- } -- break; -- default: -- /* If a manual-reset event changed between there and -- * here, it's shouldn't be a problem. */ -- break; -- } -- } -- -- /* If we got here, we successfully waited on every object. */ -- /* Make sure to let ourselves know that we grabbed the mutexes -- * and semaphores. */ -- for (i = 0; i < count; i++) -- abandoned |= update_grabbed_object( objs[i] ); -- -- if (abandoned) -- { -- TRACE("Wait successful, but some object(s) were abandoned.\n"); -- return STATUS_ABANDONED; -- } -- TRACE("Wait successful.\n"); -- return STATUS_SUCCESS; -- } -- -- /* If we got here, ppoll() returned less than all of our objects. -- * So loop back to the beginning and try again. */ -- } /* while(1) */ -- } /* else (wait-all) */ -- --err: -- /* We should only get here if poll() failed. */ -- -- if (ret == 0) -- { -- TRACE("Wait timed out.\n"); -- return STATUS_TIMEOUT; -- } -- else -- { -- ERR("ppoll failed: %s\n", strerror(errno)); -- return errno_to_status( errno ); -- } -- --userapc: -- TRACE("Woken up by user APC.\n"); -- -- /* We have to make a server call anyway to get the APC to execute, so just -- * delegate down to server_select(). */ -- ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &zero ); -- -- /* This can happen if we received a system APC, and the APC fd was woken up -- * before we got SIGUSR1. poll() doesn't return EINTR in that case. The -- * right thing to do seems to be to return STATUS_USER_APC anyway. */ -- if (ret == STATUS_TIMEOUT) ret = STATUS_USER_APC; -- return ret; --} -- --/* We need to let the server know when we are doing a message wait, and when we -- * are done with one, so that all of the code surrounding hung queues works. -- * We also need this for WaitForInputIdle(). */ --static void server_set_msgwait( int in_msgwait ) --{ -- SERVER_START_REQ( esync_msgwait ) -- { -- req->in_msgwait = in_msgwait; -- wine_server_call( req ); -- } -- SERVER_END_REQ; --} -- --/* This is a very thin wrapper around the proper implementation above. The -- * purpose is to make sure the server knows when we are doing a message wait. -- * This is separated into a wrapper function since there are at least a dozen -- * exit paths from esync_wait_objects(). */ --NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ) --{ -- BOOL msgwait = FALSE; -- struct esync *obj; -- NTSTATUS ret; -- -- if (count && !get_object( handles[count - 1], &obj ) && obj->type == ESYNC_QUEUE) -- { -- msgwait = TRUE; -- server_set_msgwait( 1 ); -- } -- -- ret = __esync_wait_objects( count, handles, wait_any, alertable, timeout ); -- -- if (msgwait) -- server_set_msgwait( 0 ); -- -- return ret; --} -- --NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -- const LARGE_INTEGER *timeout ) --{ -- struct esync *obj; -- NTSTATUS ret; -- -- if ((ret = get_object( signal, &obj ))) return ret; -- -- switch (obj->type) -- { -- case ESYNC_SEMAPHORE: -- ret = esync_release_semaphore( signal, 1, NULL ); -- break; -- case ESYNC_AUTO_EVENT: -- case ESYNC_MANUAL_EVENT: -- ret = esync_set_event( signal ); -- break; -- case ESYNC_MUTEX: -- ret = esync_release_mutex( signal, NULL ); -- break; -- default: -- return STATUS_OBJECT_TYPE_MISMATCH; -- } -- if (ret) return ret; -- -- return esync_wait_objects( 1, &wait, TRUE, alertable, timeout ); --} -- --void esync_init(void) --{ -- struct stat st; -- -- if (!do_esync()) -- { -- /* make sure the server isn't running with WINEESYNC */ -- HANDLE handle; -- NTSTATUS ret; -- -- ret = create_esync( 0, &handle, 0, NULL, 0, 0 ); -- if (ret != STATUS_NOT_IMPLEMENTED) -- { -- ERR("Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.\n"); -- exit(1); -- } -- -- return; -- } -- -- if (stat( config_dir, &st ) == -1) -- ERR("Cannot stat %s\n", config_dir); -- -- if (st.st_ino != (unsigned long)st.st_ino) -- sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino ); -- else -- sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino ); -- -- if ((shm_fd = shm_open( shm_name, O_RDWR, 0644 )) == -1) -- { -- /* probably the server isn't running with WINEESYNC, tell the user and bail */ -- if (errno == ENOENT) -- ERR("Failed to open esync shared memory file; make sure no stale wineserver instances are running without WINEESYNC.\n"); -- else -- ERR("Failed to initialize shared memory: %s\n", strerror( errno )); -- exit(1); -- } -- -- pagesize = sysconf( _SC_PAGESIZE ); -- -- shm_addrs = calloc( 128, sizeof(shm_addrs[0]) ); -- shm_addrs_size = 128; --} -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -deleted file mode 100644 -index 59f8809..0000000 ---- a/dlls/ntdll/unix/esync.h -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --extern int do_esync(void); --extern void esync_init(void); --extern NTSTATUS esync_close( HANDLE handle ); -- --extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initial, int max); --extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_query_semaphore( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_release_semaphore( HANDLE handle, unsigned int count, ULONG *prev ); -- --extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ); --extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_pulse_event( HANDLE handle ); --extern NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_reset_event( HANDLE handle ); --extern NTSTATUS esync_set_event( HANDLE handle ); -- --extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ); --extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr ); --extern NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ); --extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ); -- --extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ); --extern NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -- const LARGE_INTEGER *timeout ); -- -- --/* We have to synchronize on the fd cache mutex so that our calls to receive_fd -- * don't race with theirs. It looks weird, I know. -- * -- * If we weren't trying to avoid touching the code I'd rename the mutex to -- * "server_fd_mutex" or something similar. */ --extern pthread_mutex_t fd_cache_mutex; -- --extern int receive_fd( obj_handle_t *handle ); -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 2bfb9b7..81564d7 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -7507,7 +7507,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void - } - if (handle) - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - NtClose( handle ); - } - else /* Unix lock conflict, sleep a bit and retry */ -diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index 50d9e27..f163492 100644 ---- a/dlls/ntdll/unix/loader.c -+++ b/dlls/ntdll/unix/loader.c -@@ -88,7 +88,6 @@ extern char **environ; - #include "winioctl.h" - #include "winternl.h" - #include "unix_private.h" --#include "esync.h" - #include "wine/list.h" - #include "ntsyscalls.h" - #include "wine/debug.h" -@@ -1853,7 +1852,6 @@ static void start_main_thread(void) - signal_alloc_thread( teb ); - dbg_init(); - startup_info_size = server_init_process(); -- esync_init(); - virtual_map_user_shared_data(); - init_cpu_info(); - init_files(); -diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c -index 3591a3e..b744517 100644 ---- a/dlls/ntdll/unix/process.c -+++ b/dlls/ntdll/unix/process.c -@@ -921,7 +921,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ - - /* wait for the new process info to be ready */ - -- NtWaitForSingleObject( process_info, FALSE, NULL ); -+ server_wait_for_object( process_info, FALSE, NULL ); - SERVER_START_REQ( get_new_process_info ) - { - req->info = wine_server_obj_handle( process_info ); -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index 0d4b320..dba7645 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -83,7 +83,6 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" --#include "esync.h" - #include "ddk/wdm.h" - - WINE_DEFAULT_DEBUG_CHANNEL(server); -@@ -814,6 +813,21 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f - } - - -+/* helper function to perform a server-side wait on an internal handle without -+ * using the fast synchronization path */ -+unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ) -+{ -+ union select_op select_op; -+ UINT flags = SELECT_INTERRUPTIBLE; -+ -+ if (alertable) flags |= SELECT_ALERTABLE; -+ -+ select_op.wait.op = SELECT_WAIT; -+ select_op.wait.handles[0] = wine_server_obj_handle( handle ); -+ return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); -+} -+ -+ - /*********************************************************************** - * NtContinue (NTDLL.@) - */ -@@ -875,7 +889,7 @@ unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, a - } - else - { -- NtWaitForSingleObject( handle, FALSE, NULL ); -+ server_wait_for_object( handle, FALSE, NULL ); - - SERVER_START_REQ( get_apc_result ) - { -@@ -947,7 +961,7 @@ void wine_server_send_fd( int fd ) - * - * Receive a file descriptor passed from the server. - */ --int receive_fd( obj_handle_t *handle ) -+static int receive_fd( obj_handle_t *handle ) - { - struct iovec vec; - struct msghdr msghdr; -@@ -1826,12 +1840,17 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE - return result.dup_handle.status; - } - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - if (options & DUPLICATE_CLOSE_SOURCE) -+ { - fd = remove_fd_from_cache( source ); -+ close_inproc_sync_obj( source ); -+ } - - SERVER_START_REQ( dup_handle ) - { -@@ -1897,14 +1916,15 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) - if (HandleToLong( handle ) >= ~5 && HandleToLong( handle ) <= ~0) - return STATUS_SUCCESS; - -+ /* hold fd_cache_mutex to prevent the fd from being added again between the -+ * call to remove_fd_from_cache and close_handle */ - server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); - - /* always remove the cached fd; if the server request fails we'll just - * retrieve it again */ - fd = remove_fd_from_cache( handle ); - -- if (do_esync()) -- esync_close( handle ); -+ close_inproc_sync_obj( handle ); - - SERVER_START_REQ( close_handle ) - { -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 1072265..a9a0a2c 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -30,9 +30,11 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #ifdef HAVE_SYS_SYSCALL_H - #include -@@ -45,6 +47,7 @@ - #endif - #include - #include -+#include - #include - #include - #include -@@ -54,6 +57,9 @@ - #ifdef HAVE_KQUEUE - # include - #endif -+#ifdef HAVE_LINUX_NTSYNC_H -+# include -+#endif - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -63,7 +69,6 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" --#include "esync.h" - - WINE_DEFAULT_DEBUG_CHANNEL(sync); - -@@ -72,9 +77,11 @@ HANDLE keyed_event = 0; - static const char *debugstr_timeout( const LARGE_INTEGER *timeout ) - { - if (!timeout) return "(infinite)"; -- return wine_dbgstr_longlong( timeout->QuadPart ); -+ return wine_dbg_sprintf( "%lld.%07ld", (long long)(timeout->QuadPart / TICKSPERSEC), -+ (long)(timeout->QuadPart % TICKSPERSEC) ); - } - -+ - /* return a monotonic time counter, in Win32 ticks */ - static inline ULONGLONG monotonic_counter(void) - { -@@ -301,6 +309,901 @@ - } - - -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+static int get_linux_sync_device(void) -+{ -+ static LONG device = -2; -+ -+ if (device == -2) -+ { -+ HANDLE handle; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ SERVER_START_REQ( get_linux_sync_device ) -+ { -+ if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if (!ret) -+ { -+ if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) -+ { -+ if (InterlockedCompareExchange( &device, fd, -2 ) != -2) -+ { -+ /* someone beat us to it */ -+ if (needs_close) close( fd ); -+ NtClose( handle ); -+ } -+ /* otherwise don't close the device */ -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ NtClose( handle ); -+ } -+ } -+ else -+ { -+ InterlockedCompareExchange( &device, -1, -2 ); -+ } -+ } -+ return device; -+} -+ -+/* It's possible for synchronization primitives to remain alive even after being -+ * closed, because a thread is still waiting on them. It's rare in practice, and -+ * documented as being undefined behaviour by Microsoft, but it works, and some -+ * applications rely on it. This means we need to refcount handles, and defer -+ * deleting them on the server side until the refcount reaches zero. We do this -+ * by having each client process hold a handle to the in-process synchronization -+ * object, as well as a private refcount. When the client refcount reaches zero, -+ * it closes the handle; when all handles are closed, the server deletes the -+ * in-process synchronization object. -+ * -+ * We also need this for signal-and-wait. The signal and wait operations aren't -+ * atomic, but we can't perform the signal and then return STATUS_INVALID_HANDLE -+ * for the wait—we need to either do both operations or neither. That means we -+ * need to grab references to both objects, and prevent them from being -+ * destroyed before we're done with them. -+ * -+ * We want lookup of objects from the cache to be very fast; ideally, it should -+ * be lock-free. We achieve this by using atomic modifications to "refcount", -+ * and guaranteeing that all other fields are valid and correct *as long as* -+ * refcount is nonzero, and we store the entire structure in memory which will -+ * never be freed. -+ * -+ * This means that acquiring the object can't use a simple atomic increment; it -+ * has to use a compare-and-swap loop to ensure that it doesn't try to increment -+ * an object with a zero refcount. That's still leagues better than a real lock, -+ * though, and release can be a single atomic decrement. -+ * -+ * It also means that threads modifying the cache need to take a lock, to -+ * prevent other threads from writing to it concurrently. -+ * -+ * It's possible for an object currently in use (by a waiter) to be closed and -+ * the same handle immediately reallocated to a different object. This should be -+ * a very rare situation, and in that case we simply don't cache the handle. -+ */ -+struct inproc_sync_cache_entry -+{ -+ LONG refcount; -+ int fd; -+ enum inproc_sync_type type; -+ unsigned int access; -+ BOOL closed; -+ /* handle to the underlying in-process sync object, stored as obj_handle_t -+ * to save space */ -+ obj_handle_t handle; -+}; -+ -+ -+static void release_inproc_sync_obj( struct inproc_sync_cache_entry *cache ) -+{ -+ /* save the handle and fd now; as soon as the refcount hits 0 we cannot -+ * access the cache anymore */ -+ HANDLE handle = wine_server_ptr_handle( cache->handle ); -+ int fd = cache->fd; -+ LONG refcount = InterlockedDecrement( &cache->refcount ); -+ -+ assert( refcount >= 0 ); -+ -+ if (!refcount) -+ { -+ NTSTATUS ret; -+ -+ /* we can't call NtClose here as we may be inside fd_cache_mutex */ -+ SERVER_START_REQ( close_handle ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ ret = wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+ -+ assert( !ret ); -+ close( fd ); -+ } -+} -+ -+ -+#define INPROC_SYNC_CACHE_BLOCK_SIZE (65536 / sizeof(struct inproc_sync_cache_entry)) -+#define INPROC_SYNC_CACHE_ENTRIES 128 -+ -+static struct inproc_sync_cache_entry *inproc_sync_cache[INPROC_SYNC_CACHE_ENTRIES]; -+static struct inproc_sync_cache_entry inproc_sync_cache_initial_block[INPROC_SYNC_CACHE_BLOCK_SIZE]; -+ -+static inline unsigned int inproc_sync_handle_to_index( HANDLE handle, unsigned int *entry ) -+{ -+ unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1; -+ *entry = idx / INPROC_SYNC_CACHE_BLOCK_SIZE; -+ return idx % INPROC_SYNC_CACHE_BLOCK_SIZE; -+} -+ -+ -+static struct inproc_sync_cache_entry *cache_inproc_sync_obj( HANDLE handle, obj_handle_t inproc_sync, int fd, -+ enum inproc_sync_type type, unsigned int access ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ sigset_t sigset; -+ int refcount; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES) -+ { -+ FIXME( "too many allocated handles, not caching %p\n", handle ); -+ return NULL; -+ } -+ -+ if (!inproc_sync_cache[entry]) /* do we need to allocate a new block of entries? */ -+ { -+ if (!entry) inproc_sync_cache[0] = inproc_sync_cache_initial_block; -+ else -+ { -+ static const size_t size = INPROC_SYNC_CACHE_BLOCK_SIZE * sizeof(struct inproc_sync_cache_entry); -+ void *ptr = anon_mmap_alloc( size, PROT_READ | PROT_WRITE ); -+ if (ptr == MAP_FAILED) return NULL; -+ if (InterlockedCompareExchangePointer( (void **)&inproc_sync_cache[entry], ptr, NULL )) -+ munmap( ptr, size ); /* someone beat us to it */ -+ } -+ } -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* Hold fd_cache_mutex instead of a separate mutex, to prevent the same -+ * race between this function and NtClose. That is, prevent the object from -+ * being cached again between close_inproc_sync_obj() and close_handle. */ -+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ if (InterlockedCompareExchange( &cache->refcount, 0, 0 )) -+ { -+ /* We lost the race with another thread trying to cache this object, or -+ * the handle is currently being used for another object (i.e. it was -+ * closed and then reused). We have no way of knowing which, and in the -+ * latter case we can't cache this object until the old one is -+ * completely destroyed, so always return failure. */ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ return NULL; -+ } -+ -+ cache->handle = inproc_sync; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ /* Make sure we set the other members before the refcount; this store needs -+ * release semantics [paired with the load in get_cached_inproc_sync_obj()]. -+ * Set the refcount to 2 (one for the handle, one for the caller). */ -+ refcount = InterlockedExchange( &cache->refcount, 2 ); -+ assert( !refcount ); -+ -+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); -+ -+ return cache; -+} -+ -+ -+/* returns the previous value */ -+static inline LONG interlocked_inc_if_nonzero( LONG *dest ) -+{ -+ LONG val, tmp; -+ for (val = *dest;; val = tmp) -+ { -+ if (!val || (tmp = InterlockedCompareExchange( dest, val + 1, val )) == val) -+ break; -+ } -+ return val; -+} -+ -+ -+static struct inproc_sync_cache_entry *get_cached_inproc_sync_obj( HANDLE handle ) -+{ -+ unsigned int entry, idx = inproc_sync_handle_to_index( handle, &entry ); -+ struct inproc_sync_cache_entry *cache; -+ -+ if (entry >= INPROC_SYNC_CACHE_ENTRIES || !inproc_sync_cache[entry]) -+ return NULL; -+ -+ cache = &inproc_sync_cache[entry][idx]; -+ -+ /* this load needs acquire semantics [paired with the store in -+ * cache_inproc_sync_obj()] */ -+ if (!interlocked_inc_if_nonzero( &cache->refcount )) -+ return NULL; -+ -+ if (cache->closed) -+ { -+ /* The object is still being used, but "handle" has been closed. The -+ * handle value might have been reused for another object in the -+ * meantime, in which case we have to report that valid object, so -+ * force the caller to check the server. */ -+ release_inproc_sync_obj( cache ); -+ return NULL; -+ } -+ -+ return cache; -+} -+ -+ -+static BOOL inproc_sync_types_match( enum inproc_sync_type a, enum inproc_sync_type b ) -+{ -+ if (a == b) return TRUE; -+ if (a == INPROC_SYNC_AUTO_EVENT && b == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ if (b == INPROC_SYNC_AUTO_EVENT && a == INPROC_SYNC_MANUAL_EVENT) return TRUE; -+ return FALSE; -+} -+ -+ -+/* returns a pointer to a cache entry; if the object could not be cached, -+ * returns "stack_cache" instead, which should be allocated on stack */ -+static NTSTATUS get_inproc_sync_obj( HANDLE handle, enum inproc_sync_type desired_type, -+ ACCESS_MASK desired_access, -+ struct inproc_sync_cache_entry *stack_cache, -+ struct inproc_sync_cache_entry **ret_cache ) -+{ -+ struct inproc_sync_cache_entry *cache; -+ obj_handle_t inproc_sync_handle; -+ enum inproc_sync_type type; -+ unsigned int access; -+ int fd, needs_close; -+ NTSTATUS ret; -+ -+ /* try to find it in the cache already */ -+ if ((cache = get_cached_inproc_sync_obj( handle ))) -+ { -+ *ret_cache = cache; -+ return STATUS_SUCCESS; -+ } -+ -+ /* try to retrieve it from the server */ -+ SERVER_START_REQ( get_linux_sync_obj ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ if (!(ret = wine_server_call( req ))) -+ { -+ inproc_sync_handle = reply->handle; -+ access = reply->access; -+ type = reply->type; -+ } -+ } -+ SERVER_END_REQ; -+ -+ if (ret) return ret; -+ -+ if ((ret = server_get_unix_fd( wine_server_ptr_handle( inproc_sync_handle ), -+ 0, &fd, &needs_close, NULL, NULL ))) -+ return ret; -+ -+ cache = cache_inproc_sync_obj( handle, inproc_sync_handle, fd, type, access ); -+ if (!cache) -+ { -+ cache = stack_cache; -+ cache->handle = inproc_sync_handle; -+ cache->fd = fd; -+ cache->type = type; -+ cache->access = access; -+ cache->closed = FALSE; -+ cache->refcount = 1; -+ } -+ -+ *ret_cache = cache; -+ -+ if (desired_type && !inproc_sync_types_match( cache->type, desired_type )) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((cache->access & desired_access) != desired_access) -+ { -+ release_inproc_sync_obj( cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ -+ return STATUS_SUCCESS; -+} -+ -+ -+/* caller must hold fd_cache_mutex */ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+ struct inproc_sync_cache_entry *cache = get_cached_inproc_sync_obj( handle ); -+ -+ if (cache) -+ { -+ cache->closed = TRUE; -+ /* once for the reference we just grabbed, and once for the handle */ -+ release_inproc_sync_obj( cache ); -+ release_inproc_sync_obj( cache ); -+ } -+} -+ -+ -+static NTSTATUS linux_release_semaphore_obj( int obj, ULONG count, ULONG *prev_count ) -+{ -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_RELEASE, &count ); -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_semaphore_obj( cache->fd, count, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_semaphore_obj( int obj, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_sem_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_SEM_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->CurrentCount = args.count; -+ info->MaximumCount = args.max; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_SEMAPHORE, -+ SEMAPHORE_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_semaphore_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_set_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_SET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_set_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_reset_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_RESET, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_reset_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_pulse_event_obj( int obj, LONG *prev_state ) -+{ -+ NTSTATUS ret; -+ __u32 prev; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_PULSE, &prev ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ if (prev_state) *prev_state = prev; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_MODIFY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_pulse_event_obj( cache->fd, prev_state ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_event_obj( int obj, enum inproc_sync_type type, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_event_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_EVENT_READ, &args ); -+ if (ret < 0) -+ return errno_to_status( errno ); -+ info->EventType = (type == INPROC_SYNC_AUTO_EVENT) ? SynchronizationEvent : NotificationEvent; -+ info->EventState = args.signaled; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_AUTO_EVENT, -+ EVENT_QUERY_STATE, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_event_obj( cache->fd, cache->type, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_release_mutex_obj( int obj, LONG *prev_count ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ args.owner = GetCurrentThreadId(); -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_UNLOCK, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOVERFLOW) -+ return STATUS_MUTANT_LIMIT_EXCEEDED; -+ else if (errno == EPERM) -+ return STATUS_MUTANT_NOT_OWNED; -+ else -+ return errno_to_status( errno ); -+ } -+ if (prev_count) *prev_count = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, 0, &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_release_mutex_obj( cache->fd, prev_count ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+ -+static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct ntsync_mutex_args args = {0}; -+ NTSTATUS ret; -+ -+ ret = ioctl( obj, NTSYNC_IOC_MUTEX_READ, &args ); -+ -+ if (ret < 0) -+ { -+ if (errno == EOWNERDEAD) -+ { -+ info->AbandonedState = TRUE; -+ info->OwnedByCaller = FALSE; -+ info->CurrentCount = 1; -+ return STATUS_SUCCESS; -+ } -+ else -+ return errno_to_status( errno ); -+ } -+ info->AbandonedState = FALSE; -+ info->OwnedByCaller = (args.owner == GetCurrentThreadId()); -+ info->CurrentCount = 1 - args.count; -+ return STATUS_SUCCESS; -+} -+ -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ NTSTATUS ret; -+ -+ if ((ret = get_inproc_sync_obj( handle, INPROC_SYNC_MUTEX, MUTANT_QUERY_STATE, -+ &stack_cache, &cache ))) -+ return ret; -+ -+ ret = linux_query_mutex_obj( cache->fd, info ); -+ -+ release_inproc_sync_obj( cache ); -+ return ret; -+} -+ -+static void select_queue(void) -+{ -+ SERVER_START_REQ( select_inproc_queue ) -+ { -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static void unselect_queue( BOOL signaled ) -+{ -+ SERVER_START_REQ( unselect_inproc_queue ) -+ { -+ req->signaled = signaled; -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+static int get_inproc_alert_obj(void) -+{ -+ struct ntdll_thread_data *data = ntdll_get_thread_data(); -+ struct inproc_sync_cache_entry stack_cache, *cache; -+ HANDLE alert_handle; -+ unsigned int ret; -+ -+ if (data->linux_alert_obj == -1) -+ { -+ SERVER_START_REQ( get_inproc_alert_event ) -+ { -+ if ((ret = wine_server_call( req ))) -+ ERR( "failed to get inproc alert event, status %#x\n", ret ); -+ alert_handle = wine_server_ptr_handle( reply->handle ); -+ } -+ SERVER_END_REQ; -+ -+ if ((ret = get_inproc_sync_obj( alert_handle, 0, SYNCHRONIZE, &stack_cache, &cache ))) -+ ERR( "failed to get inproc alert obj, status %#x\n", ret ); -+ data->linux_alert_obj = cache->fd; -+ /* Set the fd to -1 so release_inproc_sync_obj() won't close it. -+ * Manhandling the cache entry here is fine since we're the only thread -+ * that can access our own alert event. */ -+ cache->fd = -1; -+ release_inproc_sync_obj( cache ); -+ NtClose( alert_handle ); -+ } -+ -+ return data->linux_alert_obj; -+} -+ -+static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, -+ BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct ntsync_wait_args args = {0}; -+ unsigned long request; -+ struct timespec now; -+ int ret; -+ -+ if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) -+ { -+ args.timeout = ~(__u64)0; -+ } -+ else if (timeout->QuadPart <= 0) -+ { -+ clock_gettime( CLOCK_MONOTONIC, &now ); -+ args.timeout = (now.tv_sec * NSECPERSEC) + now.tv_nsec + (-timeout->QuadPart * 100); -+ } -+ else -+ { -+ args.timeout = (timeout->QuadPart * 100) - (SECS_1601_TO_1970 * NSECPERSEC); -+ args.flags |= NTSYNC_WAIT_REALTIME; -+ } -+ -+ args.objs = (uintptr_t)objs; -+ args.count = count; -+ args.owner = GetCurrentThreadId(); -+ args.index = ~0u; -+ -+ if (alertable) -+ args.alert = get_inproc_alert_obj(); -+ -+ if (wait_any || count == 1) -+ request = NTSYNC_IOC_WAIT_ANY; -+ else -+ request = NTSYNC_IOC_WAIT_ALL; -+ -+ do -+ { -+ ret = ioctl( device, request, &args ); -+ } while (ret < 0 && errno == EINTR); -+ -+ if (!ret) -+ { -+ if (args.index == count) -+ { -+ static const LARGE_INTEGER timeout; -+ -+ ret = server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &timeout ); -+ assert( ret == STATUS_USER_APC ); -+ return ret; -+ } -+ -+ return wait_any ? args.index : 0; -+ } -+ else if (errno == EOWNERDEAD) -+ return STATUS_ABANDONED + (wait_any ? args.index : 0); -+ else if (errno == ETIMEDOUT) -+ return STATUS_TIMEOUT; -+ else -+ return errno_to_status( errno ); -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry stack_cache[64], *cache[64]; -+ int device, objs[64]; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ DWORD i, j; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ for (i = 0; i < count; ++i) -+ { -+ if ((ret = get_inproc_sync_obj( handles[i], 0, SYNCHRONIZE, &stack_cache[i], &cache[i] ))) -+ { -+ for (j = 0; j < i; ++j) -+ release_inproc_sync_obj( cache[j] ); -+ return ret; -+ } -+ if (cache[i]->type == INPROC_SYNC_QUEUE) -+ queue = handles[i]; -+ -+ objs[i] = cache[i]->fd; -+ } -+ -+ /* It's common to wait on the message queue alone. Some applications wait -+ * on it in fast paths, with a zero timeout. Since we take two server calls -+ * instead of one when going through inproc_wait(), and since we only need -+ * to go through that path if we're waiting on other objects, just delegate -+ * to the server if we're only waiting on the message queue. */ -+ if (count == 1 && queue) -+ { -+ release_inproc_sync_obj( cache[0] ); -+ return server_wait_for_object( handles[0], alertable, timeout ); -+ } -+ -+ if (queue) select_queue(); -+ -+ ret = linux_wait_objs( device, count, objs, wait_any, alertable, timeout ); -+ -+ if (queue) unselect_queue( handles[ret] == queue ); -+ -+ for (i = 0; i < count; ++i) -+ release_inproc_sync_obj( cache[i] ); -+ -+ return ret; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct inproc_sync_cache_entry signal_stack_cache, *signal_cache; -+ struct inproc_sync_cache_entry wait_stack_cache, *wait_cache; -+ HANDLE queue = NULL; -+ NTSTATUS ret; -+ int device; -+ -+ if ((device = get_linux_sync_device()) < 0) -+ return STATUS_NOT_IMPLEMENTED; -+ -+ if ((ret = get_inproc_sync_obj( signal, 0, 0, &signal_stack_cache, &signal_cache ))) -+ return ret; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ if (!(signal_cache->access & SEMAPHORE_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ if (!(signal_cache->access & EVENT_MODIFY_STATE)) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_ACCESS_DENIED; -+ } -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ break; -+ -+ default: -+ /* can't be signaled */ -+ release_inproc_sync_obj( signal_cache ); -+ return STATUS_OBJECT_TYPE_MISMATCH; -+ } -+ -+ if ((ret = get_inproc_sync_obj( wait, 0, SYNCHRONIZE, &wait_stack_cache, &wait_cache ))) -+ { -+ release_inproc_sync_obj( signal_cache ); -+ return ret; -+ } -+ -+ if (wait_cache->type == INPROC_SYNC_QUEUE) -+ queue = wait; -+ -+ switch (signal_cache->type) -+ { -+ case INPROC_SYNC_SEMAPHORE: -+ ret = linux_release_semaphore_obj( signal_cache->fd, 1, NULL ); -+ break; -+ -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_MANUAL_EVENT: -+ ret = linux_set_event_obj( signal_cache->fd, NULL ); -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ ret = linux_release_mutex_obj( signal_cache->fd, NULL ); -+ break; -+ -+ default: -+ assert( 0 ); -+ break; -+ } -+ -+ if (!ret) -+ { -+ if (queue) select_queue(); -+ ret = linux_wait_objs( device, 1, &wait_cache->fd, TRUE, alertable, timeout ); -+ if (queue) unselect_queue( !ret ); -+ } -+ -+ release_inproc_sync_obj( signal_cache ); -+ release_inproc_sync_obj( wait_cache ); -+ return ret; -+} -+ -+#else -+ -+void close_inproc_sync_obj( HANDLE handle ) -+{ -+} -+ -+static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_semaphore( HANDLE handle, SEMAPHORE_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_set_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_reset_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_pulse_event( HANDLE handle, LONG *prev_state ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_event( HANDLE handle, EVENT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_release_mutex( HANDLE handle, LONG *prev_count ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *info ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+#endif -+ -+ - /****************************************************************************** - * NtCreateSemaphore (NTDLL.@) - */ -@@ -249,13 +1152,13 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, initial %d, max %d\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)initial, (int)max ); -+ - *handle = 0; - if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -- if (do_esync()) -- return esync_create_semaphore( handle, access, attr, initial, max ); -- - SERVER_START_REQ( create_semaphore ) - { - req->access = access; -@@ -279,11 +1182,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC - { - unsigned int ret; - -- *handle = 0; -- -- if (do_esync()) -- return esync_open_semaphore( handle, access, attr ); -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); - -+ *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - - SERVER_START_REQ( open_semaphore ) -@@ -320,8 +1221,11 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - - if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_semaphore( handle, info, ret_len ); -+ if ((ret = inproc_query_semaphore( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_semaphore ) - { -@@ -345,8 +1249,10 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous - { - unsigned int ret; - -- if (do_esync()) -- return esync_release_semaphore( handle, count, previous ); -+ TRACE( "handle %p, count %u, prev_count %p\n", handle, (int)count, previous ); -+ -+ if ((ret = inproc_release_semaphore( handle, count, previous )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( release_semaphore ) - { -@@ -372,12 +1278,11 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u, state %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type, state ); -+ - *handle = 0; - if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER; -- -- if (do_esync()) -- return esync_create_event( handle, access, attr, type, state ); -- - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_event ) -@@ -403,12 +1308,11 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -- if (do_esync()) -- return esync_open_event( handle, access, attr ); -- - SERVER_START_REQ( open_event ) - { - req->access = access; -@@ -429,11 +1333,12 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - */ - NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - { -- /* This comment is a dummy to make sure this patch applies in the right place. */ - unsigned int ret; - -- if (do_esync()) -- return esync_set_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_set_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -452,12 +1357,12 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - */ - NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) - { -- /* This comment is a dummy to make sure this patch applies in the right place. */ - unsigned int ret; - -- if (do_esync()) -- return esync_reset_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); - -+ if ((ret = inproc_reset_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -488,8 +1393,10 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -- if (do_esync()) -- return esync_pulse_event( handle ); -+ TRACE( "handle %p, prev_state %p\n", handle, prev_state ); -+ -+ if ((ret = inproc_pulse_event( handle, prev_state )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( event_op ) - { -@@ -522,8 +1429,11 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, - - if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_event( handle, info, ret_len ); -+ if ((ret = inproc_query_event( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_event ) - { -@@ -550,11 +1460,10 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT - data_size_t len; - struct object_attributes *objattr; - -- *handle = 0; -- -- if (do_esync()) -- return esync_create_mutex( handle, access, attr, owned ); -+ TRACE( "access %#x, name %s, owned %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", owned ); - -+ *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_mutex ) -@@ -579,12 +1488,11 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -- if (do_esync()) -- return esync_open_mutex( handle, access, attr ); -- - SERVER_START_REQ( open_mutex ) - { - req->access = access; -@@ -607,8 +1515,10 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) - { - unsigned int ret; - -- if (do_esync()) -- return esync_release_mutex( handle, prev_count ); -+ TRACE( "handle %p, prev_count %p\n", handle, prev_count ); -+ -+ if ((ret = inproc_release_mutex( handle, prev_count )) != STATUS_NOT_IMPLEMENTED) -+ return ret; - - SERVER_START_REQ( release_mutex ) - { -@@ -640,8 +1550,11 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, - - if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - -- if (do_esync()) -- return esync_query_mutex( handle, info, ret_len ); -+ if ((ret = inproc_query_mutex( handle, out )) != STATUS_NOT_IMPLEMENTED) -+ { -+ if (!ret && ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION); -+ return ret; -+ } - - SERVER_START_REQ( query_mutex ) - { -@@ -1350,6 +2263,9 @@ NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, type %u\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", type ); -+ - *handle = 0; - if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; -@@ -1377,6 +2293,8 @@ NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1430,6 +2348,8 @@ NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state ) - { - unsigned int ret; - -+ TRACE( "handle %p, state %p\n", handle, state ); -+ - SERVER_START_REQ( cancel_timer ) - { - req->handle = wine_server_obj_handle( handle ); -@@ -1498,20 +2418,29 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO - { - union select_op select_op; - UINT i, flags = SELECT_INTERRUPTIBLE; -+ unsigned int ret; - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - -- if (do_esync()) -+ if (TRACE_ON(sync)) - { -- NTSTATUS ret = esync_wait_objects( count, handles, wait_any, alertable, timeout ); -- if (ret != STATUS_NOT_IMPLEMENTED) -- return ret; -+ TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); -+ for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); -+ TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); -+ } -+ -+ if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ { -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; - for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); -- return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); -+ TRACE( "-> %#x\n", ret ); -+ return ret; - } - - -@@ -1532,12 +2461,15 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, - { - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; -+ NTSTATUS ret; - -- if (do_esync()) -- return esync_signal_and_wait( signal, wait, alertable, timeout ); -+ TRACE( "signal %p, wait %p, alertable %u, timeout %s\n", signal, wait, alertable, debugstr_timeout(timeout) ); - - if (!signal) return STATUS_INVALID_HANDLE; - -+ if ((ret = inproc_signal_and_wait( signal, wait, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) -+ return ret; -+ - if (alertable) flags |= SELECT_ALERTABLE; - select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT; - select_op.signal_and_wait.wait = wine_server_obj_handle( wait ); -@@ -1760,6 +2692,9 @@ NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access, - data_size_t len; - struct object_attributes *objattr; - -+ TRACE( "access %#x, name %s, flags %#x\n", (int)access, -+ attr ? debugstr_us(attr->ObjectName) : "(null)", (int)flags ); -+ - *handle = 0; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -@@ -1784,6 +2719,8 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE - { - unsigned int ret; - -+ TRACE( "access %#x, name %s\n", (int)access, attr ? debugstr_us(attr->ObjectName) : "(null)" ); -+ - *handle = 0; - if ((ret = validate_open_object_attributes( attr ))) return ret; - -@@ -1810,6 +2747,8 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -1829,6 +2768,8 @@ NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ TRACE( "handle %p, key %p, alertable %u, timeout %s\n", handle, key, alertable, debugstr_timeout(timeout) ); -+ - if (!handle) handle = keyed_event; - if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1; - if (alertable) flags |= SELECT_ALERTABLE; -@@ -2019,7 +2019,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * - } - SERVER_END_REQ; - if (status != STATUS_PENDING) return status; -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) return status; - -@@ -2081,7 +2081,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM - assert( status == STATUS_USER_APC ); - goto done; - } -- if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout ); -+ if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout ); - else status = STATUS_TIMEOUT; - if (status != WAIT_OBJECT_0) goto done; - -diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c -index 7f2f1b9..3f706f4 100644 ---- a/dlls/ntdll/unix/thread.c -+++ b/dlls/ntdll/unix/thread.c -@@ -1776,7 +1776,7 @@ NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT ma - - if (ret == STATUS_PENDING) - { -- NtWaitForSingleObject( context_handle, FALSE, NULL ); -+ server_wait_for_object( context_handle, FALSE, NULL ); - - SERVER_START_REQ( get_thread_context ) - { -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 4e5b282..fc5b259 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -93,7 +93,6 @@ struct ntdll_thread_data - { - void *cpu_data[16]; /* reserved for CPU-specific data */ - void *kernel_stack; /* stack for thread startup and kernel syscalls */ -- int esync_apc_fd; /* fd to wait on for user APCs */ - 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 */ -@@ -102,6 +101,7 @@ struct ntdll_thread_data - PRTL_THREAD_START_ROUTINE start; /* thread entry point */ - void *param; /* thread entry point parameter */ - void *jmp_buf; /* setjmp buffer for exception handling */ -+ int linux_alert_obj; /* fd for the linux in-process alert event */ - }; - - C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -@@ -196,6 +196,8 @@ extern NTSTATUS load_start_exe( WCHAR **image, void **module ); - extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata ); - extern void start_server( BOOL debug ); - -+extern pthread_mutex_t fd_cache_mutex; -+ - extern unsigned int server_call_unlocked( void *req_ptr ); - extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); - extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); -@@ -203,6 +205,7 @@ extern unsigned int server_select( const select_op_t *select_op, data_size_t siz - timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ); - extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, - const LARGE_INTEGER *timeout ); -+extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); - extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, - union apc_result *result ); - extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, -@@ -353,6 +356,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args ); - - extern void dbg_init(void); - -+extern void close_inproc_sync_obj( HANDLE handle ); -+ - extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - PNTAPCFUNC func, NTSTATUS status ); - extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); -@@ -361,6 +366,7 @@ extern void call_raise_user_exception_dispatcher(void); - #define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */ - - #define TICKSPERSEC 10000000 -+#define NSECPERSEC 1000000000 - #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) - - static inline ULONGLONG ticks_from_time_t( time_t time ) -@@ -419,7 +425,7 @@ static inline async_data_t server_async( HANDLE handle, struct async_fileio *use - - static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) - { -- return NtWaitForSingleObject( handle, alertable, NULL ); -+ return server_wait_for_object( handle, alertable, NULL ); - } - - static inline BOOL in_wow64_call(void) -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 1e1af8c..a54ac45 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3712,11 +3712,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) - teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; - teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); - thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; -- thread_data->esync_apc_fd = -1; - thread_data->request_fd = -1; - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ thread_data->linux_alert_obj = -1; - list_add_head( &teb_list, &thread_data->entry ); - return teb; - } -diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c -index c64027f..ddcf896 100644 ---- a/dlls/webservices/tests/channel.c -+++ b/dlls/webservices/tests/channel.c -@@ -1214,6 +1214,9 @@ static const char send_record_begin[] = { - static const char send_record_middle[] = { 0x01, 0x56, 0x0e, 0x42 }; - static const char send_record_end[] = { 0x08, 0x02, 0x6e, 0x73, 0x89, 0xff, 0x01, 0x01 }; - -+#pragma GCC diagnostic ignored "-Warray-bounds" -+#pragma GCC diagnostic ignored "-Wstringop-overflow" -+ - static BOOL send_dict_str( int sock, char *addr, const char *str, int dict_str_count ) - { - char buf[512], dict_buf[256], body_buf[128], dict_size_buf[5]; -diff --git a/include/config.h.in b/include/config.h.in -index a53870f..ba0bdbd 100644 ---- a/include/config.h.in -+++ b/include/config.h.in -@@ -177,6 +177,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_MAJOR_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_NTSYNC_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_PARAM_H - -@@ -522,9 +519,6 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_EPOLL_H - --/* Define to 1 if you have the header file. */ --#undef HAVE_SYS_EVENTFD_H -- - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_EVENT_H - -diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h -index 34655d1..1f8e10a 100644 ---- a/include/wine/server_protocol.h -+++ b/include/wine/server_protocol.h -@@ -5881,6 +5881,86 @@ - }; - - -+enum inproc_sync_type -+{ -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, -+}; -+ -+ -+ -+struct get_linux_sync_device_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_linux_sync_device_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ -+ -+struct get_linux_sync_obj_request -+{ -+ struct request_header __header; -+ obj_handle_t handle; -+}; -+struct get_linux_sync_obj_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ int type; -+ unsigned int access; -+ char __pad_20[4]; -+}; -+ -+ -+ -+struct select_inproc_queue_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct select_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct unselect_inproc_queue_request -+{ -+ struct request_header __header; -+ int signaled; -+}; -+struct unselect_inproc_queue_reply -+{ -+ struct reply_header __header; -+}; -+ -+ -+ -+struct get_inproc_alert_event_request -+{ -+ struct request_header __header; -+ char __pad_12[4]; -+}; -+struct get_inproc_alert_event_reply -+{ -+ struct reply_header __header; -+ obj_handle_t handle; -+ char __pad_12[4]; -+}; -+ -+ - enum request - { - REQ_new_process, -@@ -5921,12 +6003,12 @@ enum request - REQ_suspend_process, - REQ_resume_process, - REQ_get_next_thread, -- REQ_create_esync, -- REQ_open_esync, -- REQ_get_esync_fd, -- REQ_esync_msgwait, - REQ_set_keyboard_repeat, -- REQ_get_esync_apc_fd, -+ REQ_get_linux_sync_device, -+ REQ_get_linux_sync_obj, -+ REQ_select_inproc_queue, -+ REQ_unselect_inproc_queue, -+ REQ_get_inproc_alert_event, - REQ_NB_REQUESTS - }; - -@@ -6213,12 +6300,12 @@ union generic_request - struct suspend_process_request suspend_process_request; - struct resume_process_request resume_process_request; - struct get_next_thread_request get_next_thread_request; -- struct create_esync_request create_esync_request; -- struct open_esync_request open_esync_request; -- struct get_esync_fd_request get_esync_fd_request; -- 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; -+ struct get_linux_sync_device_request get_linux_sync_device_request; -+ struct get_linux_sync_obj_request get_linux_sync_obj_request; -+ struct select_inproc_queue_request select_inproc_queue_request; -+ struct unselect_inproc_queue_request unselect_inproc_queue_request; -+ struct get_inproc_alert_event_request get_inproc_alert_event_request; - }; - union generic_reply - { -@@ -6503,12 +6595,12 @@ union generic_reply - struct suspend_process_reply suspend_process_reply; - struct resume_process_reply resume_process_reply; - struct get_next_thread_reply get_next_thread_reply; -- struct create_esync_reply create_esync_reply; -- struct open_esync_reply open_esync_reply; -- struct get_esync_fd_reply get_esync_fd_reply; -- 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; -+ struct get_linux_sync_device_reply get_linux_sync_device_reply; -+ struct get_linux_sync_obj_reply get_linux_sync_obj_reply; -+ struct select_inproc_queue_reply select_inproc_queue_reply; -+ struct unselect_inproc_queue_reply unselect_inproc_queue_reply; -+ struct get_inproc_alert_event_reply get_inproc_alert_event_reply; - }; - - /* ### protocol_version begin ### */ -diff --git a/server/Makefile.in b/server/Makefile.in -index b164193..b30df66 100644 ---- a/server/Makefile.in -+++ b/server/Makefile.in -@@ -11,8 +11,8 @@ SOURCES = \ - debugger.c \ - device.c \ - directory.c \ -- esync.c \ - event.c \ -+ inproc_sync.c \ - fd.c \ - file.c \ - handle.c \ -diff --git a/server/async.c b/server/async.c -index b0f9fe4..02fb966 100644 ---- a/server/async.c -+++ b/server/async.c -@@ -77,7 +77,6 @@ static const struct object_ops async_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - async_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - async_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -90,6 +89,7 @@ static const struct object_ops async_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - async_destroy /* destroy */ - }; -@@ -687,7 +687,6 @@ static const struct object_ops iosb_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -700,6 +699,7 @@ static const struct object_ops iosb_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - iosb_destroy /* destroy */ - }; -diff --git a/server/atom.c b/server/atom.c -index d9824de..ba320c4 100644 ---- a/server/atom.c -+++ b/server/atom.c -@@ -79,7 +79,6 @@ static const struct object_ops atom_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -92,6 +91,7 @@ static const struct object_ops atom_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - atom_table_destroy /* destroy */ - }; -diff --git a/server/change.c b/server/change.c -index ec61711..dafa7e8 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -112,7 +112,6 @@ static const struct object_ops dir_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - dir_get_fd, /* get_fd */ -@@ -125,6 +124,7 @@ static const struct object_ops dir_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - dir_close_handle, /* close_handle */ - dir_destroy /* destroy */ - }; -diff --git a/server/clipboard.c b/server/clipboard.c -index 8b265f2..de9f84f 100644 ---- a/server/clipboard.c -+++ b/server/clipboard.c -@@ -76,7 +76,6 @@ static const struct object_ops clipboard_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +88,7 @@ static const struct object_ops clipboard_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - clipboard_destroy /* destroy */ - }; -diff --git a/server/completion.c b/server/completion.c -index 3d4be86..5ec6d20 100644 ---- a/server/completion.c -+++ b/server/completion.c -@@ -77,6 +77,7 @@ - struct list wait_queue; - unsigned int depth; - int closed; -+ struct inproc_sync *inproc_sync; - }; - - static void completion_wait_dump( struct object*, int ); -@@ -92,7 +93,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - completion_wait_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - completion_wait_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -105,6 +105,7 @@ - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - completion_wait_destroy /* destroy */ - }; -@@ -156,6 +157,7 @@ - - static void completion_dump( struct object*, int ); - static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ); - static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void completion_destroy( struct object * ); - -@@ -167,7 +169,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - completion_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -180,6 +181,7 @@ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ completion_get_inproc_sync,/* get_inproc_sync */ - completion_close_handle, /* close_handle */ - completion_destroy /* destroy */ - }; -@@ -193,6 +195,7 @@ - { - free( tmp ); - } -+ if (completion->inproc_sync) release_object( completion->inproc_sync ); - } - - static void completion_dump( struct object *obj, int verbose ) -@@ -230,6 +233,7 @@ - } - completion->closed = 1; - wake_up( obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); - return 1; - } - -@@ -263,6 +267,16 @@ - return wait; - } - -+static struct inproc_sync *completion_get_inproc_sync( struct object *obj ) -+{ -+ struct completion *completion = (struct completion *)obj; -+ -+ if (!completion->inproc_sync) -+ completion->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &completion->queue ) ); -+ if (completion->inproc_sync) grab_object( completion->inproc_sync ); -+ return completion->inproc_sync; -+} -+ - static struct completion *create_completion( struct object *root, const struct unicode_str *name, - unsigned int attr, unsigned int concurrent, - const struct security_descriptor *sd ) -@@ -277,6 +291,7 @@ - list_init( &completion->wait_queue ); - completion->depth = 0; - completion->closed = 0; -+ completion->inproc_sync = NULL; - } - } - -@@ -309,7 +324,11 @@ - wake_up( &wait->obj, 1 ); - if (list_empty( &completion->queue )) return; - } -- if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); -+ if (!list_empty( &completion->queue )) -+ { -+ wake_up( &completion->obj, 0 ); -+ set_inproc_event( completion->inproc_sync ); -+ } - } - - /* create a completion */ -@@ -410,6 +429,8 @@ - reply->information = msg->information; - free( msg ); - reply->wait_handle = 0; -+ if (list_empty( &completion->queue )) -+ reset_inproc_event( completion->inproc_sync ); - } - - release_object( completion ); -diff --git a/server/console.c b/server/console.c -index dbd4a97..17708df 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -41,7 +41,6 @@ - #include "wincon.h" - #include "winternl.h" - #include "wine/condrv.h" --#include "esync.h" - - struct screen_buffer; - -@@ -62,6 +61,7 @@ struct console - struct fd *fd; /* for bare console, attached input fd */ - struct async_queue ioctl_q; /* ioctl queue */ - struct async_queue read_q; /* read queue */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_dump( struct object *obj, int verbose ); -@@ -73,6 +73,7 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st - static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); - static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_ops = - { -@@ -82,7 +83,6 @@ static const struct object_ops console_ops = - console_add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_get_fd, /* get_fd */ -@@ -95,6 +95,7 @@ static const struct object_ops console_ops = - NULL, /* unlink_name */ - console_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_destroy /* destroy */ - }; -@@ -132,27 +133,27 @@ struct console_host_ioctl - - struct console_server - { -- struct object obj; /* object header */ -- struct fd *fd; /* pseudo-fd for ioctls */ -- struct console *console; /* attached console */ -- struct list queue; /* ioctl queue */ -- struct list read_queue; /* blocking read queue */ -+ struct object obj; /* object header */ -+ struct fd *fd; /* pseudo-fd for ioctls */ -+ struct console *console; /* attached console */ -+ struct list queue; /* ioctl queue */ -+ struct list read_queue; /* blocking read queue */ - unsigned int busy : 1; /* flag if server processing an ioctl */ - unsigned int once_input : 1; /* flag if input thread has already been requested */ -- int term_fd; /* UNIX terminal fd */ -- struct termios termios; /* original termios */ -- int esync_fd; -+ int term_fd; /* UNIX terminal fd */ -+ struct termios termios; /* original termios */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void console_server_dump( struct object *obj, int verbose ); - static void console_server_destroy( struct object *obj ); - static int console_server_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int console_server_get_esync_fd( struct object *obj, enum esync_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 ); - static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ); - - static const struct object_ops console_server_ops = - { -@@ -162,7 +163,6 @@ static const struct object_ops console_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_server_signaled, /* signaled */ -- console_server_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_server_get_fd, /* get_fd */ -@@ -175,6 +175,7 @@ static const struct object_ops console_server_ops = - NULL, /* unlink_name */ - console_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_server_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_server_destroy /* destroy */ - }; -@@ -223,6 +224,7 @@ static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *screen_buffer_get_fd( struct object *obj ); - static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ); - - static const struct object_ops screen_buffer_ops = - { -@@ -232,7 +234,6 @@ static const struct object_ops screen_buffer_ops = - screen_buffer_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - screen_buffer_get_fd, /* get_fd */ -@@ -245,6 +246,7 @@ static const struct object_ops screen_buffer_ops = - NULL, /* unlink_name */ - screen_buffer_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ screen_buffer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - screen_buffer_destroy /* destroy */ - }; -@@ -282,7 +284,6 @@ static const struct object_ops console_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -295,6 +296,7 @@ static const struct object_ops console_device_ops = - default_unlink_name, /* unlink_name */ - console_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -310,6 +312,7 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - unsigned int sharing, unsigned int options ); - static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); - static struct fd *console_input_get_fd( struct object *obj ); -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ); - static void console_input_destroy( struct object *obj ); - - static const struct object_ops console_input_ops = -@@ -320,7 +323,6 @@ static const struct object_ops console_input_ops = - console_input_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_input_get_fd, /* get_fd */ -@@ -333,6 +335,7 @@ static const struct object_ops console_input_ops = - default_unlink_name, /* unlink_name */ - console_input_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_input_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_input_destroy /* destroy */ - }; -@@ -368,6 +371,7 @@ static int console_output_add_queue( struct object *obj, struct wait_queue_entry - static struct fd *console_output_get_fd( struct object *obj ); - static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ); - static void console_output_destroy( struct object *obj ); - - static const struct object_ops console_output_ops = -@@ -378,7 +382,6 @@ static const struct object_ops console_output_ops = - console_output_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_output_get_fd, /* get_fd */ -@@ -391,6 +394,7 @@ static const struct object_ops console_output_ops = - default_unlink_name, /* unlink_name */ - console_output_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ console_output_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - console_output_destroy /* destroy */ - }; -@@ -437,7 +441,6 @@ static const struct object_ops console_connection_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_connection_get_fd, /* get_fd */ -@@ -450,6 +453,7 @@ static const struct object_ops console_connection_ops = - default_unlink_name, /* unlink_name */ - console_connection_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - console_connection_close_handle, /* close_handle */ - console_connection_destroy /* destroy */ - }; -@@ -549,6 +553,7 @@ static struct object *create_console(void) - console->server = NULL; - console->fd = NULL; - console->last_id = 0; -+ console->inproc_sync = NULL; - init_async_queue( &console->ioctl_q ); - init_async_queue( &console->read_q ); - -@@ -588,6 +593,7 @@ static int queue_host_ioctl( struct console_server *server, unsigned int code, u - } - list_add_tail( &server->queue, &ioctl->entry ); - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - if (async) set_error( STATUS_PENDING ); - return 1; - } -@@ -600,8 +606,6 @@ static void disconnect_console_server( struct console_server *server ) - list_remove( &call->entry ); - console_host_ioctl_terminate( call, STATUS_CANCELLED ); - } -- if (do_esync()) -- esync_clear( server->esync_fd ); - while (!list_empty( &server->read_queue )) - { - struct console_host_ioctl *call = LIST_ENTRY( list_head( &server->read_queue ), struct console_host_ioctl, entry ); -@@ -622,6 +626,7 @@ static void disconnect_console_server( struct console_server *server ) - server->console->server = NULL; - server->console = NULL; - wake_up( &server->obj, 0 ); -+ set_inproc_event( server->inproc_sync ); - } - } - -@@ -776,6 +781,8 @@ static void console_destroy( struct object *obj ) - free_async_queue( &console->read_q ); - if (console->fd) - release_object( console->fd ); -+ -+ if (console->inproc_sync) release_object( console->inproc_sync ); - } - - static struct object *create_console_connection( struct console *console ) -@@ -823,6 +830,16 @@ static struct object *console_open_file( struct object *obj, unsigned int access - return grab_object( obj ); - } - -+static struct inproc_sync *console_get_inproc_sync( struct object *obj ) -+{ -+ struct console *console = (struct console *)obj; -+ -+ if (!console->inproc_sync) -+ console->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, console->signaled ); -+ if (console->inproc_sync) grab_object( console->inproc_sync ); -+ return console->inproc_sync; -+} -+ - static void screen_buffer_dump( struct object *obj, int verbose ) - { - struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -@@ -872,6 +889,17 @@ static struct fd *screen_buffer_get_fd( struct object *obj ) - return NULL; - } - -+static struct inproc_sync *screen_buffer_get_inproc_sync( struct object *obj ) -+{ -+ struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; -+ if (!screen_buffer->input) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( &screen_buffer->input->obj ); -+} -+ - static void console_server_dump( struct object *obj, int verbose ) - { - assert( obj->ops == &console_server_ops ); -@@ -884,7 +912,7 @@ static void console_server_destroy( struct object *obj ) - assert( obj->ops == &console_server_ops ); - disconnect_console_server( server ); - if (server->fd) release_object( server->fd ); -- if (do_esync()) close( server->esync_fd ); -+ if (server->inproc_sync) release_object( server->inproc_sync ); - } - - static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -926,13 +954,6 @@ static int console_server_signaled( struct object *obj, struct wait_queue_entry - return !server->console || !list_empty( &server->queue ); - } - --static int console_server_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct console_server *server = (struct console_server*)obj; -- *type = ESYNC_MANUAL_SERVER; -- return server->esync_fd; --} -- - static struct fd *console_server_get_fd( struct object* obj ) - { - struct console_server *server = (struct console_server*)obj; -@@ -946,6 +967,17 @@ static struct object *console_server_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_server_get_inproc_sync( struct object *obj ) -+{ -+ struct console_server *server = (struct console_server *)obj; -+ int signaled = !server->console || !list_empty( &server->queue ); -+ -+ if (!server->inproc_sync) -+ server->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (server->inproc_sync) grab_object( server->inproc_sync ); -+ return server->inproc_sync; -+} -+ - static struct object *create_console_server( void ) - { - struct console_server *server; -@@ -957,6 +989,7 @@ static struct object *create_console_server( void ) - server->term_fd = -1; - list_init( &server->queue ); - list_init( &server->read_queue ); -+ server->inproc_sync = NULL; - server->fd = alloc_pseudo_fd( &console_server_fd_ops, &server->obj, FILE_SYNCHRONOUS_IO_NONALERT ); - if (!server->fd) - { -@@ -964,10 +997,6 @@ static struct object *create_console_server( void ) - return NULL; - } - allow_fd_caching(server->fd); -- server->esync_fd = -1; -- -- if (do_esync()) -- server->esync_fd = esync_create_fd( 0, 0 ); - - return &server->obj; - } -@@ -1426,6 +1455,16 @@ static struct object *console_input_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_input_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_input_destroy( struct object *obj ) - { - struct console_input *console_input = (struct console_input *)obj; -@@ -1498,6 +1537,16 @@ static struct object *console_output_open_file( struct object *obj, unsigned int - return grab_object( obj ); - } - -+static struct inproc_sync *console_output_get_inproc_sync( struct object *obj ) -+{ -+ if (!current->process->console || !current->process->console->active) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ return NULL; -+ } -+ return console_get_inproc_sync( ¤t->process->console->obj ); -+} -+ - static void console_output_destroy( struct object *obj ) - { - struct console_output *console_output = (struct console_output *)obj; -@@ -1555,11 +1604,16 @@ DECL_HANDLER(get_next_console_request) - - if (!server->console->renderer) server->console->renderer = current; - -- if (!req->signal) server->console->signaled = 0; -+ if (!req->signal) -+ { -+ server->console->signaled = 0; -+ reset_inproc_event( server->console->inproc_sync ); -+ } - else if (!server->console->signaled) - { - server->console->signaled = 1; - wake_up( &server->console->obj, 0 ); -+ set_inproc_event( server->console->inproc_sync ); - } - - if (req->read) -@@ -1581,8 +1635,8 @@ DECL_HANDLER(get_next_console_request) - /* set result of previous ioctl */ - ioctl = LIST_ENTRY( list_head( &server->queue ), struct console_host_ioctl, entry ); - list_remove( &ioctl->entry ); -- if (do_esync() && list_empty( &server->queue )) -- esync_clear( server->esync_fd ); -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - } - - if (ioctl) -@@ -1668,8 +1722,9 @@ DECL_HANDLER(get_next_console_request) - { - set_error( STATUS_PENDING ); - } -- if (do_esync() && list_empty( &server->queue )) -- esync_clear( server->esync_fd ); -+ -+ if (list_empty( &server->queue )) -+ reset_inproc_event( server->inproc_sync ); - - release_object( server ); - } -diff --git a/server/debugger.c b/server/debugger.c -index ca04d4c..7975fc4 100644 ---- a/server/debugger.c -+++ b/server/debugger.c -@@ -71,6 +71,7 @@ struct debug_obj - struct object obj; /* object header */ - struct list event_queue; /* pending events queue */ - unsigned int flags; /* debug flags */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - -@@ -86,7 +87,6 @@ static const struct object_ops debug_event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_event_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -99,12 +99,14 @@ static const struct object_ops debug_event_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_event_destroy /* destroy */ - }; - - static void debug_obj_dump( struct object *obj, int verbose ); - static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ); - static void debug_obj_destroy( struct object *obj ); - - static const struct object_ops debug_obj_ops = -@@ -115,7 +117,6 @@ static const struct object_ops debug_obj_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_obj_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -128,6 +129,7 @@ static const struct object_ops debug_obj_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ debug_obj_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - debug_obj_destroy /* destroy */ - }; -@@ -255,6 +257,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) - /* grab reference since debugger could be killed while trying to wake up */ - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -267,6 +270,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event - { - grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); -+ set_inproc_event( debug_obj->inproc_sync ); - release_object( debug_obj ); - } - } -@@ -332,6 +336,17 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr - return find_event_to_send( debug_obj ) != NULL; - } - -+static struct inproc_sync *debug_obj_get_inproc_sync( struct object *obj ) -+{ -+ struct debug_obj *debug_obj = (struct debug_obj *)obj; -+ int signaled = find_event_to_send( debug_obj ) != NULL; -+ -+ if (!debug_obj->inproc_sync) -+ debug_obj->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, signaled ); -+ if (debug_obj->inproc_sync) grab_object( debug_obj->inproc_sync ); -+ return debug_obj->inproc_sync; -+} -+ - static void debug_obj_destroy( struct object *obj ) - { - struct list *ptr; -@@ -344,6 +359,8 @@ static void debug_obj_destroy( struct object *obj ) - /* free all pending events */ - while ((ptr = list_head( &debug_obj->event_queue ))) - unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); -+ -+ if (debug_obj->inproc_sync) release_object( debug_obj->inproc_sync ); - } - - struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) -@@ -363,6 +380,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni - { - debug_obj->flags = flags; - list_init( &debug_obj->event_queue ); -+ debug_obj->inproc_sync = NULL; - } - } - return debug_obj; -@@ -571,6 +589,9 @@ DECL_HANDLER(wait_debug_event) - reply->tid = get_thread_id( event->sender ); - alloc_event_handles( event, current->process ); - set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); -+ -+ if (!find_event_to_send( debug_obj )) -+ reset_inproc_event( debug_obj->inproc_sync ); - } - else - { -diff --git a/server/device.c b/server/device.c -index c45d010..698fee6 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -38,7 +38,6 @@ - #include "handle.h" - #include "request.h" - #include "process.h" --#include "esync.h" - - /* IRP object */ - -@@ -67,7 +66,6 @@ static const struct object_ops irp_call_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -80,6 +78,7 @@ static const struct object_ops irp_call_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - irp_call_destroy /* destroy */ - }; -@@ -94,12 +93,12 @@ struct device_manager - struct list requests; /* list of pending irps across all devices */ - struct irp_call *current_call; /* call currently executed on client side */ - struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void device_manager_dump( struct object *obj, int verbose ); - static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ); -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ); - static void device_manager_destroy( struct object *obj ); - - static const struct object_ops device_manager_ops = -@@ -110,7 +109,6 @@ static const struct object_ops device_manager_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - device_manager_signaled, /* signaled */ -- device_manager_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -123,6 +121,7 @@ static const struct object_ops device_manager_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ device_manager_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_manager_destroy /* destroy */ - }; -@@ -168,7 +167,6 @@ static const struct object_ops device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -181,6 +179,7 @@ static const struct object_ops device_ops = - default_unlink_name, /* unlink_name */ - device_open_file, /* open_file */ - device_get_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -221,7 +220,6 @@ static const struct object_ops device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - device_file_get_fd, /* get_fd */ -@@ -234,6 +232,7 @@ static const struct object_ops device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - device_file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - device_file_close_handle, /* close_handle */ - device_file_destroy /* destroy */ - }; -@@ -424,7 +423,12 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i - irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; - if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); - list_add_tail( &manager->requests, &irp->mgr_entry ); -- if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ -+ if (list_head( &manager->requests ) == &irp->mgr_entry) -+ { -+ /* first one */ -+ wake_up( &manager->obj, 0 ); -+ set_inproc_event( manager->inproc_sync ); -+ } - } - - static struct object *device_open_file( struct object *obj, unsigned int access, -@@ -754,13 +758,13 @@ static void delete_file( struct device_file *file ) - /* terminate all pending requests */ - LIST_FOR_EACH_ENTRY_SAFE( irp, next, &file->requests, struct irp_call, dev_entry ) - { -- if (do_esync() && file->device->manager && list_empty( &file->device->manager->requests )) -- esync_clear( file->device->manager->esync_fd ); -- - list_remove( &irp->mgr_entry ); - set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); - } - -+ if (list_empty( &file->device->manager->requests )) -+ reset_inproc_event( file->device->manager->inproc_sync ); -+ - release_object( file ); - } - -@@ -792,11 +796,14 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry - return !list_empty( &manager->requests ); - } - --static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type ) -+static struct inproc_sync *device_manager_get_inproc_sync( struct object *obj ) - { - struct device_manager *manager = (struct device_manager *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return manager->esync_fd; -+ -+ if (!manager->inproc_sync) -+ manager->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !list_empty( &manager->requests ) ); -+ if (manager->inproc_sync) grab_object( manager->inproc_sync ); -+ return manager->inproc_sync; - } - - static void device_manager_destroy( struct object *obj ) -@@ -834,8 +841,7 @@ static void device_manager_destroy( struct object *obj ) - release_object( irp ); - } - -- if (do_esync()) -- close( manager->esync_fd ); -+ if (manager->inproc_sync) release_object( manager->inproc_sync ); - } - - static struct device_manager *create_device_manager(void) -@@ -845,12 +851,10 @@ static struct device_manager *create_device_manager(void) - if ((manager = alloc_object( &device_manager_ops ))) - { - manager->current_call = NULL; -+ manager->inproc_sync = NULL; - list_init( &manager->devices ); - list_init( &manager->requests ); - wine_rb_init( &manager->kernel_objects, compare_kernel_object ); -- -- if (do_esync()) -- manager->esync_fd = esync_create_fd( 0, 0 ); - } - return manager; - } -@@ -1037,12 +1041,13 @@ DECL_HANDLER(get_next_device_request) - } - list_remove( &irp->mgr_entry ); - list_init( &irp->mgr_entry ); -+ -+ if (list_empty( &manager->requests )) -+ reset_inproc_event( manager->inproc_sync ); -+ - /* we already own the object if it's only on manager queue */ - if (irp->file) grab_object( irp ); - manager->current_call = irp; -- -- if (do_esync() && list_empty( &manager->requests )) -- esync_clear( manager->esync_fd ); - } - else close_handle( current->process, reply->next ); - } -diff --git a/server/directory.c b/server/directory.c -index bc161b9..8e32abb 100644 ---- a/server/directory.c -+++ b/server/directory.c -@@ -69,7 +69,6 @@ static const struct object_ops object_type_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -82,6 +81,7 @@ static const struct object_ops object_type_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -120,7 +120,6 @@ static const struct object_ops directory_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -133,6 +132,7 @@ static const struct object_ops directory_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - directory_destroy /* destroy */ - }; -diff --git a/server/esync.c b/server/esync.c -deleted file mode 100644 -index e193f61..0000000 ---- a/server/esync.c -+++ /dev/null -@@ -1,588 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#include "config.h" -- -- --#include --#include --#include --#ifdef HAVE_SYS_EVENTFD_H --# include --#endif --#include --#ifdef HAVE_SYS_STAT_H --# include --#endif --#include -- --#include "ntstatus.h" --#define WIN32_NO_STATUS --#include "windef.h" --#include "winternl.h" -- --#include "handle.h" --#include "request.h" --#include "file.h" --#include "esync.h" -- --int do_esync(void) --{ --#ifdef HAVE_SYS_EVENTFD_H -- static int do_esync_cached = -1; -- -- if (do_esync_cached == -1) -- do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); -- -- return do_esync_cached; --#else -- return 0; --#endif --} -- --static char shm_name[29]; --static int shm_fd; --static off_t shm_size; --static void **shm_addrs; --static int shm_addrs_size; /* length of the allocated shm_addrs array */ --static long pagesize; -- --static void shm_cleanup(void) --{ -- close( shm_fd ); -- if (shm_unlink( shm_name ) == -1) -- perror( "shm_unlink" ); --} -- --void esync_init(void) --{ -- struct stat st; -- -- if (fstat( config_dir_fd, &st ) == -1) -- fatal_error( "cannot stat config dir\n" ); -- -- if (st.st_ino != (unsigned long)st.st_ino) -- sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino ); -- else -- sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino ); -- -- shm_unlink( shm_name ); -- -- shm_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 ); -- if (shm_fd == -1) -- perror( "shm_open" ); -- -- pagesize = sysconf( _SC_PAGESIZE ); -- -- shm_addrs = calloc( 128, sizeof(shm_addrs[0]) ); -- shm_addrs_size = 128; -- -- shm_size = pagesize; -- if (ftruncate( shm_fd, shm_size ) == -1) -- perror( "ftruncate" ); -- -- fprintf( stderr, "esync: up and running.\n" ); -- -- atexit( shm_cleanup ); --} -- --static struct list mutex_list = LIST_INIT(mutex_list); -- --struct esync --{ -- struct object obj; /* object header */ -- int fd; /* eventfd file descriptor */ -- enum esync_type type; -- unsigned int shm_idx; /* index into the shared memory section */ -- struct list mutex_entry; /* entry in the mutex list (if applicable) */ --}; -- --static void esync_dump( struct object *obj, int verbose ); --static int esync_get_esync_fd( struct object *obj, enum esync_type *type ); --static unsigned int esync_map_access( struct object *obj, unsigned int access ); --static void esync_destroy( struct object *obj ); -- --const struct object_ops esync_ops = --{ -- sizeof(struct esync), /* size */ -- &no_type, /* type */ -- esync_dump, /* dump */ -- no_add_queue, /* add_queue */ -- NULL, /* remove_queue */ -- NULL, /* signaled */ -- esync_get_esync_fd, /* get_esync_fd */ -- NULL, /* satisfied */ -- no_signal, /* signal */ -- no_get_fd, /* get_fd */ -- esync_map_access, /* map_access */ -- default_get_sd, /* get_sd */ -- default_set_sd, /* set_sd */ -- default_get_full_name, /* get_full_name */ -- no_lookup_name, /* lookup_name */ -- directory_link_name, /* link_name */ -- default_unlink_name, /* unlink_name */ -- no_open_file, /* open_file */ -- no_kernel_obj_list, /* get_kernel_obj_list */ -- no_close_handle, /* close_handle */ -- esync_destroy /* destroy */ --}; -- --static void esync_dump( struct object *obj, int verbose ) --{ -- struct esync *esync = (struct esync *)obj; -- assert( obj->ops == &esync_ops ); -- fprintf( stderr, "esync fd=%d\n", esync->fd ); --} -- --static int esync_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct esync *esync = (struct esync *)obj; -- *type = esync->type; -- return esync->fd; --} -- --static unsigned int esync_map_access( struct object *obj, unsigned int access ) --{ -- /* Sync objects have the same flags. */ -- if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | EVENT_QUERY_STATE; -- if (access & GENERIC_WRITE) access |= STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE; -- if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE; -- if (access & GENERIC_ALL) access |= STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE; -- return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); --} -- --static void esync_destroy( struct object *obj ) --{ -- struct esync *esync = (struct esync *)obj; -- if (esync->type == ESYNC_MUTEX) -- list_remove( &esync->mutex_entry ); -- close( esync->fd ); --} -- --static int type_matches( enum esync_type type1, enum esync_type type2 ) --{ -- return (type1 == type2) || -- ((type1 == ESYNC_AUTO_EVENT || type1 == ESYNC_MANUAL_EVENT) && -- (type2 == ESYNC_AUTO_EVENT || type2 == ESYNC_MANUAL_EVENT)); --} -- --static void *get_shm( unsigned int idx ) --{ -- int entry = (idx * 8) / pagesize; -- int offset = (idx * 8) % pagesize; -- -- if (entry >= shm_addrs_size) -- { -- int new_size = max(shm_addrs_size * 2, entry + 1); -- -- if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) ))) -- fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 ); -- -- memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) ); -- -- shm_addrs_size = new_size; -- } -- -- if (!shm_addrs[entry]) -- { -- void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize ); -- if (addr == (void *)-1) -- { -- fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize ); -- perror( "mmap" ); -- } -- -- if (debug_level) -- fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr ); -- -- if (__sync_val_compare_and_swap( &shm_addrs[entry], 0, addr )) -- munmap( addr, pagesize ); /* someone beat us to it */ -- } -- -- return (void *)((unsigned long)shm_addrs[entry] + offset); --} -- --struct semaphore --{ -- int max; -- int count; --}; --C_ASSERT(sizeof(struct semaphore) == 8); -- --struct mutex --{ -- DWORD tid; -- int count; /* recursion count */ --}; --C_ASSERT(sizeof(struct mutex) == 8); -- --struct event --{ -- int signaled; -- int locked; --}; --C_ASSERT(sizeof(struct event) == 8); -- --struct esync *create_esync( struct object *root, const struct unicode_str *name, -- unsigned int attr, int initval, int max, enum esync_type type, -- const struct security_descriptor *sd ) --{ --#ifdef HAVE_SYS_EVENTFD_H -- struct esync *esync; -- -- if ((esync = create_named_object( root, &esync_ops, name, attr, sd ))) -- { -- if (get_error() != STATUS_OBJECT_NAME_EXISTS) -- { -- int flags = EFD_CLOEXEC | EFD_NONBLOCK; -- -- if (type == ESYNC_SEMAPHORE) -- flags |= EFD_SEMAPHORE; -- -- /* initialize it if it didn't already exist */ -- esync->fd = eventfd( initval, flags ); -- if (esync->fd == -1) -- { -- perror( "eventfd" ); -- file_set_error(); -- release_object( esync ); -- return NULL; -- } -- esync->type = type; -- -- /* Use the fd as index, since that'll be unique across all -- * processes, but should hopefully end up also allowing reuse. */ -- esync->shm_idx = esync->fd + 1; /* we keep index 0 reserved */ -- while (esync->shm_idx * 8 >= shm_size) -- { -- /* Better expand the shm section. */ -- shm_size += pagesize; -- if (ftruncate( shm_fd, shm_size ) == -1) -- { -- fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -- shm_name, (long)shm_size ); -- perror( "ftruncate" ); -- } -- } -- -- /* Initialize the shared memory portion. We want to do this on the -- * server side to avoid a potential though unlikely race whereby -- * the same object is opened and used between the time it's created -- * and the time its shared memory portion is initialized. */ -- switch (type) -- { -- case ESYNC_SEMAPHORE: -- { -- struct semaphore *semaphore = get_shm( esync->shm_idx ); -- semaphore->max = max; -- semaphore->count = initval; -- break; -- } -- case ESYNC_AUTO_EVENT: -- case ESYNC_MANUAL_EVENT: -- { -- struct event *event = get_shm( esync->shm_idx ); -- event->signaled = initval ? 1 : 0; -- event->locked = 0; -- break; -- } -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = get_shm( esync->shm_idx ); -- mutex->tid = initval ? 0 : current->id; -- mutex->count = initval ? 0 : 1; -- list_add_tail( &mutex_list, &esync->mutex_entry ); -- break; -- } -- default: -- assert( 0 ); -- } -- } -- else -- { -- /* validate the type */ -- if (!type_matches( type, esync->type )) -- { -- release_object( &esync->obj ); -- set_error( STATUS_OBJECT_TYPE_MISMATCH ); -- return NULL; -- } -- } -- } -- return esync; --#else -- /* FIXME: Provide a fallback implementation using pipe(). */ -- set_error( STATUS_NOT_IMPLEMENTED ); -- return NULL; --#endif --} -- --/* Create a file descriptor for an existing handle. -- * Caller must close the handle when it's done; it's not linked to an esync -- * server object in any way. */ --int esync_create_fd( int initval, int flags ) --{ --#ifdef HAVE_SYS_EVENTFD_H -- int fd; -- -- fd = eventfd( initval, flags | EFD_CLOEXEC | EFD_NONBLOCK ); -- if (fd == -1) -- perror( "eventfd" ); -- -- return fd; --#else -- return -1; --#endif --} -- --/* Wake up a specific fd. */ --void esync_wake_fd( int fd ) --{ -- static const uint64_t value = 1; -- -- if (write( fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); --} -- --/* Wake up a server-side esync object. */ --void esync_wake_up( struct object *obj ) --{ -- enum esync_type dummy; -- int fd; -- -- if (obj->ops->get_esync_fd) -- { -- fd = obj->ops->get_esync_fd( obj, &dummy ); -- esync_wake_fd( fd ); -- } --} -- --void esync_clear( int fd ) --{ -- uint64_t value; -- -- /* we don't care about the return value */ -- read( fd, &value, sizeof(value) ); --} -- --static inline void small_pause(void) --{ --#ifdef __i386__ -- __asm__ __volatile__( "rep;nop" : : : "memory" ); --#else -- __asm__ __volatile__( "" : : : "memory" ); --#endif --} -- --/* Server-side event support. */ --void esync_set_event( struct esync *esync ) --{ -- static const uint64_t value = 1; -- struct event *event = get_shm( esync->shm_idx ); -- -- assert( esync->obj.ops == &esync_ops ); -- assert( event != NULL ); -- -- if (debug_level) -- fprintf( stderr, "esync_set_event() fd=%d\n", esync->fd ); -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (__sync_val_compare_and_swap( &event->locked, 0, 1 )) -- small_pause(); -- } -- -- if (!__atomic_exchange_n( &event->signaled, 1, __ATOMIC_SEQ_CST )) -- { -- if (write( esync->fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); -- } -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } --} -- --void esync_reset_event( struct esync *esync ) --{ -- static uint64_t value = 1; -- struct event *event = get_shm( esync->shm_idx ); -- -- assert( esync->obj.ops == &esync_ops ); -- assert( event != NULL ); -- -- if (debug_level) -- fprintf( stderr, "esync_reset_event() fd=%d\n", esync->fd ); -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Acquire the spinlock. */ -- while (__sync_val_compare_and_swap( &event->locked, 0, 1 )) -- small_pause(); -- } -- -- /* Only bother signaling the fd if we weren't already signaled. */ -- if (__atomic_exchange_n( &event->signaled, 0, __ATOMIC_SEQ_CST )) -- { -- /* we don't care about the return value */ -- read( esync->fd, &value, sizeof(value) ); -- } -- -- if (esync->type == ESYNC_MANUAL_EVENT) -- { -- /* Release the spinlock. */ -- event->locked = 0; -- } --} -- --void esync_abandon_mutexes( struct thread *thread ) --{ -- struct esync *esync; -- -- LIST_FOR_EACH_ENTRY( esync, &mutex_list, struct esync, mutex_entry ) -- { -- struct mutex *mutex = get_shm( esync->shm_idx ); -- -- if (mutex->tid == thread->id) -- { -- if (debug_level) -- fprintf( stderr, "esync_abandon_mutexes() fd=%d\n", esync->fd ); -- mutex->tid = ~0; -- mutex->count = 0; -- esync_wake_fd( esync->fd ); -- } -- } --} -- --DECL_HANDLER(create_esync) --{ -- struct esync *esync; -- struct unicode_str name; -- struct object *root; -- const struct security_descriptor *sd; -- const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root ); -- -- if (!do_esync()) -- { -- set_error( STATUS_NOT_IMPLEMENTED ); -- return; -- } -- -- if (!req->type) -- { -- set_error( STATUS_INVALID_PARAMETER ); -- return; -- } -- -- if (!objattr) return; -- -- if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->max, req->type, sd ))) -- { -- if (get_error() == STATUS_OBJECT_NAME_EXISTS) -- reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes ); -- else -- reply->handle = alloc_handle_no_access_check( current->process, esync, -- req->access, objattr->attributes ); -- -- reply->type = esync->type; -- reply->shm_idx = esync->shm_idx; -- send_client_fd( current->process, esync->fd, reply->handle ); -- release_object( esync ); -- } -- -- if (root) release_object( root ); --} -- --DECL_HANDLER(open_esync) --{ -- struct unicode_str name = get_req_unicode_str(); -- -- reply->handle = open_object( current->process, req->rootdir, req->access, -- &esync_ops, &name, req->attributes ); -- -- /* send over the fd */ -- if (reply->handle) -- { -- struct esync *esync; -- -- if (!(esync = (struct esync *)get_handle_obj( current->process, reply->handle, -- 0, &esync_ops ))) -- return; -- -- if (!type_matches( req->type, esync->type )) -- { -- set_error( STATUS_OBJECT_TYPE_MISMATCH ); -- release_object( esync ); -- return; -- } -- -- reply->type = esync->type; -- reply->shm_idx = esync->shm_idx; -- -- send_client_fd( current->process, esync->fd, reply->handle ); -- release_object( esync ); -- } --} -- --/* Retrieve a file descriptor for an esync object which will be signaled by the -- * server. The client should only read from (i.e. wait on) this object. */ --DECL_HANDLER(get_esync_fd) --{ -- struct object *obj; -- enum esync_type type; -- int fd; -- -- if (!(obj = get_handle_obj( current->process, req->handle, SYNCHRONIZE, NULL ))) -- return; -- -- if (obj->ops->get_esync_fd) -- { -- fd = obj->ops->get_esync_fd( obj, &type ); -- reply->type = type; -- if (obj->ops == &esync_ops) -- { -- struct esync *esync = (struct esync *)obj; -- reply->shm_idx = esync->shm_idx; -- } -- else -- reply->shm_idx = 0; -- send_client_fd( current->process, fd, req->handle ); -- } -- else -- { -- if (debug_level) -- { -- fprintf( stderr, "%04x: esync: can't wait on object: ", current->id ); -- obj->ops->dump( obj, 0 ); -- } -- set_error( STATUS_NOT_IMPLEMENTED ); -- } -- -- release_object( obj ); --} -- --/* Return the fd used for waiting on user APCs. */ --DECL_HANDLER(get_esync_apc_fd) --{ -- send_client_fd( current->process, current->esync_apc_fd, current->id ); --} -diff --git a/server/esync.h b/server/esync.h -deleted file mode 100644 -index d39f4ef..0000000 ---- a/server/esync.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/* -- * eventfd-based synchronization objects -- * -- * Copyright (C) 2018 Zebediah Figura -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Lesser General Public -- * License as published by the Free Software Foundation; either -- * version 2.1 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Lesser General Public License for more details. -- * -- * You should have received a copy of the GNU Lesser General Public -- * License along with this library; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -- */ -- --#include -- --extern int do_esync(void); --void esync_init(void); --int esync_create_fd( int initval, int flags ); --void esync_wake_fd( int fd ); --void esync_wake_up( struct object *obj ); --void esync_clear( int fd ); -- --struct esync; -- --extern const struct object_ops esync_ops; --void esync_set_event( struct esync *esync ); --void esync_reset_event( struct esync *esync ); --void esync_abandon_mutexes( struct thread *thread ); -diff --git a/server/event.c b/server/event.c -index f4ca3e4..b750a22 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -35,7 +35,6 @@ - #include "thread.h" - #include "request.h" - #include "security.h" --#include "esync.h" - - static const WCHAR event_name[] = {'E','v','e','n','t'}; - -@@ -57,15 +56,15 @@ struct event - struct list kernel_object; /* list of kernel object pointers */ - int manual_reset; /* is it a manual reset event? */ - int signaled; /* event has been signaled */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - 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 ); --static int event_get_esync_fd( struct object *obj, enum esync_type *type ); - static int event_signal( struct object *obj, unsigned int access); - static struct list *event_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ); - static void event_destroy( struct object *obj ); - - static const struct object_ops event_ops = -@@ -76,7 +75,6 @@ static const struct object_ops event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - event_signaled, /* signaled */ -- event_get_esync_fd, /* get_esync_fd */ - event_satisfied, /* satisfied */ - event_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +87,7 @@ static const struct object_ops event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - event_get_kernel_obj_list, /* get_kernel_obj_list */ -+ event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - event_destroy /* destroy */ - }; -@@ -111,10 +110,13 @@ struct type_descr keyed_event_type = - struct keyed_event - { - struct object obj; /* object header */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void keyed_event_dump( struct object *obj, int verbose ); - static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ); -+static void keyed_event_destroy( struct object *obj ); - - static const struct object_ops keyed_event_ops = - { -@@ -124,7 +126,6 @@ static const struct object_ops keyed_event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - keyed_event_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -137,8 +138,9 @@ static const struct object_ops keyed_event_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ keyed_event_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ keyed_event_destroy /* destroy */ - }; - - -@@ -156,9 +158,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; -- -- if (do_esync()) -- event->esync_fd = esync_create_fd( initial_state, 0 ); -+ event->inproc_sync = NULL; - } - } - return event; -@@ -166,10 +166,6 @@ struct event *create_event( struct object *root, const struct unicode_str *name, - - struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access ) - { -- struct object *obj; -- if (do_esync() && (obj = get_handle_obj( process, handle, access, &esync_ops))) -- return (struct event *)obj; /* even though it's not an event */ -- - return (struct event *)get_handle_obj( process, handle, access, &event_ops ); - } - -@@ -183,28 +179,16 @@ static void pulse_event( struct event *event ) - - void set_event( struct event *event ) - { -- if (do_esync() && event->obj.ops == &esync_ops) -- { -- esync_set_event( (struct esync *)event ); -- return; -- } -- - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); -+ set_inproc_event( event->inproc_sync ); - } - - void reset_event( struct event *event ) - { -- if (do_esync() && event->obj.ops == &esync_ops) -- { -- esync_reset_event( (struct esync *)event ); -- return; -- } - event->signaled = 0; -- -- if (do_esync()) -- esync_clear( event->esync_fd ); -+ reset_inproc_event( event->inproc_sync ); - } - - static void event_dump( struct object *obj, int verbose ) -@@ -222,13 +206,6 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) - return event->signaled; - } - --static int event_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct event *event = (struct event *)obj; -- *type = event->manual_reset ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER; -- return event->esync_fd; --} -- - static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct event *event = (struct event *)obj; -@@ -257,12 +234,24 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) - return &event->kernel_object; - } - -+static struct inproc_sync *event_get_inproc_sync( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (!event->inproc_sync) -+ { -+ enum inproc_sync_type type = event->manual_reset ? INPROC_SYNC_MANUAL_EVENT : INPROC_SYNC_AUTO_EVENT; -+ event->inproc_sync = create_inproc_event( type, event->signaled ); -+ } -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ - static void event_destroy( struct object *obj ) - { - struct event *event = (struct event *)obj; - -- if (do_esync()) -- close( event->esync_fd ); -+ if (event->inproc_sync) release_object( event->inproc_sync ); - } - - struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, -@@ -275,6 +264,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod - if (get_error() != STATUS_OBJECT_NAME_EXISTS) - { - /* initialize it if it didn't already exist */ -+ event->inproc_sync = NULL; - } - } - return event; -@@ -318,6 +308,23 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en - return 0; - } - -+static struct inproc_sync *keyed_event_get_inproc_sync( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (!event->inproc_sync) -+ event->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, 1 ); -+ if (event->inproc_sync) grab_object( event->inproc_sync ); -+ return event->inproc_sync; -+} -+ -+static void keyed_event_destroy( struct object *obj ) -+{ -+ struct keyed_event *event = (struct keyed_event *)obj; -+ -+ if (event->inproc_sync) release_object( event->inproc_sync ); -+} -+ - /* create an event */ - DECL_HANDLER(create_event) - { -diff --git a/server/inproc_sync.c b/server/inproc_sync.c -new file mode 100644 -index 0000000..fed6eb9 ---- /dev/null -+++ b/server/inproc_sync.c -@@ -0,0 +1,437 @@ -+/* -+ * In-process synchronization primitives -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "ntstatus.h" -+#define WIN32_NO_STATUS -+#include "winternl.h" -+ -+#include "file.h" -+#include "handle.h" -+#include "request.h" -+#include "thread.h" -+ -+#ifdef HAVE_LINUX_NTSYNC_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct linux_device -+{ -+ struct object obj; /* object header */ -+ struct fd *fd; /* fd for unix fd */ -+}; -+ -+static struct linux_device *linux_device_object; -+ -+static void linux_device_dump( struct object *obj, int verbose ); -+static struct fd *linux_device_get_fd( struct object *obj ); -+static void linux_device_destroy( struct object *obj ); -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ); -+ -+static const struct object_ops linux_device_ops = -+{ -+ sizeof(struct linux_device), /* size */ -+ &no_type, /* type */ -+ linux_device_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_device_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_device_destroy /* destroy */ -+}; -+ -+static const struct fd_ops inproc_sync_fd_ops = -+{ -+ default_fd_get_poll_events, /* get_poll_events */ -+ default_poll_event, /* poll_event */ -+ inproc_sync_get_fd_type, /* get_fd_type */ -+ no_fd_read, /* read */ -+ no_fd_write, /* write */ -+ no_fd_flush, /* flush */ -+ no_fd_get_file_info, /* get_file_info */ -+ no_fd_get_volume_info, /* get_volume_info */ -+ no_fd_ioctl, /* ioctl */ -+ default_fd_cancel_async, /* cancel_async */ -+ no_fd_queue_async, /* queue_async */ -+ default_fd_reselect_async /* reselect_async */ -+}; -+ -+static void linux_device_dump( struct object *obj, int verbose ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ fprintf( stderr, "In-process synchronization device fd=%p\n", device->fd ); -+} -+ -+static struct fd *linux_device_get_fd( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ return (struct fd *)grab_object( device->fd ); -+} -+ -+static void linux_device_destroy( struct object *obj ) -+{ -+ struct linux_device *device = (struct linux_device *)obj; -+ assert( obj->ops == &linux_device_ops ); -+ if (device->fd) release_object( device->fd ); -+ linux_device_object = NULL; -+} -+ -+static enum server_fd_type inproc_sync_get_fd_type( struct fd *fd ) -+{ -+ return FD_TYPE_FILE; -+} -+ -+static struct linux_device *get_linux_device(void) -+{ -+ struct linux_device *device; -+ static int initialized; -+ int unix_fd; -+ -+ if (initialized) -+ { -+ if (linux_device_object) -+ grab_object( linux_device_object ); -+ else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return linux_device_object; -+ } -+ -+ if (getenv( "WINE_DISABLE_FAST_SYNC" ) && atoi( getenv( "WINE_DISABLE_FAST_SYNC" ) )) -+ { -+ static int once; -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ if (!once++) fprintf(stderr, "ntsync is explicitly disabled.\n"); -+ initialized = 1; -+ return NULL; -+ } -+ -+ unix_fd = open( "/dev/ntsync", O_CLOEXEC | O_RDONLY ); -+ if (unix_fd == -1) -+ { -+ static int once; -+ file_set_error(); -+ if (!once++) fprintf(stderr, "Cannot open /dev/ntsync: %s\n", strerror(errno)); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device = alloc_object( &linux_device_ops ))) -+ { -+ close( unix_fd ); -+ set_error( STATUS_NO_MEMORY ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ if (!(device->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &device->obj, 0 ))) -+ { -+ release_object( device ); -+ initialized = 1; -+ return NULL; -+ } -+ -+ fprintf( stderr, "wine: using fast synchronization.\n" ); -+ linux_device_object = device; -+ initialized = 1; -+ return device; -+} -+ -+struct inproc_sync -+{ -+ struct object obj; -+ enum inproc_sync_type type; -+ struct fd *fd; -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ); -+static void linux_obj_destroy( struct object *obj ); -+static struct fd *linux_obj_get_fd( struct object *obj ); -+ -+static const struct object_ops linux_obj_ops = -+{ -+ sizeof(struct inproc_sync), /* size */ -+ &no_type, /* type */ -+ linux_obj_dump, /* dump */ -+ no_add_queue, /* add_queue */ -+ NULL, /* remove_queue */ -+ NULL, /* signaled */ -+ NULL, /* satisfied */ -+ no_signal, /* signal */ -+ linux_obj_get_fd, /* get_fd */ -+ default_map_access, /* map_access */ -+ default_get_sd, /* get_sd */ -+ default_set_sd, /* set_sd */ -+ no_get_full_name, /* get_full_name */ -+ no_lookup_name, /* lookup_name */ -+ no_link_name, /* link_name */ -+ NULL, /* unlink_name */ -+ no_open_file, /* open_file */ -+ no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ -+ no_close_handle, /* close_handle */ -+ linux_obj_destroy /* destroy */ -+}; -+ -+static void linux_obj_dump( struct object *obj, int verbose ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ fprintf( stderr, "In-process synchronization object type=%u fd=%p\n", inproc_sync->type, inproc_sync->fd ); -+} -+ -+static void linux_obj_destroy( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ if (inproc_sync->fd) release_object( inproc_sync->fd ); -+} -+ -+static struct fd *linux_obj_get_fd( struct object *obj ) -+{ -+ struct inproc_sync *inproc_sync = (struct inproc_sync *)obj; -+ assert( obj->ops == &linux_obj_ops ); -+ return (struct fd *)grab_object( inproc_sync->fd ); -+} -+ -+static struct inproc_sync *create_inproc_sync( enum inproc_sync_type type, int unix_fd ) -+{ -+ struct inproc_sync *inproc_sync; -+ -+ if (!(inproc_sync = alloc_object( &linux_obj_ops ))) -+ { -+ close( unix_fd ); -+ return NULL; -+ } -+ -+ inproc_sync->type = type; -+ -+ if (!(inproc_sync->fd = create_anonymous_fd( &inproc_sync_fd_ops, unix_fd, &inproc_sync->obj, 0 ))) -+ { -+ release_object( inproc_sync ); -+ return NULL; -+ } -+ -+ return inproc_sync; -+} -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ struct ntsync_event_args args; -+ struct linux_device *device; -+ int event; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.signaled = signaled; -+ switch (type) -+ { -+ case INPROC_SYNC_AUTO_EVENT: -+ case INPROC_SYNC_AUTO_SERVER: -+ args.manual = 0; -+ break; -+ -+ case INPROC_SYNC_MANUAL_EVENT: -+ case INPROC_SYNC_MANUAL_SERVER: -+ case INPROC_SYNC_QUEUE: -+ args.manual = 1; -+ break; -+ -+ case INPROC_SYNC_MUTEX: -+ case INPROC_SYNC_SEMAPHORE: -+ assert(0); -+ break; -+ } -+ if ((event = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_EVENT, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ release_object( device ); -+ -+ return create_inproc_sync( type, event ); -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ struct ntsync_sem_args args; -+ struct linux_device *device; -+ int semaphore; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.count = count; -+ args.max = max; -+ if ((semaphore = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_SEM, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_SEMAPHORE, semaphore ); -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ struct ntsync_mutex_args args; -+ struct linux_device *device; -+ int mutex; -+ -+ if (!(device = get_linux_device())) return NULL; -+ -+ args.owner = owner; -+ args.count = count; -+ if ((mutex = ioctl( get_unix_fd( device->fd ), NTSYNC_IOC_CREATE_MUTEX, &args )) < 0) -+ { -+ file_set_error(); -+ release_object( device ); -+ return NULL; -+ } -+ -+ release_object( device ); -+ -+ return create_inproc_sync( INPROC_SYNC_MUTEX, mutex ); -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_SET, &count ); -+} -+ -+void reset_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+ __u32 count; -+ -+ if (!inproc_sync) return; -+ -+ if (debug_level) fprintf( stderr, "set_inproc_event %p\n", inproc_sync->fd ); -+ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_EVENT_RESET, &count ); -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+ ioctl( get_unix_fd( inproc_sync->fd ), NTSYNC_IOC_MUTEX_KILL, &tid ); -+} -+ -+#else -+ -+struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ) -+{ -+ set_error( STATUS_NOT_IMPLEMENTED ); -+ return NULL; -+} -+ -+void set_inproc_event( struct inproc_sync *inproc_sync ) -+{ -+} -+ -+void reset_inproc_event( struct inproc_sync *obj ) -+{ -+} -+ -+void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ) -+{ -+} -+ -+#endif -+ -+DECL_HANDLER(get_linux_sync_device) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct linux_device *device; -+ -+ if ((device = get_linux_device())) -+ { -+ reply->handle = alloc_handle( current->process, device, 0, 0 ); -+ release_object( device ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -+ -+DECL_HANDLER(get_linux_sync_obj) -+{ -+#ifdef HAVE_LINUX_NTSYNC_H -+ struct object *obj; -+ -+ if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) -+ { -+ struct inproc_sync *inproc_sync; -+ -+ if ((inproc_sync = obj->ops->get_inproc_sync( obj ))) -+ { -+ reply->handle = alloc_handle( current->process, inproc_sync, 0, 0 ); -+ reply->type = inproc_sync->type; -+ reply->access = get_handle_access( current->process, req->handle ); -+ release_object( inproc_sync ); -+ } -+ release_object( obj ); -+ } -+#else -+ set_error( STATUS_NOT_IMPLEMENTED ); -+#endif -+} -diff --git a/server/fd.c b/server/fd.c -index a6782b0..f00e22d 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -97,7 +97,6 @@ - #include "handle.h" - #include "process.h" - #include "request.h" --#include "esync.h" - - #include "winternl.h" - #include "winioctl.h" -@@ -162,7 +161,7 @@ struct fd - struct completion *completion; /* completion object attached to this fd */ - apc_param_t comp_key; /* completion key to set in completion events */ - unsigned int comp_flags; /* completion flags */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -176,7 +175,6 @@ static const struct object_ops fd_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -189,6 +187,7 @@ static const struct object_ops fd_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - fd_destroy /* destroy */ - }; -@@ -218,7 +217,6 @@ static const struct object_ops device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -231,6 +229,7 @@ static const struct object_ops device_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - device_destroy /* destroy */ - }; -@@ -259,7 +258,6 @@ static const struct object_ops inode_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -272,6 +270,7 @@ static const struct object_ops inode_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - inode_destroy /* destroy */ - }; -@@ -302,7 +301,6 @@ static const struct object_ops file_lock_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - file_lock_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -315,6 +313,7 @@ static const struct object_ops file_lock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -1651,9 +1650,7 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); - free( fd->unix_name ); - } -- -- if (do_esync()) -- close( fd->esync_fd ); -+ if (fd->inproc_sync) release_object( fd->inproc_sync ); - } - - /* check if the desired access is possible without violating */ -@@ -1772,16 +1769,13 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -- fd->esync_fd = -1; -+ fd->inproc_sync = NULL; - 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 ); - -- if (do_esync()) -- fd->esync_fd = esync_create_fd( 1, 0 ); -- - if ((fd->poll_index = add_poll_user( fd )) == -1) - { - release_object( fd ); -@@ -1816,16 +1810,13 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->inproc_sync = NULL; - fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; -- fd->esync_fd = -1; - 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 ); -- -- if (do_esync()) -- fd->esync_fd = esync_create_fd( 0, 0 ); - return fd; - } - -@@ -2282,10 +2273,15 @@ void set_fd_signaled( struct fd *fd, int signaled ) - { - if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; -- if (signaled) wake_up( fd->user, 0 ); -- -- if (do_esync() && !signaled) -- esync_clear( fd->esync_fd ); -+ if (signaled) -+ { -+ wake_up( fd->user, 0 ); -+ set_inproc_event( fd->inproc_sync ); -+ } -+ else -+ { -+ reset_inproc_event( fd->inproc_sync ); -+ } - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2311,12 +2307,16 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) - return ret; - } - --int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ) -+struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ) - { - struct fd *fd = get_obj_fd( obj ); -- int ret = fd->esync_fd; -- *type = ESYNC_MANUAL_SERVER; -+ struct inproc_sync *ret; -+ -+ if (!fd->inproc_sync) -+ fd->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, fd->signaled ); -+ ret = fd->inproc_sync; - release_object( fd ); -+ if (ret) grab_object( ret ); - return ret; - } - -diff --git a/server/file.c b/server/file.c -index 828a21c..c6bdbef 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -123,7 +123,6 @@ static const struct object_ops file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - file_get_fd, /* get_fd */ -@@ -136,6 +135,7 @@ static const struct object_ops file_ops = - NULL, /* unlink_name */ - file_open_file, /* open_file */ - file_get_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - file_destroy /* destroy */ - }; -diff --git a/server/file.h b/server/file.h -index abad355..6b4fa51 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -108,7 +108,7 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre - extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); --extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ); -+extern struct inproc_sync *default_fd_get_inproc_sync( struct object *obj ); - 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 -index cf6afe4..e07f32c 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -126,7 +126,6 @@ static const struct object_ops handle_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -139,6 +138,7 @@ static const struct object_ops handle_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handle_table_destroy /* destroy */ - }; -diff --git a/server/hook.c b/server/hook.c -index da351d6..5a00699 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -80,7 +80,6 @@ static const struct object_ops hook_table_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -93,6 +92,7 @@ static const struct object_ops hook_table_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - hook_table_destroy /* destroy */ - }; -diff --git a/server/mailslot.c b/server/mailslot.c -index 4cf9b73..d9807b4 100644 ---- a/server/mailslot.c -+++ b/server/mailslot.c -@@ -74,7 +74,6 @@ static const struct object_ops mailslot_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - mailslot_get_fd, /* get_fd */ -@@ -87,6 +86,7 @@ static const struct object_ops mailslot_ops = - default_unlink_name, /* unlink_name */ - mailslot_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync,/* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_destroy /* destroy */ - }; -@@ -134,7 +134,6 @@ static const struct object_ops mail_writer_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - mail_writer_get_fd, /* get_fd */ -@@ -147,6 +146,7 @@ static const struct object_ops mail_writer_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mail_writer_destroy /* destroy */ - }; -@@ -198,7 +198,6 @@ static const struct object_ops mailslot_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -211,6 +210,7 @@ static const struct object_ops mailslot_device_ops = - default_unlink_name, /* unlink_name */ - mailslot_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_destroy /* destroy */ - }; -@@ -229,7 +229,6 @@ static const struct object_ops mailslot_device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - mailslot_device_file_get_fd, /* get_fd */ -@@ -242,6 +241,7 @@ static const struct object_ops mailslot_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mailslot_device_file_destroy /* destroy */ - }; -diff --git a/server/main.c b/server/main.c -index 5062d09..ddda5f4 100644 ---- a/server/main.c -+++ b/server/main.c -@@ -34,7 +34,6 @@ - #include "thread.h" - #include "request.h" - #include "unicode.h" --#include "esync.h" - - /* command-line options */ - int debug_level = 0; -@@ -230,9 +229,6 @@ int main( int argc, char *argv[] ) - sock_init(); - open_master_socket(); - -- if (do_esync()) -- esync_init(); -- - if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); - set_current_time(); - init_scheduler(); -diff --git a/server/mapping.c b/server/mapping.c -index 88de806..c3cba90 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -67,7 +67,6 @@ static const struct object_ops ranges_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -80,6 +79,7 @@ static const struct object_ops ranges_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ranges_destroy /* destroy */ - }; -@@ -104,7 +104,6 @@ static const struct object_ops shared_map_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -117,6 +116,7 @@ static const struct object_ops shared_map_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - shared_map_destroy /* destroy */ - }; -@@ -178,7 +178,6 @@ static const struct object_ops mapping_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - mapping_get_fd, /* get_fd */ -@@ -191,6 +190,7 @@ static const struct object_ops mapping_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mapping_destroy /* destroy */ - }; -diff --git a/server/mutex.c b/server/mutex.c -index 4785a83..167c236 100644 ---- a/server/mutex.c -+++ b/server/mutex.c -@@ -38,6 +38,8 @@ - - static const WCHAR mutex_name[] = {'M','u','t','a','n','t'}; - -+static struct list inproc_mutexes = LIST_INIT(inproc_mutexes); -+ - struct type_descr mutex_type = - { - { mutex_name, sizeof(mutex_name) }, /* name */ -@@ -57,6 +59,8 @@ struct mutex - unsigned int count; /* recursion count */ - int abandoned; /* has it been abandoned? */ - struct list entry; /* entry in owner thread mutex list */ -+ struct list inproc_mutexes_entry; /* entry in inproc_mutexes list */ -+ struct inproc_sync *inproc_sync;/* in-process synchronization object */ - }; - - static void mutex_dump( struct object *obj, int verbose ); -@@ -64,6 +68,7 @@ static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static void mutex_destroy( struct object *obj ); - static int mutex_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ); - - static const struct object_ops mutex_ops = - { -@@ -73,7 +78,6 @@ static const struct object_ops mutex_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - mutex_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - mutex_satisfied, /* satisfied */ - mutex_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -86,6 +90,7 @@ static const struct object_ops mutex_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ mutex_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - mutex_destroy /* destroy */ - }; -@@ -128,6 +133,7 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - mutex->owner = NULL; - mutex->abandoned = 0; - if (owned) do_grab( mutex, current ); -+ mutex->inproc_sync = NULL; - } - } - return mutex; -@@ -135,16 +141,22 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str - - void abandon_mutexes( struct thread *thread ) - { -+ struct mutex *mutex; - struct list *ptr; - - while ((ptr = list_head( &thread->mutex_list )) != NULL) - { -- struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry ); -+ mutex = LIST_ENTRY( ptr, struct mutex, entry ); - assert( mutex->owner == thread ); - mutex->count = 0; - mutex->abandoned = 1; - do_release( mutex ); - } -+ -+ LIST_FOR_EACH_ENTRY(mutex, &inproc_mutexes, struct mutex, inproc_mutexes_entry) -+ { -+ abandon_inproc_mutex( thread->id, mutex->inproc_sync ); -+ } - } - - static void mutex_dump( struct object *obj, int verbose ) -@@ -190,14 +202,34 @@ static int mutex_signal( struct object *obj, unsigned int access ) - return 1; - } - -+static struct inproc_sync *mutex_get_inproc_sync( struct object *obj ) -+{ -+ struct mutex *mutex = (struct mutex *)obj; -+ -+ if (!mutex->inproc_sync) -+ { -+ mutex->inproc_sync = create_inproc_mutex( mutex->owner ? mutex->owner->id : 0, mutex->count ); -+ if (mutex->inproc_sync) list_add_tail( &inproc_mutexes, &mutex->inproc_mutexes_entry ); -+ } -+ if (mutex->inproc_sync) grab_object( mutex->inproc_sync ); -+ return mutex->inproc_sync; -+} -+ - static void mutex_destroy( struct object *obj ) - { - struct mutex *mutex = (struct mutex *)obj; - assert( obj->ops == &mutex_ops ); - -- if (!mutex->count) return; -- mutex->count = 0; -- do_release( mutex ); -+ if (mutex->count) -+ { -+ mutex->count = 0; -+ do_release( mutex ); -+ } -+ if (mutex->inproc_sync) -+ { -+ release_object( mutex->inproc_sync ); -+ list_remove( &mutex->inproc_mutexes_entry ); -+ } - } - - /* create a mutex */ -diff --git a/server/named_pipe.c b/server/named_pipe.c -index a90ec60..6d8cb3e 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -119,7 +119,6 @@ static const struct object_ops named_pipe_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -132,6 +131,7 @@ static const struct object_ops named_pipe_ops = - default_unlink_name, /* unlink_name */ - named_pipe_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_destroy /* destroy */ - }; -@@ -168,7 +168,6 @@ static const struct object_ops pipe_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -181,6 +180,7 @@ static const struct object_ops pipe_server_ops = - NULL, /* unlink_name */ - pipe_server_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_server_destroy /* destroy */ - }; -@@ -213,7 +213,6 @@ static const struct object_ops pipe_client_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -226,6 +225,7 @@ static const struct object_ops pipe_client_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - async_close_obj_handle, /* close_handle */ - pipe_end_destroy /* destroy */ - }; -@@ -261,7 +261,6 @@ static const struct object_ops named_pipe_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -274,6 +273,7 @@ static const struct object_ops named_pipe_device_ops = - default_unlink_name, /* unlink_name */ - named_pipe_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_destroy /* destroy */ - }; -@@ -293,7 +293,6 @@ static const struct object_ops named_pipe_device_file_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - named_pipe_device_file_get_fd, /* get_fd */ -@@ -306,6 +305,7 @@ static const struct object_ops named_pipe_device_file_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_device_file_destroy /* destroy */ - }; -@@ -344,7 +344,6 @@ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - named_pipe_dir_get_fd, /* get_fd */ -@@ -357,6 +356,7 @@ - NULL, /* unlink_name */ - named_pipe_dir_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - named_pipe_dir_destroy /* destroy */ - }; -diff --git a/server/object.c b/server/object.c -index 29f1ea9..33fc18c 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -120,19 +120,19 @@ static const struct object_ops apc_reserve_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - directory_link_name, /* link_name */ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -144,19 +145,19 @@ static const struct object_ops completion_reserve_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ - default_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ - directory_link_name, /* link_name */ - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -538,6 +538,12 @@ struct fd *no_get_fd( struct object *obj ) - return NULL; - } - -+struct inproc_sync *no_get_inproc_sync( struct object *obj ) -+{ -+ set_error( STATUS_OBJECT_TYPE_MISMATCH ); -+ return NULL; -+} -+ - unsigned int default_map_access( struct object *obj, unsigned int access ) - { - return map_access( access, &obj->ops->type->mapping ); -diff --git a/server/object.h b/server/object.h -index 6f4bca8..f028a8e 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -42,6 +42,7 @@ struct async; - struct async_queue; - struct winstation; - struct object_type; -+struct inproc_sync; - - - struct unicode_str -@@ -78,8 +79,6 @@ struct object_ops - void (*remove_queue)(struct object *,struct wait_queue_entry *); - /* is object signaled? */ - int (*signaled)(struct object *,struct wait_queue_entry *); -- /* return the esync fd for this object */ -- int (*get_esync_fd)(struct object *, enum esync_type *type); - /* wait satisfied */ - void (*satisfied)(struct object *,struct wait_queue_entry *); - /* signal an object */ -@@ -105,6 +104,8 @@ struct object_ops - unsigned int options); - /* return list of kernel objects */ - struct list *(*get_kernel_obj_list)(struct object *); -+ /* get a client-waitable in-process synchronization handle to this object */ -+ struct inproc_sync *(*get_inproc_sync)(struct object *); - /* close a handle to this object */ - int (*close_handle)(struct object *,struct process *,obj_handle_t); - /* destroy on refcount == 0 */ -@@ -224,6 +225,17 @@ extern void reset_event( struct event *event ); - - extern void abandon_mutexes( struct thread *thread ); - -+/* in-process synchronization functions */ -+ -+extern struct inproc_sync *create_inproc_event( enum inproc_sync_type type, int signaled ); -+extern struct inproc_sync *create_inproc_mutex( thread_id_t owner, unsigned int count ); -+extern struct inproc_sync *create_inproc_semaphore( unsigned int count, unsigned int max ); -+extern void set_inproc_event( struct inproc_sync *obj ); -+extern void reset_inproc_event( struct inproc_sync *obj ); -+extern void abandon_inproc_mutex( thread_id_t tid, struct inproc_sync *inproc_sync ); -+ -+extern struct inproc_sync *no_get_inproc_sync( struct object *obj ); -+ - /* serial functions */ - - int get_serial_async_timeout(struct object *obj, int type, int count); -diff --git a/server/process.c b/server/process.c -index 6d66a7c..34451c1 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -63,7 +63,6 @@ - #include "request.h" - #include "user.h" - #include "security.h" --#include "esync.h" - - /* process object */ - -@@ -95,8 +94,8 @@ static unsigned int process_map_access( struct object *obj, unsigned int access - static struct security_descriptor *process_get_sd( struct object *obj ); - static void process_poll_event( struct fd *fd, int event ); - static struct list *process_get_kernel_obj_list( struct object *obj ); -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ); - static void process_destroy( struct object *obj ); --static int process_get_esync_fd( struct object *obj, enum esync_type *type ); - static void terminate_process( struct process *process, struct thread *skip, int exit_code ); - - static const struct object_ops process_ops = -@@ -107,7 +106,6 @@ static const struct object_ops process_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - process_signaled, /* signaled */ -- process_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -120,6 +118,7 @@ static const struct object_ops process_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - process_get_kernel_obj_list, /* get_kernel_obj_list */ -+ process_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - process_destroy /* destroy */ - }; -@@ -159,7 +158,6 @@ static const struct object_ops startup_info_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - startup_info_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -172,6 +170,7 @@ static const struct object_ops startup_info_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - startup_info_destroy /* destroy */ - }; -@@ -194,6 +193,7 @@ struct type_descr job_type = - - static void job_dump( struct object *obj, int verbose ); - static int job_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ); - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); - static void job_destroy( struct object *obj ); - -@@ -211,6 +211,7 @@ struct job - struct job *parent; - struct list parent_job_entry; /* list entry for parent job */ - struct list child_job_list; /* list of child jobs */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static const struct object_ops job_ops = -@@ -221,7 +222,6 @@ static const struct object_ops job_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - job_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -234,6 +234,7 @@ static const struct object_ops job_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ job_get_inproc_sync, /* get_inproc_sync */ - job_close_handle, /* close_handle */ - job_destroy /* destroy */ - }; -@@ -258,6 +259,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_ - job->completion_port = NULL; - job->completion_key = 0; - job->parent = NULL; -+ job->inproc_sync = NULL; - } - } - return job; -@@ -414,6 +416,17 @@ static void terminate_job( struct job *job, int exit_code ) - job->terminating = 0; - job->signaled = 1; - wake_up( &job->obj, 0 ); -+ set_inproc_event( job->inproc_sync ); -+} -+ -+static struct inproc_sync *job_get_inproc_sync( struct object *obj ) -+{ -+ struct job *job = (struct job *)obj; -+ -+ if (!job->inproc_sync) -+ job->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, job->signaled ); -+ if (job->inproc_sync) grab_object( job->inproc_sync ); -+ return job->inproc_sync; - } - - static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) -@@ -444,6 +457,8 @@ static void job_destroy( struct object *obj ) - list_remove( &job->parent_job_entry ); - release_object( job->parent ); - } -+ -+ if (job->inproc_sync) release_object( job->inproc_sync ); - } - - static void job_dump( struct object *obj, int verbose ) -@@ -688,9 +703,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_device_count = 0; - process->rawinput_mouse = NULL; - process->rawinput_kbd = NULL; -+ process->inproc_sync = NULL; - memset( &process->image_info, 0, sizeof(process->image_info) ); - list_init( &process->rawinput_entry ); -- process->esync_fd = -1; - list_init( &process->kernel_object ); - list_init( &process->thread_list ); - list_init( &process->locks ); -@@ -747,9 +762,6 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - if (!token_assign_label( process->token, &high_label_sid )) - goto error; - -- if (do_esync()) -- process->esync_fd = esync_create_fd( 0, 0 ); -- - set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ - return process; - -@@ -798,7 +810,8 @@ static void process_destroy( struct object *obj ) - free( process->rawinput_devices ); - free( process->dir_cache ); - free( process->image ); -- if (do_esync()) close( process->esync_fd ); -+ -+ if (process->inproc_sync) release_object( process->inproc_sync ); - } - - /* dump a process on stdout for debugging purposes */ -@@ -816,13 +829,6 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry - return !process->running_threads; - } - --static int process_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct process *process = (struct process *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return process->esync_fd; --} -- - static unsigned int process_map_access( struct object *obj, unsigned int access ) - { - access = default_map_access( obj, access ); -@@ -837,6 +843,16 @@ static struct list *process_get_kernel_obj_list( struct object *obj ) - return &process->kernel_object; - } - -+static struct inproc_sync *process_get_inproc_sync( struct object *obj ) -+{ -+ struct process *process = (struct process *)obj; -+ -+ if (!process->inproc_sync) -+ process->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, !process->running_threads ); -+ if (process->inproc_sync) grab_object( process->inproc_sync ); -+ return process->inproc_sync; -+} -+ - static struct security_descriptor *process_get_sd( struct object *obj ) - { - static struct security_descriptor *process_default_sd; -@@ -1001,6 +1017,7 @@ static void process_killed( struct process *process ) - release_job_process( process ); - start_sigkill_timer( process ); - wake_up( &process->obj, 0 ); -+ set_inproc_event( process->inproc_sync ); - } - - /* add a thread to a process running threads list */ -diff --git a/server/process.h b/server/process.h -index bedd8bb..2140427 100644 ---- a/server/process.h -+++ b/server/process.h -@@ -86,7 +86,7 @@ struct process - struct list rawinput_entry; /* entry in the rawinput process list */ - struct list kernel_object; /* list of kernel object pointers */ - struct pe_image_info image_info; /* main exe image info */ -- int esync_fd; /* esync file descriptor (signaled on exit) */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - /* process functions */ -diff --git a/server/protocol.def b/server/protocol.def -index 4983691..7bc4208 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -3887,6 +3887,7 @@ struct handle_info - obj_handle_t handle; /* process handle */ - @END - -+ - /* Iterate thread list for process */ - @REQ(get_next_thread) - obj_handle_t process; /* process handle */ -@@ -3898,63 +3899,58 @@ struct handle_info - obj_handle_t handle; /* next thread handle */ - @END - --enum esync_type -+ -+enum inproc_sync_type - { -- ESYNC_SEMAPHORE = 1, -- ESYNC_AUTO_EVENT, -- ESYNC_MANUAL_EVENT, -- ESYNC_MUTEX, -- ESYNC_AUTO_SERVER, -- ESYNC_MANUAL_SERVER, -- ESYNC_QUEUE, -+ INPROC_SYNC_SEMAPHORE = 1, -+ INPROC_SYNC_MUTEX, -+ INPROC_SYNC_AUTO_EVENT, -+ INPROC_SYNC_MANUAL_EVENT, -+ INPROC_SYNC_AUTO_SERVER, -+ INPROC_SYNC_MANUAL_SERVER, -+ INPROC_SYNC_QUEUE, - }; - --/* Create a new eventfd-based synchronization object */ --@REQ(create_esync) -- unsigned int access; /* wanted access rights */ -- int initval; /* initial value */ -- int type; /* type of esync object */ -- int max; /* maximum count on a semaphore */ -- VARARG(objattr,object_attributes); /* object attributes */ -+ -+/* Obtain a handle to the fast synchronization device object */ -+@REQ(get_linux_sync_device) - @REPLY -- obj_handle_t handle; /* handle to the object */ -- int type; /* actual type (may be different for events) */ -- unsigned int shm_idx; -+ obj_handle_t handle; /* handle to the device */ - @END - --@REQ(open_esync) -- unsigned int access; /* wanted access rights */ -- unsigned int attributes; /* object attributes */ -- obj_handle_t rootdir; /* root directory */ -- int type; /* type of esync object (above) */ -- VARARG(name,unicode_str); /* object name */ -+ -+/* Get the in-process synchronization object associated with the given handle */ -+@REQ(get_linux_sync_obj) -+ obj_handle_t handle; /* handle to the object */ - @REPLY -- obj_handle_t handle; /* handle to the event */ -- int type; /* type of esync object (above) */ -- unsigned int shm_idx; /* this object's index into the shm section */ -+ obj_handle_t handle; /* handle to the fast synchronization object */ -+ int type; /* object type */ -+ unsigned int access; /* handle access rights */ - @END - --/* Retrieve the esync fd for an object. */ --@REQ(get_esync_fd) -- obj_handle_t handle; /* handle to the object */ --@REPLY -- int type; -- unsigned int shm_idx; -+ -+/* Begin a client-side wait on a message queue */ -+@REQ(select_inproc_queue) - @END - --@REQ(esync_msgwait) -- int in_msgwait; /* are we in a message wait? */ -+ -+/* End a client-side wait on a message queue */ -+@REQ(unselect_inproc_queue) -+ int signaled; /* was the queue signaled? */ - @END - - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ - int delay; /* auto-repeat delay in ms */ - int period; /* auto-repeat period in ms */ - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END - --/* Retrieve the fd to wait on for user APCs. */ --@REQ(get_esync_apc_fd) -+ -+/* Get an event handle to be used for thread alerts with in-process synchronization */ -+@REQ(get_inproc_alert_event) -+@REPLY -+ obj_handle_t handle; /* handle to the event */ - @END -diff --git a/server/queue.c b/server/queue.c -index fee3a8d..287a56e 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -43,7 +43,6 @@ - #include "process.h" - #include "request.h" - #include "user.h" --#include "esync.h" - - #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE - #define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST)) -@@ -147,8 +146,8 @@ struct msg_queue - timeout_t last_get_msg; /* time of last get message call */ - int keystate_lock; /* owns an input keystate lock */ - 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 */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ int in_inproc_wait; /* are we in a client-side wait? */ - }; - - struct hotkey -@@ -165,8 +164,8 @@ static void msg_queue_dump( struct object *obj, int verbose ); - static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ); - 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 ); - static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ); - static void msg_queue_destroy( struct object *obj ); - static void msg_queue_poll_event( struct fd *fd, int event ); - static void thread_input_dump( struct object *obj, int verbose ); -@@ -181,7 +180,6 @@ static const struct object_ops msg_queue_ops = - msg_queue_add_queue, /* add_queue */ - msg_queue_remove_queue, /* remove_queue */ - msg_queue_signaled, /* signaled */ -- msg_queue_get_esync_fd, /* get_esync_fd */ - msg_queue_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -194,6 +192,7 @@ static const struct object_ops msg_queue_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ msg_queue_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - msg_queue_destroy /* destroy */ - }; -@@ -219,7 +218,6 @@ static const struct object_ops thread_input_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -232,6 +230,7 @@ static const struct object_ops thread_input_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_input_destroy /* destroy */ - }; -@@ -321,33 +320,30 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->last_get_msg = current_time; - queue->keystate_lock = 0; - queue->ignore_post_msg = 0; -- queue->esync_fd = -1; -- queue->esync_in_msgwait = 0; -+ queue->inproc_sync = NULL; -+ queue->in_inproc_wait = 0; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); - list_init( &queue->expired_timers ); - for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] ); - - if (!(queue->shared = alloc_shared_object())) - { - release_object( queue ); - return NULL; - } - - SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) - { - memset( (void *)shared->hooks_count, 0, sizeof(shared->hooks_count) ); - shared->wake_mask = 0; - shared->wake_bits = 0; - shared->changed_mask = 0; - shared->changed_bits = 0; - } - SHARED_WRITE_END; - -- if (do_esync()) -- queue->esync_fd = esync_create_fd( 0, 0 ); -- - thread->queue = queue; - } - -@@ -606,7 +602,11 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) - } - SHARED_WRITE_END; - -- if (is_signaled( queue )) wake_up( &queue->obj, 0 ); -+ if (is_signaled( queue )) -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } - } - - /* clear some queue bits */ -@@ -620,9 +620,8 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits - if (queue->keystate_lock) unlock_input_keystate( queue->input ); - queue->keystate_lock = 0; - } -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - - /* check if message is matched by the filter */ -@@ -1112,8 +1111,8 @@ static int is_queue_hung( struct msg_queue *queue ) - return 0; /* thread is waiting on queue -> not hung */ - } - -- if (do_esync() && queue->esync_in_msgwait) -- return 0; /* thread is waiting on queue in absentia -> not hung */ -+ if (queue->in_inproc_wait) -+ return 0; /* thread is waiting on queue in absentia -> not hung */ - - return 1; - } -@@ -1168,24 +1167,29 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr - return ret || is_signaled( queue ); - } - --static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type ) -+static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct msg_queue *queue = (struct msg_queue *)obj; -- *type = ESYNC_QUEUE; -- return queue->esync_fd; -+ const queue_shm_t *queue_shm = queue->shared; -+ -+ SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) -+ { -+ shared->wake_mask = 0; -+ shared->changed_mask = 0; -+ } -+ SHARED_WRITE_END; -+ -+ reset_inproc_event( queue->inproc_sync ); - } - --static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct inproc_sync *msg_queue_get_inproc_sync( struct object *obj ) - { - struct msg_queue *queue = (struct msg_queue *)obj; -- const queue_shm_t *queue_shm = queue->shared; - -- SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) -- { -- shared->wake_mask = 0; -- shared->changed_mask = 0; -- } -- SHARED_WRITE_END; -+ if (!queue->inproc_sync) -+ queue->inproc_sync = create_inproc_event( INPROC_SYNC_QUEUE, is_signaled( queue ) ); -+ if (queue->inproc_sync) grab_object( queue->inproc_sync ); -+ return queue->inproc_sync; - } - - static void msg_queue_destroy( struct object *obj ) -@@ -1221,7 +1224,7 @@ static void msg_queue_destroy( struct object *obj ) - if (queue->hooks) release_object( queue->hooks ); - if (queue->fd) release_object( queue->fd ); - if (queue->shared) free_shared_object( queue->shared ); -- if (do_esync()) close( queue->esync_fd ); -+ if (queue->inproc_sync) release_object( queue->inproc_sync ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -1232,6 +1235,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) - if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); - else set_fd_events( queue->fd, 0 ); - wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); - } - - static void thread_input_dump( struct object *obj, int verbose ) -@@ -2982,10 +2982,15 @@ DECL_HANDLER(set_queue_mask) - } - SHARED_WRITE_END; -+ } -+ else -+ { -+ wake_up( &queue->obj, 0 ); -+ set_inproc_event( queue->inproc_sync ); -+ } -+ } -+ else -+ { -+ reset_inproc_event( queue->inproc_sync ); -- } -- else wake_up( &queue->obj, 0 ); - } -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); - } - } -@@ -2867,8 +2880,8 @@ DECL_HANDLER(get_queue_status) - } - SHARED_WRITE_END; - -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); - } - else reply->wake_bits = reply->changed_bits = 0; - } -@@ -3049,6 +3061,9 @@ DECL_HANDLER(get_message) - if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT; - if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT; - -+ if (!is_signaled( queue )) -+ reset_inproc_event( queue->inproc_sync ); -+ - /* then check for posted messages */ - if ((filter & QS_POSTMESSAGE) && - get_posted_message( queue, queue->ignore_post_msg, get_win, req->get_first, req->get_last, req->flags, reply )) -@@ -3119,11 +3134,8 @@ DECL_HANDLER(get_message) - shared->changed_mask = req->changed_mask; - } - SHARED_WRITE_END; - -+ reset_inproc_event( queue->inproc_sync ); - set_error( STATUS_PENDING ); /* FIXME */ -- -- if (do_esync() && !is_signaled( queue )) -- esync_clear( queue->esync_fd ); -- - return; - - found_msg: -diff --git a/server/registry.c b/server/registry.c -index 4454de3..dd5c556 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -180,7 +180,6 @@ static const struct object_ops key_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -193,6 +192,7 @@ static const struct object_ops key_ops = - key_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - key_close_handle, /* close_handle */ - key_destroy /* destroy */ - }; -diff --git a/server/request.c b/server/request.c -index ca83fdb..8c50f99 100644 ---- a/server/request.c -+++ b/server/request.c -@@ -90,7 +90,6 @@ static const struct object_ops master_socket_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -103,6 +102,7 @@ static const struct object_ops master_socket_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - master_socket_destroy /* destroy */ - }; -diff --git a/server/request_handlers.h b/server/request_handlers.h -index eb6b8f4..1636e98 100644 ---- a/server/request_handlers.h 2024-11-18 18:02:30.072599085 +0500 -+++ b/server/request_handlers.h 2024-11-18 18:14:42.357268807 +0500 -@@ -298,12 +298,12 @@ - DECL_HANDLER(suspend_process); - DECL_HANDLER(resume_process); - DECL_HANDLER(get_next_thread); --DECL_HANDLER(create_esync); --DECL_HANDLER(open_esync); --DECL_HANDLER(get_esync_fd); --DECL_HANDLER(esync_msgwait); - DECL_HANDLER(set_keyboard_repeat); --DECL_HANDLER(get_esync_apc_fd); -+DECL_HANDLER(get_linux_sync_device); -+DECL_HANDLER(get_linux_sync_obj); -+DECL_HANDLER(select_inproc_queue); -+DECL_HANDLER(unselect_inproc_queue); -+DECL_HANDLER(get_inproc_alert_event); - - typedef void (*req_handler)( const void *req, void *reply ); - static const req_handler req_handlers[REQ_NB_REQUESTS] = -@@ -599,12 +599,12 @@ - (req_handler)req_suspend_process, - (req_handler)req_resume_process, - (req_handler)req_get_next_thread, -- (req_handler)req_create_esync, -- (req_handler)req_open_esync, -- (req_handler)req_get_esync_fd, -- (req_handler)req_esync_msgwait, - (req_handler)req_set_keyboard_repeat, -- (req_handler)req_get_esync_apc_fd, -+ (req_handler)req_get_linux_sync_device, -+ (req_handler)req_get_linux_sync_obj, -+ (req_handler)req_select_inproc_queue, -+ (req_handler)req_unselect_inproc_queue, -+ (req_handler)req_get_inproc_alert_event, - }; - - C_ASSERT( sizeof(abstime_t) == 8 ); -@@ -2276,35 +2276,24 @@ - C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); - C_ASSERT( offsetof(struct get_next_thread_reply, handle) == 8 ); - C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); --C_ASSERT( offsetof(struct create_esync_request, access) == 12 ); --C_ASSERT( offsetof(struct create_esync_request, initval) == 16 ); --C_ASSERT( offsetof(struct create_esync_request, type) == 20 ); --C_ASSERT( offsetof(struct create_esync_request, max) == 24 ); --C_ASSERT( sizeof(struct create_esync_request) == 32 ); --C_ASSERT( offsetof(struct create_esync_reply, handle) == 8 ); --C_ASSERT( offsetof(struct create_esync_reply, type) == 12 ); --C_ASSERT( offsetof(struct create_esync_reply, shm_idx) == 16 ); --C_ASSERT( sizeof(struct create_esync_reply) == 24 ); --C_ASSERT( offsetof(struct open_esync_request, access) == 12 ); --C_ASSERT( offsetof(struct open_esync_request, attributes) == 16 ); --C_ASSERT( offsetof(struct open_esync_request, rootdir) == 20 ); --C_ASSERT( offsetof(struct open_esync_request, type) == 24 ); --C_ASSERT( sizeof(struct open_esync_request) == 32 ); --C_ASSERT( offsetof(struct open_esync_reply, handle) == 8 ); --C_ASSERT( offsetof(struct open_esync_reply, type) == 12 ); --C_ASSERT( offsetof(struct open_esync_reply, shm_idx) == 16 ); --C_ASSERT( sizeof(struct open_esync_reply) == 24 ); --C_ASSERT( offsetof(struct get_esync_fd_request, handle) == 12 ); --C_ASSERT( sizeof(struct get_esync_fd_request) == 16 ); --C_ASSERT( offsetof(struct get_esync_fd_reply, type) == 8 ); --C_ASSERT( offsetof(struct get_esync_fd_reply, shm_idx) == 12 ); --C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 ); --C_ASSERT( offsetof(struct esync_msgwait_request, in_msgwait) == 12 ); --C_ASSERT( sizeof(struct esync_msgwait_request) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, enable) == 12 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, delay) == 16 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_request, period) == 20 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_request) == 24 ); - C_ASSERT( offsetof(struct set_keyboard_repeat_reply, enable) == 8 ); - C_ASSERT( sizeof(struct set_keyboard_repeat_reply) == 16 ); --C_ASSERT( sizeof(struct get_esync_apc_fd_request) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_device_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_linux_sync_device_reply) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_request, handle) == 12 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_request) == 16 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, handle) == 8 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, type) == 12 ); -+C_ASSERT( offsetof(struct get_linux_sync_obj_reply, access) == 16 ); -+C_ASSERT( sizeof(struct get_linux_sync_obj_reply) == 24 ); -+C_ASSERT( sizeof(struct select_inproc_queue_request) == 16 ); -+C_ASSERT( offsetof(struct unselect_inproc_queue_request, signaled) == 12 ); -+C_ASSERT( sizeof(struct unselect_inproc_queue_request) == 16 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_request) == 16 ); -+C_ASSERT( offsetof(struct get_inproc_alert_event_reply, handle) == 8 ); -+C_ASSERT( sizeof(struct get_inproc_alert_event_reply) == 16 ); -diff --git a/server/semaphore.c b/server/semaphore.c -index e3889f2..9940919 100644 ---- a/server/semaphore.c -+++ b/server/semaphore.c -@@ -55,12 +55,15 @@ struct semaphore - struct object obj; /* object header */ - unsigned int count; /* current count */ - unsigned int max; /* maximum possible count */ -+ struct inproc_sync *inproc_sync; /* fast synchronization object */ - }; - - static void semaphore_dump( struct object *obj, int verbose ); - static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); - static int semaphore_signal( struct object *obj, unsigned int access ); -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ); -+static void semaphore_destroy( struct object *obj ); - - static const struct object_ops semaphore_ops = - { -@@ -70,7 +73,6 @@ static const struct object_ops semaphore_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - semaphore_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - semaphore_satisfied, /* satisfied */ - semaphore_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -83,8 +85,9 @@ static const struct object_ops semaphore_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ semaphore_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ semaphore_destroy /* destroy */ - }; - - -@@ -106,6 +109,7 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni - /* initialize it if it didn't already exist */ - sem->count = initial; - sem->max = max; -+ sem->inproc_sync = NULL; - } - } - return sem; -@@ -168,6 +172,23 @@ static int semaphore_signal( struct object *obj, unsigned int access ) - return release_semaphore( sem, 1, NULL ); - } - -+static struct inproc_sync *semaphore_get_inproc_sync( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (!semaphore->inproc_sync) -+ semaphore->inproc_sync = create_inproc_semaphore( semaphore->count, semaphore->max ); -+ if (semaphore->inproc_sync) grab_object( semaphore->inproc_sync ); -+ return semaphore->inproc_sync; -+} -+ -+static void semaphore_destroy( struct object *obj ) -+{ -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ -+ if (semaphore->inproc_sync) release_object( semaphore->inproc_sync ); -+} -+ - /* create a semaphore */ - DECL_HANDLER(create_semaphore) - { -diff --git a/server/serial.c b/server/serial.c -index 11e204e..5c210d1 100644 ---- a/server/serial.c -+++ b/server/serial.c -@@ -85,7 +85,6 @@ static const struct object_ops serial_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - serial_get_fd, /* get_fd */ -@@ -98,6 +97,7 @@ static const struct object_ops serial_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - serial_destroy /* destroy */ - }; -diff --git a/server/signal.c b/server/signal.c -index 55cd6aa..e5def3d 100644 ---- a/server/signal.c -+++ b/server/signal.c -@@ -62,7 +62,6 @@ static const struct object_ops handler_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -75,6 +74,7 @@ static const struct object_ops handler_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - handler_destroy /* destroy */ - }; -diff --git a/server/sock.c b/server/sock.c -index 104321b..3fb2e29 100644 ---- a/server/sock.c -+++ b/server/sock.c -@@ -453,7 +453,6 @@ static const struct object_ops sock_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - sock_get_fd, /* get_fd */ -@@ -466,6 +465,7 @@ static const struct object_ops sock_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ default_fd_get_inproc_sync, /* get_inproc_sync */ - sock_close_handle, /* close_handle */ - sock_destroy /* destroy */ - }; -@@ -3555,7 +3555,6 @@ static const struct object_ops ifchange_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - ifchange_get_fd, /* get_fd */ -@@ -3568,6 +3567,7 @@ static const struct object_ops ifchange_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - ifchange_destroy /* destroy */ - }; -@@ -3777,7 +3777,6 @@ static const struct object_ops socket_device_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -3790,6 +3789,7 @@ static const struct object_ops socket_device_ops = - default_unlink_name, /* unlink_name */ - socket_device_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -diff --git a/server/symlink.c b/server/symlink.c -index c7f3441..4a7cf68 100644 ---- a/server/symlink.c -+++ b/server/symlink.c -@@ -71,7 +71,6 @@ static const struct object_ops symlink_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -84,6 +83,7 @@ static const struct object_ops symlink_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - symlink_destroy /* destroy */ - }; -diff --git a/server/thread.c b/server/thread.c -index 2ce94b4..8f603fc 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -50,7 +50,6 @@ - #include "request.h" - #include "user.h" - #include "security.h" --#include "esync.h" - - - /* thread queues */ -@@ -97,7 +96,6 @@ static const struct object_ops thread_apc_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_apc_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -110,6 +108,7 @@ static const struct object_ops thread_apc_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - thread_apc_destroy /* destroy */ - }; -@@ -140,7 +139,6 @@ static const struct object_ops context_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - context_signaled, /* signaled */ -- NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -153,6 +151,7 @@ static const struct object_ops context_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - no_destroy /* destroy */ - }; -@@ -177,10 +176,10 @@ struct type_descr thread_type = - - static void dump_thread( struct object *obj, int verbose ); - static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int thread_get_esync_fd( struct object *obj, enum esync_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 ); -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ); - static void destroy_thread( struct object *obj ); - - static const struct object_ops thread_ops = -@@ -191,7 +190,6 @@ static const struct object_ops thread_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_signaled, /* signaled */ -- thread_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -204,6 +202,7 @@ static const struct object_ops thread_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - thread_get_kernel_obj_list, /* get_kernel_obj_list */ -+ thread_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - destroy_thread /* destroy */ - }; -@@ -231,8 +230,6 @@ static inline void init_thread_structure( struct thread *thread ) - thread->context = NULL; - thread->teb = 0; - thread->entry_point = 0; -- thread->esync_fd = -1; -- thread->esync_apc_fd = -1; - thread->system_regs = 0; - thread->queue = NULL; - thread->wait = NULL; -@@ -253,6 +250,7 @@ static inline void init_thread_structure( struct thread *thread ) - thread->token = NULL; - thread->desc = NULL; - thread->desc_len = 0; -+ thread->inproc_sync = NULL; -+ thread->inproc_alert_event = NULL; -- thread->exit_poll = NULL; - - thread->creation_time = current_time; -@@ -380,12 +379,6 @@ struct thread *create_thread( int fd, struct process *process, const struct secu - } - } - -- if (do_esync()) -- { -- thread->esync_fd = esync_create_fd( 0, 0 ); -- thread->esync_apc_fd = esync_create_fd( 0, 0 ); -- } -- - set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */ - add_process_thread( thread->process, thread ); - return thread; -@@ -410,6 +403,16 @@ static struct list *thread_get_kernel_obj_list( struct object *obj ) - return &thread->kernel_object; - } - -+static struct inproc_sync *thread_get_inproc_sync( struct object *obj ) -+{ -+ struct thread *thread = (struct thread *)obj; -+ -+ if (!thread->inproc_sync) -+ thread->inproc_sync = create_inproc_event( INPROC_SYNC_MANUAL_SERVER, thread->state == TERMINATED ); -+ if (thread->inproc_sync) grab_object( thread->inproc_sync ); -+ return thread->inproc_sync; -+} -+ - /* cleanup everything that is no longer needed by a dead thread */ - /* used by destroy_thread and kill_thread */ - static void cleanup_thread( struct thread *thread ) -@@ -465,9 +468,7 @@ static void destroy_thread( struct object *obj ) -- if (thread->exit_poll) remove_timeout_user( thread->exit_poll ); - if (thread->id) free_ptid( thread->id ); - if (thread->token) release_object( thread->token ); -- -- if (do_esync()) -- close( thread->esync_fd ); -+ if (thread->inproc_sync) release_object( thread->inproc_sync ); -+ if (thread->inproc_alert_event) release_object( thread->inproc_alert_event ); - } - - /* dump a thread on stdout for debugging purposes */ -@@ -486,13 +488,6 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) -- return mythread->state == TERMINATED && !mythread->exit_poll; -+ return (mythread->state == TERMINATED); - } - --static int thread_get_esync_fd( struct object *obj, enum esync_type *type ) --{ -- struct thread *thread = (struct thread *)obj; -- *type = ESYNC_MANUAL_SERVER; -- return thread->esync_fd; --} -- - static unsigned int thread_map_access( struct object *obj, unsigned int access ) - { - access = default_map_access( obj, access ); -@@ -1087,9 +1082,6 @@ void wake_up( struct object *obj, int max ) - struct list *ptr; - int ret; - -- if (do_esync()) -- esync_wake_up( obj ); -- - LIST_FOR_EACH( ptr, &obj->wait_queue ) - { - struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry ); -@@ -1177,8 +1169,8 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr - { - wake_thread( thread ); - -- if (do_esync() && queue == &thread->user_apc) -- esync_wake_fd( thread->esync_apc_fd ); -+ if (apc->call.type == APC_USER && thread->inproc_alert_event) -+ set_event( thread->inproc_alert_event ); - } - - return 1; -@@ -1211,6 +1203,8 @@ void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_ty - apc->executed = 1; - wake_up( &apc->obj, 0 ); - release_object( apc ); -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); - return; - } - } -@@ -1225,11 +1219,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system - { - apc = LIST_ENTRY( ptr, struct thread_apc, entry ); - list_remove( ptr ); -- } -- -- if (do_esync() && list_empty( &thread->system_apc ) && list_empty( &thread->user_apc )) -- esync_clear( thread->esync_apc_fd ); - -+ if (list_empty( &thread->user_apc ) && thread->inproc_alert_event) -+ reset_event( thread->inproc_alert_event ); -+ } - return apc; - } - -@@ -1305,26 +1302,6 @@ - return -1; - } - --static void check_terminated( void *arg ) --{ -- struct thread *thread = arg; -- assert( thread->obj.ops == &thread_ops ); -- assert( thread->state == TERMINATED ); -- -- /* don't wake up until the thread is really dead, to avoid race conditions */ -- if (thread->unix_tid != -1 && !kill( thread->unix_tid, 0 )) -- { -- thread->exit_poll = add_timeout_user( -TICKS_PER_SEC / 1000, check_terminated, thread ); -- return; -- } -- -- /* grab reference since object can be destroyed while trying to wake up */ -- grab_object( &thread->obj ); -- thread->exit_poll = NULL; -- wake_up( &thread->obj, 0 ); -- release_object( &thread->obj ); --} -- - /* kill a thread on the spot */ - void kill_thread( struct thread *thread, int violent_death ) - { -@@ -1345,14 +1338,9 @@ void kill_thread( struct thread *thread, int violent_death ) - } - kill_console_processes( thread, 0 ); - abandon_mutexes( thread ); -- if (do_esync()) -- esync_abandon_mutexes( thread ); -+ wake_up( &thread->obj, 0 ); -+ set_inproc_event( thread->inproc_sync ); -+ if (violent_death) send_thread_signal( thread, SIGQUIT ); -- if (violent_death) -- { -- send_thread_signal( thread, SIGQUIT ); -- check_terminated( thread ); -- } -- else wake_up( &thread->obj, 0 ); - cleanup_thread( thread ); - remove_process_thread( thread->process, thread ); - release_object( thread ); -@@ -2094,3 +2086,12 @@ DECL_HANDLER(get_next_thread) - set_error( STATUS_NO_MORE_ENTRIES ); - release_object( process ); - } -+ -+DECL_HANDLER(get_inproc_alert_event) -+{ -+ if (!current->inproc_alert_event) -+ current->inproc_alert_event = create_event( NULL, NULL, 0, 1, !list_empty( ¤t->user_apc ), NULL ); -+ -+ if (current->inproc_alert_event) -+ reply->handle = alloc_handle( current->process, current->inproc_alert_event, SYNCHRONIZE, 0 ); -+} -diff --git a/server/thread.h b/server/thread.h -index 10e9e28..cb4643a 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -55,8 +55,6 @@ struct thread - struct process *process; - thread_id_t id; /* thread id */ - struct list mutex_list; /* list of currently owned mutexes */ -- int esync_fd; /* esync file descriptor (signalled on exit) */ -- int esync_apc_fd; /* esync apc fd (signalled when APCs are present) */ - 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 */ -@@ -94,6 +92,7 @@ struct thread - WCHAR *desc; /* thread description string */ - struct completion_wait *completion_wait; /* completion port wait object the thread is associated with */ -- struct timeout_user *exit_poll; /* poll if the thread/process has exited already */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ -+ struct event *inproc_alert_event; /* in-process synchronization alert event */ - }; - - extern struct thread *current; -diff --git a/server/timer.c b/server/timer.c -index 36645a2..854a8e1 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -35,7 +35,6 @@ - #include "file.h" - #include "handle.h" - #include "request.h" --#include "esync.h" - - static const WCHAR timer_name[] = {'T','i','m','e','r'}; - -@@ -62,13 +61,13 @@ struct timer - struct thread *thread; /* thread that set the APC function */ - client_ptr_t callback; /* callback APC function */ - client_ptr_t arg; /* callback argument */ -- int esync_fd; /* esync file descriptor */ -+ struct inproc_sync *inproc_sync; /* in-process synchronization object */ - }; - - static void timer_dump( struct object *obj, int verbose ); - static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int timer_get_esync_fd( struct object *obj, enum esync_type *type ); - static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ); - static void timer_destroy( struct object *obj ); - - static const struct object_ops timer_ops = -@@ -79,7 +78,6 @@ static const struct object_ops timer_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - timer_signaled, /* signaled */ -- timer_get_esync_fd, /* get_esync_fd */ - timer_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -92,6 +90,7 @@ static const struct object_ops timer_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ timer_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - timer_destroy /* destroy */ - }; -@@ -114,10 +113,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str - timer->period = 0; - timer->timeout = NULL; - timer->thread = NULL; -- timer->esync_fd = -1; -- -- if (do_esync()) -- timer->esync_fd = esync_create_fd( 0, 0 ); -+ timer->inproc_sync = NULL; - } - } - return timer; -@@ -159,6 +155,7 @@ static void timer_callback( void *private ) - /* wake up waiters */ - timer->signaled = 1; - wake_up( &timer->obj, 0 ); -+ set_inproc_event( timer->inproc_sync ); - } - - /* cancel a running timer */ -@@ -189,9 +186,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period - { - period = 0; /* period doesn't make any sense for a manual timer */ - timer->signaled = 0; -- -- if (do_esync()) -- esync_clear( timer->esync_fd ); -+ reset_inproc_event( timer->inproc_sync ); - } - timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); - timer->period = period; -@@ -219,18 +214,24 @@ static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) - return timer->signaled; - } - --static int timer_get_esync_fd( struct object *obj, enum esync_type *type ) -+static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct timer *timer = (struct timer *)obj; -- *type = timer->manual ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER; -- return timer->esync_fd; -+ assert( obj->ops == &timer_ops ); -+ if (!timer->manual) timer->signaled = 0; - } - --static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) -+static struct inproc_sync *timer_get_inproc_sync( struct object *obj ) - { - struct timer *timer = (struct timer *)obj; -- assert( obj->ops == &timer_ops ); -- if (!timer->manual) timer->signaled = 0; -+ -+ if (!timer->inproc_sync) -+ { -+ enum inproc_sync_type type = timer->manual ? INPROC_SYNC_MANUAL_SERVER : INPROC_SYNC_AUTO_SERVER; -+ timer->inproc_sync = create_inproc_event( type, timer->signaled ); -+ } -+ if (timer->inproc_sync) grab_object( timer->inproc_sync ); -+ return timer->inproc_sync; - } - - static void timer_destroy( struct object *obj ) -@@ -240,7 +241,7 @@ static void timer_destroy( struct object *obj ) - - if (timer->timeout) remove_timeout_user( timer->timeout ); - if (timer->thread) release_object( timer->thread ); -- if (do_esync()) close( timer->esync_fd ); -+ if (timer->inproc_sync) release_object( timer->inproc_sync ); - } - - /* create a timer */ -diff --git a/server/token.c b/server/token.c -index 8b4d2f0..42562fd 100644 ---- a/server/token.c -+++ b/server/token.c -@@ -143,7 +143,6 @@ static const struct object_ops token_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -156,6 +155,7 @@ static const struct object_ops token_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - token_destroy /* destroy */ - }; -diff --git a/server/request_trace.h b/server/request_trace.h -index af96565..c027f4b 100644 ---- a/server/request_trace.h -+++ b/server/request_trace.h -@@ -4619,67 +4619,54 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req - fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_create_esync_request( const struct create_esync_request *req ) -+static void dump_get_linux_sync_device_request( const struct get_linux_sync_device_request *req ) - { -- fprintf( stderr, " access=%08x", req->access ); -- fprintf( stderr, ", initval=%d", req->initval ); -- fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", max=%d", req->max ); -- dump_varargs_object_attributes( ", objattr=", cur_size ); - } - --static void dump_create_esync_reply( const struct create_esync_reply *req ) -+static void dump_get_linux_sync_device_reply( const struct get_linux_sync_device_reply *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); -- fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); - } - --static void dump_open_esync_request( const struct open_esync_request *req ) -+static void dump_get_linux_sync_obj_request( const struct get_linux_sync_obj_request *req ) - { -- fprintf( stderr, " access=%08x", req->access ); -- fprintf( stderr, ", attributes=%08x", req->attributes ); -- fprintf( stderr, ", rootdir=%04x", req->rootdir ); -- fprintf( stderr, ", type=%d", req->type ); -- dump_varargs_unicode_str( ", name=", cur_size ); -+ fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_open_esync_reply( const struct open_esync_reply *req ) -+static void dump_get_linux_sync_obj_reply( const struct get_linux_sync_obj_reply *req ) - { - fprintf( stderr, " handle=%04x", req->handle ); - fprintf( stderr, ", type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, ", access=%08x", req->access ); - } - --static void dump_get_esync_fd_request( const struct get_esync_fd_request *req ) -+static void dump_select_inproc_queue_request( const struct select_inproc_queue_request *req ) - { -- fprintf( stderr, " handle=%04x", req->handle ); - } - --static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req ) -+static void dump_unselect_inproc_queue_request( const struct unselect_inproc_queue_request *req ) - { -- fprintf( stderr, " type=%d", req->type ); -- fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); -+ fprintf( stderr, ", signaled=%d", req->signaled ); - } - --static void dump_esync_msgwait_request( const struct esync_msgwait_request *req ) -+static void dump_get_inproc_alert_event_request( const struct get_inproc_alert_event_request *req ) - { -- fprintf( stderr, " in_msgwait=%d", req->in_msgwait ); - } - - static void dump_set_keyboard_repeat_request( const struct set_keyboard_repeat_request *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - fprintf( stderr, ", delay=%d", req->delay ); - fprintf( stderr, ", period=%d", req->period ); - } - - static void dump_set_keyboard_repeat_reply( const struct set_keyboard_repeat_reply *req ) - { - fprintf( stderr, " enable=%d", req->enable ); - } - --static void dump_get_esync_apc_fd_request( const struct get_esync_apc_fd_request *req ) -+static void dump_get_inproc_alert_event_reply( const struct get_inproc_alert_event_reply *req ) - { -+ fprintf( stderr, " handle=%04x", req->handle ); - } - - static const dump_func req_dumpers[REQ_NB_REQUESTS] = { -@@ -4959,11 +4948,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { - (dump_func)dump_suspend_process_request, - (dump_func)dump_resume_process_request, - (dump_func)dump_get_next_thread_request, -- (dump_func)dump_create_esync_request, -- (dump_func)dump_open_esync_request, -- (dump_func)dump_get_esync_fd_request, -- (dump_func)dump_esync_msgwait_request, -- (dump_func)dump_get_esync_apc_fd_request, -+ (dump_func)dump_get_linux_sync_device_request, -+ (dump_func)dump_get_linux_sync_obj_request, -+ (dump_func)dump_select_inproc_queue_request, -+ (dump_func)dump_unselect_inproc_queue_request, -+ (dump_func)dump_get_inproc_alert_event_request, - }; - - static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { -@@ -5254,12 +5243,12 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { - NULL, - NULL, - (dump_func)dump_get_next_thread_reply, -- (dump_func)dump_create_esync_reply, -- (dump_func)dump_open_esync_reply, -- (dump_func)dump_get_esync_fd_reply, - NULL, - (dump_func)dump_set_keyboard_repeat_reply, - NULL, -+ (dump_func)dump_get_linux_sync_device_reply, -+ (dump_func)dump_get_linux_sync_obj_reply, -+ NULL, -+ NULL, -+ (dump_func)dump_get_inproc_alert_event_reply, - }; - - static const char * const req_names[REQ_NB_REQUESTS] = { -@@ -5549,11 +5538,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = { - "suspend_process", - "resume_process", - "get_next_thread", -- "create_esync", -- "open_esync", -- "get_esync_fd", -- "esync_msgwait", - "set_keyboard_repeat", -- "get_esync_apc_fd", -+ "get_linux_sync_device", -+ "get_linux_sync_obj", -+ "select_inproc_queue", -+ "unselect_inproc_queue", -+ "get_inproc_alert_event", - }; - - static const struct -diff --git a/server/window.c b/server/window.c -index feac54e..f52e118 100644 ---- a/server/window.c -+++ b/server/window.c -@@ -108,7 +108,6 @@ static const struct object_ops window_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -121,6 +120,7 @@ static const struct object_ops window_ops = - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - no_close_handle, /* close_handle */ - window_destroy /* destroy */ - }; -diff --git a/server/winstation.c b/server/winstation.c -index 4ef21d9..2719c9e 100644 ---- a/server/winstation.c -+++ b/server/winstation.c -@@ -76,7 +76,6 @@ static const struct object_ops winstation_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -89,6 +88,7 @@ static const struct object_ops winstation_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - winstation_close_handle, /* close_handle */ - winstation_destroy /* destroy */ - }; -@@ -117,7 +117,6 @@ static const struct object_ops desktop_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -130,6 +129,7 @@ static const struct object_ops desktop_ops = - default_unlink_name, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ -+ no_get_inproc_sync, /* get_inproc_sync */ - desktop_close_handle, /* close_handle */ - desktop_destroy /* destroy */ - }; ---- a/server/queue.c 2024-12-20 20:01:39.879368500 +0500 -+++ b/server/queue.c 2024-12-20 20:03:11.782212833 +0500 -@@ -4252,23 +4252,6 @@ - } - } - --DECL_HANDLER(esync_msgwait) --{ -- struct msg_queue *queue = get_current_queue(); -- const queue_shm_t *queue_shm; -- -- if (!queue) return; -- queue_shm = queue->shared; -- queue->esync_in_msgwait = req->in_msgwait; -- -- if (current->process->idle_event && !(queue_shm->wake_mask & QS_SMRESULT)) -- set_event( current->process->idle_event ); -- -- /* and start/stop waiting on the driver */ -- if (queue->fd) -- set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 ); --} -- - DECL_HANDLER(set_keyboard_repeat) - { - struct desktop *desktop; -@@ -4288,3 +4271,41 @@ - release_object( desktop ); - } - -+DECL_HANDLER(select_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ check_thread_queue_idle( current ); -+ -+ if (queue->fd) -+ set_fd_events( queue->fd, POLLIN ); -+ -+ queue->in_inproc_wait = 1; -+ } -+} -+ -+DECL_HANDLER(unselect_inproc_queue) -+{ -+ struct msg_queue *queue = current->queue; -+ -+ if (!queue->in_inproc_wait) -+ { -+ set_error( STATUS_ACCESS_DENIED ); -+ } -+ else -+ { -+ if (queue->fd) -+ set_fd_events( queue->fd, 0 ); -+ -+ if (req->signaled) -+ msg_queue_satisfied( &queue->obj, NULL ); -+ -+ queue->in_inproc_wait = 0; -+ } -+} diff --git a/wine-tkg-git/wine-tkg-scripts/prepare.sh b/wine-tkg-git/wine-tkg-scripts/prepare.sh index 011793b41..e75d55829 100644 --- a/wine-tkg-git/wine-tkg-scripts/prepare.sh +++ b/wine-tkg-git/wine-tkg-scripts/prepare.sh @@ -442,7 +442,7 @@ _pkgnaming() { msg2 "Using staging patchset" fi - if [ "$_use_ntsync" = "true" ] || [ "$_use_ntsync" = "ntsync7" ] && [ "$_use_fsync" != "true" ]; then + if [ "$_use_ntsync" = "true" ] && [ "$_use_fsync" != "true" ]; then pkgname+="-ntsync" msg2 "Using ntsync patchset" elif [ "$_use_fsync" = "true" ] && [ "$_use_esync" = "true" ]; then @@ -1155,7 +1155,7 @@ _polish() { if [ "$_use_fsync" = "true" ] && [ "$_staging_esync" = "true" ] && [[ "$_custom_wine_source" != *"ValveSoftware"* ]]; then _version_tags+=(Fsync) fi - if [ "$_use_ntsync" = "true" ] || [ "$_use_ntsync" = "ntsync7" ] && [[ "$_custom_wine_source" != *"ValveSoftware"* ]]; then + if [ "$_use_ntsync" = "true" ] && [[ "$_custom_wine_source" != *"ValveSoftware"* ]]; then _version_tags+=(NTsync) fi if [ "$_use_pba" = "true" ] && [ "$_pba_version" != "none" ] && [[ "$_custom_wine_source" != *"ValveSoftware"* ]]; then