From 38d4b8ca780f51227661211ead02b1283774be0b Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Fri, 3 Oct 2025 16:39:15 -0500 Subject: [PATCH] Rebase against 01269452e0fbb1f081d506bd64996590a553e2b9. --- ...for-sys-eventfd.h-ppoll-and-shm_open.patch | 85 -- ...rver-objects-for-eventfd-based-synch.patch | 446 ----------- ...eventfd-based-objects-for-semaphores.patch | 425 ---------- ...4-ntdll-Implement-NtReleaseSemaphore.patch | 108 --- .../0005-ntdll-Implement-NtClose.patch | 77 -- ...l-Implement-NtWaitForMultipleObjects.patch | 243 ------ ...ntdll-server-Implement-NtCreateEvent.patch | 129 --- .../0008-ntdll-Implement-NtSetEvent.patch | 69 -- .../0009-ntdll-Implement-NtResetEvent.patch | 70 -- ...ement-waiting-on-manual-reset-events.patch | 59 -- ...ject-operation-to-grab-the-esync-fil.patch | 749 ------------------ ...uest-to-get-the-eventfd-file-descrip.patch | 83 -- ...entfd-file-descriptors-for-process-o.patch | 134 ---- ...lement-waiting-on-server-bound-objec.patch | 236 ------ ...entfd-file-descriptors-for-event-obj.patch | 141 ---- ...setting-esync-events-on-the-server-s.patch | 115 --- ...tdll-Try-again-if-poll-returns-EINTR.patch | 68 -- ...entfd-file-descriptors-for-thread-ob.patch | 88 -- ...sing-the-server-thread-handle-while-.patch | 48 -- ...entfd-file-descriptors-for-message-q.patch | 130 --- ...server-ntdll-Implement-message-waits.patch | 184 ----- ...entfd-descriptors-for-device-manager.patch | 107 --- ...tdll-server-Implement-NtCreateMutant.patch | 110 --- ...0024-ntdll-Implement-NtReleaseMutant.patch | 85 -- ...5-ntdll-Implement-waiting-on-mutexes.patch | 61 -- .../0026-ntdll-Implement-wait-all.patch | 186 ----- .../0027-esync-Add-a-README.patch | 204 ----- ...ement-NtSignalAndWaitForSingleObject.patch | 80 -- ...0029-ntdll-Implement-NtOpenSemaphore.patch | 174 ---- .../0030-ntdll-Implement-NtOpenEvent.patch | 60 -- .../0031-ntdll-Implement-NtOpenMutant.patch | 60 -- ...32-server-Implement-esync_map_access.patch | 50 -- ...3-server-Implement-NtDuplicateObject.patch | 47 -- ...reate-eventfd-descriptors-for-timers.patch | 89 --- ...dll-server-Implement-alertable-waits.patch | 320 -------- .../0036-esync-Update-README.patch | 85 -- ...ark-some-existing-tests-as-failing-u.patch | 35 - ...nel32-tests-Add-some-semaphore-tests.patch | 128 --- ...-kernel32-tests-Add-some-event-tests.patch | 154 ---- ...-kernel32-tests-Add-some-mutex-tests.patch | 126 --- ...sts-Add-some-tests-for-wait-timeouts.patch | 117 --- .../0042-kernel32-tests-Zigzag-test.patch | 109 --- ...043-ntdll-Implement-NtQuerySemaphore.patch | 70 -- .../0044-ntdll-Implement-NtQueryEvent.patch | 71 -- .../0045-ntdll-Implement-NtQueryMutant.patch | 71 -- ...entfd-descriptors-for-pseudo-fd-obje.patch | 129 --- .../0047-esync-Update-README.patch | 55 -- ...bout-file-limits-not-being-raised-wh.patch | 41 - ...o-avoid-poll-for-uncontended-objects.patch | 93 --- ...ry-to-avoid-poll-for-signaled-events.patch | 287 ------- .../0051-esync-Update-README.patch | 52 -- .../0052-ntdll-Implement-NtPulseEvent.patch | 76 -- .../0053-esync-Update-README.patch | 24 - ...ync-file-descriptors-for-true-file-o.patch | 41 - ...Abandon-esync-mutexes-on-thread-exit.patch | 192 ----- ...ync-file-descriptors-for-console-ser.patch | 123 --- ...tdll-Compile-warning-fixes-for-esync.patch | 126 --- patches/eventfd_synchronization/definition | 5 - ...ConnectW-fallback-to-SQLDriverConnec.patch | 64 -- ...32-SQLGetInfoW-support-ANSI-fallback.patch | 100 --- ...cDirectW-call-fallback-SQLExecDirect.patch | 57 -- ...32-SQLDescribeColW-add-ANSI-fallback.patch | 10 +- ...bc32-SQLNativeSqlW-add-ANSI-fallback.patch | 10 +- ...odbc32-SQLPrepareW-add-ANSI-fallback.patch | 10 +- ...ing-of-GetMessage-after-previous-Pee.patch | 46 +- staging/upstream-commit | 2 +- 66 files changed, 39 insertions(+), 7790 deletions(-) delete mode 100644 patches/eventfd_synchronization/0001-configure-Check-for-sys-eventfd.h-ppoll-and-shm_open.patch delete mode 100644 patches/eventfd_synchronization/0002-server-Create-server-objects-for-eventfd-based-synch.patch delete mode 100644 patches/eventfd_synchronization/0003-ntdll-Create-eventfd-based-objects-for-semaphores.patch delete mode 100644 patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch delete mode 100644 patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch delete mode 100644 patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch delete mode 100644 patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch delete mode 100644 patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch delete mode 100644 patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch delete mode 100644 patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch delete mode 100644 patches/eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch delete mode 100644 patches/eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch delete mode 100644 patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch delete mode 100644 patches/eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch delete mode 100644 patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch delete mode 100644 patches/eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch delete mode 100644 patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch delete mode 100644 patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch delete mode 100644 patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch delete mode 100644 patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch delete mode 100644 patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch delete mode 100644 patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch delete mode 100644 patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch delete mode 100644 patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch delete mode 100644 patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch delete mode 100644 patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch delete mode 100644 patches/eventfd_synchronization/0027-esync-Add-a-README.patch delete mode 100644 patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch delete mode 100644 patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch delete mode 100644 patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch delete mode 100644 patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch delete mode 100644 patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch delete mode 100644 patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch delete mode 100644 patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch delete mode 100644 patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch delete mode 100644 patches/eventfd_synchronization/0036-esync-Update-README.patch delete mode 100644 patches/eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch delete mode 100644 patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch delete mode 100644 patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch delete mode 100644 patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch delete mode 100644 patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch delete mode 100644 patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch delete mode 100644 patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch delete mode 100644 patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch delete mode 100644 patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch delete mode 100644 patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch delete mode 100644 patches/eventfd_synchronization/0047-esync-Update-README.patch delete mode 100644 patches/eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch delete mode 100644 patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch delete mode 100644 patches/eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch delete mode 100644 patches/eventfd_synchronization/0051-esync-Update-README.patch delete mode 100644 patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch delete mode 100644 patches/eventfd_synchronization/0053-esync-Update-README.patch delete mode 100644 patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch delete mode 100644 patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch delete mode 100644 patches/eventfd_synchronization/0056-server-Create-esync-file-descriptors-for-console-ser.patch delete mode 100644 patches/eventfd_synchronization/0057-ntdll-Compile-warning-fixes-for-esync.patch delete mode 100644 patches/eventfd_synchronization/definition delete mode 100644 patches/odbc32-fixes/0009-odbc32-SQLDriverConnectW-fallback-to-SQLDriverConnec.patch delete mode 100644 patches/odbc32-fixes/0010-odbc32-SQLGetInfoW-support-ANSI-fallback.patch delete mode 100644 patches/odbc32-fixes/0011-odbc32-SQLExecDirectW-call-fallback-SQLExecDirect.patch diff --git a/patches/eventfd_synchronization/0001-configure-Check-for-sys-eventfd.h-ppoll-and-shm_open.patch b/patches/eventfd_synchronization/0001-configure-Check-for-sys-eventfd.h-ppoll-and-shm_open.patch deleted file mode 100644 index 8138fc42..00000000 --- a/patches/eventfd_synchronization/0001-configure-Check-for-sys-eventfd.h-ppoll-and-shm_open.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 6c64a33f908b9fade24fe11d89533a70fdce352f Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 10:44:49 -0500 -Subject: [PATCH] configure: Check for sys/eventfd.h, ppoll(), and shm_open(). - -We use ppoll() instead of poll() for the better time granularity. - -Although perhaps we shouldn't since the server doesn't do this. ---- - configure.ac | 8 ++++++++ - include/config.h.in | 11 ++++++++++- - 2 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index eb7f8223b51..388ac14dc8a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -411,6 +411,7 @@ AC_CHECK_HEADERS(\ - sys/cdio.h \ - sys/epoll.h \ - sys/event.h \ -+ sys/eventfd.h \ - sys/extattr.h \ - sys/filio.h \ - sys/ipc.h \ -@@ -2079,6 +2080,7 @@ AC_CHECK_FUNCS(\ - port_create \ - posix_fadvise \ - posix_fallocate \ -+ ppoll \ - prctl \ - sched_getcpu \ - sched_yield \ -@@ -2100,6 +2102,12 @@ AC_SEARCH_LIBS(clock_gettime, rt, - test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")]) - LIBS=$ac_save_LIBS - -+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/include/config.h.in b/include/config.h.in -index 6033d8674f3..563b63a92df 100644 ---- a/include/config.h.in -+++ b/include/config.h.in -@@ -321,6 +321,9 @@ - /* Define to 1 if you have the 'posix_fallocate' function. */ - #undef HAVE_POSIX_FALLOCATE - -+/* Define to 1 if you have the `ppoll' function. */ -+#undef HAVE_PPOLL -+ - /* Define to 1 if you have the 'prctl' function. */ - #undef HAVE_PRCTL - -@@ -381,7 +384,10 @@ - /* Define to 1 if 'interface_id' is a member of 'sg_io_hdr_t'. */ - #undef HAVE_SG_IO_HDR_T_INTERFACE_ID - --/* Define to 1 if 'si_fd' is a member of 'siginfo_t'. */ -+/* Define to 1 if you have the `shm_open' function. */ -+#undef HAVE_SHM_OPEN -+ -+/* Define to 1 if `si_fd' is a member of `siginfo_t'. */ - #undef HAVE_SIGINFO_T_SI_FD - - /* Define to 1 if you have the 'sigprocmask' function. */ -@@ -510,6 +516,9 @@ - /* 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 - --- -2.45.2 - diff --git a/patches/eventfd_synchronization/0002-server-Create-server-objects-for-eventfd-based-synch.patch b/patches/eventfd_synchronization/0002-server-Create-server-objects-for-eventfd-based-synch.patch deleted file mode 100644 index e3cfe8a9..00000000 --- a/patches/eventfd_synchronization/0002-server-Create-server-objects-for-eventfd-based-synch.patch +++ /dev/null @@ -1,446 +0,0 @@ -From da832ae3626406e9aee5f9f78bce01f2a0d49691 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 20:09:59 -0500 -Subject: [PATCH] server: Create server objects for eventfd-based - synchronization objects. - ---- - server/Makefile.in | 1 + - server/esync.c | 318 ++++++++++++++++++++++++++++++++++++++++++++ - server/esync.h | 24 ++++ - server/main.c | 4 + - server/protocol.def | 24 ++++ - 5 files changed, 371 insertions(+) - create mode 100644 server/esync.c - create mode 100644 server/esync.h - -diff --git a/server/Makefile.in b/server/Makefile.in -index 7e571ac2ba6..9632c4e694f 100644 ---- a/server/Makefile.in -+++ b/server/Makefile.in -@@ -11,6 +11,7 @@ SOURCES = \ - debugger.c \ - device.c \ - directory.c \ -+ esync.c \ - event.c \ - fd.c \ - file.c \ -diff --git a/server/esync.c b/server/esync.c -new file mode 100644 -index 00000000000..35b4833fd4c ---- /dev/null -+++ b/server/esync.c -@@ -0,0 +1,318 @@ -+/* -+ * 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" -+ -+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 ); -+} -+ -+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 */ -+}; -+ -+static void esync_dump( struct object *obj, int verbose ); -+static void esync_destroy( struct object *obj ); -+ -+static 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 */ -+ NULL, /* 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_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 void esync_destroy( struct object *obj ) -+{ -+ struct esync *esync = (struct esync *)obj; -+ 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 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; -+ } -+ 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 -+} -+ -+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 ); -+} -diff --git a/server/esync.h b/server/esync.h -new file mode 100644 -index 00000000000..00f9e638d83 ---- /dev/null -+++ b/server/esync.h -@@ -0,0 +1,24 @@ -+/* -+ * 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); -diff --git a/server/main.c b/server/main.c -index e014ec535ff..052667b4c6b 100644 ---- a/server/main.c -+++ b/server/main.c -@@ -34,6 +34,7 @@ - #include "thread.h" - #include "request.h" - #include "unicode.h" -+#include "esync.h" - - /* command-line options */ - int debug_level = 0; -@@ -229,6 +230,9 @@ 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_signals(); -diff --git a/server/protocol.def b/server/protocol.def -index fa4ca4aaa9e..a9ee996a8ab 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4080,6 +4080,29 @@ struct handle_info - obj_handle_t handle; /* next thread handle */ - @END - -+enum esync_type -+{ -+ ESYNC_SEMAPHORE = 1, -+ ESYNC_AUTO_EVENT, -+ ESYNC_MANUAL_EVENT, -+ ESYNC_MUTEX, -+ ESYNC_AUTO_SERVER, -+ ESYNC_MANUAL_SERVER, -+ ESYNC_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 */ -+@REPLY -+ obj_handle_t handle; /* handle to the object */ -+ int type; /* actual type (may be different for events) */ -+ unsigned int shm_idx; -+@END - - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) -@@ -4089,3 +4112,4 @@ struct handle_info - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END -+ --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0003-ntdll-Create-eventfd-based-objects-for-semaphores.patch b/patches/eventfd_synchronization/0003-ntdll-Create-eventfd-based-objects-for-semaphores.patch deleted file mode 100644 index 672ba499..00000000 --- a/patches/eventfd_synchronization/0003-ntdll-Create-eventfd-based-objects-for-semaphores.patch +++ /dev/null @@ -1,425 +0,0 @@ -From 955a93ac10d1328e293fbf033e28107f98c43c7f Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 12:09:22 -0500 -Subject: [PATCH] ntdll: Create eventfd-based objects for semaphores. - ---- - dlls/ntdll/Makefile.in | 1 + - dlls/ntdll/unix/esync.c | 270 +++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 35 +++++ - dlls/ntdll/unix/loader.c | 2 + - dlls/ntdll/unix/server.c | 4 +- - dlls/ntdll/unix/sync.c | 4 + - server/esync.c | 1 + - 7 files changed, 315 insertions(+), 2 deletions(-) - create mode 100644 dlls/ntdll/unix/esync.c - create mode 100644 dlls/ntdll/unix/esync.h - -diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in -index 74e6da5bb56..a2b498759a9 100644 ---- a/dlls/ntdll/Makefile.in -+++ b/dlls/ntdll/Makefile.in -@@ -48,6 +48,7 @@ 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 -new file mode 100644 -index 00000000000..7be4e03fa34 ---- /dev/null -+++ b/dlls/ntdll/unix/esync.c -@@ -0,0 +1,270 @@ -+/* -+ * 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" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef HAVE_SYS_STAT_H -+# include -+#endif -+#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 -+{ -+ enum esync_type type; -+ int fd; -+ void *shm; -+}; -+ -+struct semaphore -+{ -+ int max; -+ int count; -+}; -+C_ASSERT(sizeof(struct semaphore) == 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( (int *)&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 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; -+} -+ -+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG 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 ); -+} -+ -+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 -new file mode 100644 -index 00000000000..5fec18860f8 ---- /dev/null -+++ b/dlls/ntdll/unix/esync.h -@@ -0,0 +1,35 @@ -+/* -+ * 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_create_semaphore(HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max); -+ -+ -+/* 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/loader.c b/dlls/ntdll/unix/loader.c -index aa120ae38ec..fdda50575d1 100644 ---- a/dlls/ntdll/unix/loader.c -+++ b/dlls/ntdll/unix/loader.c -@@ -87,6 +87,7 @@ - #include "winioctl.h" - #include "winternl.h" - #include "unix_private.h" -+#include "esync.h" - #include "wine/list.h" - #include "ntsyscalls.h" - #include "wine/debug.h" -@@ -1790,6 +1791,7 @@ 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/server.c b/dlls/ntdll/unix/server.c -index 7211457387c..cd8dbbdcc10 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 ) -@@ -918,7 +918,7 @@ void wine_server_send_fd( int fd ) - * - * Receive a file descriptor passed from the server. - */ --static int receive_fd( obj_handle_t *handle ) -+int receive_fd( obj_handle_t *handle ) - { - struct iovec vec; - struct msghdr msghdr; -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index bfbcaf4a851..f21ceb80298 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -63,6 +63,7 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" -+#include "esync.h" - - WINE_DEFAULT_DEBUG_CHANNEL(sync); - -@@ -272,6 +273,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ - if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER; - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - -+ if (do_esync()) -+ return esync_create_semaphore( handle, access, attr, initial, max ); -+ - SERVER_START_REQ( create_semaphore ) - { - req->access = access; -diff --git a/server/esync.c b/server/esync.c -index 35b4833fd4c..75ef586df30 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -41,6 +41,7 @@ - #include "handle.h" - #include "request.h" - #include "file.h" -+#include "esync.h" - - int do_esync(void) - { --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch b/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch deleted file mode 100644 index 6ef0b197..00000000 --- a/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch +++ /dev/null @@ -1,108 +0,0 @@ -From d8135b1bdafffc23be62c216edda9ac280045753 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 12:16:34 -0500 -Subject: [PATCH] ntdll: Implement NtReleaseSemaphore(). - ---- - dlls/ntdll/unix/esync.c | 43 +++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 47 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 7be4e03fa34..e8da4bd311b 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - #ifdef HAVE_SYS_STAT_H -@@ -170,6 +171,16 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v - 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]; -+} -+ - static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, int initval, int max ) - { -@@ -225,6 +236,38 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max ); - } - -+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) -+{ -+ struct esync *obj; -+ struct semaphore *semaphore; -+ uint64_t count64 = count; -+ ULONG current; -+ -+ TRACE("%p, %d, %p.\n", handle, count, prev); -+ -+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ 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; -+} -+ - void esync_init(void) - { - struct stat st; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 5fec18860f8..cbaaed3e308 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -23,6 +23,7 @@ extern void esync_init(void); - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max); -+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ); - - - /* We have to synchronize on the fd cache mutex so that our calls to receive_fd -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index f21ceb80298..c85f985b4f3 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -358,6 +358,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous - { - unsigned int ret; - -+ if (do_esync()) -+ return esync_release_semaphore( handle, count, previous ); -+ - SERVER_START_REQ( release_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch b/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch deleted file mode 100644 index 14ae0de0..00000000 --- a/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e57a0ae8ff11195fa4a29aa1c1ccc250c0036073 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 12:20:44 -0500 -Subject: [PATCH] ntdll: Implement NtClose(). - ---- - dlls/ntdll/unix/esync.c | 18 ++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/server.c | 4 ++++ - 3 files changed, 23 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index e8da4bd311b..e031e9cb94f 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -181,6 +181,24 @@ static struct esync *get_cached_object( HANDLE handle ) - return &esync_list[entry][idx]; - } - -+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((int *)&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 ) - { -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index cbaaed3e308..c63491dcaad 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -20,6 +20,7 @@ - - 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, LONG initial, LONG max); -diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index cd8dbbdcc10..00d665d9e62 100644 ---- a/dlls/ntdll/unix/server.c -+++ b/dlls/ntdll/unix/server.c -@@ -79,6 +79,7 @@ - #include "wine/server.h" - #include "wine/debug.h" - #include "unix_private.h" -+#include "esync.h" - #include "ddk/wdm.h" - - WINE_DEFAULT_DEBUG_CHANNEL(server); -@@ -1839,6 +1840,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) - * retrieve it again */ - fd = remove_fd_from_cache( handle ); - -+ if (do_esync()) -+ esync_close( handle ); -+ - SERVER_START_REQ( close_handle ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch b/patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch deleted file mode 100644 index d59a8996..00000000 --- a/patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch +++ /dev/null @@ -1,243 +0,0 @@ -From 4865ed639a87ee06ffcf6a7a74b6c97ef448e7ab Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 12:34:42 -0500 -Subject: [PATCH] ntdll: Implement NtWaitForMultipleObjects(). - ---- - dlls/ntdll/unix/esync.c | 172 ++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 3 + - dlls/ntdll/unix/sync.c | 7 ++ - 3 files changed, 182 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index e031e9cb94f..85db837f16b 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -24,6 +24,10 @@ - - #include "config.h" - -+#ifndef _GNU_SOURCE -+#define _GNU_SOURCE -+#endif -+ - #include - #include - #include -@@ -34,6 +38,12 @@ - #ifdef HAVE_SYS_STAT_H - # include - #endif -+#ifdef HAVE_POLL_H -+#include -+#endif -+#ifdef HAVE_SYS_POLL_H -+# include -+#endif - #include - #include - -@@ -286,6 +296,168 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - 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 ) -+{ -+ 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; -+ return ppoll( fds, nfds, &tmo_p, NULL ); -+#else -+ return poll( fds, nfds, timeleft / TICKSPERMSEC ); -+#endif -+ } -+ else -+ return poll( fds, nfds, -1 ); -+} -+ -+static void update_grabbed_object( struct esync *obj ) -+{ -+ 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 ); -+ } -+} -+ -+/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we -+ * need to delegate to server_select(). */ -+NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ struct esync *objs[MAXIMUM_WAIT_OBJECTS]; -+ struct pollfd fds[MAXIMUM_WAIT_OBJECTS]; -+ int has_esync = 0, has_server = 0; -+ LONGLONG timeleft; -+ LARGE_INTEGER now; -+ ULONGLONG end; -+ int i, ret; -+ -+ 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++) -+ { -+ if ((objs[i] = get_cached_object( handles[i] ))) -+ has_esync = 1; -+ else -+ has_server = 1; -+ } -+ -+ 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 (!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) -+ { -+ for (i = 0; i < count; i++) -+ { -+ fds[i].fd = objs[i] ? objs[i]->fd : -1; -+ fds[i].events = POLLIN; -+ } -+ -+ while (1) -+ { -+ ret = do_poll( fds, count, timeout ? &end : NULL ); -+ if (ret > 0) -+ { -+ /* 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) -+ { -+ int64_t value; -+ ssize_t size; -+ -+ 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); -+ update_grabbed_object( obj ); -+ return i; -+ } -+ } -+ } -+ -+ /* If we got here, someone else stole (or reset, etc.) whatever -+ * we were waiting for. So keep waiting. */ -+ NtQuerySystemTime( &now ); -+ } -+ else if (ret == 0) -+ { -+ TRACE("Wait timed out.\n"); -+ return STATUS_TIMEOUT; -+ } -+ else -+ { -+ ERR("ppoll failed: %s\n", strerror( errno )); -+ return errno_to_status( errno ); -+ } -+ } -+ } -+ else -+ { -+ FIXME("Wait-all not implemented.\n"); -+ return STATUS_NOT_IMPLEMENTED; -+ } -+} -+ - void esync_init(void) - { - struct stat st; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index c63491dcaad..92b609ebd27 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max); - extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ); - -+extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ 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. -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index dd938c95873..4361813e628 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -1588,6 +1588,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO - - if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; - -+ if (do_esync()) -+ { -+ NTSTATUS ret = esync_wait_objects( count, handles, wait_any, alertable, timeout ); -+ if (ret != STATUS_NOT_IMPLEMENTED) -+ 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] ); --- -2.43.0 - diff --git a/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch b/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch deleted file mode 100644 index a6ef5475..00000000 --- a/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 9c2870d27349ce3548c84ff1f7b5825b5c398296 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 14:40:43 -0500 -Subject: [PATCH] ntdll, server: Implement NtCreateEvent(). - ---- - dlls/ntdll/unix/esync.c | 27 +++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 3 +++ - dlls/ntdll/unix/sync.c | 4 ++++ - server/esync.c | 15 +++++++++++++++ - 4 files changed, 49 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 75ceb95bc66..06842f0c8f5 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -88,6 +88,13 @@ struct semaphore - }; - C_ASSERT(sizeof(struct semaphore) == 8); - -+struct event -+{ -+ int signaled; -+ int locked; -+}; -+C_ASSERT(sizeof(struct event) == 8); -+ - static char shm_name[29]; - static int shm_fd; - static void **shm_addrs; -@@ -294,6 +301,18 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - 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 ); -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -@@ -339,6 +358,14 @@ static void update_grabbed_object( struct esync *obj ) - * 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; -+ } - } - - /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 92b609ebd27..7bb963faf51 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max); - extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG 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_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ); - -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 79141999e33..161c170f59c 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -387,6 +387,10 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ - - *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 ) -diff --git a/server/esync.c b/server/esync.c -index 75ef586df30..6a63c0dd5e9 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -201,6 +201,13 @@ struct semaphore - }; - C_ASSERT(sizeof(struct semaphore) == 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 ) -@@ -256,6 +263,14 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, - 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; -+ } - default: - assert( 0 ); - } --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch b/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch deleted file mode 100644 index ae903f2f..00000000 --- a/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e2ab736b2e8b98268bdf840a460ee54b8388328e Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 14:46:24 -0500 -Subject: [PATCH] ntdll: Implement NtSetEvent(). - ---- - dlls/ntdll/unix/esync.c | 15 +++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 4 ++++ - 3 files changed, 20 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 06842f0c8f5..3bb7f2daf8f 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -313,6 +313,21 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - return create_esync( type, handle, access, attr, initial, 0 ); - } - -+NTSTATUS esync_set_event( HANDLE handle ) -+{ -+ static const uint64_t value = 1; -+ struct esync *obj; -+ -+ TRACE("%p.\n", handle); -+ -+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ -+ if (write( obj->fd, &value, sizeof(value) ) == -1) -+ ERR("write: %s\n", strerror(errno)); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 7bb963faf51..d92165214d6 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG 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_set_event( HANDLE handle ); - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ); -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 161c170f59c..706d381d7c7 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -439,8 +439,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 ); -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch b/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch deleted file mode 100644 index 26bd8d0a..00000000 --- a/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 98024ae21fbeb4f86c89000bd7953cf192c833ef Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 14:51:21 -0500 -Subject: [PATCH] ntdll: Implement NtResetEvent(). - ---- - dlls/ntdll/unix/esync.c | 15 +++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 5 +++++ - 3 files changed, 21 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 3bb7f2daf8f..8ee0c99c5d9 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -328,6 +328,21 @@ NTSTATUS esync_set_event( HANDLE handle ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_reset_event( HANDLE handle ) -+{ -+ uint64_t value; -+ struct esync *obj; -+ -+ TRACE("%p.\n", handle); -+ -+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ -+ if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) -+ ERR("read: %s\n", strerror(errno)); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index d92165214d6..6e5d6233a2e 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG 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_reset_event( HANDLE handle ); - extern NTSTATUS esync_set_event( HANDLE handle ); - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 706d381d7c7..fdf4215039b 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -462,8 +462,13 @@ 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 ); -+ -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch b/patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch deleted file mode 100644 index 108776e1..00000000 --- a/patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 4a9eff3f22bfe2c6463e3064ec862617d5dd07d7 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 14:57:42 -0500 -Subject: [PATCH] ntdll: Implement waiting on manual-reset events. - ---- - dlls/ntdll/unix/esync.c | 27 +++++++++++++++++---------- - 1 file changed, 17 insertions(+), 10 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 80eb3773ee4..f4c27796189 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -36,12 +36,7 @@ - #ifdef HAVE_SYS_STAT_H - # include - #endif --#ifdef HAVE_POLL_H - #include --#endif --#ifdef HAVE_SYS_POLL_H --# include --#endif - #include - #include - -@@ -481,12 +476,24 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - int64_t value; - ssize_t size; - -- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value)) -+ if (obj->type == ESYNC_MANUAL_EVENT) -+ { -+ /* 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 - { -- /* We found our object. */ -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- update_grabbed_object( obj ); -- return i; -+ 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); -+ update_grabbed_object( obj ); -+ return i; -+ } - } - } - } --- -2.33.0 - diff --git a/patches/eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch b/patches/eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch deleted file mode 100644 index e7cd15cf..00000000 --- a/patches/eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch +++ /dev/null @@ -1,749 +0,0 @@ -From 16f5ebca082d65ca9abeddb857f30ef58f590ea3 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 18:51:40 -0500 -Subject: [PATCH] server: Add an object operation to grab the esync file - descriptor. - -Split off to decrease patch size. ---- - server/async.c | 2 ++ - server/atom.c | 1 + - server/change.c | 1 + - server/clipboard.c | 1 + - server/completion.c | 2 ++ - server/console.c | 7 +++++++ - server/debugger.c | 2 ++ - server/device.c | 4 ++++ - server/directory.c | 2 ++ - server/esync.c | 1 + - server/event.c | 2 ++ - server/fd.c | 4 ++++ - server/file.c | 1 + - server/handle.c | 1 + - server/hook.c | 1 + - server/mailslot.c | 4 ++++ - server/mapping.c | 3 +++ - server/mutex.c | 1 + - server/named_pipe.c | 5 +++++ - server/object.c | 2 ++ - server/object.h | 2 ++ - server/process.c | 3 +++ - server/queue.c | 2 ++ - server/registry.c | 1 + - server/request.c | 1 + - server/semaphore.c | 1 + - server/serial.c | 1 + - server/signal.c | 1 + - server/sock.c | 3 +++ - server/symlink.c | 1 + - server/thread.c | 3 +++ - server/timer.c | 1 + - server/token.c | 1 + - server/window.c | 1 + - server/winstation.c | 2 ++ - 35 files changed, 71 insertions(+) - -diff --git a/server/async.c b/server/async.c -index d2d929c9709..9768a4932a6 100644 ---- a/server/async.c -+++ b/server/async.c -@@ -78,6 +78,7 @@ 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 */ -@@ -698,6 +699,7 @@ 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 */ -diff --git a/server/atom.c b/server/atom.c -index ff0799f5880..d9824de8eac 100644 ---- a/server/atom.c -+++ b/server/atom.c -@@ -79,6 +79,7 @@ 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 */ -diff --git a/server/change.c b/server/change.c -index f42ce066340..d0a90a99261 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -112,6 +112,7 @@ static const struct object_ops dir_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - dir_get_fd, /* get_fd */ -diff --git a/server/clipboard.c b/server/clipboard.c -index 91f159bc7c9..0df7fd2f18e 100644 ---- a/server/clipboard.c -+++ b/server/clipboard.c -@@ -76,6 +76,7 @@ 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 */ -diff --git a/server/completion.c b/server/completion.c -index 99680ae0680..3d750154d1b 100644 ---- a/server/completion.c -+++ b/server/completion.c -@@ -92,6 +92,7 @@ static const struct object_ops completion_wait_ops = - 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 */ -@@ -166,6 +167,7 @@ static const struct object_ops completion_ops = - 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 */ -diff --git a/server/console.c b/server/console.c -index de6f4e73e31..9bdba479e8c 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -84,6 +84,7 @@ 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 */ -@@ -161,6 +162,7 @@ static const struct object_ops console_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_server_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_server_get_fd, /* get_fd */ -@@ -230,6 +232,7 @@ static const struct object_ops screen_buffer_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - screen_buffer_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - screen_buffer_get_fd, /* get_fd */ -@@ -279,6 +282,7 @@ 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 */ -@@ -318,6 +322,7 @@ static const struct object_ops console_input_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_input_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_input_get_fd, /* get_fd */ -@@ -377,6 +382,7 @@ static const struct object_ops console_output_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_output_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_output_get_fd, /* get_fd */ -@@ -435,6 +441,7 @@ 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 */ -diff --git a/server/debugger.c b/server/debugger.c -index 39a740e07e5..0c01ec1c0d3 100644 ---- a/server/debugger.c -+++ b/server/debugger.c -@@ -86,6 +86,7 @@ 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 */ -@@ -114,6 +115,7 @@ 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 */ -diff --git a/server/device.c b/server/device.c -index 1f93cca437d..a0608aa6164 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -66,6 +66,7 @@ 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 */ -@@ -106,6 +107,7 @@ static const struct object_ops device_manager_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - device_manager_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -163,6 +165,7 @@ 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 */ -@@ -215,6 +218,7 @@ 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 */ -diff --git a/server/directory.c b/server/directory.c -index fd689c561bc..2894f7669db 100644 ---- a/server/directory.c -+++ b/server/directory.c -@@ -69,6 +69,7 @@ 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 */ -@@ -119,6 +120,7 @@ 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 */ -diff --git a/server/esync.c b/server/esync.c -index 6a63c0dd5e9..f95dc5a391f 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -122,6 +122,7 @@ static const struct object_ops esync_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 */ -diff --git a/server/event.c b/server/event.c -index ad7c09acc99..16cea16e9c2 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -72,6 +72,7 @@ static const struct object_ops event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - event_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - event_satisfied, /* satisfied */ - event_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -119,6 +120,7 @@ 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 */ -diff --git a/server/fd.c b/server/fd.c -index dde92beb664..b0c28e54360 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -172,6 +172,7 @@ 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 */ -@@ -213,6 +214,7 @@ 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 */ -@@ -253,6 +255,7 @@ 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 */ -@@ -295,6 +298,7 @@ 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 */ -diff --git a/server/file.c b/server/file.c -index 2a839968c25..cbef0c63383 100644 ---- a/server/file.c -+++ b/server/file.c -@@ -94,6 +94,7 @@ 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 */ -diff --git a/server/handle.c b/server/handle.c -index 8968df73647..3d36af360c2 100644 ---- a/server/handle.c -+++ b/server/handle.c -@@ -126,6 +126,7 @@ 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 */ -diff --git a/server/hook.c b/server/hook.c -index ffe7206369e..921aa8aba2e 100644 ---- a/server/hook.c -+++ b/server/hook.c -@@ -81,6 +81,7 @@ 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 */ -diff --git a/server/mailslot.c b/server/mailslot.c -index c54281c2101..e4c24459f22 100644 ---- a/server/mailslot.c -+++ b/server/mailslot.c -@@ -81,6 +81,7 @@ 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 */ -@@ -142,6 +143,7 @@ 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 */ -@@ -207,6 +209,7 @@ 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 */ -@@ -237,6 +240,7 @@ 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 */ -diff --git a/server/mapping.c b/server/mapping.c -index 247b28cf6f5..d8498b65054 100644 ---- a/server/mapping.c -+++ b/server/mapping.c -@@ -67,6 +67,7 @@ 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 */ -@@ -103,6 +104,7 @@ 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 */ -@@ -176,6 +178,7 @@ 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 */ -diff --git a/server/mutex.c b/server/mutex.c -index af0efe72132..4785a830e92 100644 ---- a/server/mutex.c -+++ b/server/mutex.c -@@ -73,6 +73,7 @@ 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 */ -diff --git a/server/named_pipe.c b/server/named_pipe.c -index 6e4ae371a1b..0eebd68abe6 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -119,6 +119,7 @@ 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 */ -@@ -167,6 +168,7 @@ static const struct object_ops pipe_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -211,6 +213,7 @@ static const struct object_ops pipe_client_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -258,6 +261,7 @@ 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 */ -@@ -289,6 +293,7 @@ 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 */ -diff --git a/server/object.c b/server/object.c -index cd368ef724a..4d8fcc5a774 100644 ---- a/server/object.c -+++ b/server/object.c -@@ -108,6 +108,7 @@ 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 */ -@@ -132,6 +133,7 @@ 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 */ -diff --git a/server/object.h b/server/object.h -index 1058f9bfb0a..4acf6f03572 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -78,6 +78,8 @@ 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 */ -diff --git a/server/process.c b/server/process.c -index b161e3394ba..b3676936317 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -105,6 +105,7 @@ static const struct object_ops process_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - process_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -156,6 +157,7 @@ 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 */ -@@ -217,6 +219,7 @@ 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 */ -diff --git a/server/queue.c b/server/queue.c -index 2d23fb0def8..19486a745be 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -165,6 +165,7 @@ static const struct object_ops msg_queue_ops = - msg_queue_add_queue, /* add_queue */ - msg_queue_remove_queue, /* remove_queue */ - msg_queue_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - msg_queue_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -202,6 +203,7 @@ 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 */ -diff --git a/server/registry.c b/server/registry.c -index c60c737feff..34c422dcc6f 100644 ---- a/server/registry.c -+++ b/server/registry.c -@@ -180,6 +180,7 @@ 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 */ -diff --git a/server/request.c b/server/request.c -index 2254315b79e..f4f5e713935 100644 ---- a/server/request.c -+++ b/server/request.c -@@ -89,6 +89,7 @@ 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 */ -diff --git a/server/semaphore.c b/server/semaphore.c -index 53b42a886df..e3889f24601 100644 ---- a/server/semaphore.c -+++ b/server/semaphore.c -@@ -70,6 +70,7 @@ 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 */ -diff --git a/server/serial.c b/server/serial.c -index 209f2e9174e..0d49a996c2a 100644 ---- a/server/serial.c -+++ b/server/serial.c -@@ -91,6 +91,7 @@ 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 */ -diff --git a/server/signal.c b/server/signal.c -index 19b76d44c16..55cd6aa037e 100644 ---- a/server/signal.c -+++ b/server/signal.c -@@ -62,6 +62,7 @@ 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 */ -diff --git a/server/sock.c b/server/sock.c -index e064f867ff4..e9e81d9ecd0 100644 ---- a/server/sock.c -+++ b/server/sock.c -@@ -486,6 +486,7 @@ 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 */ -@@ -3695,6 +3696,7 @@ 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 */ -@@ -3916,6 +3918,7 @@ 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 */ -diff --git a/server/symlink.c b/server/symlink.c -index 74b60162c01..2dd9c6a798d 100644 ---- a/server/symlink.c -+++ b/server/symlink.c -@@ -71,6 +71,7 @@ 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 */ -diff --git a/server/thread.c b/server/thread.c -index c7d1c6c55c8..ac000826599 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -106,6 +106,7 @@ 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 */ -@@ -148,6 +149,7 @@ 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 */ -@@ -197,6 +199,7 @@ static const struct object_ops thread_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -diff --git a/server/timer.c b/server/timer.c -index b0b6ec81535..883f30fa97e 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -76,6 +76,7 @@ static const struct object_ops timer_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - timer_signaled, /* signaled */ -+ NULL, /* get_esync_fd */ - timer_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -diff --git a/server/token.c b/server/token.c -index 7e20c670a16..b638ed192cb 100644 ---- a/server/token.c -+++ b/server/token.c -@@ -145,6 +145,7 @@ 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 */ -diff --git a/server/window.c b/server/window.c -index f7f9d5e517f..8c416d8c88f 100644 ---- a/server/window.c -+++ b/server/window.c -@@ -107,6 +107,7 @@ 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 */ -diff --git a/server/winstation.c b/server/winstation.c -index b3746090ccf..126b70d625a 100644 ---- a/server/winstation.c -+++ b/server/winstation.c -@@ -76,6 +76,7 @@ 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 */ -@@ -116,6 +117,7 @@ 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 */ --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch b/patches/eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch deleted file mode 100644 index cf011c95..00000000 --- a/patches/eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 2f23f37d5a1ba0d59d367729d96285ac7c470e8d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 18:55:49 -0500 -Subject: [PATCH] server: Add a request to get the eventfd file descriptor - associated with a waitable handle. - ---- - server/esync.c | 37 +++++++++++++++++++++++++++++++++++++ - server/protocol.def | 9 ++++++++- - 2 files changed, 45 insertions(+), 1 deletion(-) - -diff --git a/server/esync.c b/server/esync.c -index f95dc5a391f..85f7f1e060f 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -333,3 +333,40 @@ DECL_HANDLER(create_esync) - - if (root) release_object( root ); - } -+ -+/* 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 ); -+} -diff --git a/server/protocol.def b/server/protocol.def -index 03bc0aeb11e..4ab6b97ba93 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -3902,6 +3902,14 @@ enum esync_type - unsigned int shm_idx; - @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; -+@END -+ - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ -@@ -3910,4 +3918,3 @@ enum esync_type - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END -- --- -2.43.0 - diff --git a/patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch b/patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch deleted file mode 100644 index b580bc53..00000000 --- a/patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch +++ /dev/null @@ -1,134 +0,0 @@ -From ce164f9c292bc93ad50055bdb0a786e8a8770afa Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 15:11:12 -0500 -Subject: [PATCH] server: Create eventfd file descriptors for process objects. - ---- - server/esync.c | 18 ++++++++++++++++++ - server/esync.h | 1 + - server/process.c | 16 +++++++++++++++- - server/process.h | 1 + - 4 files changed, 35 insertions(+), 1 deletion(-) - -diff --git a/server/esync.c b/server/esync.c -index 85f7f1e060f..44214e5fe02 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -295,6 +295,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, - #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 -+} -+ - DECL_HANDLER(create_esync) - { - struct esync *esync; -diff --git a/server/esync.h b/server/esync.h -index 00f9e638d83..8522d8a69ae 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -22,3 +22,4 @@ - - extern int do_esync(void); - void esync_init(void); -+int esync_create_fd( int initval, int flags ); -diff --git a/server/process.c b/server/process.c -index 3c5a58b7b03..30555d516c8 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -63,6 +63,7 @@ - #include "request.h" - #include "user.h" - #include "security.h" -+#include "esync.h" - - /* process object */ - -@@ -95,6 +96,7 @@ 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 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 = -@@ -105,7 +107,7 @@ static const struct object_ops process_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - process_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ process_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -689,6 +691,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - process->rawinput_kbd = 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 ); -@@ -739,6 +742,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla - if (!process->handles || !process->token) goto error; - process->session_id = token_get_session_id( process->token ); - -+ if (do_esync()) -+ process->esync_fd = esync_create_fd( 0, 0 ); -+ - set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ - return process; - -@@ -787,6 +793,7 @@ 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 ); - } - - /* dump a process on stdout for debugging purposes */ -@@ -804,6 +811,13 @@ 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 ); -diff --git a/server/process.h b/server/process.h -index 96814ab7cf8..ec74ba0490a 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 */ -+ int esync_fd; /* esync file descriptor (signaled on exit) */ - }; - - /* process functions */ --- -2.45.2 - diff --git a/patches/eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch b/patches/eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch deleted file mode 100644 index 8a3b1a90..00000000 --- a/patches/eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 0ef3de9bd3b51a1e37c50fd75ceb3db6ea24abd0 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 15:19:37 -0500 -Subject: [PATCH] ntdll, server: Implement waiting on server-bound objects. - -The code here is sort of self-explanatory, but since I split it up over -several patches I'll provide a quick explanation. The basic principle is -that we can create an eventfd descriptor for any synchronizable handle, and -signal it on the server side whenever a wakeup would be triggered. This means -not only that we can wait simultaneously on esync primitives and on other -primitives, but that we can do it all in "user-mode", i.e. without having to -make a server call. - -With this patch we break waiting on svcctl.exe. ---- - dlls/ntdll/unix/esync.c | 84 ++++++++++++++++++++++++++++++++++++++--- - server/esync.c | 16 ++++++++ - server/esync.h | 1 + - server/named_pipe.c | 1 + - server/thread.c | 4 ++ - 5 files changed, 100 insertions(+), 6 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 65ef70acd36..b0168f5cde5 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -193,6 +193,72 @@ static struct esync *get_cached_object( HANDLE handle ) - 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 ) -+{ -+ NTSTATUS 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 ); -@@ -272,10 +338,11 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - struct semaphore *semaphore; - uint64_t count64 = count; - ULONG current; -+ NTSTATUS ret; - - TRACE("%p, %d, %p.\n", handle, count, prev); - -- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj))) return ret; - semaphore = obj->shm; - - do -@@ -314,10 +381,11 @@ NTSTATUS esync_set_event( HANDLE handle ) - { - static const uint64_t value = 1; - struct esync *obj; -+ NTSTATUS ret; - - TRACE("%p.\n", handle); - -- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj))) return ret; - - if (write( obj->fd, &value, sizeof(value) ) == -1) - ERR("write: %s\n", strerror(errno)); -@@ -329,10 +397,11 @@ NTSTATUS esync_reset_event( HANDLE handle ) - { - uint64_t value; - struct esync *obj; -+ NTSTATUS ret; - - TRACE("%p.\n", handle); - -- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj))) return ret; - - if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) - ERR("read: %s\n", strerror(errno)); -@@ -421,10 +490,13 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - - for (i = 0; i < count; i++) - { -- if ((objs[i] = get_cached_object( handles[i] ))) -+ ret = get_object( handles[i], &objs[i] ); -+ if (ret == STATUS_SUCCESS) - has_esync = 1; -- else -+ else if (ret == STATUS_NOT_IMPLEMENTED) - has_server = 1; -+ else -+ return ret; - } - - if (has_esync && has_server) -@@ -477,7 +549,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - int64_t value; - ssize_t size; - -- if (obj->type == ESYNC_MANUAL_EVENT) -+ if (obj->type == ESYNC_MANUAL_EVENT || obj->type == ESYNC_MANUAL_SERVER) - { - /* Don't grab the object, just check if it's signaled. */ - if (fds[i].revents & POLLIN) -diff --git a/server/esync.c b/server/esync.c -index 44214e5fe02..60e98936455 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -313,6 +313,22 @@ int esync_create_fd( int initval, int flags ) - #endif - } - -+/* Wake up a server-side esync object. */ -+void esync_wake_up( struct object *obj ) -+{ -+ static const uint64_t value = 1; -+ enum esync_type dummy; -+ int fd; -+ -+ if (obj->ops->get_esync_fd) -+ { -+ fd = obj->ops->get_esync_fd( obj, &dummy ); -+ -+ if (write( fd, &value, sizeof(value) ) == -1) -+ perror( "esync: write" ); -+ } -+} -+ - DECL_HANDLER(create_esync) - { - struct esync *esync; -diff --git a/server/esync.h b/server/esync.h -index 8522d8a69ae..1241e6d9f1a 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -23,3 +23,4 @@ - extern int do_esync(void); - void esync_init(void); - int esync_create_fd( int initval, int flags ); -+void esync_wake_up( struct object *obj ); -diff --git a/server/named_pipe.c b/server/named_pipe.c -index 68fa8953cca..1535c5188ec 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -344,6 +344,7 @@ static const struct object_ops named_pipe_dir_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_dir_get_fd, /* get_fd */ -diff --git a/server/thread.c b/server/thread.c -index 339cdfec1fa..4262b841fca 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -50,6 +50,7 @@ - #include "request.h" - #include "user.h" - #include "security.h" -+#include "esync.h" - - - /* thread queues */ -@@ -1073,6 +1074,9 @@ 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 ); --- -2.45.2 - diff --git a/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch b/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch deleted file mode 100644 index d81267e5..00000000 --- a/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch +++ /dev/null @@ -1,141 +0,0 @@ -From dcb50e04b4ec205f4a6688c71a23cb2863cffce6 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 21:01:24 -0500 -Subject: [PATCH] server: Create eventfd file descriptors for event objects. - -We still need this, since there are some events which the server signals. - -This lets system processes shut down. ---- - server/esync.c | 8 ++++++++ - server/esync.h | 1 + - server/event.c | 29 +++++++++++++++++++++++++++-- - 3 files changed, 36 insertions(+), 2 deletions(-) - -diff --git a/server/esync.c b/server/esync.c -index 6696119b207..8cb46c4f2ce 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -329,6 +329,14 @@ void esync_wake_up( struct object *obj ) - } - } - -+void esync_clear( int fd ) -+{ -+ uint64_t value; -+ -+ /* we don't care about the return value */ -+ read( fd, &value, sizeof(value) ); -+} -+ - DECL_HANDLER(create_esync) - { - struct esync *esync; -diff --git a/server/esync.h b/server/esync.h -index 1241e6d9f1a..d259b5f604d 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -24,3 +24,4 @@ extern int do_esync(void); - void esync_init(void); - int esync_create_fd( int initval, int flags ); - void esync_wake_up( struct object *obj ); -+void esync_clear( int fd ); -diff --git a/server/event.c b/server/event.c -index c727bfdd1ba..f1a88e3d23f 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -35,6 +35,7 @@ - #include "thread.h" - #include "request.h" - #include "security.h" -+#include "esync.h" - - static const WCHAR event_name[] = {'E','v','e','n','t'}; - -@@ -56,13 +57,16 @@ 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 */ - }; - - 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 void event_destroy( struct object *obj ); - - static const struct object_ops event_ops = - { -@@ -72,7 +76,7 @@ static const struct object_ops event_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - event_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ event_get_esync_fd, /* get_esync_fd */ - event_satisfied, /* satisfied */ - event_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -86,7 +90,7 @@ static const struct object_ops event_ops = - no_open_file, /* open_file */ - event_get_kernel_obj_list, /* get_kernel_obj_list */ - no_close_handle, /* close_handle */ -- no_destroy /* destroy */ -+ event_destroy /* destroy */ - }; - - -@@ -152,6 +156,9 @@ 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 ); - } - } - return event; -@@ -180,6 +187,9 @@ void set_event( struct event *event ) - void reset_event( struct event *event ) - { - event->signaled = 0; -+ -+ if (do_esync()) -+ esync_clear( event->esync_fd ); - } - - static void event_dump( struct object *obj, int verbose ) -@@ -197,6 +207,13 @@ 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; -@@ -225,6 +242,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) - return &event->kernel_object; - } - -+static void event_destroy( struct object *obj ) -+{ -+ struct event *event = (struct event *)obj; -+ -+ if (do_esync()) -+ close( event->esync_fd ); -+} -+ - struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, - unsigned int attr, const struct security_descriptor *sd ) - { --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch b/patches/eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch deleted file mode 100644 index c5b8d4db..00000000 --- a/patches/eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 949b61856a56c339cbe6f8ec88a34902e200ae8e Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 21:43:37 -0500 -Subject: [PATCH] server: Allow (re)setting esync events on the server side. - -Some server calls pass an event handle, most notably asyncs. We need to be -able to handle these correctly. Accordingly we pass them along to esync if -it turns out the underlying object is actually an esync object. - -In an ideal world we'd just convert all instances of events on the server -side to use esyncs instead. But we want to keep esync perfectly configurable, -so this is how we do it. ---- - server/esync.c | 22 +++++++++++++++++++++- - server/esync.h | 6 ++++++ - server/event.c | 15 +++++++++++++++ - 3 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/server/esync.c b/server/esync.c -index 975e5d2ddd6..ac59779a454 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -116,7 +116,7 @@ struct esync - static void esync_dump( struct object *obj, int verbose ); - static void esync_destroy( struct object *obj ); - --static const struct object_ops esync_ops = -+const struct object_ops esync_ops = - { - sizeof(struct esync), /* size */ - &no_type, /* type */ -@@ -339,6 +339,26 @@ void esync_clear( int fd ) - read( fd, &value, sizeof(value) ); - } - -+/* Server-side event support. */ -+void esync_set_event( struct esync *esync ) -+{ -+ static const uint64_t value = 1; -+ -+ assert( esync->obj.ops == &esync_ops ); -+ if (write( esync->fd, &value, sizeof(value) ) == -1) -+ perror( "esync: write" ); -+} -+ -+void esync_reset_event( struct esync *esync ) -+{ -+ static uint64_t value = 1; -+ -+ assert( esync->obj.ops == &esync_ops ); -+ -+ /* we don't care about the return value */ -+ read( esync->fd, &value, sizeof(value) ); -+} -+ - DECL_HANDLER(create_esync) - { - struct esync *esync; -diff --git a/server/esync.h b/server/esync.h -index fcbfd0989bb..aeb58c5469c 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -23,3 +23,9 @@ void esync_init(void); - int esync_create_fd( int initval, int flags ); - 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 ); -diff --git a/server/event.c b/server/event.c -index 78d90dac5d6..bc2948c30aa 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -154,6 +154,10 @@ 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 ); - } - -@@ -167,6 +171,12 @@ 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 ); -@@ -174,6 +184,11 @@ void set_event( struct event *event ) - - 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()) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch b/patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch deleted file mode 100644 index 00198a56..00000000 --- a/patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 07f3e8af59a9083ecd5abe31a48670a18dac2e84 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 21:58:37 -0500 -Subject: [PATCH] ntdll: Try again if poll() returns EINTR. - -I originally had this return STATUS_USER_APC, but that isn't correct. The -server code here is a bit confusing, but only the thread that waits *during* -the suspend should receive STATUS_USER_APC (and I imagine that it really -should receive STATUS_KERNEL_APC instead). The thread that is suspended -should just keep on waiting. - -Besides, we could be suspended for reasons other than to deliver a system -APC. ---- - dlls/ntdll/unix/esync.c | 32 +++++++++++++++++++++----------- - 1 file changed, 21 insertions(+), 11 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 6fd195df759..fcbe563bb5a 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -431,22 +431,32 @@ static LONGLONG update_timeout( ULONGLONG end ) - - static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) - { -- if (end) -+ int ret; -+ -+ do - { -- LONGLONG timeleft = update_timeout( *end ); -+ 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; -- return ppoll( fds, nfds, &tmo_p, NULL ); -+ /* 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 -- return poll( fds, nfds, timeleft / TICKSPERMSEC ); -+ ret = poll( fds, nfds, timeleft / TICKSPERMSEC ); - #endif -- } -- else -- return poll( fds, nfds, -1 ); -+ } -+ 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; - } - - static void update_grabbed_object( struct esync *obj ) --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch b/patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch deleted file mode 100644 index 880aa945..00000000 --- a/patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch +++ /dev/null @@ -1,88 +0,0 @@ -From f72b878cf5dcf8f20d485f7b3e75d86e303393e7 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 22:04:29 -0500 -Subject: [PATCH] server: Create eventfd file descriptors for thread objects. - ---- - server/thread.c | 17 ++++++++++++++++- - server/thread.h | 1 + - 2 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/server/thread.c b/server/thread.c -index e7795c21136..ef5b3fbf313 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -186,6 +186,7 @@ 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 ); -@@ -199,7 +200,7 @@ static const struct object_ops thread_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - thread_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ thread_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -239,6 +240,7 @@ static inline void init_thread_structure( struct thread *thread ) - thread->context = NULL; - thread->teb = 0; - thread->entry_point = 0; -+ thread->esync_fd = -1; - thread->system_regs = 0; - thread->queue = NULL; - thread->wait = NULL; -@@ -385,6 +387,9 @@ struct thread *create_thread( int fd, struct process *process, const struct secu - } - } - -+ if (do_esync()) -+ thread->esync_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; -@@ -464,6 +469,9 @@ 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 ); - } - - /* dump a thread on stdout for debugging purposes */ -@@ -482,6 +490,13 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) - return mythread->state == TERMINATED && !mythread->exit_poll; - } - -+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 ); -diff --git a/server/thread.h b/server/thread.h -index 077ab0929ba..99904557d44 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -54,6 +54,7 @@ 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) */ - 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 */ --- -2.30.2 - diff --git a/patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch b/patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch deleted file mode 100644 index 98ce6650..00000000 --- a/patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From b3b91529f2e57720b52553dd0477c6077ab1a04b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 23:30:17 -0500 -Subject: [PATCH] rpcrt4: Avoid closing the server thread handle while it is - being waited on. - -This, or something like this, should go upstream. This is invalid behaviour. ---- - dlls/rpcrt4/rpc_server.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c -index cb62c59e368..2fd1e1bc4b4 100644 ---- a/dlls/rpcrt4/rpc_server.c -+++ b/dlls/rpcrt4/rpc_server.c -@@ -699,10 +699,6 @@ 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; - } -@@ -1570,7 +1566,10 @@ 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) -@@ -1579,6 +1578,7 @@ 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) --- -2.34.1 - diff --git a/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch b/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch deleted file mode 100644 index d7694e4a..00000000 --- a/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 52be83d9a557eec924a964944e6b926fb1e347ad Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:01:56 -0500 -Subject: [PATCH] server: Create eventfd file descriptors for message queues. - ---- - server/queue.c | 30 +++++++++++++++++++++++++++++- - 1 file changed, 29 insertions(+), 1 deletion(-) - -diff --git a/server/queue.c b/server/queue.c -index a3479055ed4..08635c047b2 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -45,6 +45,7 @@ - #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)) -@@ -135,6 +136,7 @@ struct msg_queue - int keystate_lock; /* owns an input keystate lock */ - queue_shm_t *shared; /* queue in session shared memory */ - unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */ -+ int esync_fd; /* esync file descriptor (signalled on message) */ - }; - - struct hotkey -@@ -151,6 +153,7 @@ 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 void msg_queue_destroy( struct object *obj ); - static void msg_queue_poll_event( struct fd *fd, int event ); -@@ -166,7 +169,7 @@ static const struct object_ops msg_queue_ops = - msg_queue_add_queue, /* add_queue */ - msg_queue_remove_queue, /* remove_queue */ - msg_queue_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ msg_queue_get_esync_fd, /* get_esync_fd */ - msg_queue_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -317,6 +320,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->last_get_msg = current_time; - queue->keystate_lock = 0; - queue->ignore_post_msg = 0; -+ queue->esync_fd = -1; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); -@@ -339,6 +343,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - } - SHARED_WRITE_END; - -+ if (do_esync()) -+ queue->esync_fd = esync_create_fd( 0, 0 ); -+ - thread->queue = queue; - - if ((desktop = get_thread_desktop( thread, 0 ))) -@@ -753,6 +760,9 @@ 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 ); - } - - /* check if message is matched by the filter */ -@@ -1335,6 +1345,13 @@ 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 ) -+{ -+ struct msg_queue *queue = (struct msg_queue *)obj; -+ *type = ESYNC_QUEUE; -+ return queue->esync_fd; -+} -+ - static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct msg_queue *queue = (struct msg_queue *)obj; -@@ -1391,6 +1408,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 ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -3181,6 +3199,9 @@ DECL_HANDLER(set_queue_mask) - } - else wake_up( &queue->obj, 0 ); - } -+ -+ if (do_esync() && !is_signaled( queue )) -+ esync_clear( queue->esync_fd ); - } - } - -@@ -3201,6 +3222,9 @@ DECL_HANDLER(get_queue_status) - shared->changed_bits &= ~req->clear_bits; - } - SHARED_WRITE_END; -+ -+ if (do_esync() && !is_signaled( queue )) -+ esync_clear( queue->esync_fd ); - } - else reply->wake_bits = reply->changed_bits = 0; - } -@@ -3469,6 +3493,10 @@ DECL_HANDLER(get_message) - SHARED_WRITE_END; - - set_error( STATUS_PENDING ); /* FIXME */ -+ -+ if (do_esync() && !is_signaled( queue )) -+ esync_clear( queue->esync_fd ); -+ - return; - - found_msg: --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch b/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch deleted file mode 100644 index f119ffe8..00000000 --- a/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch +++ /dev/null @@ -1,184 +0,0 @@ -From c9d64a429d4343f4ceb53ae28ecc380aaa42b09e Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:11:23 -0500 -Subject: [PATCH] server, ntdll: Implement message waits. - ---- - dlls/ntdll/unix/esync.c | 51 +++++++++++++++++++++++++++++++++++++++-- - server/protocol.def | 4 ++++ - server/queue.c | 24 +++++++++++++++++++ - 3 files changed, 77 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index b2204d44ed9..3af79a2de15 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -476,12 +476,13 @@ static void update_grabbed_object( struct esync *obj ) - - /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we - * need to delegate to server_select(). */ --NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) - { - struct esync *objs[MAXIMUM_WAIT_OBJECTS]; - struct pollfd fds[MAXIMUM_WAIT_OBJECTS]; - int has_esync = 0, has_server = 0; -+ BOOL msgwait = FALSE; - LONGLONG timeleft; - LARGE_INTEGER now; - ULONGLONG end; -@@ -509,6 +510,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - 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) -@@ -520,6 +524,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - for (i = 0; i < count; i++) - TRACE(" %p", handles[i]); - -+ if (msgwait) -+ TRACE(" or driver events"); -+ - if (!timeout) - TRACE(", timeout = INFINITE.\n"); - else -@@ -559,7 +566,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - int64_t value; - ssize_t size; - -- if (obj->type == ESYNC_MANUAL_EVENT || obj->type == ESYNC_MANUAL_SERVER) -+ 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) -@@ -604,6 +613,44 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - } - } - -+/* 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; -+} -+ - void esync_init(void) - { - struct stat st; -diff --git a/server/protocol.def b/server/protocol.def -index 86040d5b619..c2fdec93b8d 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4121,6 +4121,10 @@ enum esync_type - unsigned int shm_idx; - @END - -+@REQ(esync_msgwait) -+ int in_msgwait; /* are we in a message wait? */ -+@END -+ - /* Setup keyboard auto-repeat */ - @REQ(set_keyboard_repeat) - int enable; /* whether to enable auto-repeat */ -diff --git a/server/queue.c b/server/queue.c -index 08635c047b2..8f1a68acd7f 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -137,6 +137,7 @@ struct msg_queue - queue_shm_t *shared; /* queue in session shared memory */ - unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */ - int esync_fd; /* esync file descriptor (signalled on message) */ -+ int esync_in_msgwait; /* our thread is currently waiting on us */ - }; - - struct hotkey -@@ -321,6 +322,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ - queue->keystate_lock = 0; - queue->ignore_post_msg = 0; - queue->esync_fd = -1; -+ queue->esync_in_msgwait = 0; - list_init( &queue->send_result ); - list_init( &queue->callback_result ); - list_init( &queue->pending_timers ); -@@ -1291,6 +1293,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 (do_esync() && queue->esync_in_msgwait) -+ return 0; /* thread is waiting on queue in absentia -> not hung */ -+ - return 1; - } - -@@ -4281,6 +4287,23 @@ DECL_HANDLER(update_rawinput_devices) - } - } - -+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; -@@ -4299,3 +4322,4 @@ DECL_HANDLER(set_keyboard_repeat) - - release_object( desktop ); - } -+ --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch b/patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch deleted file mode 100644 index c445c5a0..00000000 --- a/patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 8111350c608821aa86c6acfb4959446abf97d382 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 15:39:37 -0500 -Subject: [PATCH] server: Create eventfd descriptors for device manager - objects. - -We don't have to worry about synchronization here because -wine_ntoskrnl_main_loop() is only ever called from one thread per winedevice -process. - -This lets drivers like mountmgr finally work, and so winecfg can open the -Drives tab. ---- - server/device.c | 24 +++++++++++++++++++++++- - 1 file changed, 23 insertions(+), 1 deletion(-) - -diff --git a/server/device.c b/server/device.c -index f730fa81afa..c45d0102a56 100644 ---- a/server/device.c -+++ b/server/device.c -@@ -38,6 +38,7 @@ - #include "handle.h" - #include "request.h" - #include "process.h" -+#include "esync.h" - - /* IRP object */ - -@@ -93,10 +94,12 @@ struct device_manager - struct list requests; /* list of pending irps across all devices */ - struct irp_call *current_call; /* call currently executed on client side */ - struct wine_rb_tree kernel_objects; /* map of objects that have client side pointer associated */ -+ int esync_fd; /* esync file descriptor */ - }; - - 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 void device_manager_destroy( struct object *obj ); - - static const struct object_ops device_manager_ops = -@@ -107,7 +110,7 @@ static const struct object_ops device_manager_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - device_manager_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ device_manager_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -751,6 +754,9 @@ 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 ); - } -@@ -786,6 +792,13 @@ 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 ) -+{ -+ struct device_manager *manager = (struct device_manager *)obj; -+ *type = ESYNC_MANUAL_SERVER; -+ return manager->esync_fd; -+} -+ - static void device_manager_destroy( struct object *obj ) - { - struct device_manager *manager = (struct device_manager *)obj; -@@ -820,6 +833,9 @@ static void device_manager_destroy( struct object *obj ) - assert( !irp->file && !irp->async ); - release_object( irp ); - } -+ -+ if (do_esync()) -+ close( manager->esync_fd ); - } - - static struct device_manager *create_device_manager(void) -@@ -832,6 +848,9 @@ static struct device_manager *create_device_manager(void) - 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; - } -@@ -1021,6 +1040,9 @@ DECL_HANDLER(get_next_device_request) - /* 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 ); - } --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch b/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch deleted file mode 100644 index ed7d5692..00000000 --- a/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch +++ /dev/null @@ -1,110 +0,0 @@ -From a4145f3d6ea7973ce83c7eef109613482c6adf11 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:34:56 -0500 -Subject: [PATCH] ntdll, server: Implement NtCreateMutant(). - ---- - dlls/ntdll/unix/esync.c | 16 ++++++++++++++++ - dlls/ntdll/unix/esync.h | 3 +++ - dlls/ntdll/unix/sync.c | 4 ++++ - server/esync.c | 14 ++++++++++++++ - 4 files changed, 37 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 06d7d8babc6..e979a5b81ae 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -83,6 +83,13 @@ struct semaphore - }; - C_ASSERT(sizeof(struct semaphore) == 8); - -+struct mutex -+{ -+ DWORD tid; -+ int count; /* recursion count */ -+}; -+C_ASSERT(sizeof(struct mutex) == 8); -+ - struct event - { - int signaled; -@@ -407,6 +414,15 @@ NTSTATUS esync_reset_event( HANDLE handle ) - 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 ); -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 6e5d6233a2e..9b2f88670d1 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -31,6 +31,9 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - 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_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ); - -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index fdf4215039b..1bf4a381a8f 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -555,6 +555,10 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT - struct object_attributes *objattr; - - *handle = 0; -+ -+ if (do_esync()) -+ return esync_create_mutex( handle, access, attr, owned ); -+ - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_mutex ) -diff --git a/server/esync.c b/server/esync.c -index 669afbc70d7..3f1c61bc1f0 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -202,6 +202,13 @@ struct semaphore - }; - C_ASSERT(sizeof(struct semaphore) == 8); - -+struct mutex -+{ -+ DWORD tid; -+ int count; /* recursion count */ -+}; -+C_ASSERT(sizeof(struct mutex) == 8); -+ - struct event - { - int signaled; -@@ -272,6 +279,13 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, - 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; -+ break; -+ } - default: - assert( 0 ); - } --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch b/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch deleted file mode 100644 index ec10184a..00000000 --- a/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 9ec9a7f034e533a613288382aaf93b468eafb945 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:37:49 -0500 -Subject: [PATCH] ntdll: Implement NtReleaseMutant(). - ---- - dlls/ntdll/unix/esync.c | 34 ++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 38 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index e979a5b81ae..48fcf38a64c 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -423,6 +423,40 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - return create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); - } - -+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; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 9b2f88670d1..8eaa79a5823 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -33,6 +33,7 @@ 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_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 ); -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 1bf4a381a8f..20391617e40 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -608,6 +608,9 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) - { - unsigned int ret; - -+ if (do_esync()) -+ return esync_release_mutex( handle, prev_count ); -+ - SERVER_START_REQ( release_mutex ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch b/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch deleted file mode 100644 index ccacbbc7..00000000 --- a/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 11cf48e4839f45845e0f5dc94fa1084165e7dcf4 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:42:13 -0500 -Subject: [PATCH] ntdll: Implement waiting on mutexes. - ---- - dlls/ntdll/unix/esync.c | 31 +++++++++++++++++++++++++++++-- - 1 file changed, 29 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 48482a31ea2..7ba1606489f 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -511,7 +511,16 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) - - static void update_grabbed_object( struct esync *obj ) - { -- if (obj->type == ESYNC_SEMAPHORE) -+ 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). */ -+ 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 -@@ -597,7 +606,25 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - { - for (i = 0; i < count; i++) - { -- fds[i].fd = objs[i] ? objs[i]->fd : -1; -+ struct esync *obj = objs[i]; -+ -+ if (obj && obj->type == ESYNC_MUTEX) -+ { -+ /* If we already own the mutex, return immediately. */ -+ /* Note: This violates the assumption that the *first* object -+ * to be signaled will be returned. If that becomes a problem, -+ * we can always check the state of each object before waiting. */ -+ struct mutex *mutex = (struct mutex *)obj; -+ -+ if (mutex->tid == GetCurrentThreadId()) -+ { -+ TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ mutex->count++; -+ return i; -+ } -+ } -+ -+ fds[i].fd = obj ? obj->fd : -1; - fds[i].events = POLLIN; - } - --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch b/patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch deleted file mode 100644 index 3bc9b230..00000000 --- a/patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 92524f81f5091276f2c1b99b670472519a74d121 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:47:38 -0500 -Subject: [PATCH] ntdll: Implement wait-all. - ---- - dlls/ntdll/unix/esync.c | 142 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 129 insertions(+), 13 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 7ba1606489f..0682428372c 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -551,7 +551,9 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - LONGLONG timeleft; - LARGE_INTEGER now; - ULONGLONG end; -- int i, ret; -+ int64_t value; -+ ssize_t size; -+ int i, j, ret; - - NtQuerySystemTime( &now ); - if (timeout) -@@ -646,9 +648,6 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - - if (obj) - { -- int64_t value; -- ssize_t size; -- - if (obj->type == ESYNC_MANUAL_EVENT - || obj->type == ESYNC_MANUAL_SERVER - || obj->type == ESYNC_QUEUE) -@@ -677,22 +676,139 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - * we were waiting for. So keep waiting. */ - NtQuerySystemTime( &now ); - } -- else if (ret == 0) -+ 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; -+ for (i = 0; i < count; i++) - { -- TRACE("Wait timed out.\n"); -- return STATUS_TIMEOUT; -+ 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, 1, timeout ? &end : NULL ); -+ if (ret <= 0) -+ goto err; -+ -+ 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; -+ } - } -- else -+ -+ /* 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++) - { -- ERR("ppoll failed: %s\n", strerror( errno )); -- return errno_to_status( errno ); -+ fds[i].fd = objs[i] ? objs[i]->fd : -1; -+ fds[i].events = POLLIN; - } -- } -+ -+ /* Poll everything to see if they're still signaled. */ -+ ret = poll( fds, count, 0 ); -+ if (ret == count) -+ { -+ /* 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++) -+ update_grabbed_object( objs[i] ); -+ -+ 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 - { -- FIXME("Wait-all not implemented.\n"); -- return STATUS_NOT_IMPLEMENTED; -+ ERR("ppoll failed: %s\n", strerror(errno)); -+ return errno_to_status( errno ); - } - } - --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0027-esync-Add-a-README.patch b/patches/eventfd_synchronization/0027-esync-Add-a-README.patch deleted file mode 100644 index 94920f13..00000000 --- a/patches/eventfd_synchronization/0027-esync-Add-a-README.patch +++ /dev/null @@ -1,204 +0,0 @@ -From bc9c29c1264f10d9de28dbfdd088c3da022be715 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 22:44:57 -0500 -Subject: [PATCH] esync: Add a README. - ---- - README.esync | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 184 insertions(+) - create mode 100644 README.esync - -diff --git a/README.esync b/README.esync -new file mode 100644 -index 00000000000..8fcb969011b ---- /dev/null -+++ b/README.esync -@@ -0,0 +1,184 @@ -+This is eventfd-based synchronization, or 'esync' for short. Turn it on with -+WINEESYNC=1 (note that it checks the presence and not the value); debug it -+with +esync. -+ -+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. -+ -+I had kind of figured that APCs just wouldn't work, but then poll() spat EINTR -+at me and I realized that this wasn't necessarily true. It seems that the -+server will suspend a thread when trying to deliver a system APC to a thread -+that's not waiting, and since the server has no idea that we're waiting it -+just suspends us. This of course interrupts poll(), which complains at us, and -+it turns out that just returning STATUS_USER_APC in that case is enough to -+make rpcrt4 happy. -+ -+There are a couple things that this infrastructure can't handle, although -+surprisingly there aren't that many. In particular: -+* We can't return the previous count on a semaphore, since we have no way to -+ query the count on a semaphore through eventfd. Currently the code lies and -+ returns 1 every time. We can make this work (in a single process, or [if -+ necessary] in multiple processes through shared memory) by keeping a count -+ locally. We can't guarantee that it's the exact count at the moment the -+ semaphore was released, but I guess any program that runs into that race -+ shouldn't be depending on that fact anyway. -+* Similarly, we can't enforce the maximum count on a semaphore, since we have -+ no way to get the current count and subsequently compare it with the -+ maximum. -+* We can't use NtQueryMutant to get the mutant's owner or count if it lives in -+ a different process. If necessary we can use shared memory to make this -+ work, I guess, but see below. -+* User APCs don't work. However, it's not impossible to make them work; in -+ particular I think this could be relatively easily implemented by waiting on -+ another internal file descriptor when we execute an alertable wait. -+* 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. -+* We might hit the maximum number of open fd's. On my system the soft limit is -+ 1024 and the hard limit is 1048576. I'm inclined to hope this won't be an -+ issue, since a hypothetical Linux port of any application might just as well -+ use the same number of eventfds. -+* 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: -+* NtOpen* (aka Open*). This is just a matter of adding another open_esync -+ request analogous to those for other server primitives. -+* NtQuery*. This can be done to some degree (the difficulties are outlined -+ above). That said, these APIs aren't exposed through kernel32 in any way, so -+ I doubt anyone is going to be using them. -+* SignalObjectAndWait(). The server combines this into a single operation, but -+ according to MSDN it doesn't need to be atomic, so we can just signal the -+ appropriate object and wait, and woe betide anyone who gets in the way of -+ those two operations. -+* 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. -+ -+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 -\ No newline at end of file --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch b/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch deleted file mode 100644 index 11b5850f..00000000 --- a/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 631ec6bff81bb2e3389d0c2030364dea91719bf6 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:52:39 -0500 -Subject: [PATCH] ntdll: Implement NtSignalAndWaitForSingleObject(). - ---- - dlls/ntdll/unix/esync.c | 28 ++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 2 ++ - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 33 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 6d07d8057a1..ca0ffd2b8b1 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -844,6 +844,34 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - 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; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 8eaa79a5823..88a6d5c8975 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -37,6 +37,8 @@ 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 -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 943ba6c0da9..51fca406a4c 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -1636,6 +1636,9 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, - union select_op select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ if (do_esync()) -+ return esync_signal_and_wait( signal, wait, alertable, timeout ); -+ - if (!signal) return STATUS_INVALID_HANDLE; - - if (alertable) flags |= SELECT_ALERTABLE; --- -2.45.2 - diff --git a/patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch b/patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch deleted file mode 100644 index 941b77aa..00000000 --- a/patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 494fb32d263fe0329a3672e9244ba44623d9ba07 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:56:09 -0500 -Subject: [PATCH] ntdll: Implement NtOpenSemaphore(). - ---- - dlls/ntdll/unix/esync.c | 47 +++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 2 ++ - dlls/ntdll/unix/sync.c | 4 ++++ - server/esync.c | 31 +++++++++++++++++++++++++++ - server/protocol.def | 12 +++++++++++ - 5 files changed, 96 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index db70e5075d1..f03ad7b7b73 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -328,6 +328,45 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK - 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, LONG initial, LONG max) - { -@@ -337,6 +376,14 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - 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, ULONG count, ULONG *prev ) - { - struct esync *obj; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 88a6d5c8975..6818be9c16f 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -24,6 +24,8 @@ extern NTSTATUS esync_close( HANDLE handle ); - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max); -+extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr ); - extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ); - - extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 12ed44f7a8e..31253e2235b 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -300,6 +300,10 @@ 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 ); -+ - if ((ret = validate_open_object_attributes( attr ))) return ret; - - SERVER_START_REQ( open_semaphore ) -diff --git a/server/esync.c b/server/esync.c -index 3f1c61bc1f0..eca9b6aa67d 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -410,6 +410,37 @@ DECL_HANDLER(create_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) -diff --git a/server/protocol.def b/server/protocol.def -index 55a6310e603..c9ebc5528c1 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -3908,6 +3908,18 @@ enum esync_type - unsigned int shm_idx; - @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 */ -+@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 */ -+@END -+ - /* Retrieve the esync fd for an object. */ - @REQ(get_esync_fd) - obj_handle_t handle; /* handle to the object */ --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch b/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch deleted file mode 100644 index 7ed19699..00000000 --- a/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f2313d3bdf72803a41a8d38604b6ebdba4440e24 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:58:19 -0500 -Subject: [PATCH] ntdll: Implement NtOpenEvent(). - ---- - dlls/ntdll/unix/esync.c | 8 ++++++++ - dlls/ntdll/unix/esync.h | 2 ++ - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 13 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index f03ad7b7b73..c0ee03c5828 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -429,6 +429,14 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - 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 */ -+} -+ - NTSTATUS esync_set_event( HANDLE handle ) - { - static const uint64_t value = 1; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 6818be9c16f..03894d61fcf 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -30,6 +30,8 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG 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_reset_event( HANDLE handle ); - extern NTSTATUS esync_set_event( HANDLE handle ); - -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 31253e2235b..fcd0413ce42 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -423,6 +423,9 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - *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; --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch b/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch deleted file mode 100644 index 2689fc73..00000000 --- a/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 07946ba13f255372cd72467a30ef2a24ed6714c5 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 16:59:35 -0500 -Subject: [PATCH] ntdll: Implement NtOpenMutant(). - ---- - dlls/ntdll/unix/esync.c | 8 ++++++++ - dlls/ntdll/unix/esync.h | 2 ++ - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 13 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index c0ee03c5828..2844f9f760c 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -478,6 +478,14 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - 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; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 03894d61fcf..ac12604a815 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -37,6 +37,8 @@ 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_release_mutex( HANDLE *handle, LONG *prev ); - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index fcd0413ce42..33a1dc77c47 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -593,6 +593,9 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - *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; --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch b/patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch deleted file mode 100644 index ecaa5091..00000000 --- a/patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 614c13aed3d20a772c3ccd26547fa93a56fcc40b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 19:08:18 -0500 -Subject: [PATCH] server: Implement esync_map_access(). - ---- - server/esync.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/server/esync.c b/server/esync.c -index eca9b6aa67d..3a334b3b330 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -112,6 +112,7 @@ struct esync - }; - - static void esync_dump( struct object *obj, int verbose ); -+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 = -@@ -126,7 +127,7 @@ const struct object_ops esync_ops = - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -- default_map_access, /* map_access */ -+ esync_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - default_get_full_name, /* get_full_name */ -@@ -146,6 +147,16 @@ static void esync_dump( struct object *obj, int verbose ) - fprintf( stderr, "esync fd=%d\n", 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; --- -2.38.1 - diff --git a/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch b/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch deleted file mode 100644 index 17c54734..00000000 --- a/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 9e19e1992e3956088d4aaa56929fa4da9344e98c Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:03:05 -0500 -Subject: [PATCH] server: Implement NtDuplicateObject(). - ---- - server/esync.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/server/esync.c b/server/esync.c -index 20f149cdad3..7b5b0761516 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -114,6 +114,7 @@ struct esync - }; - - 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 ); - -@@ -125,7 +126,7 @@ const struct object_ops esync_ops = - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ -- NULL, /* get_esync_fd */ -+ esync_get_esync_fd, /* get_esync_fd */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -149,6 +150,13 @@ static void esync_dump( struct object *obj, int verbose ) - 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. */ --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch b/patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch deleted file mode 100644 index de79ebae..00000000 --- a/patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 543476e8a53d41c69e89fbaa7d9cee8a48059944 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 15 Jun 2018 11:01:44 -0500 -Subject: [PATCH] server: Create eventfd descriptors for timers. - ---- - server/timer.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/server/timer.c b/server/timer.c -index f59902d5607..36645a2a8d2 100644 ---- a/server/timer.c -+++ b/server/timer.c -@@ -35,6 +35,7 @@ - #include "file.h" - #include "handle.h" - #include "request.h" -+#include "esync.h" - - static const WCHAR timer_name[] = {'T','i','m','e','r'}; - -@@ -61,10 +62,12 @@ 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 */ - }; - - 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 void timer_destroy( struct object *obj ); - -@@ -76,7 +79,7 @@ static const struct object_ops timer_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - timer_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ timer_get_esync_fd, /* get_esync_fd */ - timer_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -111,6 +114,10 @@ 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 ); - } - } - return timer; -@@ -182,6 +189,9 @@ 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 ); - } - timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); - timer->period = period; -@@ -209,6 +219,13 @@ 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 ) -+{ -+ struct timer *timer = (struct timer *)obj; -+ *type = timer->manual ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER; -+ return timer->esync_fd; -+} -+ - static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) - { - struct timer *timer = (struct timer *)obj; -@@ -223,6 +240,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 ); - } - - /* create a timer */ --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch b/patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch deleted file mode 100644 index ba1581e3..00000000 --- a/patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 50f9168ed92d261de21615b250dfac115160cc2e Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:17:31 -0500 -Subject: [PATCH] ntdll, server: Implement alertable waits. - ---- - dlls/ntdll/unix/esync.c | 77 +++++++++++++++++++++++++++++++--- - dlls/ntdll/unix/unix_private.h | 1 + - dlls/ntdll/unix/virtual.c | 1 + - server/esync.c | 20 +++++++-- - server/esync.h | 1 + - server/protocol.def | 4 ++ - server/thread.c | 13 ++++++ - server/thread.h | 1 + - 8 files changed, 109 insertions(+), 9 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index f805af251bb..a80019b76dd 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -601,17 +601,42 @@ static void update_grabbed_object( struct esync *obj ) - static NTSTATUS __esync_wait_objects( DWORD 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]; -+ 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) - { -@@ -650,6 +675,8 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - - if (msgwait) - TRACE(" or driver events"); -+ if (alertable) -+ TRACE(", alertable"); - - if (!timeout) - TRACE(", timeout = INFINITE.\n"); -@@ -686,12 +713,27 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - 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, count, timeout ? &end : NULL ); -+ 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++) - { -@@ -765,6 +807,14 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - 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]; -@@ -780,9 +830,11 @@ tryagain: - continue; - } - -- ret = do_poll( fds, 1, timeout ? &end : NULL ); -+ 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)) - { -@@ -798,10 +850,12 @@ tryagain: - 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, count, 0 ); -- if (ret == count) -+ ret = poll( fds, pollcount, 0 ); -+ if (ret == pollcount) - { - /* Quick, grab everything. */ - for (i = 0; i < count; i++) -@@ -867,6 +921,19 @@ err: - 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 -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index b9043351d57..283fd7d7ff6 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -105,6 +105,7 @@ struct ntdll_thread_data - SYSTEM_SERVICE_TABLE *syscall_table; /* 214/0370 syscall table */ - struct syscall_frame *syscall_frame; /* 218/0378 current syscall frame */ - int syscall_trace; /* 21c/0380 syscall trace flag */ -+ 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 */ -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index c797c89952f..0778ad73984 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -4014,6 +4014,7 @@ 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; -diff --git a/server/esync.c b/server/esync.c -index c5587bef6cf..0c365006f0b 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -346,19 +346,25 @@ int esync_create_fd( int initval, int flags ) - #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 ) - { -- static const uint64_t value = 1; - enum esync_type dummy; - int fd; - - if (obj->ops->get_esync_fd) - { - fd = obj->ops->get_esync_fd( obj, &dummy ); -- -- if (write( fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); -+ esync_wake_fd( fd ); - } - } - -@@ -496,3 +502,9 @@ DECL_HANDLER(get_esync_fd) - - 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 -index 689d8569b73..e1588d205d9 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -23,6 +23,7 @@ - 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 ); - -diff --git a/server/protocol.def b/server/protocol.def -index 807298b6bab..a2dcdd37204 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4148,3 +4148,7 @@ enum esync_type - @REPLY - int enable; /* previous state of auto-repeat enable */ - @END -+ -+/* Retrieve the fd to wait on for user APCs. */ -+@REQ(get_esync_apc_fd) -+@END -diff --git a/server/thread.c b/server/thread.c -index 11c36e49ae4..3a771838a98 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -400,6 +400,7 @@ static inline void init_thread_structure( struct thread *thread ) - 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; -@@ -550,7 +551,10 @@ 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 ); -@@ -1384,8 +1388,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 (do_esync() && queue == &thread->user_apc) -+ esync_wake_fd( thread->esync_apc_fd ); -+ } -+ - return 1; - } - -@@ -1431,6 +1440,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 ); -+ - return apc; - } - -diff --git a/server/thread.h b/server/thread.h -index e826a7a25de..c320ac83af7 100644 ---- a/server/thread.h -+++ b/server/thread.h -@@ -57,6 +57,7 @@ struct thread - 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 */ --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0036-esync-Update-README.patch b/patches/eventfd_synchronization/0036-esync-Update-README.patch deleted file mode 100644 index fec3618d..00000000 --- a/patches/eventfd_synchronization/0036-esync-Update-README.patch +++ /dev/null @@ -1,85 +0,0 @@ -From d00c4483de7260cae76a82291d179e8c33e5b732 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 13:53:08 -0500 -Subject: [PATCH] esync: Update README. - ---- - README.esync | 48 +++++++++++++++++------------------------------- - 1 file changed, 17 insertions(+), 31 deletions(-) - -diff --git a/README.esync b/README.esync -index 8fcb969011b..627cc3f481e 100644 ---- a/README.esync -+++ b/README.esync -@@ -88,32 +88,23 @@ also kind of ugly basically because we have to wait on both X11's fd and the - messages. The upshot about the whole thing was that races are basically - impossible, since a thread can only wait on its own queue. - --I had kind of figured that APCs just wouldn't work, but then poll() spat EINTR --at me and I realized that this wasn't necessarily true. It seems that the --server will suspend a thread when trying to deliver a system APC to a thread --that's not waiting, and since the server has no idea that we're waiting it --just suspends us. This of course interrupts poll(), which complains at us, and --it turns out that just returning STATUS_USER_APC in that case is enough to --make rpcrt4 happy. -+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: --* We can't return the previous count on a semaphore, since we have no way to -- query the count on a semaphore through eventfd. Currently the code lies and -- returns 1 every time. We can make this work (in a single process, or [if -- necessary] in multiple processes through shared memory) by keeping a count -- locally. We can't guarantee that it's the exact count at the moment the -- semaphore was released, but I guess any program that runs into that race -- shouldn't be depending on that fact anyway. --* Similarly, we can't enforce the maximum count on a semaphore, since we have -- no way to get the current count and subsequently compare it with the -- maximum. --* We can't use NtQueryMutant to get the mutant's owner or count if it lives in -- a different process. If necessary we can use shared memory to make this -- work, I guess, but see below. --* User APCs don't work. However, it's not impossible to make them work; in -- particular I think this could be relatively easily implemented by waiting on -- another internal file descriptor when we execute an alertable wait. - * 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 -@@ -144,18 +135,13 @@ surprisingly there aren't that many. In particular: - - There are some things that are perfectly implementable but that I just haven't - done yet: --* NtOpen* (aka Open*). This is just a matter of adding another open_esync -- request analogous to those for other server primitives. --* NtQuery*. This can be done to some degree (the difficulties are outlined -- above). That said, these APIs aren't exposed through kernel32 in any way, so -+* NtQuery*. That said, these APIs aren't exposed through kernel32 in any way, so - I doubt anyone is going to be using them. --* SignalObjectAndWait(). The server combines this into a single operation, but -- according to MSDN it doesn't need to be atomic, so we can just signal the -- appropriate object and wait, and woe betide anyone who gets in the way of -- those two operations. - * 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 --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch b/patches/eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch deleted file mode 100644 index 99f70111..00000000 --- a/patches/eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch +++ /dev/null @@ -1,35 +0,0 @@ -From fb71b7bedd8d2863a588473dc09a04dcd8b43b44 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 22:25:40 -0500 -Subject: [PATCH] kernel32/tests: Mark some existing tests as failing under - esync. - ---- - dlls/kernel32/tests/sync.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 93cae1c84d5..b158ac905fd 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -223,7 +223,8 @@ 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, INFINITE); -+ wait_ret = WaitForSingleObject(hOpened, 0); -+todo_wine_if(getenv("WINEESYNC")) /* XFAIL: validation is not implemented */ - ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); - CloseHandle(hOpened); - -@@ -254,6 +255,7 @@ static void test_mutex(void) - - 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()); - --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch b/patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch deleted file mode 100644 index 5d0aa283..00000000 --- a/patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 8592fcfbee64b776ce90c5edc5e9b67350665213 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 22:40:47 -0500 -Subject: [PATCH] kernel32/tests: Add some semaphore tests. - ---- - dlls/kernel32/tests/sync.c | 98 +++++++++++++++++++++++++++++++++++++- - 1 file changed, 97 insertions(+), 1 deletion(-) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index b158ac905fd..ad6ab1adc96 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -582,7 +582,10 @@ static void test_event(void) - - static void test_semaphore(void) - { -- HANDLE handle, handle2; -+ HANDLE handle, handle2, handles[2]; -+ DWORD ret; -+ LONG prev; -+ int i; - - /* test case sensitivity */ - -@@ -624,6 +627,99 @@ 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) --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch b/patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch deleted file mode 100644 index dfd3e273..00000000 --- a/patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 8790bcd9d5ff4b2e38ca00a4ba7d1d884924b25e Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 22:59:37 -0500 -Subject: [PATCH] kernel32/tests: Add some event tests. - ---- - dlls/kernel32/tests/sync.c | 119 ++++++++++++++++++++++++++++++++++++- - 1 file changed, 118 insertions(+), 1 deletion(-) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index ad6ab1adc96..95f51f54b83 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -469,12 +469,13 @@ static void test_slist(void) - - static void test_event(void) - { -- HANDLE handle, handle2; -+ HANDLE handle, handle2, handles[2]; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - ACL acl; - DWORD ret; - BOOL val; -+ int i; - - /* no sd */ - handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); -@@ -578,6 +579,122 @@ 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) --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch b/patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch deleted file mode 100644 index 5e42a832..00000000 --- a/patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 07694655cf43e87ffc6185a5e7fe8d1bdd8658a4 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 23:32:04 -0500 -Subject: [PATCH] kernel32/tests: Add some mutex tests. - ---- - dlls/kernel32/tests/sync.c | 94 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 94 insertions(+) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index bc85126d9aa..491052d5593 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -227,8 +227,23 @@ 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; -@@ -339,6 +354,85 @@ 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) --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch b/patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch deleted file mode 100644 index a6285c40..00000000 --- a/patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 9d683eab1efae1c8dcd5b571e8a31ac0f13fc563 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 23:58:01 -0500 -Subject: [PATCH] kernel32/tests: Add some tests for wait timeouts. - ---- - dlls/kernel32/tests/sync.c | 68 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 68 insertions(+) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 4685b7bec06..117edf12fb6 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -57,6 +57,7 @@ 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, -@@ -1485,11 +1486,15 @@ 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); -@@ -1574,6 +1579,68 @@ 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); - } -@@ -3113,6 +3180,7 @@ 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"); --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch b/patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch deleted file mode 100644 index 049f723d..00000000 --- a/patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch +++ /dev/null @@ -1,109 +0,0 @@ -From b0d987483476c7c6517a81e602f3bb8c20033f08 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 26 Jun 2018 18:44:44 -0500 -Subject: [PATCH] kernel32/tests: Zigzag test. - -The primary function is to check for races. The secondary function is to measure performance. ---- - dlls/kernel32/tests/sync.c | 79 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 79 insertions(+) - -diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 997c34ed0fd..79dbcc19660 100644 ---- a/dlls/kernel32/tests/sync.c -+++ b/dlls/kernel32/tests/sync.c -@@ -3154,6 +3154,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; -@@ -3220,5 +3298,6 @@ START_TEST(sync) - test_srwlock_example(); - test_alertable_wait(); - test_apc_deadlock(); -+ test_zigzag_event(); - test_crit_section(); - } --- -2.30.2 - diff --git a/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch b/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch deleted file mode 100644 index c7fd2f2e..00000000 --- a/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch +++ /dev/null @@ -1,70 +0,0 @@ -From e79efd700a74900e5268b736dc3bbb86b0db00ce Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:24:17 -0500 -Subject: [PATCH] ntdll: Implement NtQuerySemaphore(). - ---- - dlls/ntdll/unix/esync.c | 19 +++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 23 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index aeeea1731ce..f65e5389986 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -417,6 +417,25 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - 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 ) - { -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index ac12604a815..e7d4cd2aba4 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -26,6 +26,7 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG 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, ULONG count, ULONG *prev ); - - extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 33a1dc77c47..c9450003ce3 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -340,6 +340,9 @@ 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 ); -+ - SERVER_START_REQ( query_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch b/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch deleted file mode 100644 index 24b8c154..00000000 --- a/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From f4ff71d953f4f6fc91f0ac3cdea8c964a2911f07 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:26:56 -0500 -Subject: [PATCH] ntdll: Implement NtQueryEvent(). - ---- - dlls/ntdll/unix/esync.c | 20 ++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 24 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index f65e5389986..c75dd23d897 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -488,6 +488,26 @@ NTSTATUS esync_reset_event( HANDLE handle ) - 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 ) - { -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index e7d4cd2aba4..9a0fcd163dd 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -33,6 +33,7 @@ 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_query_event( HANDLE handle, void *info, ULONG *ret_len ); - extern NTSTATUS esync_reset_event( HANDLE handle ); - extern NTSTATUS esync_set_event( HANDLE handle ); - -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index c9450003ce3..2fea9f532bd 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -539,6 +539,9 @@ 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 ); -+ - SERVER_START_REQ( query_event ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch b/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch deleted file mode 100644 index 30d315e8..00000000 --- a/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch +++ /dev/null @@ -1,71 +0,0 @@ -From b930741dcf601f4a9f5cf761d57154c9216c5ec9 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:28:58 -0500 -Subject: [PATCH] ntdll: Implement NtQueryMutant(). - ---- - dlls/ntdll/unix/esync.c | 20 ++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 24 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index c75dd23d897..68c060a294c 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -559,6 +559,26 @@ NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - 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 = FALSE; -+ if (ret_len) *ret_len = sizeof(*out); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 9a0fcd163dd..61846238ab7 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -41,6 +41,7 @@ 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, -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 2fea9f532bd..5d25f086d5d 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -657,6 +657,9 @@ 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 ); -+ - SERVER_START_REQ( query_mutex ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch b/patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch deleted file mode 100644 index deb61ffa..00000000 --- a/patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch +++ /dev/null @@ -1,129 +0,0 @@ -From b4f92dd9311882607cedd7d247ddf3069ae33d8b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 7 Jul 2018 12:57:47 +0200 -Subject: [PATCH] server: Create eventfd descriptors for pseudo-fd objects and - use them for named pipes. - ---- - server/fd.c | 22 ++++++++++++++++++++++ - server/file.h | 1 + - server/named_pipe.c | 4 ++-- - 3 files changed, 25 insertions(+), 2 deletions(-) - -diff --git a/server/fd.c b/server/fd.c -index 737f7ee67b9..01a055f8b2d 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -95,6 +95,7 @@ - #include "handle.h" - #include "process.h" - #include "request.h" -+#include "esync.h" - - #include "winternl.h" - #include "winioctl.h" -@@ -159,6 +160,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 */ - }; - - static void fd_dump( struct object *obj, int verbose ); -@@ -1668,6 +1670,9 @@ 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 ); - } - - /* check if the desired access is possible without violating */ -@@ -1786,6 +1791,7 @@ static struct fd *alloc_fd_object(void) - fd->poll_index = -1; - fd->completion = NULL; - fd->comp_flags = 0; -+ fd->esync_fd = -1; - init_async_queue( &fd->read_q ); - init_async_queue( &fd->write_q ); - init_async_queue( &fd->wait_q ); -@@ -1827,11 +1833,15 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use - fd->completion = NULL; - fd->comp_flags = 0; - 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; - } - -@@ -2283,6 +2293,9 @@ 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 ); - } - - /* check if events are pending and if yes return which one(s) */ -@@ -2324,6 +2337,15 @@ WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_ - return ret; - } - -+int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ) -+{ -+ struct fd *fd = get_obj_fd( obj ); -+ int ret = fd->esync_fd; -+ *type = ESYNC_MANUAL_SERVER; -+ release_object( fd ); -+ return ret; -+} -+ - int default_fd_get_poll_events( struct fd *fd ) - { - int events = 0; -diff --git a/server/file.h b/server/file.h -index 7742e705e49..d86a9fc159d 100644 ---- a/server/file.h -+++ b/server/file.h -@@ -110,6 +110,7 @@ extern void get_nt_name( struct fd *fd, struct unicode_str *name ); - - extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); - extern WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_t *ret_len ); -+extern int default_fd_get_esync_fd( struct object *obj, enum esync_type *type ); - extern int default_fd_get_poll_events( struct fd *fd ); - extern void default_poll_event( struct fd *fd, int event ); - extern void fd_cancel_async( struct fd *fd, struct async *async ); -diff --git a/server/named_pipe.c b/server/named_pipe.c -index cdb27ed45c0..d4f8cf5e964 100644 ---- a/server/named_pipe.c -+++ b/server/named_pipe.c -@@ -168,7 +168,7 @@ static const struct object_ops pipe_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ -@@ -213,7 +213,7 @@ static const struct object_ops pipe_client_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - pipe_end_get_fd, /* get_fd */ --- -2.47.2 - diff --git a/patches/eventfd_synchronization/0047-esync-Update-README.patch b/patches/eventfd_synchronization/0047-esync-Update-README.patch deleted file mode 100644 index edb79f68..00000000 --- a/patches/eventfd_synchronization/0047-esync-Update-README.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 2565f5c43a6acedee00a029947ed91d724ea0b67 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 4 Jul 2018 14:58:33 +0200 -Subject: [PATCH] esync: Update README. - ---- - README.esync | 25 +++++++++++++++++++++++-- - 1 file changed, 23 insertions(+), 2 deletions(-) - -diff --git a/README.esync b/README.esync -index 627cc3f481e..30e241755ad 100644 ---- a/README.esync -+++ b/README.esync -@@ -2,6 +2,29 @@ This is eventfd-based synchronization, or 'esync' for short. Turn it on with - WINEESYNC=1 (note that it checks the presence and not the value); 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. -+ -+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. -+ -+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 -@@ -135,8 +158,6 @@ surprisingly there aren't that many. In particular: - - There are some things that are perfectly implementable but that I just haven't - done yet: --* NtQuery*. That said, these APIs aren't exposed through kernel32 in any way, so -- I doubt anyone is going to be using them. - * 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. --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch b/patches/eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch deleted file mode 100644 index 0de735aa..00000000 --- a/patches/eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a92204fc7b6569c625a95bfed1a76c54b2998169 Mon Sep 17 00:00:00 2001 -From: Mathieu Comandon -Date: Sat, 21 Jul 2018 12:56:50 -0700 -Subject: [PATCH] esync: Add note about file limits not being raised when using - systemd. - ---- - README.esync | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/README.esync b/README.esync -index 30e241755ad..7706f395ebd 100644 ---- a/README.esync -+++ b/README.esync -@@ -20,6 +20,16 @@ have a reasonable limit.) To raise the limit you'll want to edit - - 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=100000 -+ -+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. - -@@ -188,4 +198,4 @@ done by the kernel. - - Anyway, yeah, this is esync. Use it if you like. - ----Zebediah Figura -\ No newline at end of file -+--Zebediah Figura --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch b/patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch deleted file mode 100644 index 56e30604..00000000 --- a/patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 34c1ce614c464389f0ecf3d11c425591482bfaec Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:37:29 -0500 -Subject: [PATCH] ntdll: Try to avoid poll() for uncontended objects. - -Just semaphores and mutexes thus far. - -We don't have to worry about races because this is just a hint: we still call read() eventually. ---- - dlls/ntdll/unix/esync.c | 60 ++++++++++++++++++++++++++++++++++------- - 1 file changed, 50 insertions(+), 10 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 13cdaf4f73e..a306826e2da 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -755,23 +755,63 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - - 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 && obj->type == ESYNC_MUTEX) -+ if (obj) - { -- /* If we already own the mutex, return immediately. */ -- /* Note: This violates the assumption that the *first* object -- * to be signaled will be returned. If that becomes a problem, -- * we can always check the state of each object before waiting. */ -- struct mutex *mutex = (struct mutex *)obj; -+ switch (obj->type) -+ { -+ case ESYNC_MUTEX: -+ { -+ struct mutex *mutex = obj->shm; - -- if (mutex->tid == GetCurrentThreadId()) -+ 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)) -+ { -+ TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ mutex->tid = GetCurrentThreadId(); -+ mutex->count++; -+ return i; -+ } -+ } -+ break; -+ } -+ case ESYNC_SEMAPHORE: - { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- mutex->count++; -- return i; -+ 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: -+ case ESYNC_MANUAL_EVENT: -+ /* TODO */ -+ 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; - } - } - --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch b/patches/eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch deleted file mode 100644 index 79f99c8d..00000000 --- a/patches/eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch +++ /dev/null @@ -1,287 +0,0 @@ -From 01dfd774936575b49fff774124a36749c6080c2c Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:44:26 -0500 -Subject: [PATCH] ntdll, server: Try to avoid poll() for signaled events. - ---- - dlls/ntdll/unix/esync.c | 147 ++++++++++++++++++++++++++++++++++++++-- - server/esync.c | 61 +++++++++++++++-- - 2 files changed, 197 insertions(+), 11 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index a306826e2da..91a85253a83 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -464,18 +464,103 @@ NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - 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; -+ 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 (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; - } -@@ -484,14 +569,40 @@ 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; -+ if ((ret = get_object( handle, &obj ))) return ret; -+ event = obj->shm; - -- if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) -- ERR("read: %s\n", strerror(errno)); -+ 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; - } -@@ -802,9 +913,31 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - 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: -- /* TODO */ -+ { -+ 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: -diff --git a/server/esync.c b/server/esync.c -index 33a448d0a57..11785d28bab 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -378,24 +378,77 @@ void esync_clear( int fd ) - 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 ); -- if (write( esync->fd, &value, sizeof(value) ) == -1) -- perror( "esync: write" ); -+ 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 ); - -- /* we don't care about the return value */ -- read( esync->fd, &value, sizeof(value) ); -+ 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; -+ } - } - - DECL_HANDLER(create_esync) --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0051-esync-Update-README.patch b/patches/eventfd_synchronization/0051-esync-Update-README.patch deleted file mode 100644 index 5d584c0a..00000000 --- a/patches/eventfd_synchronization/0051-esync-Update-README.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 3e93bc895e5d943d02b5dfaa0b80c73dcf53c1b8 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 4 Aug 2018 15:18:24 -0500 -Subject: [PATCH] esync: Update README. - ---- - README.esync | 14 +++++--------- - 1 file changed, 5 insertions(+), 9 deletions(-) - -diff --git a/README.esync b/README.esync -index 7706f395ebd..b64bfefc1a3 100644 ---- a/README.esync -+++ b/README.esync -@@ -5,7 +5,7 @@ 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. -++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 -@@ -20,11 +20,11 @@ have a reasonable limit.) To raise the limit you'll want to edit - - 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 -+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=100000 -+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 -@@ -157,10 +157,6 @@ surprisingly there aren't that many. In particular: - 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. --* We might hit the maximum number of open fd's. On my system the soft limit is -- 1024 and the hard limit is 1048576. I'm inclined to hope this won't be an -- issue, since a hypothetical Linux port of any application might just as well -- use the same number of eventfds. - * 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 --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch b/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch deleted file mode 100644 index 55203181..00000000 --- a/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 41abb8ffe452643a16622e8e543f9b95ad8dc291 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 17:56:40 -0500 -Subject: [PATCH] ntdll: Implement NtPulseEvent(). - ---- - dlls/ntdll/unix/esync.c | 25 +++++++++++++++++++++++++ - dlls/ntdll/unix/esync.h | 1 + - dlls/ntdll/unix/sync.c | 3 +++ - 3 files changed, 29 insertions(+) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index 6ebc09d87bf..31f268c69d5 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -599,6 +599,31 @@ NTSTATUS esync_reset_event( HANDLE handle ) - 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; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 61846238ab7..59f8809fc1a 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -33,6 +33,7 @@ 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 ); -diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 5d25f086d5d..3a9fc76c2e4 100644 ---- a/dlls/ntdll/unix/sync.c -+++ b/dlls/ntdll/unix/sync.c -@@ -508,6 +508,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - unsigned int ret; - -+ if (do_esync()) -+ return esync_pulse_event( handle ); -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.42.0 - diff --git a/patches/eventfd_synchronization/0053-esync-Update-README.patch b/patches/eventfd_synchronization/0053-esync-Update-README.patch deleted file mode 100644 index e998b1b0..00000000 --- a/patches/eventfd_synchronization/0053-esync-Update-README.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 64d0157285ea05a7ea934d8567ce1a6087fb1d41 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 19 Aug 2018 13:40:05 -0500 -Subject: [PATCH] esync: Update README. - ---- - README.esync | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/README.esync b/README.esync -index b64bfefc1a3..11d86563a10 100644 ---- a/README.esync -+++ b/README.esync -@@ -1,6 +1,5 @@ - This is eventfd-based synchronization, or 'esync' for short. Turn it on with --WINEESYNC=1 (note that it checks the presence and not the value); debug it --with +esync. -+WINEESYNC=1; debug it with +esync. - - == BUGS AND LIMITATIONS == - --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch b/patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch deleted file mode 100644 index 4c1c345e..00000000 --- a/patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 92408fdf4e119340b330d2ac4711b0e0d25b0060 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 24 Apr 2019 23:21:25 -0500 -Subject: [PATCH] server: Create esync file descriptors for true file objects - and use them for directory change notifications. - ---- - server/change.c | 2 +- - server/fd.c | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/server/change.c b/server/change.c -index a79b6d61939..9c84f01180c 100644 ---- a/server/change.c -+++ b/server/change.c -@@ -115,7 +115,7 @@ static const struct object_ops dir_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ default_fd_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - dir_get_fd, /* get_fd */ -diff --git a/server/fd.c b/server/fd.c -index a7d81ec055b..ea6ece2a111 100644 ---- a/server/fd.c -+++ b/server/fd.c -@@ -1720,6 +1720,9 @@ static struct fd *alloc_fd_object(void) - 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 ); --- -2.28.0 - diff --git a/patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch b/patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch deleted file mode 100644 index 02393d04..00000000 --- a/patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 075bdc732f12d42184ee6a906f58051739972322 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 6 Jul 2020 18:01:32 -0500 -Subject: [PATCH] ntdll, server: Abandon esync mutexes on thread exit. - ---- - dlls/ntdll/unix/esync.c | 31 ++++++++++++++++++++++++++----- - server/esync.c | 25 +++++++++++++++++++++++++ - server/esync.h | 1 + - server/thread.c | 2 ++ - 4 files changed, 54 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index d7511f39601..ed801c71991 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -717,7 +717,7 @@ NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ) - - out->CurrentCount = 1 - mutex->count; - out->OwnedByCaller = (mutex->tid == GetCurrentThreadId()); -- out->AbandonedState = FALSE; -+ out->AbandonedState = (mutex->tid == ~0); - if (ret_len) *ret_len = sizeof(*out); - - return STATUS_SUCCESS; -@@ -767,14 +767,19 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) - return ret; - } - --static void update_grabbed_object( struct esync *obj ) -+/* 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++; - } -@@ -795,6 +800,8 @@ static void update_grabbed_object( struct esync *obj ) - * 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 -@@ -914,7 +921,13 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - { - if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value)) - { -- TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ 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; -@@ -1027,7 +1040,8 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEA - { - /* We found our object. */ - TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- update_grabbed_object( obj ); -+ if (update_grabbed_object( obj )) -+ return STATUS_ABANDONED_WAIT_0 + i; - return i; - } - } -@@ -1120,6 +1134,8 @@ tryagain: - ret = poll( fds, pollcount, 0 ); - if (ret == pollcount) - { -+ BOOL abandoned = FALSE; -+ - /* Quick, grab everything. */ - for (i = 0; i < count; i++) - { -@@ -1160,8 +1176,13 @@ tryagain: - /* Make sure to let ourselves know that we grabbed the mutexes - * and semaphores. */ - for (i = 0; i < count; i++) -- update_grabbed_object( objs[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; - } -diff --git a/server/esync.c b/server/esync.c -index 11785d28bab..d79be851c8f 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -105,12 +105,15 @@ void esync_init(void) - 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 ); -@@ -170,6 +173,8 @@ static unsigned int esync_map_access( struct object *obj, unsigned int access ) - 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 ); - } - -@@ -305,6 +310,7 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, - 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: -@@ -451,6 +457,25 @@ void esync_reset_event( struct esync *esync ) - } - } - -+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; -diff --git a/server/esync.h b/server/esync.h -index cea025d9308..125da8e9d12 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -30,3 +30,4 @@ 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/thread.c b/server/thread.c -index 83f80740a46..bffe229586f 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -1325,6 +1325,8 @@ void kill_thread( struct thread *thread, int violent_death ) - } - kill_console_processes( thread, 0 ); - abandon_mutexes( thread ); -+ if (do_esync()) -+ esync_abandon_mutexes( thread ); - if (violent_death) - { - send_thread_signal( thread, SIGQUIT ); --- -2.29.2 - diff --git a/patches/eventfd_synchronization/0056-server-Create-esync-file-descriptors-for-console-ser.patch b/patches/eventfd_synchronization/0056-server-Create-esync-file-descriptors-for-console-ser.patch deleted file mode 100644 index fbd13bfc..00000000 --- a/patches/eventfd_synchronization/0056-server-Create-esync-file-descriptors-for-console-ser.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 6adfd0593d10cc9ec8ed8364de167d40ee2098ce Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 17 Oct 2020 19:13:16 -0500 -Subject: [PATCH] server: Create esync file descriptors for console servers. - ---- - server/console.c | 37 +++++++++++++++++++++++++++++-------- - 1 file changed, 29 insertions(+), 8 deletions(-) - -diff --git a/server/console.c b/server/console.c -index ae5d84f7a06..3f9c0ce356c 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -41,6 +41,7 @@ - #include "wincon.h" - #include "winternl.h" - #include "wine/condrv.h" -+#include "esync.h" - - struct screen_buffer; - -@@ -131,20 +132,22 @@ 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 term_fd; /* UNIX terminal fd */ -+ struct termios termios; /* original termios */ -+ int esync_fd; - }; - - 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 ); -@@ -159,7 +162,7 @@ static const struct object_ops console_server_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_server_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ console_server_get_esync_fd, /* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - console_server_get_fd, /* get_fd */ -@@ -597,6 +600,8 @@ 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 ); -@@ -877,6 +882,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 ); - } - - static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, -@@ -918,6 +924,13 @@ 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; -@@ -949,6 +962,10 @@ 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; - } -@@ -1562,6 +1579,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 (ioctl) -@@ -1647,6 +1666,8 @@ DECL_HANDLER(get_next_console_request) - { - set_error( STATUS_PENDING ); - } -+ if (do_esync() && list_empty( &server->queue )) -+ esync_clear( server->esync_fd ); - - release_object( server ); - } --- -2.35.1 - diff --git a/patches/eventfd_synchronization/0057-ntdll-Compile-warning-fixes-for-esync.patch b/patches/eventfd_synchronization/0057-ntdll-Compile-warning-fixes-for-esync.patch deleted file mode 100644 index f80cdd93..00000000 --- a/patches/eventfd_synchronization/0057-ntdll-Compile-warning-fixes-for-esync.patch +++ /dev/null @@ -1,126 +0,0 @@ -From fed04f8ef69b829fa2cf3c7051160a6f822912dd Mon Sep 17 00:00:00 2001 -From: Elizabeth Figura -Date: Mon, 12 Aug 2024 16:54:44 -0500 -Subject: [PATCH] ntdll: Compile warning fixes for esync. - ---- - dlls/ntdll/unix/esync.c | 26 +++++++++++++------------- - dlls/ntdll/unix/esync.h | 4 ++-- - 2 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c -index f4748e405ef..86809b610c7 100644 ---- a/dlls/ntdll/unix/esync.c -+++ b/dlls/ntdll/unix/esync.c -@@ -73,29 +73,29 @@ int do_esync(void) - - struct esync - { -- enum esync_type type; -+ LONG type; - int fd; - void *shm; - }; - - struct semaphore - { -- int max; -- int count; -+ LONG max; -+ LONG count; - }; - C_ASSERT(sizeof(struct semaphore) == 8); - - struct mutex - { -- DWORD tid; -- int count; /* recursion count */ -+ LONG tid; -+ LONG count; /* recursion count */ - }; - C_ASSERT(sizeof(struct mutex) == 8); - - struct event - { -- int signaled; -- int locked; -+ LONG signaled; -+ LONG locked; - }; - C_ASSERT(sizeof(struct event) == 8); - -@@ -182,7 +182,7 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v - } - } - -- if (!InterlockedCompareExchange( (int *)&esync_list[entry][idx].type, type, 0 )) -+ if (!InterlockedCompareExchange( &esync_list[entry][idx].type, type, 0 )) - { - esync_list[entry][idx].fd = fd; - esync_list[entry][idx].shm = shm; -@@ -206,7 +206,7 @@ static struct esync *get_cached_object( HANDLE handle ) - * message queue, etc.) */ - static NTSTATUS get_object( HANDLE handle, struct esync **obj ) - { -- NTSTATUS ret = STATUS_SUCCESS; -+ int ret = STATUS_SUCCESS; - enum esync_type type = 0; - unsigned int shm_idx = 0; - obj_handle_t fd_handle; -@@ -274,7 +274,7 @@ NTSTATUS esync_close( HANDLE handle ) - - if (entry < ESYNC_LIST_ENTRIES && esync_list[entry]) - { -- if (InterlockedExchange((int *)&esync_list[entry][idx].type, 0)) -+ if (InterlockedExchange(&esync_list[entry][idx].type, 0)) - { - close( esync_list[entry][idx].fd ); - return STATUS_SUCCESS; -@@ -370,7 +370,7 @@ static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, - } - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) -+ const OBJECT_ATTRIBUTES *attr, int initial, int max) - { - TRACE("name %s, initial %d, max %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial, max); -@@ -386,7 +386,7 @@ NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); - } - --NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) -+NTSTATUS esync_release_semaphore( HANDLE handle, unsigned int count, ULONG *prev ) - { - struct esync *obj; - struct semaphore *semaphore; -@@ -800,7 +800,7 @@ static BOOL update_grabbed_object( struct esync *obj ) - - /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we - * need to delegate to server_select(). */ --static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+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; -diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h -index 59f8809fc1a..9102cf911aa 100644 ---- a/dlls/ntdll/unix/esync.h -+++ b/dlls/ntdll/unix/esync.h -@@ -23,11 +23,11 @@ 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, LONG initial, LONG max); -+ 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, ULONG count, ULONG *prev ); -+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 ); --- -2.45.2 - diff --git a/patches/eventfd_synchronization/definition b/patches/eventfd_synchronization/definition deleted file mode 100644 index 2ad18768..00000000 --- a/patches/eventfd_synchronization/definition +++ /dev/null @@ -1,5 +0,0 @@ -Fixes: [36692] Many multi-threaded applications have poor performance due to heavy use of synchronization primitives -Depends: ntdll-Junction_Points -Depends: server-PeekMessage -Depends: server-Signal_Thread -Disabled: True diff --git a/patches/odbc32-fixes/0009-odbc32-SQLDriverConnectW-fallback-to-SQLDriverConnec.patch b/patches/odbc32-fixes/0009-odbc32-SQLDriverConnectW-fallback-to-SQLDriverConnec.patch deleted file mode 100644 index 754db17c..00000000 --- a/patches/odbc32-fixes/0009-odbc32-SQLDriverConnectW-fallback-to-SQLDriverConnec.patch +++ /dev/null @@ -1,64 +0,0 @@ -From e6c3fae4360c375015e75165fc9a3c16af79ec4a Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 26 Apr 2025 12:33:23 +1000 -Subject: [PATCH] odbc32: SQLDriverConnectW fallback to SQLDriverConnect when - required. - ---- - dlls/odbc32/proxyodbc.c | 37 +++++++++++++++++++++++++++++++++++-- - 1 file changed, 35 insertions(+), 2 deletions(-) - -diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index 0893537aef9..6685b4306f5 100644 ---- a/dlls/odbc32/proxyodbc.c -+++ b/dlls/odbc32/proxyodbc.c -@@ -6937,11 +6937,44 @@ static SQLRETURN driver_connect_win32_w( struct connection *con, SQLHWND window, - SQLSMALLINT len, SQLWCHAR *out_conn_str, SQLSMALLINT buflen, SQLSMALLINT *len2, - SQLUSMALLINT completion ) - { -+ SQLRETURN ret = SQL_ERROR; -+ - if (con->hdr.win32_funcs->SQLDriverConnectW) - return con->hdr.win32_funcs->SQLDriverConnectW( con->hdr.win32_handle, window, in_conn_str, len, out_conn_str, - buflen, len2, completion ); -- if (con->hdr.win32_funcs->SQLDriverConnect) FIXME( "Unicode to ANSI conversion not handled\n" ); -- return SQL_ERROR; -+ if (con->hdr.win32_funcs->SQLDriverConnect) -+ { -+ SQLCHAR *in = NULL, *out = NULL; -+ SQLSMALLINT in_len = 0, out_len = 0; -+ -+ in_len = WideCharToMultiByte(CP_ACP, 0, in_conn_str, len, NULL, 0, NULL, NULL); -+ if (!(in = malloc(in_len + 1))) return SQL_ERROR; -+ -+ WideCharToMultiByte(CP_ACP, 0, in_conn_str, len, (char *)in, in_len, NULL, NULL); -+ in[in_len] = 0; -+ -+ if (out_conn_str && buflen > 0) -+ { -+ if (!(out = malloc(buflen))) -+ { -+ free(in); -+ return SQL_ERROR; -+ } -+ } -+ -+ ret = con->hdr.win32_funcs->SQLDriverConnect( con->hdr.win32_handle, window, in, in_len, out, buflen, &out_len, completion ); -+ -+ if (SQL_SUCCEEDED(ret) && out_conn_str && out) -+ { -+ MultiByteToWideChar(CP_ACP, 0, (char *)out, out_len, out_conn_str, buflen); -+ if (len2) *len2 = out_len; -+ } -+ -+ free(in); -+ free(out); -+ } -+ -+ return ret; - } - - static SQLRETURN driver_connect_unix_w( struct connection *con, SQLHWND window, SQLWCHAR *in_conn_str, SQLSMALLINT len, --- -2.50.1 - diff --git a/patches/odbc32-fixes/0010-odbc32-SQLGetInfoW-support-ANSI-fallback.patch b/patches/odbc32-fixes/0010-odbc32-SQLGetInfoW-support-ANSI-fallback.patch deleted file mode 100644 index 51cf55d7..00000000 --- a/patches/odbc32-fixes/0010-odbc32-SQLGetInfoW-support-ANSI-fallback.patch +++ /dev/null @@ -1,100 +0,0 @@ -From f451eeaf15d825d8be8f5c661f5a9f249935674d Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 26 Apr 2025 16:27:58 +1000 -Subject: [PATCH] odbc32: SQLGetInfoW support ANSI fallback. - ---- - dlls/odbc32/proxyodbc.c | 72 +++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 70 insertions(+), 2 deletions(-) - -diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index 6685b4306f5..e18117d5ad8 100644 ---- a/dlls/odbc32/proxyodbc.c -+++ b/dlls/odbc32/proxyodbc.c -@@ -7104,13 +7104,81 @@ static SQLRETURN get_info_unix_w( struct connection *con, SQLUSMALLINT type, SQL - return ODBC_CALL( SQLGetInfoW, ¶ms ); - } - -+static BOOL typeinfo_is_string( SQLSMALLINT type ) -+{ -+ switch (type) -+ { -+ case SQL_ACCESSIBLE_PROCEDURES: -+ case SQL_ACCESSIBLE_TABLES: -+ case SQL_CATALOG_NAME: -+ case SQL_CATALOG_NAME_SEPARATOR: -+ case SQL_CATALOG_TERM: -+ case SQL_COLLATION_SEQ: -+ case SQL_COLUMN_ALIAS: -+ case SQL_DATA_SOURCE_NAME: -+ case SQL_DATA_SOURCE_READ_ONLY: -+ case SQL_DATABASE_NAME: -+ case SQL_DBMS_NAME: -+ case SQL_DBMS_VER: -+ case SQL_DESCRIBE_PARAMETER: -+ case SQL_DRIVER_NAME: -+ case SQL_DRIVER_ODBC_VER: -+ case SQL_DRIVER_VER: -+ case SQL_ODBC_VER: -+ case SQL_EXPRESSIONS_IN_ORDERBY: -+ case SQL_IDENTIFIER_QUOTE_CHAR: -+ case SQL_INTEGRITY: -+ case SQL_KEYWORDS: -+ case SQL_LIKE_ESCAPE_CLAUSE: -+ case SQL_MAX_ROW_SIZE_INCLUDES_LONG: -+ case SQL_MULT_RESULT_SETS: -+ case SQL_MULTIPLE_ACTIVE_TXN: -+ case SQL_NEED_LONG_DATA_LEN: -+ case SQL_ORDER_BY_COLUMNS_IN_SELECT: -+ case SQL_PROCEDURE_TERM: -+ case SQL_PROCEDURES: -+ case SQL_ROW_UPDATES: -+ case SQL_SCHEMA_TERM: -+ case SQL_SEARCH_PATTERN_ESCAPE: -+ case SQL_SERVER_NAME: -+ case SQL_SPECIAL_CHARACTERS: -+ case SQL_TABLE_TERM: -+ case SQL_USER_NAME: -+ case SQL_XOPEN_CLI_YEAR: -+ case SQL_OUTER_JOINS: -+ return TRUE; -+ default: -+ return FALSE; -+ } -+} -+ - static SQLRETURN get_info_win32_w( struct connection *con, SQLUSMALLINT type, SQLPOINTER value, SQLSMALLINT buflen, - SQLSMALLINT *retlen ) - { -+ SQLRETURN ret = SQL_ERROR; -+ - if (con->hdr.win32_funcs->SQLGetInfoW) - return con->hdr.win32_funcs->SQLGetInfoW( con->hdr.win32_handle, type, value, buflen, retlen ); -- if (con->hdr.win32_funcs->SQLGetInfo) FIXME( "Unicode to ANSI conversion not handled\n" ); -- return SQL_ERROR; -+ if (con->hdr.win32_funcs->SQLGetInfo) -+ { -+ ret = con->hdr.win32_funcs->SQLGetInfo( con->hdr.win32_handle, type, value, buflen, retlen ); -+ if (SQL_SUCCEEDED(ret) && typeinfo_is_string(type)) -+ { -+ if (value) -+ { -+ WCHAR *p = strnAtoW(value, -1); -+ wcscpy(value, p); -+ free(p); -+ -+ if (retlen) -+ *retlen = wcslen(value) * sizeof(WCHAR); -+ } -+ -+ if (retlen) -+ *retlen = *retlen * sizeof(WCHAR); -+ } -+ } -+ return ret; - } - - /************************************************************************* --- -2.50.1 - diff --git a/patches/odbc32-fixes/0011-odbc32-SQLExecDirectW-call-fallback-SQLExecDirect.patch b/patches/odbc32-fixes/0011-odbc32-SQLExecDirectW-call-fallback-SQLExecDirect.patch deleted file mode 100644 index 64dde06c..00000000 --- a/patches/odbc32-fixes/0011-odbc32-SQLExecDirectW-call-fallback-SQLExecDirect.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 8b2a6e19672b17ea61b2b4b5e141368a988ec9cf Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 26 Apr 2025 17:07:21 +1000 -Subject: [PATCH] odbc32: SQLExecDirectW call fallback SQLExecDirect - ---- - dlls/odbc32/proxyodbc.c | 25 +++++++++++++++++++++++-- - 1 file changed, 23 insertions(+), 2 deletions(-) - -diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index e18117d5ad8..aace16cde55 100644 ---- a/dlls/odbc32/proxyodbc.c -+++ b/dlls/odbc32/proxyodbc.c -@@ -1113,6 +1113,20 @@ static SQLWCHAR *strnAtoW( const SQLCHAR *str, int len ) - return ret; - } - -+static inline char *strdupWtoA(const WCHAR *str) -+{ -+ char *ret = NULL; -+ -+ if(str) { -+ DWORD size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); -+ ret = malloc(size); -+ if(ret) -+ WideCharToMultiByte(CP_ACP, 0, str, -1, ret, size, NULL, NULL); -+ } -+ -+ return ret; -+} -+ - static SQLRETURN columns_unix_a( struct statement *stmt, SQLCHAR *catalog, SQLSMALLINT len1, SQLCHAR *schema, - SQLSMALLINT len2, SQLCHAR *table, SQLSMALLINT len3, SQLCHAR *column, - SQLSMALLINT len4 ) -@@ -6148,10 +6162,17 @@ static SQLRETURN exec_direct_unix_w( struct statement *stmt, SQLWCHAR *text, SQL - - static SQLRETURN exec_direct_win32_w( struct statement *stmt, SQLWCHAR *text, SQLINTEGER len ) - { -+ SQLRETURN ret = SQL_ERROR; -+ - if (stmt->hdr.win32_funcs->SQLExecDirectW) - return stmt->hdr.win32_funcs->SQLExecDirectW( stmt->hdr.win32_handle, text, len ); -- if (stmt->hdr.win32_funcs->SQLExecDirect) FIXME( "Unicode to ANSI conversion not handled\n" ); -- return SQL_ERROR; -+ if (stmt->hdr.win32_funcs->SQLExecDirect) -+ { -+ SQLCHAR *textA = (SQLCHAR*)strdupWtoA( text ); -+ ret = stmt->hdr.win32_funcs->SQLExecDirect( stmt->hdr.win32_handle, textA, len ); -+ free(textA); -+ } -+ return ret; - } - - /************************************************************************* --- -2.50.1 - diff --git a/patches/odbc32-fixes/0012-odbc32-SQLDescribeColW-add-ANSI-fallback.patch b/patches/odbc32-fixes/0012-odbc32-SQLDescribeColW-add-ANSI-fallback.patch index 63fc52ad..8752d196 100644 --- a/patches/odbc32-fixes/0012-odbc32-SQLDescribeColW-add-ANSI-fallback.patch +++ b/patches/odbc32-fixes/0012-odbc32-SQLDescribeColW-add-ANSI-fallback.patch @@ -1,4 +1,4 @@ -From e482d2dec06bdbefa1aafff913cb34aeaa7c854e Mon Sep 17 00:00:00 2001 +From 1afac79a78e568ed8fa6e2f2aa5b9eef986188b8 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 26 Apr 2025 17:32:49 +1000 Subject: [PATCH] odbc32: SQLDescribeColW add ANSI fallback @@ -8,10 +8,10 @@ Subject: [PATCH] odbc32: SQLDescribeColW add ANSI fallback 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index aace16cde55..00d25d06ec2 100644 +index 0beeafd27cd..7a0d5e46cda 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c -@@ -6050,11 +6050,21 @@ static SQLRETURN describe_col_win32_w( struct statement *stmt, SQLUSMALLINT col_ +@@ -6059,11 +6059,21 @@ static SQLRETURN describe_col_win32_w( struct statement *stmt, SQLUSMALLINT col_ SQLSMALLINT buf_len, SQLSMALLINT *name_len, SQLSMALLINT *data_type, SQLULEN *col_size, SQLSMALLINT *decimal_digits, SQLSMALLINT *nullable ) { @@ -24,7 +24,7 @@ index aace16cde55..00d25d06ec2 100644 - return SQL_ERROR; + if (stmt->hdr.win32_funcs->SQLDescribeCol) + { -+ SQLCHAR *name = (SQLCHAR*)strdupWtoA( (WCHAR*)col_name ); ++ SQLCHAR *name = (SQLCHAR*)strdupWA( (WCHAR*)col_name ); + + ret = stmt->hdr.win32_funcs->SQLDescribeCol( stmt->hdr.win32_handle, col_number, name, buf_len, name_len, + data_type, col_size, decimal_digits, nullable); @@ -36,5 +36,5 @@ index aace16cde55..00d25d06ec2 100644 /************************************************************************* -- -2.50.1 +2.51.0 diff --git a/patches/odbc32-fixes/0019-odbc32-SQLNativeSqlW-add-ANSI-fallback.patch b/patches/odbc32-fixes/0019-odbc32-SQLNativeSqlW-add-ANSI-fallback.patch index 1a0cd153..0c5a8d79 100644 --- a/patches/odbc32-fixes/0019-odbc32-SQLNativeSqlW-add-ANSI-fallback.patch +++ b/patches/odbc32-fixes/0019-odbc32-SQLNativeSqlW-add-ANSI-fallback.patch @@ -1,4 +1,4 @@ -From 472c0a3a3962a82dc17fc3c0aa2dc6ed5ade8b22 Mon Sep 17 00:00:00 2001 +From 0affa8ade82076038f5c5ccfc9bb295401be7f95 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 1 May 2025 08:05:31 +1000 Subject: [PATCH] odbc32: SQLNativeSqlW add ANSI fallback @@ -8,10 +8,10 @@ Subject: [PATCH] odbc32: SQLNativeSqlW add ANSI fallback 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index 4ff20236cce..416d5aa77fa 100644 +index e39964d3489..cbd769fff44 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c -@@ -7895,11 +7895,33 @@ static SQLRETURN native_sql_unix_w( struct connection *con, SQLWCHAR *in_stateme +@@ -7888,11 +7888,33 @@ static SQLRETURN native_sql_unix_w( struct connection *con, SQLWCHAR *in_stateme static SQLRETURN native_sql_win32_w( struct connection *con, SQLWCHAR *in_statement, SQLINTEGER len, SQLWCHAR *out_statement, SQLINTEGER buflen, SQLINTEGER *retlen ) { @@ -24,7 +24,7 @@ index 4ff20236cce..416d5aa77fa 100644 - return SQL_ERROR; + if (con->hdr.win32_funcs->SQLNativeSql) + { -+ SQLCHAR *statement = (SQLCHAR*)strdupWtoA( (WCHAR*)in_statement ); ++ SQLCHAR *statement = (SQLCHAR *)strdupWA( (WCHAR *)in_statement ); + SQLCHAR *out = NULL; + if (buflen) + out = malloc( buflen ); @@ -48,5 +48,5 @@ index 4ff20236cce..416d5aa77fa 100644 /************************************************************************* -- -2.50.1 +2.51.0 diff --git a/patches/odbc32-fixes/0020-odbc32-SQLPrepareW-add-ANSI-fallback.patch b/patches/odbc32-fixes/0020-odbc32-SQLPrepareW-add-ANSI-fallback.patch index cac88cf7..c7c5e513 100644 --- a/patches/odbc32-fixes/0020-odbc32-SQLPrepareW-add-ANSI-fallback.patch +++ b/patches/odbc32-fixes/0020-odbc32-SQLPrepareW-add-ANSI-fallback.patch @@ -1,4 +1,4 @@ -From 52ea953c3395206435d5bd9eb9f3dbbebde47993 Mon Sep 17 00:00:00 2001 +From b9c01073dd390b5b241b1e87afefb5e61dbd1635 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 1 May 2025 08:10:04 +1000 Subject: [PATCH] odbc32: SQLPrepareW add ANSI fallback @@ -8,10 +8,10 @@ Subject: [PATCH] odbc32: SQLPrepareW add ANSI fallback 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c -index 416d5aa77fa..138ccb0f112 100644 +index cbd769fff44..b20ccaf5e55 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c -@@ -6274,10 +6274,17 @@ static SQLRETURN prepare_unix_w( struct statement *stmt, SQLWCHAR *statement, SQ +@@ -6307,10 +6307,17 @@ static SQLRETURN prepare_unix_w( struct statement *stmt, SQLWCHAR *statement, SQ static SQLRETURN prepare_win32_w( struct statement *stmt, SQLWCHAR *statement, SQLINTEGER len ) { @@ -23,7 +23,7 @@ index 416d5aa77fa..138ccb0f112 100644 - return SQL_ERROR; + if (stmt->hdr.win32_funcs->SQLPrepare) + { -+ SQLCHAR *statementA = (SQLCHAR*)strdupWtoA( statement ); ++ SQLCHAR *statementA = (SQLCHAR *)strdupWA( statement ); + ret = stmt->hdr.win32_funcs->SQLPrepare( stmt->hdr.win32_handle, statementA, len ); + free(statementA); + } @@ -32,5 +32,5 @@ index 416d5aa77fa..138ccb0f112 100644 /************************************************************************* -- -2.50.1 +2.51.0 diff --git a/patches/server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch b/patches/server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch index 0c46f1b0..5cee3fd7 100644 --- a/patches/server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch +++ b/patches/server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch @@ -1,4 +1,4 @@ -From de5dc4769ee2493fbfc157d5b565c72d56613151 Mon Sep 17 00:00:00 2001 +From 8ce710ee30e95c93b36e4d5e9d4bcba8fd6f0493 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 15 Mar 2015 01:05:48 +0100 Subject: [PATCH] server: Fix handling of GetMessage after previous PeekMessage @@ -15,10 +15,10 @@ Changes in v3: 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c -index c8a12a6f998..618eba3419a 100644 +index 8671134f349..219cdd805f2 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c -@@ -14609,13 +14609,10 @@ static void test_PeekMessage3(void) +@@ -14612,13 +14612,10 @@ static void test_PeekMessage3(void) ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = PeekMessageA(&msg, hwnd, 0, 0, PM_NOREMOVE); @@ -32,7 +32,7 @@ index c8a12a6f998..618eba3419a 100644 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, hwnd, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); -@@ -14625,10 +14622,8 @@ static void test_PeekMessage3(void) +@@ -14628,10 +14625,8 @@ static void test_PeekMessage3(void) ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE); @@ -43,7 +43,7 @@ index c8a12a6f998..618eba3419a 100644 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, hwnd, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); -@@ -14640,10 +14635,11 @@ static void test_PeekMessage3(void) +@@ -14643,10 +14638,11 @@ static void test_PeekMessage3(void) ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = GetMessageA(&msg, hwnd, 0, 0); @@ -57,7 +57,7 @@ index c8a12a6f998..618eba3419a 100644 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, hwnd, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret); -@@ -14671,14 +14667,32 @@ static void test_PeekMessage3(void) +@@ -14674,14 +14670,32 @@ static void test_PeekMessage3(void) ret = GetMessageA(&msg, hwnd, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = GetMessageA(&msg, hwnd, 0, 0); @@ -93,7 +93,7 @@ index c8a12a6f998..618eba3419a 100644 * because both messages are in the same queue. */ diff --git a/server/queue.c b/server/queue.c -index ffb1d441e60..60537685dc2 100644 +index fb9499b5589..6b374797b42 100644 --- a/server/queue.c +++ b/server/queue.c @@ -138,6 +138,7 @@ struct msg_queue @@ -104,7 +104,7 @@ index ffb1d441e60..60537685dc2 100644 }; struct hotkey -@@ -320,6 +321,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ +@@ -317,6 +318,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->input = (struct thread_input *)grab_object( input ); queue->hooks = NULL; queue->keystate_lock = 0; @@ -113,7 +113,7 @@ index ffb1d441e60..60537685dc2 100644 list_init( &queue->send_result ); list_init( &queue->callback_result ); list_init( &queue->pending_timers ); -@@ -827,13 +830,21 @@ static inline struct msg_queue *get_current_queue(void) +@@ -812,13 +815,21 @@ static inline struct msg_queue *get_current_queue(void) } /* get a (pseudo-)unique id to tag hardware messages */ @@ -136,7 +136,7 @@ index ffb1d441e60..60537685dc2 100644 /* lookup an already queued mouse message that matches the message, window and type */ static struct message *find_mouse_message( struct thread_input *input, const struct message *msg ) { -@@ -1184,7 +1195,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win ) +@@ -1169,7 +1180,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win ) } /* retrieve a posted message */ @@ -145,7 +145,7 @@ index ffb1d441e60..60537685dc2 100644 unsigned int first, unsigned int last, unsigned int flags, struct get_message_reply *reply ) { -@@ -1195,6 +1206,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win, +@@ -1180,6 +1191,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win, { if (!match_window( win, msg->win )) continue; if (!check_msg_filter( msg->msg, first, last )) continue; @@ -153,7 +153,7 @@ index ffb1d441e60..60537685dc2 100644 goto found; /* found one */ } return 0; -@@ -1857,6 +1869,7 @@ found: +@@ -1799,6 +1811,7 @@ found: msg->msg = WM_HOTKEY; msg->wparam = hotkey->id; msg->lparam = ((hotkey->vkey & 0xffff) << 16) | modifiers; @@ -161,7 +161,7 @@ index ffb1d441e60..60537685dc2 100644 free( msg->data ); msg->data = NULL; -@@ -2843,7 +2856,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user +@@ -2786,7 +2799,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user } /* now we can return it */ @@ -170,7 +170,7 @@ index ffb1d441e60..60537685dc2 100644 reply->type = MSG_HARDWARE; reply->win = win; reply->msg = msg_code; -@@ -2950,6 +2963,7 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa +@@ -2925,6 +2938,7 @@ void send_notify_message( user_handle_t win, unsigned int message, lparam_t wpar msg->result = NULL; msg->data = NULL; msg->data_size = 0; @@ -178,7 +178,7 @@ index ffb1d441e60..60537685dc2 100644 get_message_defaults( thread->queue, &msg->x, &msg->y, &msg->time ); -@@ -3254,6 +3268,7 @@ DECL_HANDLER(send_message) +@@ -3208,6 +3222,7 @@ DECL_HANDLER(send_message) set_queue_bits( recv_queue, QS_SENDMESSAGE ); break; case MSG_POSTED: @@ -186,7 +186,7 @@ index ffb1d441e60..60537685dc2 100644 list_add_tail( &recv_queue->msg_list[POST_MESSAGE], &msg->entry ); set_queue_bits( recv_queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE ); if (msg->msg == WM_HOTKEY) -@@ -3394,12 +3409,12 @@ DECL_HANDLER(get_message) +@@ -3348,12 +3363,12 @@ DECL_HANDLER(get_message) /* then check for posted messages */ if ((filter & QS_POSTMESSAGE) && @@ -201,7 +201,7 @@ index ffb1d441e60..60537685dc2 100644 return; /* only check for quit messages if not posted messages pending */ -@@ -3410,7 +3425,7 @@ DECL_HANDLER(get_message) +@@ -3364,7 +3379,7 @@ DECL_HANDLER(get_message) if ((filter & QS_INPUT) && filter_contains_hw_range( req->get_first, req->get_last ) && get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, req->flags, reply )) @@ -210,7 +210,7 @@ index ffb1d441e60..60537685dc2 100644 /* now check for WM_PAINT */ if ((filter & QS_PAINT) && -@@ -3423,7 +3438,7 @@ DECL_HANDLER(get_message) +@@ -3377,7 +3392,7 @@ DECL_HANDLER(get_message) reply->wparam = 0; reply->lparam = 0; get_message_defaults( queue, &reply->x, &reply->y, &reply->time ); @@ -219,7 +219,7 @@ index ffb1d441e60..60537685dc2 100644 } /* now check for timer */ -@@ -3439,9 +3454,19 @@ DECL_HANDLER(get_message) +@@ -3393,9 +3408,19 @@ DECL_HANDLER(get_message) get_message_defaults( queue, &reply->x, &reply->y, &reply->time ); if (!(req->flags & PM_NOYIELD) && current->process->idle_event) set_event( current->process->idle_event ); @@ -240,9 +240,9 @@ index ffb1d441e60..60537685dc2 100644 if (get_win == -1 && current->process->idle_event) set_event( current->process->idle_event ); SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) -@@ -3454,6 +3479,13 @@ DECL_HANDLER(get_message) - if (!get_queue_status( queue )) reset_queue_sync( queue ); - else signal_queue_sync( queue ); +@@ -3408,6 +3433,13 @@ DECL_HANDLER(get_message) + if (!get_queue_status( queue )) reset_sync( queue->sync ); + else signal_sync( queue->sync ); set_error( STATUS_PENDING ); /* FIXME */ + return; + @@ -254,7 +254,7 @@ index ffb1d441e60..60537685dc2 100644 } -@@ -3471,7 +3503,10 @@ DECL_HANDLER(reply_message) +@@ -3425,7 +3457,10 @@ DECL_HANDLER(reply_message) DECL_HANDLER(accept_hardware_message) { if (current->queue) diff --git a/staging/upstream-commit b/staging/upstream-commit index 0eefeb11..2e274a82 100644 --- a/staging/upstream-commit +++ b/staging/upstream-commit @@ -1 +1 @@ -192d335facd5ec6ff2b9acec615efff16385a416 +01269452e0fbb1f081d506bd64996590a553e2b9