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 index 9f144db4..28e81b73 100644 --- 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 @@ -1,4 +1,4 @@ -From e0719eabba7a7c187767441b361acedd50766234 Mon Sep 17 00:00:00 2001 +From 723ccff12d0b9516490e34519e244a6486d11b8b 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(). @@ -7,14 +7,16 @@ 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 | 12 ++++++++++++ - 1 file changed, 12 insertions(+) + configure | 68 +++++++++++++++++++++++++++++++++++++++++++++ + configure.ac | 12 ++++++++ + include/config.h.in | 9 ++++++ + 3 files changed, 89 insertions(+) -diff --git a/configure.ac b/configure.ac -index da5f24aba5f..6c2653c4c82 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -509,6 +509,7 @@ AC_CHECK_HEADERS(\ +diff --git a/configure b/configure +index 5672688a0d7..24ae489c3a9 100755 +--- a/configure ++++ b/configure +@@ -7467,6 +7467,7 @@ for ac_header in \ sys/cdio.h \ sys/epoll.h \ sys/event.h \ @@ -22,7 +24,7 @@ index da5f24aba5f..6c2653c4c82 100644 sys/filio.h \ sys/ioctl.h \ sys/ipc.h \ -@@ -2191,6 +2192,7 @@ AC_CHECK_FUNCS(\ +@@ -17815,6 +17816,7 @@ for ac_func in \ pipe2 \ poll \ port_create \ @@ -30,7 +32,100 @@ index da5f24aba5f..6c2653c4c82 100644 prctl \ pread \ proc_pidinfo \ -@@ -2265,6 +2267,16 @@ case $host_os in +@@ -18224,6 +18226,72 @@ fi + ;; + esac + ++if test "$ac_cv_header_sys_mman_h" = "yes" -a "x$RT_LIBS" = "x" ++then ++ ac_save_LIBS=$LIBS ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5 ++$as_echo_n "checking for library containing shm_open... " >&6; } ++if ${ac_cv_search_shm_open+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char shm_open (); ++int ++main () ++{ ++return shm_open (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' rt; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_shm_open=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if ${ac_cv_search_shm_open+:} false; then : ++ break ++fi ++done ++if ${ac_cv_search_shm_open+:} false; then : ++ ++else ++ ac_cv_search_shm_open=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_shm_open" >&5 ++$as_echo "$ac_cv_search_shm_open" >&6; } ++ac_res=$ac_cv_search_shm_open ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ ++$as_echo "#define HAVE_SHM_OPEN 1" >>confdefs.h ++ ++ test "$ac_res" = "none required" || RT_LIBS="$ac_res" ++ ++fi ++ ++fi ++LIBS=$ac_save_LIBS ++ + if test "x$with_ldap" != "xno" + then + if ${LDAP_CFLAGS:+false} :; then : +diff --git a/configure.ac b/configure.ac +index 7a03cbc1cab..bfa64a8d68a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -494,6 +494,7 @@ AC_CHECK_HEADERS(\ + sys/cdio.h \ + sys/epoll.h \ + sys/event.h \ ++ sys/eventfd.h \ + sys/filio.h \ + sys/ioctl.h \ + sys/ipc.h \ +@@ -2207,6 +2208,7 @@ AC_CHECK_FUNCS(\ + pipe2 \ + poll \ + port_create \ ++ ppoll \ + prctl \ + pread \ + proc_pidinfo \ +@@ -2271,6 +2273,16 @@ case $host_os in ;; esac @@ -47,6 +142,40 @@ index da5f24aba5f..6c2653c4c82 100644 dnl **** Check for OpenLDAP *** if test "x$with_ldap" != "xno" then +diff --git a/include/config.h.in b/include/config.h.in +index 4adb6325e14..6f1323311d9 100644 +--- a/include/config.h.in ++++ b/include/config.h.in +@@ -687,6 +687,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_PORT_H + ++/* Define to 1 if you have the `ppoll' function. */ ++#undef HAVE_PPOLL ++ + /* Define to 1 if you have the `prctl' function. */ + #undef HAVE_PRCTL + +@@ -804,6 +807,9 @@ + /* 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 you have the `shm_open' function. */ ++#undef HAVE_SHM_OPEN ++ + /* Define if sigaddset is supported */ + #undef HAVE_SIGADDSET + +@@ -1004,6 +1010,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.25.1 +2.28.0 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 index 1df95688..da0e20cd 100644 --- 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 @@ -1,4 +1,4 @@ -From d407857d923dd08446cf38f83549c0b76442cc81 Mon Sep 17 00:00:00 2001 +From d10e2324d1295c27e00975526420375a338b5eb1 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 @@ -6,13 +6,16 @@ Subject: [PATCH] server: Create server objects for eventfd-based --- server/Makefile.in | 1 + - server/esync.c | 137 ++++++++++++++++++++++++++++++++++++++++++++ - server/protocol.def | 10 ++++ - 3 files changed, 148 insertions(+) + server/esync.c | 320 ++++++++++++++++++++++++++++++++++++++++++++ + server/esync.h | 22 +++ + 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 60ecca706..2c895bcec 100644 +index 9a695cefc30..8bd612b4728 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ @@ -25,10 +28,10 @@ index 60ecca706..2c895bcec 100644 file.c \ diff --git a/server/esync.c b/server/esync.c new file mode 100644 -index 000000000..147fb7724 +index 00000000000..b8b257281bf --- /dev/null +++ b/server/esync.c -@@ -0,0 +1,137 @@ +@@ -0,0 +1,320 @@ +/* + * eventfd-based synchronization objects + * @@ -52,11 +55,19 @@ index 000000000..147fb7724 +#include "config.h" +#include "wine/port.h" + ++#include +#include +#include +#ifdef HAVE_SYS_EVENTFD_H +# include +#endif ++#ifdef HAVE_SYS_MMAN_H ++# include ++#endif ++#ifdef HAVE_SYS_STAT_H ++# include ++#endif ++#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS @@ -67,10 +78,72 @@ index 000000000..147fb7724 +#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 */ ++ 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 ); @@ -90,6 +163,7 @@ index 000000000..147fb7724 + no_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 */ @@ -112,8 +186,58 @@ index 000000000..147fb7724 + 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 flags, ++ unsigned int attr, int initval, int max, enum esync_type type, + const struct security_descriptor *sd ) +{ +#ifdef HAVE_SYS_EVENTFD_H @@ -123,8 +247,13 @@ index 000000000..147fb7724 + { + 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 | EFD_CLOEXEC | EFD_NONBLOCK ); ++ esync->fd = eventfd( initval, flags ); + if (esync->fd == -1) + { + perror( "eventfd" ); @@ -132,6 +261,49 @@ index 000000000..147fb7724 + 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; @@ -150,9 +322,21 @@ index 000000000..147fb7724 + 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->flags, sd ))) ++ 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 ); @@ -160,30 +344,96 @@ index 000000000..147fb7724 + 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..7ca4ca89394 +--- /dev/null ++++ b/server/esync.h +@@ -0,0 +1,22 @@ ++/* ++ * 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); ++void esync_init(void); +diff --git a/server/main.c b/server/main.c +index 2b5065e1852..385ae5ee370 100644 +--- a/server/main.c ++++ b/server/main.c +@@ -36,6 +36,7 @@ + #include "file.h" + #include "thread.h" + #include "request.h" ++#include "esync.h" + + /* command-line options */ + int debug_level = 0; +@@ -140,6 +141,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_scheduler(); diff --git a/server/protocol.def b/server/protocol.def -index 007ef1f67..cd97ba008 100644 +index 5ca762fdabf..552d504cc8d 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -4021,3 +4021,13 @@ struct handle_info - unsigned int threads; /* number of threads */ - unsigned int handles; /* number of handles */ +@@ -3665,3 +3665,27 @@ struct handle_info + @REQ(resume_process) + obj_handle_t handle; /* process 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 flags; /* flags (EFD_SEMAPHORE or 0) */ ++ 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 -- -2.21.0 +2.28.0 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 index eeef2e5c..01186e3b 100644 --- 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 @@ -1,38 +1,38 @@ -From f75d03835dd04b2838a2cdcde64346efc26e9972 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 20:29:21 -0500 +From fd3e782fbebdfbac412ab3ee9ba01c2a562b61ee 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. -This patch break things, of course. That is fine. Its purpose is to prevent a Massive Patch Munge. --- - dlls/ntdll/Makefile.in | 1 + - dlls/ntdll/esync.c | 141 ++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 32 +++++++++ - dlls/ntdll/ntdll_misc.h | 1 + - dlls/ntdll/server.c | 7 +- - dlls/ntdll/sync.c | 5 ++ - 6 files changed, 184 insertions(+), 3 deletions(-) - create mode 100644 dlls/ntdll/esync.c - create mode 100644 dlls/ntdll/esync.h + dlls/ntdll/Makefile.in | 1 + + dlls/ntdll/unix/esync.c | 273 +++++++++++++++++++++++++++++++++++++++ + 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, 318 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 7971ef98cf0..2f26f0dc958 100644 +index f39ffb42c6f..f742d084906 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in -@@ -17,6 +17,7 @@ C_SRCS = \ - directory.c \ - env.c \ - error.c \ -+ esync.c \ - exception.c \ - file.c \ - handletable.c \ -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c +@@ -46,6 +46,7 @@ C_SRCS = \ + unix/cdrom.c \ + unix/debug.c \ + unix/env.c \ ++ unix/esync.c \ + unix/file.c \ + unix/loader.c \ + unix/process.c \ +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c new file mode 100644 -index 00000000000..da35bdf854a +index 00000000000..7c409c7a9ca --- /dev/null -+++ b/dlls/ntdll/esync.c -@@ -0,0 +1,141 @@ ++++ b/dlls/ntdll/unix/esync.c +@@ -0,0 +1,273 @@ +/* + * eventfd-based synchronization objects + * @@ -53,14 +53,25 @@ index 00000000000..da35bdf854a + * 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 -+#ifdef HAVE_SYS_EVENTFD_H -+# include ++#ifdef HAVE_SYS_MMAN_H ++# include +#endif ++#ifdef HAVE_SYS_STAT_H ++# include ++#endif ++#include ++#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS @@ -70,13 +81,9 @@ index 00000000000..da35bdf854a +#include "wine/server.h" +#include "wine/debug.h" + -+#include "ntdll_misc.h" ++#include "unix_private.h" +#include "esync.h" + -+#ifndef EFD_SEMAPHORE -+#define EFD_SEMAPHORE 1 -+#endif -+ +WINE_DEFAULT_DEBUG_CHANNEL(esync); + +int do_esync(void) @@ -85,7 +92,7 @@ index 00000000000..da35bdf854a + static int do_esync_cached = -1; + + if (do_esync_cached == -1) -+ do_esync_cached = (getenv("WINEESYNC") != NULL); ++ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); + + return do_esync_cached; +#else @@ -96,90 +103,215 @@ index 00000000000..da35bdf854a +#endif +} + -+enum esync_type -+{ -+ ESYNC_SEMAPHORE = 1, -+}; -+ +struct esync +{ + enum esync_type type; + int fd; ++ void *shm; +}; + +struct semaphore +{ -+ struct esync obj; + int max; ++ int count; +}; ++C_ASSERT(sizeof(struct semaphore) == 8); + -+static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, int initval, int flags) ++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_section, &sigset ); ++ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + SERVER_START_REQ( create_esync ) + { + req->access = access; + req->initval = initval; -+ req->flags = flags; ++ 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 ); -+ *fd = receive_fd( &fd_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_section, &sigset ); ++ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + -+ TRACE("-> handle %p, fd %d.\n", *handle, *fd); ++ 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); ++ } + -+ RtlFreeHeap( GetProcessHeap(), 0, objattr ); ++ free( objattr ); + return ret; +} + +extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) +{ -+ struct semaphore *semaphore; -+ NTSTATUS ret; -+ int fd = -1; -+ + TRACE("name %s, initial %d, max %d.\n", + attr ? debugstr_us(attr->ObjectName) : "", initial, max); + -+ ret = create_esync( &fd, handle, access, attr, initial, EFD_SEMAPHORE ); -+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ { -+ semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -+ if (!semaphore) -+ return STATUS_NO_MEMORY; ++ return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max ); ++} + -+ semaphore->obj.type = ESYNC_SEMAPHORE; -+ semaphore->obj.fd = fd; -+ semaphore->max = 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; + } + -+ return ret; ++ 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/esync.h b/dlls/ntdll/esync.h +diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h new file mode 100644 -index 00000000000..1a88170cfc4 +index 00000000000..a50a755149a --- /dev/null -+++ b/dlls/ntdll/esync.h -@@ -0,0 +1,32 @@ ++++ b/dlls/ntdll/unix/esync.h +@@ -0,0 +1,35 @@ +/* + * eventfd-based synchronization objects + * @@ -201,59 +333,54 @@ index 00000000000..1a88170cfc4 + */ + +extern int do_esync(void) DECLSPEC_HIDDEN; ++extern void esync_init(void) DECLSPEC_HIDDEN; + +extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; + + -+/* We have to synchronize on the fd cache CS so that our calls to receive_fd ++/* 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 CS to -+ * "server_fd_section" or something similar. */ -+extern RTL_CRITICAL_SECTION fd_cache_section; -diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 177d4fd9e44..51c067bb8a0 100644 ---- a/dlls/ntdll/ntdll_misc.h -+++ b/dlls/ntdll/ntdll_misc.h -@@ -136,6 +136,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t * - extern int server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN; - extern int server_get_unix_fd( HANDLE handle, unsigned int access, int *unix_fd, - int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN; ++ * 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 ) DECLSPEC_HIDDEN; - extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN; - extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, - data_size_t *ret_len ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c -index 973804967d1..c240bd1d9f8 100644 ---- a/dlls/ntdll/server.c -+++ b/dlls/ntdll/server.c -@@ -98,6 +98,7 @@ - #include "wine/debug.h" - #include "ntdll_misc.h" - #include "ddk/wdm.h" +diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c +index c2b6ea603e3..ab2d9e347c3 100644 +--- a/dlls/ntdll/unix/loader.c ++++ b/dlls/ntdll/unix/loader.c +@@ -86,6 +86,7 @@ + #include "winioctl.h" + #include "winternl.h" + #include "unix_private.h" +#include "esync.h" + #include "wine/list.h" + #include "wine/debug.h" - WINE_DEFAULT_DEBUG_CHANNEL(server); - WINE_DECLARE_DEBUG_CHANNEL(winediag); -@@ -170,14 +171,14 @@ sigset_t server_block_set; /* signals to block during server calls */ +@@ -1564,6 +1565,7 @@ static void start_main_thread(void) + dbg_init(); + server_init_process(); + startup_info_size = server_init_thread( teb->Peb, &suspend ); ++ 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 7236f0acb83..971341bf6e0 100644 +--- a/dlls/ntdll/unix/server.c ++++ b/dlls/ntdll/unix/server.c +@@ -112,7 +112,7 @@ timeout_t server_start_time = 0; /* time of server startup */ + 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 pid_t server_pid; - --static RTL_CRITICAL_SECTION fd_cache_section; -+RTL_CRITICAL_SECTION fd_cache_section; - static RTL_CRITICAL_SECTION_DEBUG critsect_debug = - { - 0, 0, &fd_cache_section, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") } - }; --static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -+RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +-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 ) -@@ -919,7 +920,7 @@ void CDECL wine_server_send_fd( int fd ) +@@ -813,7 +813,7 @@ void CDECL wine_server_send_fd( int fd ) * * Receive a file descriptor passed from the server. */ @@ -262,30 +389,40 @@ index 973804967d1..c240bd1d9f8 100644 { struct iovec vec; struct msghdr msghdr; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index fbfb8f893ec..74dbde017e8 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -59,7 +59,9 @@ - #include "winternl.h" - #include "wine/server.h" +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index bba7af7e34f..663a170fc61 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -72,6 +72,7 @@ + #include "wine/exception.h" #include "wine/debug.h" -+ - #include "ntdll_misc.h" + #include "unix_private.h" +#include "esync.h" WINE_DEFAULT_DEBUG_CHANNEL(sync); -@@ -259,6 +261,9 @@ NTSTATUS WINAPI NtCreateSemaphore( OUT PHANDLE SemaphoreHandle, - if (MaximumCount <= 0 || InitialCount < 0 || InitialCount > MaximumCount) - return STATUS_INVALID_PARAMETER; - -+ if (do_esync()) -+ return esync_create_semaphore( SemaphoreHandle, access, attr, InitialCount, MaximumCount ); -+ +@@ -322,6 +323,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 b8b257281bf..226e70cd1ad 100644 +--- a/server/esync.c ++++ b/server/esync.c +@@ -43,6 +43,7 @@ + #include "handle.h" + #include "request.h" + #include "file.h" ++#include "esync.h" + + int do_esync(void) + { -- -2.26.2 +2.28.0 diff --git a/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch b/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch new file mode 100644 index 00000000..08e474b1 --- /dev/null +++ b/patches/eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch @@ -0,0 +1,108 @@ +From e5a3456cde339352e78b10fed8a2fc65ca560041 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 7c409c7a9ca..8f28a36d93f 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #ifdef HAVE_SYS_MMAN_H + # include +@@ -173,6 +174,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 ) + { +@@ -228,6 +239,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 a50a755149a..09838e95535 100644 +--- a/dlls/ntdll/unix/esync.h ++++ b/dlls/ntdll/unix/esync.h +@@ -23,6 +23,7 @@ extern void esync_init(void) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; + + + /* 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 663a170fc61..f4bcda4b473 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -407,6 +407,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous + { + NTSTATUS ret; + ++ if (do_esync()) ++ return esync_release_semaphore( handle, count, previous ); ++ + SERVER_START_REQ( release_semaphore ) + { + req->handle = wine_server_obj_handle( handle ); +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0004-ntdll-Store-esync-objects-locally.patch b/patches/eventfd_synchronization/0004-ntdll-Store-esync-objects-locally.patch deleted file mode 100644 index 70f52e36..00000000 --- a/patches/eventfd_synchronization/0004-ntdll-Store-esync-objects-locally.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 3f6f2c22a0ee8e7c9067b74aef67018ed0739484 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 20:45:57 -0500 -Subject: [PATCH 04/83] ntdll: Store esync objects locally. - -Slight tweak for optimization: return UINT_PTR instead, and remove a useless -cmpxchg. - ---- - dlls/ntdll/esync.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 61 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index da35bdf85..2bb85d910 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -19,6 +19,7 @@ - */ - - #include "config.h" -+#include "wine/port.h" - - #include - #include -@@ -26,6 +27,9 @@ - #ifdef HAVE_SYS_EVENTFD_H - # include - #endif -+#ifdef HAVE_SYS_MMAN_H -+# include -+#endif - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -34,6 +38,7 @@ - #include "winternl.h" - #include "wine/server.h" - #include "wine/debug.h" -+#include "wine/library.h" - - #include "ntdll_misc.h" - #include "esync.h" -@@ -78,6 +83,59 @@ struct semaphore - int max; - }; - -+/* 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 128 -+ -+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 BOOL add_to_list( HANDLE handle, struct esync *obj ) -+{ -+ 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 = wine_anon_mmap( NULL, ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync *), -+ PROT_READ | PROT_WRITE, 0 ); -+ if (ptr == MAP_FAILED) return FALSE; -+ esync_list[entry] = ptr; -+ } -+ } -+ -+ obj = InterlockedExchangePointer((void **)&esync_list[entry][idx], obj); -+ assert(!obj); -+ return TRUE; -+} -+ -+static void *esync_get_object( HANDLE handle ) -+{ -+ UINT_PTR entry, idx = handle_to_index( handle, &entry ); -+ -+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL; -+ -+ return esync_list[entry][idx]; -+} -+ -+ - static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, int initval, int flags) - { -@@ -115,7 +173,7 @@ static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, - return ret; - } - --extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -+NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) - { - struct semaphore *semaphore; -@@ -135,6 +193,8 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - semaphore->obj.type = ESYNC_SEMAPHORE; - semaphore->obj.fd = fd; - semaphore->max = max; -+ -+ add_to_list( *handle, &semaphore->obj ); - } - - return ret; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch b/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch new file mode 100644 index 00000000..2abda076 --- /dev/null +++ b/patches/eventfd_synchronization/0005-ntdll-Implement-NtClose.patch @@ -0,0 +1,77 @@ +From f0d0cdcb048b4af8003ba5279bd90293ecc7f8ba 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 8f28a36d93f..02b07bf36be 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -184,6 +184,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 09838e95535..14e52416764 100644 +--- a/dlls/ntdll/unix/esync.h ++++ b/dlls/ntdll/unix/esync.h +@@ -20,6 +20,7 @@ + + extern int do_esync(void) DECLSPEC_HIDDEN; + extern void esync_init(void) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; +diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c +index 971341bf6e0..d8837f6fde0 100644 +--- a/dlls/ntdll/unix/server.c ++++ b/dlls/ntdll/unix/server.c +@@ -88,6 +88,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); +@@ -1644,6 +1645,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle ) + NTSTATUS ret; + int 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.28.0 + diff --git a/patches/eventfd_synchronization/0005-ntdll-Implement-NtReleaseSemaphore.patch b/patches/eventfd_synchronization/0005-ntdll-Implement-NtReleaseSemaphore.patch deleted file mode 100644 index 0095b474..00000000 --- a/patches/eventfd_synchronization/0005-ntdll-Implement-NtReleaseSemaphore.patch +++ /dev/null @@ -1,78 +0,0 @@ -From eb0273dfd273f1f6c48db45b444ec318fe514699 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 21:02:14 -0500 -Subject: [PATCH 05/83] ntdll: Implement NtReleaseSemaphore(). - ---- - dlls/ntdll/esync.c | 22 ++++++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/sync.c | 4 ++++ - 3 files changed, 27 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 2bb85d910..bca95b9b2 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -23,6 +23,7 @@ - - #include - #include -+#include - #include - #ifdef HAVE_SYS_EVENTFD_H - # include -@@ -199,3 +200,24 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - - return ret; - } -+ -+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) -+{ -+ struct semaphore *semaphore = esync_get_object( handle ); -+ uint64_t count64 = count; -+ -+ TRACE("%p, %d, %p.\n", handle, count, prev); -+ -+ if (!semaphore) return STATUS_INVALID_HANDLE; -+ -+ if (prev) -+ { -+ FIXME("Can't write previous value.\n"); -+ *prev = 1; -+ } -+ -+ if (write( semaphore->obj.fd, &count64, sizeof(count64) ) == -1) -+ return FILE_GetNtStatus(); -+ -+ return STATUS_SUCCESS; -+} -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 1a88170cf..fec0b68e8 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -22,6 +22,7 @@ extern int do_esync(void) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; - - - /* We have to synchronize on the fd cache CS so that our calls to receive_fd -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index c259267fb..93052ddb5 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -333,6 +333,10 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, PULONG previous ) - { - NTSTATUS ret; -+ -+ if (do_esync()) -+ return esync_release_semaphore( handle, count, previous ); -+ - SERVER_START_REQ( release_semaphore ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0006-ntdll-Close-esync-objects.patch b/patches/eventfd_synchronization/0006-ntdll-Close-esync-objects.patch deleted file mode 100644 index e8087720..00000000 --- a/patches/eventfd_synchronization/0006-ntdll-Close-esync-objects.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 2aba7f5090f92b609f6d2763603dbeb761f9c65a Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 21:07:51 -0500 -Subject: [PATCH] ntdll: Close esync objects. - ---- - dlls/ntdll/esync.c | 19 +++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/om.c | 4 ++++ - 3 files changed, 24 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index bca95b9b2d9..f7a427425b7 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -136,6 +136,25 @@ static void *esync_get_object( HANDLE handle ) - return esync_list[entry][idx]; - } - -+NTSTATUS esync_close( HANDLE handle ) -+{ -+ UINT_PTR entry, idx = handle_to_index( handle, &entry ); -+ struct esync *obj; -+ -+ TRACE("%p.\n", handle); -+ -+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry]) -+ { -+ if ((obj = InterlockedExchangePointer( (void **)&esync_list[entry][idx], 0 ))) -+ { -+ close( obj->fd ); -+ RtlFreeHeap( GetProcessHeap(), 0, obj ); -+ return STATUS_SUCCESS; -+ } -+ } -+ -+ return STATUS_INVALID_HANDLE; -+} - - static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, int initval, int flags) -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index fec0b68e8d5..a22618de849 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -19,6 +19,7 @@ - */ - - extern int do_esync(void) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c -index f8f0760de70..b8d73a982b2 100644 ---- a/dlls/ntdll/om.c -+++ b/dlls/ntdll/om.c -@@ -34,6 +34,7 @@ - #include "windef.h" - #include "winternl.h" - #include "ntdll_misc.h" -+#include "esync.h" - #include "wine/server.h" - #include "wine/exception.h" - -@@ -387,6 +388,9 @@ NTSTATUS close_handle( HANDLE handle ) - NTSTATUS ret; - int fd = server_remove_fd_from_cache( handle ); - -+ if (do_esync()) -+ esync_close( handle ); -+ - SERVER_START_REQ( close_handle ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.26.0 - diff --git a/patches/eventfd_synchronization/0007-ntdll-Implement-waiting-on-esync-objects.patch b/patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch similarity index 70% rename from patches/eventfd_synchronization/0007-ntdll-Implement-waiting-on-esync-objects.patch rename to patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch index bf7ca6c8..4fc9ea28 100644 --- a/patches/eventfd_synchronization/0007-ntdll-Implement-waiting-on-esync-objects.patch +++ b/patches/eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch @@ -1,39 +1,48 @@ -From bb968ec541ccdcd1b04b4b967065d5ee81f3fd78 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 7 Jun 2018 21:23:52 -0500 -Subject: [PATCH] ntdll: Implement waiting on esync objects. +From 908363daafc3b5220967d31e2e878f617d465026 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Mon, 6 Jul 2020 12:34:42 -0500 +Subject: [PATCH] ntdll: Implement NtWaitForMultipleObjects(). -This is the most basic case: WAIT_ANY. We use poll() (actually ppoll(), for -the better granularity) to select on all of the handles that we can. --- - dlls/ntdll/esync.c | 161 +++++++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 3 + - dlls/ntdll/sync.c | 7 ++ - 3 files changed, 171 insertions(+) + dlls/ntdll/unix/esync.c | 170 ++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/unix/esync.h | 3 + + dlls/ntdll/unix/sync.c | 7 ++ + 3 files changed, 180 insertions(+) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index f7a427425..f6ceefe53 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -22,6 +22,13 @@ - #include "wine/port.h" +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 02b07bf36be..1b71105491c 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -22,17 +22,25 @@ + #pragma makedep unix + #endif + ++#define _GNU_SOURCE ++ + #include "config.h" #include -+#include + #include + #include +#ifdef HAVE_POLL_H +#include -+#endif -+#ifdef HAVE_SYS_POLL_H -+# include +#endif #include #include #include -@@ -240,3 +247,157 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - + #ifdef HAVE_SYS_MMAN_H + # include + #endif ++#ifdef HAVE_SYS_POLL_H ++# include ++#endif + #ifdef HAVE_SYS_STAT_H + # include + #endif +@@ -289,6 +297,168 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) return STATUS_SUCCESS; } -+ + +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 + @@ -68,6 +77,19 @@ index f7a427425..f6ceefe53 100644 + 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, @@ -79,8 +101,7 @@ index f7a427425..f6ceefe53 100644 + LONGLONG timeleft; + LARGE_INTEGER now; + ULONGLONG end; -+ int ret; -+ int i; ++ int i, ret; + + NtQuerySystemTime( &now ); + if (timeout) @@ -95,23 +116,16 @@ index f7a427425..f6ceefe53 100644 + + for (i = 0; i < count; i++) + { -+ objs[i] = esync_get_object( handles[i] ); -+ if (objs[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"); -+ /* Wait on just the eventfds; it's the best we can do. */ -+ } + else if (has_server) -+ { -+ /* It's just server objects, so delegate to the server. */ + return STATUS_NOT_IMPLEMENTED; -+ } + + if (TRACE_ON(esync)) + { @@ -145,13 +159,15 @@ index f7a427425..f6ceefe53 100644 + /* 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 (objs[i]) ++ if (obj) + { + int64_t value; + ssize_t size; @@ -160,6 +176,7 @@ index f7a427425..f6ceefe53 100644 + { + /* We found our object. */ + TRACE("Woken up by handle %p [%d].\n", handles[i], i); ++ update_grabbed_object( obj ); + return i; + } + } @@ -176,8 +193,8 @@ index f7a427425..f6ceefe53 100644 + } + else + { -+ ERR("ppoll failed: %s\n", strerror(errno)); -+ return FILE_GetNtStatus(); ++ ERR("ppoll failed: %s\n", strerror( errno )); ++ return errno_to_status( errno ); + } + } + } @@ -187,11 +204,15 @@ index f7a427425..f6ceefe53 100644 + return STATUS_NOT_IMPLEMENTED; + } +} -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index a22618de8..8f7f9b030 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -25,6 +25,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, ++ + void esync_init(void) + { + struct stat st; +diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h +index 14e52416764..87516e7597a 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) DECLSPEC_HIDDEN; extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; @@ -199,13 +220,13 @@ index a22618de8..8f7f9b030 100644 + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; + - /* We have to synchronize on the fd cache CS so that our calls to receive_fd + /* 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/sync.c b/dlls/ntdll/sync.c -index 93052ddb5..40bc619a2 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -1089,6 +1089,13 @@ static NTSTATUS wait_objects( DWORD count, const HANDLE *handles, +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index f4bcda4b473..445c2a4324d 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -1273,6 +1273,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; @@ -220,5 +241,5 @@ index 93052ddb5..40bc619a2 100644 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.21.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch b/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch new file mode 100644 index 00000000..3e8d1b3d --- /dev/null +++ b/patches/eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch @@ -0,0 +1,128 @@ +From d8cf82ba904cfa956dc5e2146ab98afa6efc46ff 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 | 3 +++ + server/esync.c | 15 +++++++++++++++ + 4 files changed, 48 insertions(+) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 1b71105491c..e440e9baa4a 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -91,6 +91,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; +@@ -297,6 +304,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 + +@@ -342,6 +361,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 87516e7597a..d9c7df967f8 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) DECLSPEC_HIDDEN; + extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; + ++extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, ++ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN; ++ + extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; + +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 445c2a4324d..51f77b1015f 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -434,6 +434,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ + data_size_t len; + struct object_attributes *objattr; + ++ 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 226e70cd1ad..b9e0a455629 100644 +--- a/server/esync.c ++++ b/server/esync.c +@@ -203,6 +203,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 ) +@@ -258,6 +265,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.28.0 + diff --git a/patches/eventfd_synchronization/0008-ntdll-Create-esync-objects-for-events.patch b/patches/eventfd_synchronization/0008-ntdll-Create-esync-objects-for-events.patch deleted file mode 100644 index 410371b4..00000000 --- a/patches/eventfd_synchronization/0008-ntdll-Create-esync-objects-for-events.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0ab9981b2309831fb12ee778e026cb1b4651dab6 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 15:33:46 -0500 -Subject: [PATCH 08/83] ntdll: Create esync objects for events. - ---- - dlls/ntdll/esync.c | 34 ++++++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 39 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 0950d8b5a..ace2f4a45 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -77,6 +77,8 @@ int do_esync(void) - enum esync_type - { - ESYNC_SEMAPHORE = 1, -+ ESYNC_AUTO_EVENT, -+ ESYNC_MANUAL_EVENT, - }; - - struct esync -@@ -91,6 +93,11 @@ struct semaphore - int max; - }; - -+struct event -+{ -+ struct esync obj; -+}; -+ - /* 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. */ - -@@ -248,6 +255,33 @@ 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 type, BOOLEAN initial ) -+{ -+ struct event *event; -+ NTSTATUS ret; -+ int fd; -+ -+ TRACE("name %s, %s-reset, initial %d.\n", -+ attr ? debugstr_us(attr->ObjectName) : "", -+ type == NotificationEvent ? "manual" : "auto", initial); -+ -+ ret = create_esync( &fd, handle, access, attr, initial, 0 ); -+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ { -+ event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -+ if (!event) -+ return STATUS_NO_MEMORY; -+ -+ event->obj.type = (type == NotificationEvent ? ESYNC_MANUAL_EVENT : ESYNC_AUTO_EVENT); -+ event->obj.fd = fd; -+ -+ add_to_list( *handle, &event->obj); -+ } -+ -+ return ret; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 8f7f9b030..32a259e39 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -24,6 +24,8 @@ extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; - extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 40bc619a2..6f0e72125 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -365,6 +365,9 @@ NTSTATUS WINAPI NtCreateEvent( PHANDLE EventHandle, ACCESS_MASK DesiredAccess, - data_size_t len; - struct object_attributes *objattr; - -+ if (do_esync()) -+ return esync_create_event( EventHandle, DesiredAccess, attr, type, InitialState ); -+ - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_event ) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch b/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch new file mode 100644 index 00000000..c73b035f --- /dev/null +++ b/patches/eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch @@ -0,0 +1,66 @@ +From cc0ae54c2b35967c6cebc1ec2f6c5058e7027185 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 | 3 +++ + 3 files changed, 19 insertions(+) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index e440e9baa4a..b8fb27edf38 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -316,6 +316,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 d9c7df967f8..b585af047ee 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 ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 51f77b1015f..60be9a0885a 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -486,6 +486,9 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) + { + NTSTATUS ret; + ++ if (do_esync()) ++ return esync_set_event( handle ); ++ + SERVER_START_REQ( event_op ) + { + req->handle = wine_server_obj_handle( handle ); +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch b/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch new file mode 100644 index 00000000..3c5b8c80 --- /dev/null +++ b/patches/eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch @@ -0,0 +1,66 @@ +From 333c6f445c9a0c2ef8b055e970e53b6c2b160ded 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 | 3 +++ + 3 files changed, 19 insertions(+) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index b8fb27edf38..97d468b2449 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -331,6 +331,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 b585af047ee..8480a213b2a 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 ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_reset_event( HANDLE handle ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + + 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 60be9a0885a..1d2e831964f 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -508,6 +508,9 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) + { + NTSTATUS ret; + ++ if (do_esync()) ++ return esync_reset_event( handle ); ++ + SERVER_START_REQ( event_op ) + { + req->handle = wine_server_obj_handle( handle ); +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0009-ntdll-Implement-NtSetEvent.patch b/patches/eventfd_synchronization/0009-ntdll-Implement-NtSetEvent.patch deleted file mode 100644 index 7edbb0db..00000000 --- a/patches/eventfd_synchronization/0009-ntdll-Implement-NtSetEvent.patch +++ /dev/null @@ -1,73 +0,0 @@ -From b3f22ae85154f22532b66362a2399592d755ce33 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 15:41:01 -0500 -Subject: [PATCH 09/83] ntdll: Implement NtSetEvent(). - ---- - dlls/ntdll/esync.c | 21 +++++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/sync.c | 4 ++++ - 3 files changed, 26 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index ace2f4a45..62c56af75 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -282,6 +282,27 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - return ret; - } - -+NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) -+{ -+ struct event *event = esync_get_object( handle ); -+ static const uint64_t value = 1; -+ -+ TRACE("%p.\n", handle); -+ -+ if (!event) return STATUS_INVALID_HANDLE; -+ -+ if (prev) -+ { -+ FIXME("Can't write previous value.\n"); -+ *prev = 1; -+ } -+ -+ if (write( event->obj.fd, &value, sizeof(value) ) == -1) -+ return FILE_GetNtStatus(); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 32a259e39..ba1c89665 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -26,6 +26,7 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 6f0e72125..1e1e381b4 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -417,6 +417,10 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - { - NTSTATUS ret; -+ -+ if (do_esync()) -+ return esync_set_event( handle, prev_state ); -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0010-ntdll-Implement-NtResetEvent.patch b/patches/eventfd_synchronization/0010-ntdll-Implement-NtResetEvent.patch deleted file mode 100644 index 0c0c8b60..00000000 --- a/patches/eventfd_synchronization/0010-ntdll-Implement-NtResetEvent.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 022deba562034611dccefaf2af504861e391fe7c Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 15:44:49 -0500 -Subject: [PATCH 10/83] ntdll: Implement NtResetEvent(). - ---- - dlls/ntdll/esync.c | 21 +++++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/sync.c | 4 ++++ - 3 files changed, 26 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 62c56af75..9e091819a 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -303,6 +303,27 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) -+{ -+ struct event *event = esync_get_object( handle ); -+ static uint64_t value; -+ -+ TRACE("%p.\n", handle); -+ -+ if (!event) return STATUS_INVALID_HANDLE; -+ -+ if (prev) -+ { -+ FIXME("Can't write previous value.\n"); -+ *prev = 1; -+ } -+ -+ /* we don't care about the return value */ -+ read( event->obj.fd, &value, sizeof(value) ); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index ba1c89665..8d2b4683e 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -27,6 +27,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 ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 1e1e381b4..4be641eb5 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -438,6 +438,10 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state ) - NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state ) - { - NTSTATUS ret; -+ -+ if (do_esync()) -+ return esync_reset_event( handle, prev_state ); -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0012-ntdll-Implement-waiting-on-events.patch b/patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch similarity index 63% rename from patches/eventfd_synchronization/0012-ntdll-Implement-waiting-on-events.patch rename to patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch index 48c7be4b..ea084c0b 100644 --- a/patches/eventfd_synchronization/0012-ntdll-Implement-waiting-on-events.patch +++ b/patches/eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch @@ -1,27 +1,26 @@ -From ba99a79e4ed4be4525e14aec71eaf52421580c32 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 15:55:39 -0500 -Subject: [PATCH 12/83] ntdll: Implement waiting on events. - -More specifically, implement waiting on manual-reset events. Auto-reset events already worked. +From f260254e168fbaad0321273037762e218eb6b7a6 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/esync.c | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) + dlls/ntdll/unix/esync.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 1055e11ae..7a384dc61 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -471,11 +471,23 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 97d468b2449..4f993689e0d 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -483,12 +483,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 (objs[i]->type == ESYNC_MANUAL_EVENT) ++ if (obj->type == ESYNC_MANUAL_EVENT) { - /* We found our object. */ - TRACE("Woken up by handle %p [%d].\n", handles[i], i); +- update_grabbed_object( obj ); - return i; + /* Don't grab the object, just check if it's signaled. */ + if (fds[i].revents & POLLIN) @@ -36,11 +35,12 @@ index 1055e11ae..7a384dc61 100644 + { + /* We found our object. */ + TRACE("Woken up by handle %p [%d].\n", handles[i], i); ++ update_grabbed_object( obj ); + return i; + } } } } -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0011-ntdll-Implement-NtPulseEvent.patch b/patches/eventfd_synchronization/0011-ntdll-Implement-NtPulseEvent.patch deleted file mode 100644 index 0444abaf..00000000 --- a/patches/eventfd_synchronization/0011-ntdll-Implement-NtPulseEvent.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 728fb6100bab81223baad2815878fccfe7fe17a6 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 15:47:16 -0500 -Subject: [PATCH 11/83] ntdll: Implement NtPulseEvent(). - ---- - dlls/ntdll/esync.c | 25 +++++++++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 29 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 9e091819a..1055e11ae 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -324,6 +324,31 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) -+{ -+ struct event *event = esync_get_object( handle ); -+ static uint64_t value = 1; -+ -+ TRACE("%p.\n", handle); -+ -+ if (!event) return STATUS_INVALID_HANDLE; -+ -+ if (prev) -+ { -+ FIXME("Can't write previous value.\n"); -+ *prev = 1; -+ } -+ -+ /* 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( event->obj.fd, &value, sizeof(value) ) == -1) -+ return FILE_GetNtStatus(); -+ read( event->obj.fd, &value, sizeof(value) ); -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 8d2b4683e..551257fbc 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -28,6 +28,7 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 4be641eb5..74b50cbc7 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -474,6 +474,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) - { - NTSTATUS ret; - -+ if (do_esync()) -+ return esync_pulse_event( handle, prev_state ); -+ - SERVER_START_REQ( event_op ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0013-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 similarity index 82% rename from patches/eventfd_synchronization/0013-server-Add-an-object-operation-to-grab-the-esync-fil.patch rename to patches/eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch index de481a4d..e09cf878 100644 --- a/patches/eventfd_synchronization/0013-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 @@ -1,4 +1,4 @@ -From 66e4235ff8436b648ad7db3e5163bb73bcc8b6e5 Mon Sep 17 00:00:00 2001 +From c5e2bf28d7a1ce4008a8b6173fd66b035a2010d3 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 @@ -11,7 +11,7 @@ Split off to decrease patch size. server/change.c | 1 + server/clipboard.c | 1 + server/completion.c | 1 + - server/console.c | 3 +++ + server/console.c | 5 +++++ server/debugger.c | 2 ++ server/device.c | 4 ++++ server/directory.c | 2 ++ @@ -21,7 +21,7 @@ Split off to decrease patch size. server/file.c | 1 + server/handle.c | 1 + server/hook.c | 1 + - server/mailslot.c | 3 +++ + server/mailslot.c | 4 ++++ server/mapping.c | 3 +++ server/mutex.c | 1 + server/named_pipe.c | 5 +++++ @@ -33,17 +33,16 @@ Split off to decrease patch size. server/semaphore.c | 1 + server/serial.c | 1 + server/signal.c | 1 + - server/snapshot.c | 1 + - server/sock.c | 2 ++ + server/sock.c | 3 +++ server/symlink.c | 1 + server/thread.c | 3 +++ server/timer.c | 1 + server/token.c | 1 + server/winstation.c | 2 ++ - 34 files changed, 62 insertions(+) + 33 files changed, 65 insertions(+) diff --git a/server/async.c b/server/async.c -index 03994e8fac2..cadd3563232 100644 +index 24fed811da2..1b4f86a1b8b 100644 --- a/server/async.c +++ b/server/async.c @@ -70,6 +70,7 @@ static const struct object_ops async_ops = @@ -54,7 +53,7 @@ index 03994e8fac2..cadd3563232 100644 async_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -483,6 +484,7 @@ static const struct object_ops iosb_ops = +@@ -484,6 +485,7 @@ static const struct object_ops iosb_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -63,7 +62,7 @@ index 03994e8fac2..cadd3563232 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/atom.c b/server/atom.c -index 57aff7b8918..a3b0d83f68d 100644 +index b61fa276661..73d858fef82 100644 --- a/server/atom.c +++ b/server/atom.c @@ -80,6 +80,7 @@ static const struct object_ops atom_table_ops = @@ -75,7 +74,7 @@ index 57aff7b8918..a3b0d83f68d 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/change.c b/server/change.c -index 6091d21f7f2..2be6a8360dd 100644 +index 8e4a272bc8b..a79b6d61939 100644 --- a/server/change.c +++ b/server/change.c @@ -115,6 +115,7 @@ static const struct object_ops dir_ops = @@ -87,7 +86,7 @@ index 6091d21f7f2..2be6a8360dd 100644 no_signal, /* signal */ dir_get_fd, /* get_fd */ diff --git a/server/clipboard.c b/server/clipboard.c -index e6884dd75fa..673aabbd080 100644 +index e4546832620..54a5fb683cc 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -77,6 +77,7 @@ static const struct object_ops clipboard_ops = @@ -99,7 +98,7 @@ index e6884dd75fa..673aabbd080 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/completion.c b/server/completion.c -index db04727b93b..4da2ed844aa 100644 +index 0bad4d7a260..176cf1b817e 100644 --- a/server/completion.c +++ b/server/completion.c @@ -64,6 +64,7 @@ static const struct object_ops completion_ops = @@ -111,10 +110,10 @@ index db04727b93b..4da2ed844aa 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/console.c b/server/console.c -index 5feb1c2ba7a..4100cb1c0ae 100644 +index d1e3cae8919..c0892b251c4 100644 --- a/server/console.c +++ b/server/console.c -@@ -84,6 +84,7 @@ static const struct object_ops console_input_ops = +@@ -80,6 +80,7 @@ static const struct object_ops console_input_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -122,15 +121,15 @@ index 5feb1c2ba7a..4100cb1c0ae 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ console_input_get_fd, /* get_fd */ -@@ -119,6 +120,7 @@ static const struct object_ops console_input_events_ops = +@@ -151,6 +152,7 @@ static const struct object_ops console_server_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ - console_input_events_signaled, /* signaled */ + console_server_signaled, /* signaled */ + NULL, /* get_esync_fd */ no_satisfied, /* satisfied */ no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -180,6 +182,7 @@ static const struct object_ops screen_buffer_ops = + console_server_get_fd, /* get_fd */ +@@ -218,6 +220,7 @@ static const struct object_ops screen_buffer_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -138,8 +137,24 @@ index 5feb1c2ba7a..4100cb1c0ae 100644 NULL, /* satisfied */ no_signal, /* signal */ screen_buffer_get_fd, /* get_fd */ +@@ -265,6 +268,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 */ +@@ -303,6 +307,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 401ce36a47a..ad581be8458 100644 +index e4a6c1e43a8..c37f97aa0b6 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -73,6 +73,7 @@ static const struct object_ops debug_event_ops = @@ -150,7 +165,7 @@ index 401ce36a47a..ad581be8458 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -100,6 +101,7 @@ static const struct object_ops debug_ctx_ops = +@@ -101,6 +102,7 @@ static const struct object_ops debug_ctx_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ debug_ctx_signaled, /* signaled */ @@ -159,7 +174,7 @@ index 401ce36a47a..ad581be8458 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/device.c b/server/device.c -index 01e08f295f7..368f6cf9c11 100644 +index 652da83e1e2..cc9aa2358a4 100644 --- a/server/device.c +++ b/server/device.c @@ -68,6 +68,7 @@ static const struct object_ops irp_call_ops = @@ -170,7 +185,7 @@ index 01e08f295f7..368f6cf9c11 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -107,6 +108,7 @@ static const struct object_ops device_manager_ops = +@@ -108,6 +109,7 @@ static const struct object_ops device_manager_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ device_manager_signaled, /* signaled */ @@ -178,7 +193,7 @@ index 01e08f295f7..368f6cf9c11 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -150,6 +152,7 @@ static const struct object_ops device_ops = +@@ -152,6 +154,7 @@ static const struct object_ops device_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -186,7 +201,7 @@ index 01e08f295f7..368f6cf9c11 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -199,6 +202,7 @@ static const struct object_ops device_file_ops = +@@ -203,6 +206,7 @@ static const struct object_ops device_file_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -195,7 +210,7 @@ index 01e08f295f7..368f6cf9c11 100644 no_signal, /* signal */ device_file_get_fd, /* get_fd */ diff --git a/server/directory.c b/server/directory.c -index 30cdd79b4a6..8083c686e11 100644 +index 6f8fb179808..faf41585ed8 100644 --- a/server/directory.c +++ b/server/directory.c @@ -57,6 +57,7 @@ static const struct object_ops object_type_ops = @@ -206,7 +221,7 @@ index 30cdd79b4a6..8083c686e11 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -93,6 +94,7 @@ static const struct object_ops directory_ops = +@@ -94,6 +95,7 @@ static const struct object_ops directory_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -215,10 +230,10 @@ index 30cdd79b4a6..8083c686e11 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/esync.c b/server/esync.c -index 147fb77247d..f3a139da48b 100644 +index b9e0a455629..d646cb52bc2 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -53,6 +53,7 @@ static const struct object_ops esync_ops = +@@ -124,6 +124,7 @@ static const struct object_ops esync_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -227,7 +242,7 @@ index 147fb77247d..f3a139da48b 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/event.c b/server/event.c -index d339d85aa45..84354bacbd2 100644 +index cba9472aa3d..06655fc7dd6 100644 --- a/server/event.c +++ b/server/event.c @@ -60,6 +60,7 @@ static const struct object_ops event_ops = @@ -238,7 +253,7 @@ index d339d85aa45..84354bacbd2 100644 event_satisfied, /* satisfied */ event_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -94,6 +95,7 @@ static const struct object_ops keyed_event_ops = +@@ -95,6 +96,7 @@ static const struct object_ops keyed_event_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ keyed_event_signaled, /* signaled */ @@ -247,10 +262,10 @@ index d339d85aa45..84354bacbd2 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/fd.c b/server/fd.c -index cc8df828a65..8e544ea95c1 100644 +index c3c53489212..d3b1e515b52 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -212,6 +212,7 @@ static const struct object_ops fd_ops = +@@ -216,6 +216,7 @@ static const struct object_ops fd_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -258,7 +273,7 @@ index cc8df828a65..8e544ea95c1 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -252,6 +253,7 @@ static const struct object_ops device_ops = +@@ -257,6 +258,7 @@ static const struct object_ops device_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -266,7 +281,7 @@ index cc8df828a65..8e544ea95c1 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -291,6 +293,7 @@ static const struct object_ops inode_ops = +@@ -297,6 +299,7 @@ static const struct object_ops inode_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -274,7 +289,7 @@ index cc8df828a65..8e544ea95c1 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -332,6 +335,7 @@ static const struct object_ops file_lock_ops = +@@ -339,6 +342,7 @@ static const struct object_ops file_lock_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ file_lock_signaled, /* signaled */ @@ -283,10 +298,10 @@ index cc8df828a65..8e544ea95c1 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/file.c b/server/file.c -index bce202138e0..8ab254d1abf 100644 +index 4690af2424e..2c0d24da21d 100644 --- a/server/file.c +++ b/server/file.c -@@ -86,6 +86,7 @@ static const struct object_ops file_ops = +@@ -85,6 +85,7 @@ static const struct object_ops file_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -295,7 +310,7 @@ index bce202138e0..8ab254d1abf 100644 no_signal, /* signal */ file_get_fd, /* get_fd */ diff --git a/server/handle.c b/server/handle.c -index a2a8bb5479c..6ca4489a828 100644 +index 15382256f10..2f123515c7c 100644 --- a/server/handle.c +++ b/server/handle.c @@ -123,6 +123,7 @@ static const struct object_ops handle_table_ops = @@ -307,7 +322,7 @@ index a2a8bb5479c..6ca4489a828 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/hook.c b/server/hook.c -index ec6be582482..f5d7639fd74 100644 +index 2a3da247313..61b5014c442 100644 --- a/server/hook.c +++ b/server/hook.c @@ -81,6 +81,7 @@ static const struct object_ops hook_table_ops = @@ -319,7 +334,7 @@ index ec6be582482..f5d7639fd74 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/mailslot.c b/server/mailslot.c -index 781e6f3141a..3523e18d8f6 100644 +index e0294d946e4..378c0bbb274 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -78,6 +78,7 @@ static const struct object_ops mailslot_ops = @@ -330,7 +345,7 @@ index 781e6f3141a..3523e18d8f6 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ mailslot_get_fd, /* get_fd */ -@@ -135,6 +136,7 @@ static const struct object_ops mail_writer_ops = +@@ -136,6 +137,7 @@ static const struct object_ops mail_writer_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -338,19 +353,27 @@ index 781e6f3141a..3523e18d8f6 100644 NULL, /* satisfied */ no_signal, /* signal */ mail_writer_get_fd, /* get_fd */ -@@ -193,6 +195,7 @@ static const struct object_ops mailslot_device_ops = +@@ -199,6 +201,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 */ - mailslot_device_get_fd, /* get_fd */ + no_get_fd, /* get_fd */ +@@ -229,6 +232,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 3d794bfaaf9..b19403b18f9 100644 +index 769a986ae21..37da37d6ab3 100644 --- a/server/mapping.c +++ b/server/mapping.c -@@ -91,6 +91,7 @@ static const struct object_ops ranges_ops = +@@ -68,6 +68,7 @@ static const struct object_ops ranges_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -358,7 +381,7 @@ index 3d794bfaaf9..b19403b18f9 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -126,6 +127,7 @@ static const struct object_ops shared_map_ops = +@@ -104,6 +105,7 @@ static const struct object_ops shared_map_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -366,7 +389,7 @@ index 3d794bfaaf9..b19403b18f9 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -182,6 +184,7 @@ static const struct object_ops mapping_ops = +@@ -162,6 +164,7 @@ static const struct object_ops mapping_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -375,7 +398,7 @@ index 3d794bfaaf9..b19403b18f9 100644 no_signal, /* signal */ mapping_get_fd, /* get_fd */ diff --git a/server/mutex.c b/server/mutex.c -index 8a8f7248eae..f5f969b3d6e 100644 +index 823ad54ffc3..fc236b3e623 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -61,6 +61,7 @@ static const struct object_ops mutex_ops = @@ -387,7 +410,7 @@ index 8a8f7248eae..f5f969b3d6e 100644 mutex_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/named_pipe.c b/server/named_pipe.c -index f97b1416415..d2ac7223b37 100644 +index 60bd059d93d..9ab99d915b9 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -118,6 +118,7 @@ static const struct object_ops named_pipe_ops = @@ -398,7 +421,7 @@ index f97b1416415..d2ac7223b37 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -160,6 +161,7 @@ static const struct object_ops pipe_server_ops = +@@ -162,6 +163,7 @@ static const struct object_ops pipe_server_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -406,7 +429,7 @@ index f97b1416415..d2ac7223b37 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ -@@ -202,6 +204,7 @@ static const struct object_ops pipe_client_ops = +@@ -205,6 +207,7 @@ static const struct object_ops pipe_client_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -414,7 +437,7 @@ index f97b1416415..d2ac7223b37 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ -@@ -248,6 +251,7 @@ static const struct object_ops named_pipe_device_ops = +@@ -252,6 +255,7 @@ static const struct object_ops named_pipe_device_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -422,7 +445,7 @@ index f97b1416415..d2ac7223b37 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -277,6 +281,7 @@ static const struct object_ops named_pipe_device_file_ops = +@@ -283,6 +287,7 @@ static const struct object_ops named_pipe_device_file_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -431,7 +454,7 @@ index f97b1416415..d2ac7223b37 100644 no_signal, /* signal */ named_pipe_device_file_get_fd, /* get_fd */ diff --git a/server/object.h b/server/object.h -index 3144eb56678..9299d844828 100644 +index 394a4aac463..10a049c8fb8 100644 --- a/server/object.h +++ b/server/object.h @@ -68,6 +68,8 @@ struct object_ops @@ -439,15 +462,15 @@ index 3144eb56678..9299d844828 100644 /* is object signaled? */ int (*signaled)(struct object *,struct wait_queue_entry *); + /* return the esync fd for this object */ -+ int (*get_esync_fd)(struct 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 2876bbfe67f..af370245c78 100644 +index 1786493a814..30699fbaeae 100644 --- a/server/process.c +++ b/server/process.c -@@ -77,6 +77,7 @@ static const struct object_ops process_ops = +@@ -78,6 +78,7 @@ static const struct object_ops process_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ process_signaled, /* signaled */ @@ -455,7 +478,7 @@ index 2876bbfe67f..af370245c78 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -127,6 +128,7 @@ static const struct object_ops startup_info_ops = +@@ -129,6 +130,7 @@ static const struct object_ops startup_info_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ startup_info_signaled, /* signaled */ @@ -463,7 +486,7 @@ index 2876bbfe67f..af370245c78 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -171,6 +173,7 @@ static const struct object_ops job_ops = +@@ -175,6 +177,7 @@ static const struct object_ops job_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ job_signaled, /* signaled */ @@ -472,10 +495,10 @@ index 2876bbfe67f..af370245c78 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/queue.c b/server/queue.c -index 05dd5059bc4..1fc1043a38b 100644 +index 7e7e6fbdf29..0ee2da59bcd 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -178,6 +178,7 @@ static const struct object_ops msg_queue_ops = +@@ -171,6 +171,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 */ @@ -483,7 +506,7 @@ index 05dd5059bc4..1fc1043a38b 100644 msg_queue_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -214,6 +215,7 @@ static const struct object_ops thread_input_ops = +@@ -208,6 +209,7 @@ static const struct object_ops thread_input_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -492,10 +515,10 @@ index 05dd5059bc4..1fc1043a38b 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/registry.c b/server/registry.c -index dcbb3f791e1..ec30b7b2355 100644 +index c937e051597..8110bbb340c 100644 --- a/server/registry.c +++ b/server/registry.c -@@ -159,6 +159,7 @@ static const struct object_ops key_ops = +@@ -160,6 +160,7 @@ static const struct object_ops key_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -504,7 +527,7 @@ index dcbb3f791e1..ec30b7b2355 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/request.c b/server/request.c -index 321bb6cfa81..4807ca9398f 100644 +index 97bf1a746d2..20b0ec309f3 100644 --- a/server/request.c +++ b/server/request.c @@ -96,6 +96,7 @@ static const struct object_ops master_socket_ops = @@ -516,7 +539,7 @@ index 321bb6cfa81..4807ca9398f 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/semaphore.c b/server/semaphore.c -index 6e2415fd79a..36e3e79e5d6 100644 +index cbcf4a4f942..ff94e42576b 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -58,6 +58,7 @@ static const struct object_ops semaphore_ops = @@ -528,7 +551,7 @@ index 6e2415fd79a..36e3e79e5d6 100644 semaphore_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/serial.c b/server/serial.c -index 4292472613a..2848e1dc795 100644 +index 30fe6e8380f..a50ace9903f 100644 --- a/server/serial.c +++ b/server/serial.c @@ -92,6 +92,7 @@ static const struct object_ops serial_ops = @@ -540,7 +563,7 @@ index 4292472613a..2848e1dc795 100644 no_signal, /* signal */ serial_get_fd, /* get_fd */ diff --git a/server/signal.c b/server/signal.c -index c81f6b8e989..ca200394f7e 100644 +index 7c2bf2cc154..b6d6dcfc4b6 100644 --- a/server/signal.c +++ b/server/signal.c @@ -67,6 +67,7 @@ static const struct object_ops handler_ops = @@ -551,23 +574,11 @@ index c81f6b8e989..ca200394f7e 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -diff --git a/server/snapshot.c b/server/snapshot.c -index 2b7438c00e0..7d0d742ee9e 100644 ---- a/server/snapshot.c -+++ b/server/snapshot.c -@@ -61,6 +61,7 @@ static const struct object_ops snapshot_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 5095a6ef9f0..4a10aaccf94 100644 +index 4f97fe72080..8898b66f7a5 100644 --- a/server/sock.c +++ b/server/sock.c -@@ -144,6 +144,7 @@ static const struct object_ops sock_ops = +@@ -172,6 +172,7 @@ static const struct object_ops sock_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ sock_signaled, /* signaled */ @@ -575,7 +586,7 @@ index 5095a6ef9f0..4a10aaccf94 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ sock_get_fd, /* get_fd */ -@@ -959,6 +960,7 @@ static const struct object_ops ifchange_ops = +@@ -1173,6 +1174,7 @@ static const struct object_ops ifchange_ops = add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -583,8 +594,16 @@ index 5095a6ef9f0..4a10aaccf94 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ ifchange_get_fd, /* get_fd */ +@@ -1393,6 +1395,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 e5ee09f015a..b4b6a44616e 100644 +index b620f2accb9..1f5ee0bf72b 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -60,6 +60,7 @@ static const struct object_ops symlink_ops = @@ -596,7 +615,7 @@ index e5ee09f015a..b4b6a44616e 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/thread.c b/server/thread.c -index e9918408f64..067037449be 100644 +index 6da77ad17a3..1bde63120ed 100644 --- a/server/thread.c +++ b/server/thread.c @@ -110,6 +110,7 @@ static const struct object_ops thread_apc_ops = @@ -607,7 +626,7 @@ index e9918408f64..067037449be 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -146,6 +147,7 @@ static const struct object_ops context_ops = +@@ -147,6 +148,7 @@ static const struct object_ops context_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ context_signaled, /* signaled */ @@ -615,7 +634,7 @@ index e9918408f64..067037449be 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -180,6 +182,7 @@ static const struct object_ops thread_ops = +@@ -182,6 +184,7 @@ static const struct object_ops thread_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ thread_signaled, /* signaled */ @@ -624,7 +643,7 @@ index e9918408f64..067037449be 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/timer.c b/server/timer.c -index 6460acbf519..8ce19c01177 100644 +index d4e5c56267c..319b9d142db 100644 --- a/server/timer.c +++ b/server/timer.c @@ -65,6 +65,7 @@ static const struct object_ops timer_ops = @@ -636,10 +655,10 @@ index 6460acbf519..8ce19c01177 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/token.c b/server/token.c -index 23bc1cc13f7..5e47d76ef40 100644 +index 30320851436..fafa86f292c 100644 --- a/server/token.c +++ b/server/token.c -@@ -150,6 +150,7 @@ static const struct object_ops token_ops = +@@ -147,6 +147,7 @@ static const struct object_ops token_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -648,7 +667,7 @@ index 23bc1cc13f7..5e47d76ef40 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ diff --git a/server/winstation.c b/server/winstation.c -index 43d112334d4..d7c1a8ca8bf 100644 +index c9c85e50fff..12060b82c83 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -64,6 +64,7 @@ static const struct object_ops winstation_ops = @@ -659,7 +678,7 @@ index 43d112334d4..d7c1a8ca8bf 100644 NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -88,6 +89,7 @@ static const struct object_ops desktop_ops = +@@ -89,6 +90,7 @@ static const struct object_ops desktop_ops = no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -668,5 +687,5 @@ index 43d112334d4..d7c1a8ca8bf 100644 no_signal, /* signal */ no_get_fd, /* get_fd */ -- -2.26.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0014-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 similarity index 55% rename from patches/eventfd_synchronization/0014-server-Add-a-request-to-get-the-eventfd-file-descrip.patch rename to patches/eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch index 66a1ba35..11ee26b0 100644 --- a/patches/eventfd_synchronization/0014-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 @@ -1,19 +1,19 @@ -From 74d7000943e1037303294332b415b0b4b5e8291c Mon Sep 17 00:00:00 2001 +From 193c44f510beed365640159cbdaeb0cb8186a7b0 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 8 Jun 2018 18:55:49 -0500 -Subject: [PATCH 14/83] server: Add a request to get the eventfd file - descriptor associated with a waitable handle. +Subject: [PATCH] server: Add a request to get the eventfd file descriptor + associated with a waitable handle. --- - server/esync.c | 28 ++++++++++++++++++++++++++++ - server/protocol.def | 6 ++++++ - 2 files changed, 34 insertions(+) + server/esync.c | 37 +++++++++++++++++++++++++++++++++++++ + server/protocol.def | 8 ++++++++ + 2 files changed, 45 insertions(+) diff --git a/server/esync.c b/server/esync.c -index f3a139da4..351da1a7c 100644 +index d646cb52bc2..cfbbcf55c48 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -136,3 +136,31 @@ DECL_HANDLER(create_esync) +@@ -335,3 +335,40 @@ DECL_HANDLER(create_esync) if (root) release_object( root ); } @@ -23,6 +23,7 @@ index f3a139da4..351da1a7c 100644 +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 ))) @@ -30,7 +31,15 @@ index f3a139da4..351da1a7c 100644 + + if (obj->ops->get_esync_fd) + { -+ fd = obj->ops->get_esync_fd( obj ); ++ 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 @@ -46,19 +55,21 @@ index f3a139da4..351da1a7c 100644 + release_object( obj ); +} diff --git a/server/protocol.def b/server/protocol.def -index a56f098ab..5f2d77bc7 100644 +index 552d504cc8d..9062a5020c2 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -4051,3 +4051,9 @@ struct handle_info - @REPLY - obj_handle_t handle; /* handle to the object */ +@@ -3689,3 +3689,11 @@ enum esync_type + int type; /* actual type (may be different for events) */ + 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 -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-process-o.patch b/patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch similarity index 56% rename from patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-process-o.patch rename to patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch index 533a255f..797a370e 100644 --- a/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-process-o.patch +++ b/patches/eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch @@ -1,43 +1,20 @@ -From e6e0ef574ce53d5b5e94068ae9dc137c2c7dee92 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 18:57:12 -0500 +From 05c4a58d8cc0fbafc760d3a0d4d6c14975e33fe2 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 | 33 +++++++++++++++++++++++++++++++++ - server/esync.h | 22 ++++++++++++++++++++++ - server/process.c | 17 ++++++++++++++++- + server/esync.c | 18 ++++++++++++++++++ + server/esync.h | 1 + + server/process.c | 16 +++++++++++++++- server/process.h | 1 + - 4 files changed, 72 insertions(+), 1 deletion(-) - create mode 100644 server/esync.h + 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/server/esync.c b/server/esync.c -index 351da1a7cb2..da26d27cbc8 100644 +index cfbbcf55c48..61513333bfd 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -35,6 +35,21 @@ - #include "handle.h" - #include "request.h" - #include "file.h" -+#include "esync.h" -+ -+int do_esync(void) -+{ -+#ifdef HAVE_SYS_EVENTFD_H -+ static int do_esync_cached = -1; -+ -+ if (do_esync_cached == -1) -+ do_esync_cached = (getenv("WINEESYNC") != NULL); -+ -+ return do_esync_cached; -+#else -+ return 0; -+#endif -+} - - struct esync - { -@@ -112,6 +127,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, +@@ -297,6 +297,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, #endif } @@ -63,38 +40,19 @@ index 351da1a7cb2..da26d27cbc8 100644 { struct esync *esync; diff --git a/server/esync.h b/server/esync.h -new file mode 100644 -index 00000000000..f93535b7b4c ---- /dev/null +index 7ca4ca89394..6a0a367124d 100644 +--- a/server/esync.h +++ b/server/esync.h -@@ -0,0 +1,22 @@ -+/* -+ * 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); +@@ -20,3 +20,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 c4cb041f293..ed03210a5f5 100644 +index 30699fbaeae..febfc0237c6 100644 --- a/server/process.c +++ b/server/process.c -@@ -48,6 +48,7 @@ +@@ -49,6 +49,7 @@ #include "request.h" #include "user.h" #include "security.h" @@ -102,15 +60,15 @@ index c4cb041f293..ed03210a5f5 100644 /* process structure */ -@@ -67,6 +68,7 @@ static struct security_descriptor *process_get_sd( struct object *obj ); +@@ -68,6 +69,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 ); ++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 = -@@ -77,7 +79,7 @@ static const struct object_ops process_ops = +@@ -78,7 +80,7 @@ static const struct object_ops process_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ process_signaled, /* signaled */ @@ -119,7 +77,7 @@ index c4cb041f293..ed03210a5f5 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -531,6 +533,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, +@@ -545,6 +547,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, process->trace_data = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; @@ -127,9 +85,9 @@ index c4cb041f293..ed03210a5f5 100644 list_init( &process->kernel_object ); list_init( &process->thread_list ); list_init( &process->locks ); -@@ -575,6 +578,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, - } - if (!process->handles || !process->token) goto error; +@@ -601,6 +604,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, + if (!token_assign_label( process->token, security_high_label_sid )) + goto error; + if (do_esync()) + process->esync_fd = esync_create_fd( 0, 0 ); @@ -137,23 +95,22 @@ index c4cb041f293..ed03210a5f5 100644 set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ return process; -@@ -623,6 +629,9 @@ static void process_destroy( struct object *obj ) +@@ -649,6 +655,7 @@ static void process_destroy( struct object *obj ) if (process->id) free_ptid( process->id ); if (process->token) release_object( process->token ); free( process->dir_cache ); -+ -+ if (do_esync()) -+ close( process->esync_fd ); ++ if (do_esync()) close( process->esync_fd ); } /* dump a process on stdout for debugging purposes */ -@@ -647,6 +656,12 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry +@@ -673,6 +680,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 ) ++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; +} + @@ -161,17 +118,17 @@ index c4cb041f293..ed03210a5f5 100644 { if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; diff --git a/server/process.h b/server/process.h -index 41267a27df5..02765f2f122 100644 +index 56092e5b1ac..eec69ddbcaf 100644 --- a/server/process.h +++ b/server/process.h -@@ -97,6 +97,7 @@ struct process +@@ -98,6 +98,7 @@ struct process const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */ const struct rawinput_device *rawinput_kbd; /* rawinput keyboard device, if any */ struct list kernel_object; /* list of kernel object pointers */ + int esync_fd; /* esync file descriptor (signaled on exit) */ }; - struct process_snapshot + #define CPU_FLAG(cpu) (1 << (cpu)) -- -2.20.1 +2.28.0 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 new file mode 100644 index 00000000..923a5712 --- /dev/null +++ b/patches/eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch @@ -0,0 +1,223 @@ +From 6f58d9519f2f2c440e6e64159a09f877a4a83c88 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/thread.c | 4 ++ + 4 files changed, 99 insertions(+), 6 deletions(-) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 4f993689e0d..6fd195df759 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -199,6 +199,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 ); +@@ -278,10 +344,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 +@@ -320,10 +387,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)); +@@ -335,10 +403,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)); +@@ -427,10 +496,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) +@@ -483,7 +555,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 61513333bfd..5f6e60ab24c 100644 +--- a/server/esync.c ++++ b/server/esync.c +@@ -315,6 +315,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 6a0a367124d..1e12560ddd6 100644 +--- a/server/esync.h ++++ b/server/esync.h +@@ -21,3 +21,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/thread.c b/server/thread.c +index 1bde63120ed..abe1bd44982 100644 +--- a/server/thread.c ++++ b/server/thread.c +@@ -51,6 +51,7 @@ + #include "request.h" + #include "user.h" + #include "security.h" ++#include "esync.h" + + + #ifdef __i386__ +@@ -1047,6 +1048,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.28.0 + diff --git a/patches/eventfd_synchronization/0017-server-Create-eventfd-file-descriptors-for-event-obj.patch b/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch similarity index 78% rename from patches/eventfd_synchronization/0017-server-Create-eventfd-file-descriptors-for-event-obj.patch rename to patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch index 44e1199b..4984973c 100644 --- a/patches/eventfd_synchronization/0017-server-Create-eventfd-file-descriptors-for-event-obj.patch +++ b/patches/eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch @@ -1,24 +1,22 @@ -From da31b19b8edb1c270fe3735ac2f5d54132c3007c Mon Sep 17 00:00:00 2001 +From 3ff6192702c06e77ef2e6790215ec3a40216052f Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 8 Jun 2018 21:01:24 -0500 -Subject: [PATCH 17/83] server: Create eventfd file descriptors for event - objects. +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 | 28 ++++++++++++++++++++++++++-- - 3 files changed, 35 insertions(+), 2 deletions(-) + server/event.c | 29 +++++++++++++++++++++++++++-- + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/server/esync.c b/server/esync.c -index 96bf6a57f..406c1a557 100644 +index 5f6e60ab24c..cb9bfba4463 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -161,6 +161,14 @@ void esync_wake_up( struct object *obj ) +@@ -331,6 +331,14 @@ void esync_wake_up( struct object *obj ) } } @@ -34,16 +32,16 @@ index 96bf6a57f..406c1a557 100644 { struct esync *esync; diff --git a/server/esync.h b/server/esync.h -index bbfe0aef8..054a77190 100644 +index 1e12560ddd6..fcbfd0989bb 100644 --- a/server/esync.h +++ b/server/esync.h -@@ -21,3 +21,4 @@ - extern int do_esync(void); +@@ -22,3 +22,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 f78c12d26..12724c581 100644 +index 06655fc7dd6..a416d214912 100644 --- a/server/event.c +++ b/server/event.c @@ -35,6 +35,7 @@ @@ -65,7 +63,7 @@ index f78c12d26..12724c581 100644 static struct object_type *event_get_type( struct object *obj ); static int event_signaled( struct object *obj, struct wait_queue_entry *entry ); static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); -+static int event_get_esync_fd( struct object *obj ); ++static int event_get_esync_fd( struct object *obj, enum esync_type *type ); static unsigned int event_map_access( struct object *obj, unsigned int access ); static int event_signal( struct object *obj, unsigned int access); static struct list *event_get_kernel_obj_list( struct object *obj ); @@ -82,7 +80,7 @@ index f78c12d26..12724c581 100644 event_satisfied, /* satisfied */ event_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -73,7 +77,7 @@ static const struct object_ops event_ops = +@@ -74,7 +78,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 */ @@ -91,7 +89,7 @@ index f78c12d26..12724c581 100644 }; -@@ -126,6 +130,9 @@ struct event *create_event( struct object *root, const struct unicode_str *name, +@@ -128,6 +132,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; @@ -101,7 +99,7 @@ index f78c12d26..12724c581 100644 } } return event; -@@ -154,6 +161,9 @@ void set_event( struct event *event ) +@@ -156,6 +163,9 @@ void set_event( struct event *event ) void reset_event( struct event *event ) { event->signaled = 0; @@ -111,20 +109,21 @@ index f78c12d26..12724c581 100644 } static void event_dump( struct object *obj, int verbose ) -@@ -177,6 +187,12 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) +@@ -180,6 +190,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 ) ++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; -@@ -214,6 +230,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) +@@ -217,6 +234,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj ) return &event->kernel_object; } @@ -140,5 +139,5 @@ index f78c12d26..12724c581 100644 unsigned int attr, const struct security_descriptor *sd ) { -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0016-ntdll-server-Implement-waiting-on-server-bound-objec.patch b/patches/eventfd_synchronization/0016-ntdll-server-Implement-waiting-on-server-bound-objec.patch deleted file mode 100644 index 7024feb7..00000000 --- a/patches/eventfd_synchronization/0016-ntdll-server-Implement-waiting-on-server-bound-objec.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 4f6cb6b5955df87982491aed1fd23e18051d095a Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 19:25:05 -0500 -Subject: [PATCH 16/83] 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/esync.c | 68 +++++++++++++++++++++++++++++++++++++++++++--- - server/esync.c | 16 +++++++++++ - server/esync.h | 1 + - server/thread.c | 4 +++ - 4 files changed, 85 insertions(+), 4 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 7a384dc61..23b03b23b 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -79,6 +79,7 @@ enum esync_type - ESYNC_SEMAPHORE = 1, - ESYNC_AUTO_EVENT, - ESYNC_MANUAL_EVENT, -+ ESYNC_MANUAL_SERVER, - }; - - struct esync -@@ -150,6 +151,63 @@ static void *esync_get_object( HANDLE handle ) - return esync_list[entry][idx]; - } - -+/* Gets a waitable 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_waitable_object( HANDLE handle, struct esync **obj ) -+{ -+ obj_handle_t fd_handle; -+ struct esync *esync; -+ sigset_t sigset; -+ NTSTATUS ret; -+ int fd; -+ -+ if ((*obj = esync_get_object( handle ))) return STATUS_SUCCESS; -+ -+ /* We need to try grabbing it from the server. */ -+ server_enter_uninterrupted_section( &fd_cache_section, &sigset ); -+ if (!(esync = esync_get_object( handle ))) -+ { -+ SERVER_START_REQ( get_esync_fd ) -+ { -+ req->handle = wine_server_obj_handle( handle ); -+ if (!(ret = wine_server_call( req ))) -+ { -+ fd = receive_fd( &fd_handle ); -+ assert( wine_server_ptr_handle(fd_handle) == handle ); -+ } -+ } -+ SERVER_END_REQ; -+ } -+ server_leave_uninterrupted_section( &fd_cache_section, &sigset ); -+ -+ if (esync) -+ { -+ /* We managed to grab it while in the CS; return it. */ -+ *obj = esync; -+ 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); -+ -+ esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -+ esync->fd = fd; -+ esync->type = ESYNC_MANUAL_SERVER; -+ -+ add_to_list( handle, esync ); -+ -+ *obj = esync; -+ return ret; -+} -+ - NTSTATUS esync_close( HANDLE handle ) - { - UINT_PTR entry, idx = handle_to_index( handle, &entry ); -@@ -410,11 +468,13 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - - for (i = 0; i < count; i++) - { -- objs[i] = esync_get_object( handles[i] ); -- if (objs[i]) -+ ret = get_waitable_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) -@@ -471,7 +531,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - int64_t value; - ssize_t size; - -- if (objs[i]->type == ESYNC_MANUAL_EVENT) -+ if (objs[i]->type == ESYNC_MANUAL_EVENT || objs[i]->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 da26d27cb..96bf6a57f 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -21,6 +21,7 @@ - #include "config.h" - #include "wine/port.h" - -+#include - #include - #include - #ifdef HAVE_SYS_EVENTFD_H -@@ -145,6 +146,21 @@ 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; -+ int fd; -+ -+ if (obj->ops->get_esync_fd) -+ { -+ fd = obj->ops->get_esync_fd( obj ); -+ -+ 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 f93535b7b..bbfe0aef8 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -20,3 +20,4 @@ - - extern int do_esync(void); - int esync_create_fd( int initval, int flags ); -+void esync_wake_up( struct object *obj ); -diff --git a/server/thread.c b/server/thread.c -index cf401f79b..ae00c89da 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -51,6 +51,7 @@ - #include "request.h" - #include "user.h" - #include "security.h" -+#include "esync.h" - - - #ifdef __i386__ -@@ -940,6 +941,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.20.1 - diff --git a/patches/eventfd_synchronization/0018-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 similarity index 84% rename from patches/eventfd_synchronization/0018-server-Allow-re-setting-esync-events-on-the-server-s.patch rename to patches/eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch index 305294d1..0d72660a 100644 --- a/patches/eventfd_synchronization/0018-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 @@ -1,8 +1,7 @@ -From 06935535827e6ce33ce77ae9c17165d4623b22ec Mon Sep 17 00:00:00 2001 +From 21ef43501fbef2d5ded6890932294b1160ccc810 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 8 Jun 2018 21:43:37 -0500 -Subject: [PATCH 18/83] server: Allow (re)setting esync events on the server - side. +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 @@ -11,7 +10,6 @@ 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 ++++++ @@ -19,10 +17,10 @@ so this is how we do it. 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/server/esync.c b/server/esync.c -index 406c1a557..4f7ff6bda 100644 +index cb9bfba4463..ddee22432e5 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -61,7 +61,7 @@ struct esync +@@ -116,7 +116,7 @@ struct esync static void esync_dump( struct object *obj, int verbose ); static void esync_destroy( struct object *obj ); @@ -31,7 +29,7 @@ index 406c1a557..4f7ff6bda 100644 { sizeof(struct esync), /* size */ esync_dump, /* dump */ -@@ -169,6 +169,26 @@ void esync_clear( int fd ) +@@ -339,6 +339,26 @@ void esync_clear( int fd ) read( fd, &value, sizeof(value) ); } @@ -59,10 +57,10 @@ index 406c1a557..4f7ff6bda 100644 { struct esync *esync; diff --git a/server/esync.h b/server/esync.h -index 054a77190..2687c72e4 100644 +index fcbfd0989bb..aeb58c5469c 100644 --- a/server/esync.h +++ b/server/esync.h -@@ -22,3 +22,9 @@ extern int do_esync(void); +@@ -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 ); @@ -73,10 +71,10 @@ index 054a77190..2687c72e4 100644 +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 12724c581..62d8bf7d3 100644 +index a416d214912..b6f989d4d6a 100644 --- a/server/event.c +++ b/server/event.c -@@ -140,6 +140,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name, +@@ -142,6 +142,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 ) { @@ -87,7 +85,7 @@ index 12724c581..62d8bf7d3 100644 return (struct event *)get_handle_obj( process, handle, access, &event_ops ); } -@@ -153,6 +157,12 @@ void pulse_event( struct event *event ) +@@ -155,6 +159,12 @@ void pulse_event( struct event *event ) void set_event( struct event *event ) { @@ -100,7 +98,7 @@ index 12724c581..62d8bf7d3 100644 event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ wake_up( &event->obj, !event->manual_reset ); -@@ -160,6 +170,11 @@ void set_event( struct event *event ) +@@ -162,6 +172,11 @@ void set_event( struct event *event ) void reset_event( struct event *event ) { @@ -113,5 +111,5 @@ index 12724c581..62d8bf7d3 100644 if (do_esync()) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0019-ntdll-Try-again-if-poll-returns-EINTR.patch b/patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch similarity index 79% rename from patches/eventfd_synchronization/0019-ntdll-Try-again-if-poll-returns-EINTR.patch rename to patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch index 1312eebb..00198a56 100644 --- a/patches/eventfd_synchronization/0019-ntdll-Try-again-if-poll-returns-EINTR.patch +++ b/patches/eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch @@ -1,7 +1,7 @@ -From fe2e94200cfb6a88e82b9261f2d8a05a6fae0cbe Mon Sep 17 00:00:00 2001 +From 07f3e8af59a9083ecd5abe31a48670a18dac2e84 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 8 Jun 2018 21:58:37 -0500 -Subject: [PATCH 19/83] ntdll: Try again if poll() returns EINTR. +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* @@ -11,16 +11,15 @@ should just keep on waiting. Besides, we could be suspended for reasons other than to deliver a system APC. - --- - dlls/ntdll/esync.c | 32 +++++++++++++++++++++----------- + dlls/ntdll/unix/esync.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 23b03b23b..0655ab779 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -423,22 +423,32 @@ static LONGLONG update_timeout( ULONGLONG end ) +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 ) { @@ -63,7 +62,7 @@ index 23b03b23b..0655ab779 100644 + return ret; } - /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we + static void update_grabbed_object( struct esync *obj ) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-thread-ob.patch b/patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch similarity index 78% rename from patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-thread-ob.patch rename to patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch index bd3bc4c3..f2d1f3d8 100644 --- a/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-thread-ob.patch +++ b/patches/eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch @@ -1,26 +1,26 @@ -From 5209675d0aac52f20b5af95ef39f85f000b79434 Mon Sep 17 00:00:00 2001 +From 3d3cd983add6183a0e38c427d15895c331a2b666 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 | 16 +++++++++++++++- + server/thread.c | 17 ++++++++++++++++- server/thread.h | 1 + - 2 files changed, 16 insertions(+), 1 deletion(-) + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/server/thread.c b/server/thread.c -index dd94522a2b9..5c52cca0923 100644 +index 785203b7fa6..b52a1f5048c 100644 --- a/server/thread.c +++ b/server/thread.c -@@ -133,6 +133,7 @@ static const struct object_ops thread_apc_ops = +@@ -172,6 +172,7 @@ static const struct object_ops context_ops = static void dump_thread( struct object *obj, int verbose ); static struct object_type *thread_get_type( struct object *obj ); static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static int thread_get_esync_fd( struct object *obj ); ++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 ); -@@ -146,7 +147,7 @@ static const struct object_ops thread_ops = +@@ -185,7 +186,7 @@ static const struct object_ops thread_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ thread_signaled, /* signaled */ @@ -29,7 +29,7 @@ index dd94522a2b9..5c52cca0923 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -185,6 +186,7 @@ static inline void init_thread_structure( struct thread *thread ) +@@ -225,6 +226,7 @@ static inline void init_thread_structure( struct thread *thread ) thread->context = NULL; thread->teb = 0; thread->entry_point = 0; @@ -37,7 +37,7 @@ index dd94522a2b9..5c52cca0923 100644 thread->debug_ctx = NULL; thread->system_regs = 0; thread->queue = NULL; -@@ -293,6 +295,9 @@ struct thread *create_thread( int fd, struct process *process, const struct secu +@@ -361,6 +363,9 @@ struct thread *create_thread( int fd, struct process *process, const struct secu return NULL; } @@ -47,7 +47,7 @@ index dd94522a2b9..5c52cca0923 100644 set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */ add_process_thread( thread->process, thread ); return thread; -@@ -373,6 +378,9 @@ static void destroy_thread( struct object *obj ) +@@ -441,6 +446,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 ); @@ -57,13 +57,14 @@ index dd94522a2b9..5c52cca0923 100644 } /* dump a thread on stdout for debugging purposes */ -@@ -398,6 +406,12 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) +@@ -466,6 +474,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 ) ++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; +} + @@ -71,7 +72,7 @@ index dd94522a2b9..5c52cca0923 100644 { if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT; diff --git a/server/thread.h b/server/thread.h -index 8029d65df44..21b303aa20a 100644 +index 78ca4c201b2..faffe13d795 100644 --- a/server/thread.h +++ b/server/thread.h @@ -54,6 +54,7 @@ struct thread @@ -83,5 +84,5 @@ index 8029d65df44..21b303aa20a 100644 unsigned int system_regs; /* which system regs have been set */ struct msg_queue *queue; /* message queue */ -- -2.26.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0021-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch b/patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch similarity index 75% rename from patches/eventfd_synchronization/0021-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch rename to patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch index c6f2120f..f503b1d6 100644 --- a/patches/eventfd_synchronization/0021-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch +++ b/patches/eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch @@ -1,20 +1,19 @@ -From 57dfceffa275576dd721d18702a231d495e8a611 Mon Sep 17 00:00:00 2001 +From 2cb70cc63fe4352ba6b6d813b1b386a210754d02 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 8 Jun 2018 23:30:17 -0500 -Subject: [PATCH 21/83] rpcrt4: Avoid closing the server thread handle while it - is being waited on. +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 91de3b95f..af79dc56c 100644 +index 12260b7298b..a7cad5e273f 100644 --- a/dlls/rpcrt4/rpc_server.c +++ b/dlls/rpcrt4/rpc_server.c -@@ -702,10 +702,6 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) +@@ -699,10 +699,6 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) } LeaveCriticalSection(&cps->cs); @@ -25,7 +24,7 @@ index 91de3b95f..af79dc56c 100644 TRACE("done\n"); return 0; } -@@ -1573,7 +1569,10 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) +@@ -1570,7 +1566,10 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) { if ((wait_thread = protseq->server_thread)) @@ -36,7 +35,7 @@ index 91de3b95f..af79dc56c 100644 } LeaveCriticalSection(&server_cs); if (!wait_thread) -@@ -1582,6 +1581,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) +@@ -1579,6 +1578,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) TRACE("waiting for thread %u\n", GetThreadId(wait_thread)); LeaveCriticalSection(&listen_cs); WaitForSingleObject(wait_thread, INFINITE); @@ -45,5 +44,5 @@ index 91de3b95f..af79dc56c 100644 } if (listen_done_event == event) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0022-server-Create-eventfd-file-descriptors-for-message-q.patch b/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch similarity index 53% rename from patches/eventfd_synchronization/0022-server-Create-eventfd-file-descriptors-for-message-q.patch rename to patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch index 2139dc23..922b0fd0 100644 --- a/patches/eventfd_synchronization/0022-server-Create-eventfd-file-descriptors-for-message-q.patch +++ b/patches/eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch @@ -1,18 +1,14 @@ -From 6e75c09ce0d31bd7c8aec3129d0f9d2fe711b412 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 8 Jun 2018 23:41:54 -0500 -Subject: [PATCH 22/83] server: Create eventfd file descriptors for message - queues. - -Note that we don't have to worry about races here, because a thread can only -check its own queue. +From 1aac9111b536d35eec696e20141b6c5d6d92579b 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 | 24 +++++++++++++++++++++++- - 1 file changed, 23 insertions(+), 1 deletion(-) + server/queue.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/server/queue.c b/server/queue.c -index 3817ce543..0ea95291c 100644 +index 263bb46ea00..4d416a88d88 100644 --- a/server/queue.c +++ b/server/queue.c @@ -43,6 +43,7 @@ @@ -23,23 +19,23 @@ index 3817ce543..0ea95291c 100644 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST)) -@@ -124,6 +125,7 @@ struct msg_queue - struct object obj; /* object header */ - struct thread *thread; /* reference to the thread owning the queue */ - struct fd *fd; /* optional file descriptor to poll */ +@@ -141,6 +142,7 @@ struct msg_queue + struct hook_table *hooks; /* hook table */ + timeout_t last_get_msg; /* time of last get message call */ + unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */ + int esync_fd; /* esync file descriptor (signalled on message) */ - unsigned int wake_bits; /* wakeup bits */ - unsigned int wake_mask; /* wakeup mask */ - unsigned int changed_bits; /* changed wakeup bits */ -@@ -163,6 +165,7 @@ static void msg_queue_dump( struct object *obj, int verbose ); + }; + + struct hotkey +@@ -157,6 +159,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 ); ++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 ); -@@ -178,7 +181,7 @@ static const struct object_ops msg_queue_ops = +@@ -172,7 +175,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 */ @@ -48,15 +44,14 @@ index 3817ce543..0ea95291c 100644 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_ - if ((queue = alloc_object( &msg_queue_ops ))) - { - queue->fd = NULL; +@@ -309,12 +312,16 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ + queue->hooks = NULL; + queue->last_get_msg = current_time; + queue->ignore_post_msg = 0; + queue->esync_fd = -1; - queue->thread = thread; - queue->wake_bits = 0; - queue->wake_mask = 0; -@@ -341,6 +345,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ + list_init( &queue->send_result ); + list_init( &queue->callback_result ); + list_init( &queue->pending_timers ); list_init( &queue->expired_timers ); for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] ); @@ -65,41 +60,32 @@ index 3817ce543..0ea95291c 100644 + thread->queue = queue; } - if (new_input) -@@ -517,6 +524,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits + if (new_input) release_object( new_input ); +@@ -491,6 +498,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits + { queue->wake_bits &= ~bits; queue->changed_bits &= ~bits; - update_shm_queue_bits( queue ); + + if (do_esync() && !is_signaled( queue )) + esync_clear( queue->esync_fd ); } /* check whether msg is a keyboard message */ -@@ -1030,6 +1040,12 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr +@@ -1004,6 +1014,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 ) ++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; -@@ -1075,6 +1091,9 @@ static void msg_queue_destroy( struct object *obj ) - release_object( queue->input ); - if (queue->hooks) release_object( queue->hooks ); - if (queue->fd) release_object( queue->fd ); -+ -+ if (do_esync()) -+ close( queue->esync_fd ); - } - - static void msg_queue_poll_event( struct fd *fd, int event ) -@@ -2350,6 +2369,9 @@ DECL_HANDLER(get_queue_status) +@@ -2381,6 +2398,9 @@ DECL_HANDLER(get_queue_status) reply->wake_bits = queue->wake_bits; reply->changed_bits = queue->changed_bits; queue->changed_bits &= ~req->clear_bits; @@ -110,5 +96,5 @@ index 3817ce543..0ea95291c 100644 else reply->wake_bits = reply->changed_bits = 0; } -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch b/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch new file mode 100644 index 00000000..f226f4d3 --- /dev/null +++ b/patches/eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch @@ -0,0 +1,172 @@ +From df50f6973c1fa60db18b408001ac50c03fb2fa07 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 | 5 ++++ + server/queue.c | 21 +++++++++++++++++ + 3 files changed, 75 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index fcbe563bb5a..88490e08ef9 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -482,12 +482,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; +@@ -515,6 +516,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) +@@ -526,6 +530,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 +@@ -565,7 +572,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) +@@ -610,6 +619,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 9062a5020c2..789bc56e7f1 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -3697,3 +3697,8 @@ enum esync_type + int type; + unsigned int shm_idx; + @END ++ ++/* Notify the server that we are doing a message wait or done with one. */ ++@REQ(esync_msgwait) ++ int in_msgwait; /* are we in a message wait? */ ++@END +diff --git a/server/queue.c b/server/queue.c +index 4d416a88d88..efaf8a0f7e7 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -143,6 +143,7 @@ struct msg_queue + timeout_t last_get_msg; /* time of last get message call */ + 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 +@@ -313,6 +314,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ + queue->last_get_msg = current_time; + 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 ); +@@ -959,6 +961,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; + } + +@@ -3385,3 +3391,18 @@ DECL_HANDLER(get_rawinput_devices) + devices[i++] = e->device; + } + } ++ ++DECL_HANDLER(esync_msgwait) ++{ ++ struct msg_queue *queue = get_current_queue(); ++ ++ if (!queue) return; ++ queue->esync_in_msgwait = req->in_msgwait; ++ ++ if (current->process->idle_event && !(queue->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 ); ++} +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0025-server-Create-eventfd-descriptors-for-device-manager.patch b/patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch similarity index 87% rename from patches/eventfd_synchronization/0025-server-Create-eventfd-descriptors-for-device-manager.patch rename to patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch index c0ce3392..189f7c03 100644 --- a/patches/eventfd_synchronization/0025-server-Create-eventfd-descriptors-for-device-manager.patch +++ b/patches/eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch @@ -1,4 +1,4 @@ -From 5eddf968dfe301274c53a11f1f4d28e8b77fdb87 Mon Sep 17 00:00:00 2001 +From 2053200985a44de70df5b6024177927b64689954 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 @@ -15,7 +15,7 @@ Drives tab. 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/server/device.c b/server/device.c -index a6bfa06eb..5f82daa73 100644 +index cc9aa2358a4..b8ce131c732 100644 --- a/server/device.c +++ b/server/device.c @@ -39,6 +39,7 @@ @@ -26,7 +26,7 @@ index a6bfa06eb..5f82daa73 100644 /* IRP object */ -@@ -92,10 +93,12 @@ struct device_manager +@@ -95,10 +96,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 */ @@ -39,7 +39,7 @@ index a6bfa06eb..5f82daa73 100644 static void device_manager_destroy( struct object *obj ); static const struct object_ops device_manager_ops = -@@ -106,7 +109,7 @@ static const struct object_ops device_manager_ops = +@@ -109,7 +112,7 @@ static const struct object_ops device_manager_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ device_manager_signaled, /* signaled */ @@ -48,7 +48,7 @@ index a6bfa06eb..5f82daa73 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -694,6 +697,9 @@ static void delete_file( struct device_file *file ) +@@ -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 ) { @@ -58,7 +58,7 @@ index a6bfa06eb..5f82daa73 100644 list_remove( &irp->mgr_entry ); set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); } -@@ -726,6 +732,13 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry +@@ -786,6 +792,13 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry return !list_empty( &manager->requests ); } @@ -72,7 +72,7 @@ index a6bfa06eb..5f82daa73 100644 static void device_manager_destroy( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; -@@ -760,6 +773,9 @@ static void device_manager_destroy( struct object *obj ) +@@ -820,6 +833,9 @@ static void device_manager_destroy( struct object *obj ) assert( !irp->file && !irp->async ); release_object( irp ); } @@ -82,7 +82,7 @@ index a6bfa06eb..5f82daa73 100644 } static struct device_manager *create_device_manager(void) -@@ -772,6 +788,9 @@ 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 ); @@ -92,7 +92,7 @@ index a6bfa06eb..5f82daa73 100644 } return manager; } -@@ -930,6 +949,9 @@ DECL_HANDLER(get_next_device_request) +@@ -997,6 +1016,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; @@ -103,5 +103,5 @@ index a6bfa06eb..5f82daa73 100644 else close_handle( current->process, reply->next ); } -- -2.21.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch b/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch new file mode 100644 index 00000000..4595048e --- /dev/null +++ b/patches/eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch @@ -0,0 +1,109 @@ +From 8770d44fb2cdaf01cfd74321712b3b63a2906e31 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 | 3 +++ + server/esync.c | 14 ++++++++++++++ + 4 files changed, 36 insertions(+) + +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 88490e08ef9..df9eb2696a1 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -91,6 +91,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; +@@ -415,6 +422,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 8480a213b2a..38ebefc9eed 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 ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + ++extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, ++ const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; ++ + extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; + +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 1d2e831964f..56292db271a 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -597,6 +597,9 @@ NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT + data_size_t len; + struct object_attributes *objattr; + ++ 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 ddee22432e5..12911fccb6a 100644 +--- a/server/esync.c ++++ b/server/esync.c +@@ -204,6 +204,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; +@@ -274,6 +281,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.28.0 + diff --git a/patches/eventfd_synchronization/0023-ntdll-wineandroid.drv-winemac.drv-winex11.drv-Store-.patch b/patches/eventfd_synchronization/0023-ntdll-wineandroid.drv-winemac.drv-winex11.drv-Store-.patch deleted file mode 100644 index 0e0e1e1f..00000000 --- a/patches/eventfd_synchronization/0023-ntdll-wineandroid.drv-winemac.drv-winex11.drv-Store-.patch +++ /dev/null @@ -1,147 +0,0 @@ -From ad744b5d30474d7f46bf69dcdf829aa75b813879 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 12 Jun 2018 10:01:08 -0500 -Subject: [PATCH] ntdll, wineandroid.drv, winemac.drv, winex11.drv: Store the - thread's queue fd in ntdll. - -I originally had esync grab it from the server in order to avoid touching the USER drivers, but this doesn't really work since we might perform a MsgWait before ever doing any operations which might initialize the USER driver's thread data. Doing it this way also has the advantage that we won't use extra file descriptors. - -In any case I haven't bothered to guard this code with do_esync(); it'd require adding that function to each USER driver and it's pretty obvious it's not going to affect anything if esync is disabled. ---- - dlls/ntdll/esync.c | 6 ++++++ - dlls/ntdll/ntdll.spec | 2 ++ - dlls/ntdll/ntdll_misc.h | 1 + - dlls/ntdll/thread.c | 2 ++ - dlls/wineandroid.drv/window.c | 3 +++ - dlls/winemac.drv/macdrv_main.c | 3 +++ - dlls/winex11.drv/x11drv_main.c | 3 +++ - 7 files changed, 20 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index ea7517d3f1d2..94838d322132 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -74,6 +74,12 @@ int do_esync(void) - #endif - } - -+/* Entry point for drivers to set queue fd. */ -+void __wine_esync_set_queue_fd( int fd ) -+{ -+ ntdll_get_thread_data()->esync_queue_fd = fd; -+} -+ - enum esync_type - { - ESYNC_SEMAPHORE = 1, -diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 44a65711c908..c24d4c807348 100644 ---- a/dlls/ntdll/ntdll.spec -+++ b/dlls/ntdll/ntdll.spec -@@ -1567,6 +1567,8 @@ - # All functions must be prefixed with '__wine_' (for internal functions) - # or 'wine_' (for user-visible functions) to avoid namespace conflicts. - -+@ cdecl __wine_esync_set_queue_fd(long) -+ - # Server interface - @ cdecl -norelay wine_server_call(ptr) - @ cdecl wine_server_close_fds_by_type(long) -diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index dd5db3f18f32..e9262de93da9 100644 ---- a/dlls/ntdll/ntdll_misc.h -+++ b/dlls/ntdll/ntdll_misc.h -@@ -267,6 +267,7 @@ struct debug_info - struct ntdll_thread_data - { - struct debug_info *debug_info; /* info for debugstr functions */ -+ int esync_queue_fd;/* fd to wait on for driver events */ - void *start_stack; /* stack for thread startup */ - int request_fd; /* fd for sending server requests */ - int reply_fd; /* fd for receiving server replies */ -diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c -index 0bc3971508fd..a3dd918fdf58 100644 ---- a/dlls/ntdll/thread.c -+++ b/dlls/ntdll/thread.c -@@ -438,6 +438,7 @@ TEB *thread_init(void) - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; -+ thread_data->esync_queue_fd = -1; - - unix_funcs->dbg_init(); - unix_funcs->get_paths( &build_dir, &data_dir, &config_dir ); -@@ -745,6 +746,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle_ptr, ACCESS_MASK access, OBJECT - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; - thread_data->start_stack = (char *)teb->Tib.StackBase; -+ thread_data->esync_queue_fd = -1; - - pthread_attr_init( &pthread_attr ); - pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, -diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c -index c1e7b000a8f3..d96f001432d4 100644 ---- a/dlls/wineandroid.drv/window.c -+++ b/dlls/wineandroid.drv/window.c -@@ -364,6 +364,8 @@ jboolean motion_event( JNIEnv *env, jobject obj, jint win, jint action, jint x, - } - - -+extern void __wine_esync_set_queue_fd( int fd ); -+ - /*********************************************************************** - * init_event_queue - */ -@@ -377,6 +379,7 @@ static void init_event_queue(void) - ERR( "could not create data\n" ); - ExitProcess(1); - } -+ __wine_esync_set_queue_fd( event_pipe[0] ); - if (wine_server_fd_to_handle( event_pipe[0], GENERIC_READ | SYNCHRONIZE, 0, &handle )) - { - ERR( "Can't allocate handle for event fd\n" ); -diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c -index 694a46b11e64..64b8d69b16de 100644 ---- a/dlls/winemac.drv/macdrv_main.c -+++ b/dlls/winemac.drv/macdrv_main.c -@@ -323,6 +323,7 @@ void CDECL macdrv_ThreadDetach(void) - } - } - -+extern void __wine_esync_set_queue_fd( int fd ); - - /*********************************************************************** - * set_queue_display_fd -@@ -334,6 +335,8 @@ static void set_queue_display_fd(int fd) - HANDLE handle; - int ret; - -+ __wine_esync_set_queue_fd(fd); -+ - if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle)) - { - MESSAGE("macdrv: Can't allocate handle for event queue fd\n"); -diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c -index 4eaedd1c5567..323b71534ace 100644 ---- a/dlls/winex11.drv/x11drv_main.c -+++ b/dlls/winex11.drv/x11drv_main.c -@@ -643,6 +643,7 @@ void CDECL X11DRV_ThreadDetach(void) - } - } - -+extern void __wine_esync_set_queue_fd( int fd ); - - /* store the display fd into the message queue */ - static void set_queue_display_fd( Display *display ) -@@ -650,6 +651,8 @@ static void set_queue_display_fd( Display *display ) - HANDLE handle; - int ret; - -+ __wine_esync_set_queue_fd( ConnectionNumber(display) ); -+ - if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle )) - { - MESSAGE( "x11drv: Can't allocate handle for display fd\n" ); --- -2.26.2 - diff --git a/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch b/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch new file mode 100644 index 00000000..ca8319d5 --- /dev/null +++ b/patches/eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch @@ -0,0 +1,85 @@ +From 5b4a4557f47415d9a78185a3be8b0a9d7d6bdc33 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 df9eb2696a1..48482a31ea2 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -431,6 +431,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 38ebefc9eed..e69c46ca462 100644 +--- a/dlls/ntdll/unix/esync.h ++++ b/dlls/ntdll/unix/esync.h +@@ -33,6 +33,7 @@ extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 56292db271a..1a19bb78a9c 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -648,6 +648,9 @@ NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count ) + { + NTSTATUS ret; + ++ if (do_esync()) ++ return esync_release_mutex( handle, prev_count ); ++ + SERVER_START_REQ( release_mutex ) + { + req->handle = wine_server_obj_handle( handle ); +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0024-server-ntdll-Also-wait-on-the-queue-fd-when-waiting-.patch b/patches/eventfd_synchronization/0024-server-ntdll-Also-wait-on-the-queue-fd-when-waiting-.patch deleted file mode 100644 index 3fef9600..00000000 --- a/patches/eventfd_synchronization/0024-server-ntdll-Also-wait-on-the-queue-fd-when-waiting-.patch +++ /dev/null @@ -1,312 +0,0 @@ -From 91c96ca57892577e20be532ae58b423fea1750b2 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 14:44:54 -0500 -Subject: [PATCH] server, ntdll: Also wait on the queue fd when waiting for - driver events. - -Normally the server handles this, by polling on the fd during its main loop. -The problem there is that the server only polls when the thread is waiting -for messages. We want to replicate that behaviour, otherwise wineserver spins -forever trying to wake up a thread that just doesn't care. - -With this patch, I'm finally able to interact with winecfg. Next step is to -fix the 'drives' tab. ---- - dlls/ntdll/esync.c | 44 ++++++++++++++++++++++++++++++++------------ - server/esync.c | 7 +++++-- - server/event.c | 5 +++-- - server/object.h | 2 +- - server/process.c | 5 +++-- - server/protocol.def | 10 ++++++++++ - server/queue.c | 5 +++-- - server/thread.c | 5 +++-- - 8 files changed, 60 insertions(+), 23 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 5d8dbac2df4..dcb7801d912 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -80,17 +80,9 @@ void __wine_esync_set_queue_fd( int fd ) - ntdll_get_thread_data()->esync_queue_fd = fd; - } - --enum esync_type --{ -- ESYNC_SEMAPHORE = 1, -- ESYNC_AUTO_EVENT, -- ESYNC_MANUAL_EVENT, -- ESYNC_MANUAL_SERVER, --}; -- - struct esync - { -- enum esync_type type; -+ enum esync_type type; /* defined in protocol.def */ - int fd; - }; - -@@ -164,6 +156,7 @@ static void *esync_get_object( HANDLE handle ) - static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - { - obj_handle_t fd_handle; -+ enum esync_type type; - struct esync *esync; - sigset_t sigset; - NTSTATUS ret; -@@ -180,6 +173,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - req->handle = wine_server_obj_handle( handle ); - if (!(ret = wine_server_call( req ))) - { -+ type = reply->type; - fd = receive_fd( &fd_handle ); - assert( wine_server_ptr_handle(fd_handle) == handle ); - } -@@ -206,7 +200,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - - esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); - esync->fd = fd; -- esync->type = ESYNC_MANUAL_SERVER; -+ esync->type = type; - - add_to_list( handle, esync ); - -@@ -463,8 +457,10 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - BOOLEAN alertable, const LARGE_INTEGER *timeout ) - { - 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; -+ DWORD pollcount = count; -+ BOOL msgwait = FALSE; - LONGLONG timeleft; - LARGE_INTEGER now; - ULONGLONG end; -@@ -493,6 +489,15 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - return ret; - } - -+ if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE) -+ { -+ /* Last object in the list is a queue, which means someone is using -+ * MsgWaitForMultipleObjects(). We have to wait not only for the server -+ * fd (signaled on send_message, etc.) but also the USER driver's fd -+ * (signaled on e.g. X11 events.) */ -+ msgwait = TRUE; -+ } -+ - if (has_esync && has_server) - { - FIXME("Can't wait on esync and server objects at the same time!\n"); -@@ -510,6 +515,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 (fd %d)", ntdll_get_thread_data()->esync_queue_fd); -+ - if (!timeout) - TRACE(", timeout = INFINITE.\n"); - else -@@ -527,10 +535,16 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - fds[i].fd = objs[i] ? objs[i]->fd : -1; - fds[i].events = POLLIN; - } -+ if (msgwait) -+ { -+ fds[count].fd = ntdll_get_thread_data()->esync_queue_fd; -+ fds[count].events = POLLIN; -+ pollcount++; -+ } - - while (1) - { -- ret = do_poll( fds, count, timeout ? &end : NULL ); -+ ret = do_poll( fds, pollcount, timeout ? &end : NULL ); - if (ret > 0) - { - /* Find out which object triggered the wait. */ -@@ -568,6 +582,12 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - } - } - -+ if (msgwait && (fds[count].revents & POLLIN)) -+ { -+ TRACE("Woken up by driver events.\n"); -+ return count - 1; -+ } -+ - /* If we got here, someone else stole (or reset, etc.) whatever - * we were waiting for. So keep waiting. */ - NtQuerySystemTime( &now ); -diff --git a/server/esync.c b/server/esync.c -index 4f7ff6bdaed..1f8c0d5167a 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -150,11 +150,12 @@ int esync_create_fd( int initval, int flags ) - 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 ); -+ fd = obj->ops->get_esync_fd( obj, &dummy ); - - if (write( fd, &value, sizeof(value) ) == -1) - perror( "esync: write" ); -@@ -219,6 +220,7 @@ DECL_HANDLER(create_esync) - 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 ))) -@@ -226,7 +228,8 @@ DECL_HANDLER(get_esync_fd) - - if (obj->ops->get_esync_fd) - { -- fd = obj->ops->get_esync_fd( obj ); -+ fd = obj->ops->get_esync_fd( obj, &type ); -+ reply->type = type; - send_client_fd( current->process, fd, req->handle ); - } - else -diff --git a/server/event.c b/server/event.c -index d2f9e378cb1..79287e7edc0 100644 ---- a/server/event.c -+++ b/server/event.c -@@ -50,7 +50,7 @@ static void event_dump( struct object *obj, int verbose ); - static struct object_type *event_get_type( struct object *obj ); - static int event_signaled( struct object *obj, struct wait_queue_entry *entry ); - static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); --static int event_get_esync_fd( struct object *obj ); -+static int event_get_esync_fd( struct object *obj, enum esync_type *type ); - static unsigned int event_map_access( struct object *obj, unsigned int access ); - static int event_signal( struct object *obj, unsigned int access); - static struct list *event_get_kernel_obj_list( struct object *obj ); -@@ -203,9 +203,10 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) - return event->signaled; - } - --static int event_get_esync_fd( struct object *obj ) -+static int event_get_esync_fd( struct object *obj, enum esync_type *type ) - { - struct event *event = (struct event *)obj; -+ *type = ESYNC_MANUAL_SERVER; /* all server-created events are manual-reset */ - return event->esync_fd; - } - -diff --git a/server/object.h b/server/object.h -index ee0f1f776e3..ca5a191f975 100644 ---- a/server/object.h -+++ b/server/object.h -@@ -69,7 +69,7 @@ struct object_ops - /* is object signaled? */ - int (*signaled)(struct object *,struct wait_queue_entry *); - /* return the esync fd for this object */ -- int (*get_esync_fd)(struct 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 ed03210a5f5..7fdbfb98cae 100644 ---- a/server/process.c -+++ b/server/process.c -@@ -68,7 +68,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 ); -+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 = -@@ -656,9 +656,10 @@ 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 ) -+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; - } - -diff --git a/server/protocol.def b/server/protocol.def -index 7a383590c55..7644a25b8ec 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4011,4 +4011,14 @@ struct handle_info - @REQ(get_esync_fd) - obj_handle_t handle; /* handle to the object */ - @REPLY -+ int type; /* esync type (defined below) */ - @END -+ -+enum esync_type -+{ -+ ESYNC_SEMAPHORE = 1, -+ ESYNC_AUTO_EVENT, -+ ESYNC_MANUAL_EVENT, -+ ESYNC_MANUAL_SERVER, -+ ESYNC_QUEUE, -+}; -diff --git a/server/queue.c b/server/queue.c -index 0ea95291c34..91de4a3a85f 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -165,7 +165,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 ); -+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 ); -@@ -1040,9 +1040,10 @@ 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 ) -+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; - } - -diff --git a/server/thread.c b/server/thread.c -index 83781f0d712..ae2112486b2 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -133,7 +133,7 @@ static const struct object_ops thread_apc_ops = - static void dump_thread( struct object *obj, int verbose ); - static struct object_type *thread_get_type( struct object *obj ); - static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ); --static int thread_get_esync_fd( struct object *obj ); -+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 ); -@@ -405,9 +405,10 @@ 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 ) -+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; - } - --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch b/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch new file mode 100644 index 00000000..ccacbbc7 --- /dev/null +++ b/patches/eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch @@ -0,0 +1,61 @@ +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-Create-esync-objects-for-mutexes.patch b/patches/eventfd_synchronization/0026-ntdll-Create-esync-objects-for-mutexes.patch deleted file mode 100644 index aa59b0f4..00000000 --- a/patches/eventfd_synchronization/0026-ntdll-Create-esync-objects-for-mutexes.patch +++ /dev/null @@ -1,111 +0,0 @@ -From c6654c5479568c9bc5d5d64457c3cfbbf1c27f70 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 15:48:46 -0500 -Subject: [PATCH 26/83] ntdll: Create esync objects for mutexes. - ---- - dlls/ntdll/esync.c | 39 +++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - server/protocol.def | 1 + - 4 files changed, 45 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 4d708c6df..0798786df 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -97,6 +97,13 @@ struct event - struct esync obj; - }; - -+struct mutex -+{ -+ struct esync obj; -+ DWORD tid; -+ int count; /* recursion count */ -+}; -+ - /* 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. */ - -@@ -407,6 +414,38 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) -+{ -+ struct mutex *mutex; -+ NTSTATUS ret; -+ int fd; -+ -+ TRACE("name %s, initial %d.\n", -+ attr ? debugstr_us(attr->ObjectName) : "", initial); -+ -+ ret = create_esync( &fd, handle, access, attr, initial ? 0 : 1, 0 ); -+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ { -+ mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -+ if (!mutex) -+ return STATUS_NO_MEMORY; -+ -+ /* can't take ownership of the mutex if we didn't create it */ -+ if (ret == STATUS_OBJECT_NAME_EXISTS) -+ initial = FALSE; -+ -+ mutex->obj.type = ESYNC_MUTEX; -+ mutex->obj.fd = fd; -+ mutex->tid = initial ? GetCurrentThreadId() : 0; -+ mutex->count = initial ? 1 : 0; -+ -+ add_to_list( *handle, &mutex->obj); -+ } -+ -+ return ret; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 551257fbc..7af718027 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -29,6 +29,8 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 74b50cbc7..f6e507c2f 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -540,6 +540,9 @@ NTSTATUS WINAPI NtCreateMutant(OUT HANDLE* MutantHandle, - data_size_t len; - struct object_attributes *objattr; - -+ if (do_esync()) -+ return esync_create_mutex( MutantHandle, access, attr, InitialOwner ); -+ - if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; - - SERVER_START_REQ( create_mutex ) -diff --git a/server/protocol.def b/server/protocol.def -index cebe0e88e..721ffb96d 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4064,6 +4064,7 @@ enum esync_type - ESYNC_SEMAPHORE = 1, - ESYNC_AUTO_EVENT, - ESYNC_MANUAL_EVENT, -+ ESYNC_MUTEX, - ESYNC_MANUAL_SERVER, - ESYNC_QUEUE, - }; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0029-ntdll-Implement-wait-all.patch b/patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch similarity index 68% rename from patches/eventfd_synchronization/0029-ntdll-Implement-wait-all.patch rename to patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch index 952d3c6e..3bc9b230 100644 --- a/patches/eventfd_synchronization/0029-ntdll-Implement-wait-all.patch +++ b/patches/eventfd_synchronization/0026-ntdll-Implement-wait-all.patch @@ -1,44 +1,38 @@ -From 54a92fb487e2b3529974513a88de821edd4970f3 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 20:21:00 -0500 -Subject: [PATCH 29/83] ntdll: Implement wait-all. +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. -Most of the comments I would put here are covered in the code. I will just -amend: - -Mutexes are extremely annoying. Microsoft should never have let you grab a -mutex more than once. --- - dlls/ntdll/esync.c | 162 +++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 149 insertions(+), 13 deletions(-) + dlls/ntdll/unix/esync.c | 142 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 129 insertions(+), 13 deletions(-) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 79d9c2e46..1eab7367f 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -534,8 +534,10 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an +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; - int ret; -- int i; ++ int i, j, ret; NtQuerySystemTime( &now ); if (timeout) -@@ -648,9 +650,6 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an +@@ -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) - { - /* Don't grab the object, just check if it's signaled. */ -@@ -688,21 +687,158 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an + 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 ); } @@ -86,7 +80,7 @@ index 79d9c2e46..1eab7367f 100644 + if (obj && obj->type == ESYNC_MUTEX) + { + /* It might be ours. */ -+ struct mutex *mutex = (struct mutex *)obj; ++ struct mutex *mutex = obj->shm; + + if (mutex->tid == GetCurrentThreadId()) + continue; @@ -104,38 +98,23 @@ index 79d9c2e46..1eab7367f 100644 } - else + -+ /* Don't forget to wait for driver messages. */ -+ if (msgwait) - { -- ERR("ppoll failed: %s\n", strerror(errno)); -- return FILE_GetNtStatus(); -+ fds[0].fd = ntdll_get_thread_data()->esync_queue_fd; -+ ret = do_poll( fds, 1, timeout ? &end : NULL ); -+ if (ret <= 0) -+ goto err; - } -- } -+ + /* 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; -+ } -+ if (msgwait) -+ { -+ fds[count].fd = ntdll_get_thread_data()->esync_queue_fd; -+ fds[count].events = POLLIN; -+ pollcount++; -+ } + } +- } + + /* Poll everything to see if they're still signaled. */ -+ ret = poll( fds, pollcount, 0 ); -+ if (ret == pollcount) ++ ret = poll( fds, count, 0 ); ++ if (ret == count) + { + /* Quick, grab everything. */ -+ for (i = 0; i < pollcount; i++) ++ for (i = 0; i < count; i++) + { + struct esync *obj = objs[i]; + @@ -143,7 +122,7 @@ index 79d9c2e46..1eab7367f 100644 + { + case ESYNC_MUTEX: + { -+ struct mutex *mutex = (struct mutex *)obj; ++ struct mutex *mutex = obj->shm; + if (mutex->tid == GetCurrentThreadId()) + break; + /* otherwise fall through */ @@ -157,7 +136,7 @@ index 79d9c2e46..1eab7367f 100644 + for (j = i; j >= 0; j--) + { + if (write( obj->fd, &value, sizeof(value) ) == -1) -+ return FILE_GetNtStatus(); ++ return errno_to_status( errno ); + } + + goto tryagain; /* break out of two loops and a switch */ @@ -171,16 +150,11 @@ index 79d9c2e46..1eab7367f 100644 + } + + /* If we got here, we successfully waited on every object. */ -+ /* Make sure to let ourselves know that we grabbed the mutexes. */ ++ /* Make sure to let ourselves know that we grabbed the mutexes ++ * and semaphores. */ + for (i = 0; i < count; i++) -+ { -+ if (objs[i]->type == ESYNC_MUTEX) -+ { -+ struct mutex *mutex = (struct mutex *)objs[i]; -+ mutex->tid = GetCurrentThreadId(); -+ mutex->count++; -+ } -+ } ++ update_grabbed_object( objs[i] ); ++ + TRACE("Wait successful.\n"); + return STATUS_SUCCESS; + } @@ -203,9 +177,10 @@ index 79d9c2e46..1eab7367f 100644 - FIXME("Wait-all not implemented.\n"); - return STATUS_NOT_IMPLEMENTED; + ERR("ppoll failed: %s\n", strerror(errno)); -+ return FILE_GetNtStatus(); ++ return errno_to_status( errno ); } } + -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0030-esync-Add-a-README.patch b/patches/eventfd_synchronization/0027-esync-Add-a-README.patch similarity index 98% rename from patches/eventfd_synchronization/0030-esync-Add-a-README.patch rename to patches/eventfd_synchronization/0027-esync-Add-a-README.patch index 99ee4e9b..94920f13 100644 --- a/patches/eventfd_synchronization/0030-esync-Add-a-README.patch +++ b/patches/eventfd_synchronization/0027-esync-Add-a-README.patch @@ -1,7 +1,7 @@ -From e5a2557a4de8eee42b216dfd89d2ef4ea980fb14 Mon Sep 17 00:00:00 2001 +From bc9c29c1264f10d9de28dbfdd088c3da022be715 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sat, 9 Jun 2018 22:44:57 -0500 -Subject: [PATCH 30/83] esync: Add a README. +Subject: [PATCH] esync: Add a README. --- README.esync | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -10,7 +10,7 @@ Subject: [PATCH 30/83] esync: Add a README. diff --git a/README.esync b/README.esync new file mode 100644 -index 000000000..8fcb96901 +index 00000000000..8fcb969011b --- /dev/null +++ b/README.esync @@ -0,0 +1,184 @@ @@ -200,5 +200,5 @@ index 000000000..8fcb96901 +--Zebediah Figura \ No newline at end of file -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0027-ntdll-Implement-NtReleaseMutant.patch b/patches/eventfd_synchronization/0027-ntdll-Implement-NtReleaseMutant.patch deleted file mode 100644 index 1771802b..00000000 --- a/patches/eventfd_synchronization/0027-ntdll-Implement-NtReleaseMutant.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 26522cb866aa9d615a537195138fda6c24b43154 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 15:57:48 -0500 -Subject: [PATCH 27/83] ntdll: Implement NtReleaseMutant(). - ---- - dlls/ntdll/esync.c | 31 +++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 1 + - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 35 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 0798786df..640625813 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -446,6 +446,37 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - return ret; - } - -+NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) -+{ -+ struct mutex *mutex = esync_get_object( handle ); -+ static const uint64_t value = 1; -+ -+ TRACE("%p, %p.\n", handle, prev); -+ -+ if (!mutex) return STATUS_INVALID_HANDLE; -+ -+ /* 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( mutex->obj.fd, &value, sizeof(value) ) == -1) -+ return FILE_GetNtStatus(); -+ } -+ -+ return STATUS_SUCCESS; -+} -+ - #define TICKSPERSEC 10000000 - #define TICKSPERMSEC 10000 - -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 7af718027..47ab7815d 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -31,6 +31,7 @@ extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index f6e507c2f..3bc8fab8f 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -591,6 +591,9 @@ NTSTATUS WINAPI NtReleaseMutant( IN HANDLE handle, OUT PLONG prev_count OPTIONAL - { - NTSTATUS status; - -+ if (do_esync()) -+ return esync_release_mutex( handle, prev_count ); -+ - SERVER_START_REQ( release_mutex ) - { - req->handle = wine_server_obj_handle( handle ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch b/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch new file mode 100644 index 00000000..6f46a7af --- /dev/null +++ b/patches/eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch @@ -0,0 +1,80 @@ +From 69a95eb896feed92ce839162b83b79701d02cdcd 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 0682428372c..6d8653cd107 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -850,6 +850,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 e69c46ca462..bee08ff857f 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 ) DECLSPEC_HIDDE + + extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, + BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, ++ const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; + + + /* 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 1a19bb78a9c..64f96a32ccf 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -1320,6 +1320,9 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, + select_op_t 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.28.0 + diff --git a/patches/eventfd_synchronization/0028-ntdll-Implement-waiting-on-mutexes.patch b/patches/eventfd_synchronization/0028-ntdll-Implement-waiting-on-mutexes.patch deleted file mode 100644 index 0b8ecc5e..00000000 --- a/patches/eventfd_synchronization/0028-ntdll-Implement-waiting-on-mutexes.patch +++ /dev/null @@ -1,79 +0,0 @@ -From c811c73edf608b6c4120770a5dc34d99d39bde5d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 16:05:02 -0500 -Subject: [PATCH 28/83] ntdll: Implement waiting on mutexes. - ---- - dlls/ntdll/esync.c | 32 +++++++++++++++++++++++++++++--- - 1 file changed, 29 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 640625813..79d9c2e46 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -602,7 +602,25 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - { - 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; - } - if (msgwait) -@@ -620,18 +638,20 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - /* 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 (objs[i]) -+ if (obj) - { - int64_t value; - ssize_t size; - -- if (objs[i]->type == ESYNC_MANUAL_EVENT || objs[i]->type == ESYNC_MANUAL_SERVER) -+ 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) -@@ -646,6 +666,12 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - { - /* We found our object. */ - TRACE("Woken up by handle %p [%d].\n", handles[i], i); -+ if (obj->type == ESYNC_MUTEX) -+ { -+ struct mutex *mutex = (struct mutex *)obj; -+ mutex->tid = GetCurrentThreadId(); -+ mutex->count = 1; -+ } - return i; - } - } --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0033-ntdll-server-Implement-NtOpenSemaphore.patch b/patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch similarity index 52% rename from patches/eventfd_synchronization/0033-ntdll-server-Implement-NtOpenSemaphore.patch rename to patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch index 4dbff8ad..643498b8 100644 --- a/patches/eventfd_synchronization/0033-ntdll-server-Implement-NtOpenSemaphore.patch +++ b/patches/eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch @@ -1,126 +1,113 @@ -From 730ad81287cfb42dae5f4dd070cc0ea6979d5c54 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 00:29:27 -0500 -Subject: [PATCH 33/83] ntdll, server: Implement NtOpenSemaphore(). +From a934f314a164256748e2e9764343504f7cf8050b 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/esync.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - server/esync.c | 30 +++++++++++++++++++++++ - server/protocol.def | 12 +++++++++ - 5 files changed, 107 insertions(+) + dlls/ntdll/unix/esync.c | 47 +++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/unix/esync.h | 2 ++ + dlls/ntdll/unix/sync.c | 3 +++ + server/esync.c | 31 +++++++++++++++++++++++++++ + server/protocol.def | 12 +++++++++++ + 5 files changed, 95 insertions(+) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 2b4555959..f014003fc 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -276,6 +276,37 @@ static NTSTATUS create_esync(enum esync_type *type, int *fd, HANDLE *handle, +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index 6d8653cd107..8e7e50ce777 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -336,6 +336,45 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK return ret; } -+static NTSTATUS open_esync( enum esync_type *type, int *fd, HANDLE *handle, ++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_section, &sigset ); ++ 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; ++ 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; -+ *fd = receive_fd( &fd_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_section, &sigset ); ++ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + -+ TRACE("-> handle %p, fd %d.\n", *handle, *fd); ++ 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; +} + - NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) { -@@ -304,6 +335,35 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - return ret; +@@ -345,6 +384,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 ) +{ -+ enum esync_type type = ESYNC_SEMAPHORE; -+ struct semaphore *semaphore; -+ NTSTATUS ret; -+ int fd = -1; -+ + TRACE("name %s.\n", debugstr_us(attr->ObjectName)); + -+ ret = open_esync( &type, &fd, handle, access, attr ); -+ if (!ret) -+ { -+ semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -+ if (!semaphore) -+ return STATUS_NO_MEMORY; -+ -+ semaphore->obj.type = ESYNC_SEMAPHORE; -+ semaphore->obj.fd = fd; -+ -+ FIXME("Attempt to open a semaphore, this will not work.\n"); -+ semaphore->max = 0xdeadbeef; -+ -+ add_to_list( *handle, &semaphore->obj ); -+ } -+ -+ return ret; ++ return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); +} + NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) { - struct semaphore *semaphore = esync_get_object( handle ); -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index ebf5c97c2..b0d756ec1 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -32,6 +32,8 @@ extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; + struct esync *obj; +diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h +index bee08ff857f..2738e8b7f87 100644 +--- a/dlls/ntdll/unix/esync.h ++++ b/dlls/ntdll/unix/esync.h +@@ -24,6 +24,8 @@ extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN; +extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 2f54bb4a1..3b902e669 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -279,6 +279,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC - - if ((ret = validate_open_object_attributes( attr ))) return ret; + 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 64f96a32ccf..35f2ac95d36 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -349,6 +349,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC + { + NTSTATUS ret; + if (do_esync()) + return esync_open_semaphore( handle, access, attr ); + + if ((ret = validate_open_object_attributes( attr ))) return ret; + SERVER_START_REQ( open_semaphore ) - { - req->access = access; diff --git a/server/esync.c b/server/esync.c -index 9ff1a847b..1f9602a43 100644 +index 12911fccb6a..1703608263f 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -235,6 +235,36 @@ DECL_HANDLER(create_esync) +@@ -412,6 +412,37 @@ DECL_HANDLER(create_esync) if (root) release_object( root ); } @@ -148,6 +135,7 @@ index 9ff1a847b..1f9602a43 100644 + } + + reply->type = esync->type; ++ reply->shm_idx = esync->shm_idx; + + send_client_fd( current->process, esync->fd, reply->handle ); + release_object( esync ); @@ -158,14 +146,13 @@ index 9ff1a847b..1f9602a43 100644 * 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 50735ee78..7dbd0a6db 100644 +index 789bc56e7f1..5b8f66ffd80 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -4054,6 +4054,18 @@ struct handle_info - int type; /* type of esync object (see below) */ +@@ -3690,6 +3690,18 @@ enum esync_type + unsigned int shm_idx; @END -+/* Open an esync object */ +@REQ(open_esync) + unsigned int access; /* wanted access rights */ + unsigned int attributes; /* object attributes */ @@ -175,11 +162,12 @@ index 50735ee78..7dbd0a6db 100644 +@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.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch b/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch new file mode 100644 index 00000000..a3f2d9ef --- /dev/null +++ b/patches/eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch @@ -0,0 +1,60 @@ +From 9898e1c47bdba4bda336b9c17a20d34d68e66215 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 8e7e50ce777..a03a3a09b36 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -437,6 +437,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 2738e8b7f87..da1b72d4413 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 ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, ++ const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_reset_event( HANDLE handle ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 35f2ac95d36..9296b172f88 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -467,6 +467,9 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT + + 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.28.0 + diff --git a/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch b/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch new file mode 100644 index 00000000..32a49ca2 --- /dev/null +++ b/patches/eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch @@ -0,0 +1,60 @@ +From 7f91f35e896ffb63409c1d1a619565f35a65ef7f 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 a03a3a09b36..d1a282c65e9 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -486,6 +486,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 da1b72d4413..cb48e2cd022 100644 +--- a/dlls/ntdll/unix/esync.h ++++ b/dlls/ntdll/unix/esync.h +@@ -37,6 +37,8 @@ extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + + extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, ++ const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; + + 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 9296b172f88..4a97cdd32fd 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -632,6 +632,9 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A + + 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.28.0 + diff --git a/patches/eventfd_synchronization/0031-ntdll-Implement-NtSignalAndWaitForSingleObject.patch b/patches/eventfd_synchronization/0031-ntdll-Implement-NtSignalAndWaitForSingleObject.patch deleted file mode 100644 index 447a53d8..00000000 --- a/patches/eventfd_synchronization/0031-ntdll-Implement-NtSignalAndWaitForSingleObject.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 41213edda4d5f04455c1b02561899bdebc5cf8e1 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 9 Jun 2018 23:34:27 -0500 -Subject: [PATCH 31/83] ntdll: Implement NtSignalAndWaitForSingleObject(). - ---- - dlls/ntdll/esync.c | 28 ++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 33 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 1eab7367f..130357ce6 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -842,3 +842,31 @@ err: - return FILE_GetNtStatus(); - } - } -+ -+NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -+ const LARGE_INTEGER *timeout ) -+{ -+ struct esync *obj = esync_get_object( signal ); -+ NTSTATUS ret; -+ -+ if (!obj) return STATUS_INVALID_HANDLE; -+ -+ 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, NULL ); -+ 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 ); -+} -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 47ab7815d..ebf5c97c2 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -35,6 +35,8 @@ extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDE - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; - - - /* We have to synchronize on the fd cache CS so that our calls to receive_fd -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 3bc8fab8f..2f54bb4a1 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -1152,6 +1152,9 @@ NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWa - select_op_t select_op; - UINT flags = SELECT_INTERRUPTIBLE; - -+ if (do_esync()) -+ return esync_signal_and_wait( hSignalObject, hWaitObject, alertable, timeout ); -+ - if (!hSignalObject) return STATUS_INVALID_HANDLE; - - if (alertable) flags |= SELECT_ALERTABLE; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0037-server-Implement-esync_map_access.patch b/patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch similarity index 80% rename from patches/eventfd_synchronization/0037-server-Implement-esync_map_access.patch rename to patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch index df8c7901..8c443920 100644 --- a/patches/eventfd_synchronization/0037-server-Implement-esync_map_access.patch +++ b/patches/eventfd_synchronization/0032-server-Implement-esync_map_access.patch @@ -1,17 +1,17 @@ -From 9bd148fedb51a9fc6672b64c7a9f2346c45cb458 Mon Sep 17 00:00:00 2001 +From 161ae4c64b5e3bd33771671f518c482a6a66700b Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 10 Jun 2018 19:08:18 -0500 -Subject: [PATCH 37/83] server: Implement esync_map_access(). +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 1f9602a43..62e6df30b 100644 +index 1703608263f..20f149cdad3 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -60,6 +60,7 @@ struct esync +@@ -114,6 +114,7 @@ struct esync }; static void esync_dump( struct object *obj, int verbose ); @@ -19,7 +19,7 @@ index 1f9602a43..62e6df30b 100644 static void esync_destroy( struct object *obj ); const struct object_ops esync_ops = -@@ -74,7 +75,7 @@ const struct object_ops esync_ops = +@@ -128,7 +129,7 @@ const struct object_ops esync_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ @@ -27,8 +27,8 @@ index 1f9602a43..62e6df30b 100644 + esync_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ - no_lookup_name, /* lookup_name */ -@@ -93,6 +94,16 @@ static void esync_dump( struct object *obj, int verbose ) + default_get_full_name, /* get_full_name */ +@@ -148,6 +149,16 @@ static void esync_dump( struct object *obj, int verbose ) fprintf( stderr, "esync fd=%d\n", esync->fd ); } @@ -46,5 +46,5 @@ index 1f9602a43..62e6df30b 100644 { struct esync *esync = (struct esync *)obj; -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0032-server-ntdll-Also-store-the-esync-type-in-the-server.patch b/patches/eventfd_synchronization/0032-server-ntdll-Also-store-the-esync-type-in-the-server.patch deleted file mode 100644 index fed4f30b..00000000 --- a/patches/eventfd_synchronization/0032-server-ntdll-Also-store-the-esync-type-in-the-server.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 4d40a736740ec865c3beee3cfa321477a1faca49 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 16:11:54 -0500 -Subject: [PATCH 32/83] server, ntdll: Also store the esync type in the server. - -And validate it there while we're at it. - -We need to do this because CreateEvent() ignores the passed-in parameter -when opening an existing event. ---- - dlls/ntdll/esync.c | 23 +++++++++++++++-------- - server/esync.c | 28 ++++++++++++++++++++++++---- - server/protocol.def | 2 ++ - 3 files changed, 41 insertions(+), 12 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 130357ce6..2b4555959 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -235,8 +235,10 @@ NTSTATUS esync_close( HANDLE handle ) - return STATUS_INVALID_HANDLE; - } - --static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, int initval, int flags) -+/* type is an in-out parameter; if the object already existed it returns the -+ * actual type. */ -+static NTSTATUS create_esync(enum esync_type *type, int *fd, HANDLE *handle, -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags) - { - NTSTATUS ret; - data_size_t len; -@@ -254,11 +256,13 @@ static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, - req->access = access; - req->initval = initval; - req->flags = flags; -+ req->type = *type; - 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; - *fd = receive_fd( &fd_handle ); - assert( wine_server_ptr_handle(fd_handle) == *handle ); - } -@@ -275,6 +279,7 @@ static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access, - NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) - { -+ enum esync_type type = ESYNC_SEMAPHORE; - struct semaphore *semaphore; - NTSTATUS ret; - int fd = -1; -@@ -282,7 +287,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - TRACE("name %s, initial %d, max %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial, max); - -- ret = create_esync( &fd, handle, access, attr, initial, EFD_SEMAPHORE ); -+ ret = create_esync( &type, &fd, handle, access, attr, initial, EFD_SEMAPHORE ); - if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) - { - semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -@@ -321,24 +326,25 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - } - - NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, -- const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) -+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE event_type, BOOLEAN initial ) - { -+ enum esync_type type = (event_type == SynchronizationEvent ? ESYNC_AUTO_EVENT : ESYNC_MANUAL_EVENT); - struct event *event; - NTSTATUS ret; - int fd; - - TRACE("name %s, %s-reset, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", -- type == NotificationEvent ? "manual" : "auto", initial); -+ event_type == NotificationEvent ? "manual" : "auto", initial); - -- ret = create_esync( &fd, handle, access, attr, initial, 0 ); -+ ret = create_esync( &type, &fd, handle, access, attr, initial, 0 ); - if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) - { - event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); - if (!event) - return STATUS_NO_MEMORY; - -- event->obj.type = (type == NotificationEvent ? ESYNC_MANUAL_EVENT : ESYNC_AUTO_EVENT); -+ event->obj.type = type; /* note that the server might give us the real type */ - event->obj.fd = fd; - - add_to_list( *handle, &event->obj); -@@ -417,6 +423,7 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) - { -+ enum esync_type type = ESYNC_MUTEX; - struct mutex *mutex; - NTSTATUS ret; - int fd; -@@ -424,7 +431,7 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - TRACE("name %s, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial); - -- ret = create_esync( &fd, handle, access, attr, initial ? 0 : 1, 0 ); -+ ret = create_esync( &type, &fd, handle, access, attr, initial ? 0 : 1, 0 ); - if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) - { - mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -diff --git a/server/esync.c b/server/esync.c -index 1f8c0d516..9ff1a847b 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -56,6 +56,7 @@ struct esync - { - struct object obj; /* object header */ - int fd; /* eventfd file descriptor */ -+ enum esync_type type; - }; - - static void esync_dump( struct object *obj, int verbose ); -@@ -98,9 +99,16 @@ static void esync_destroy( struct object *obj ) - close( esync->fd ); - } - --struct esync *create_esync( struct object *root, const struct unicode_str *name, -- unsigned int attr, int initval, int flags, -- const struct security_descriptor *sd ) -+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 struct esync *create_esync( struct object *root, const struct unicode_str *name, -+ unsigned int attr, int initval, int flags, enum esync_type type, -+ const struct security_descriptor *sd ) - { - #ifdef HAVE_SYS_EVENTFD_H - struct esync *esync; -@@ -118,6 +126,17 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name, - release_object( esync ); - return NULL; - } -+ esync->type = type; -+ } -+ else -+ { -+ /* validate the type */ -+ if (!type_matches( type, esync->type )) -+ { -+ release_object( &esync->obj ); -+ set_error( STATUS_OBJECT_TYPE_MISMATCH ); -+ return NULL; -+ } - } - } - return esync; -@@ -200,7 +219,7 @@ DECL_HANDLER(create_esync) - - if (!objattr) return; - -- if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, sd ))) -+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, req->type, sd ))) - { - if (get_error() == STATUS_OBJECT_NAME_EXISTS) - reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes ); -@@ -208,6 +227,7 @@ DECL_HANDLER(create_esync) - reply->handle = alloc_handle_no_access_check( current->process, esync, - req->access, objattr->attributes ); - -+ reply->type = esync->type; - send_client_fd( current->process, esync->fd, reply->handle ); - release_object( esync ); - } -diff --git a/server/protocol.def b/server/protocol.def -index 721ffb96d..50735ee78 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4047,9 +4047,11 @@ struct handle_info - unsigned int access; /* wanted access rights */ - int initval; /* initial value */ - int flags; /* flags (EFD_SEMAPHORE or 0) */ -+ int type; /* type of esync object (see below) */ - VARARG(objattr,object_attributes); /* object attributes */ - @REPLY - obj_handle_t handle; /* handle to the object */ -+ int type; /* type of esync object (see below) */ - @END - - /* Retrieve the esync fd for an object. */ --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch b/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch new file mode 100644 index 00000000..17c54734 --- /dev/null +++ b/patches/eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch @@ -0,0 +1,47 @@ +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-ntdll-Implement-NtOpenEvent.patch b/patches/eventfd_synchronization/0034-ntdll-Implement-NtOpenEvent.patch deleted file mode 100644 index 73827294..00000000 --- a/patches/eventfd_synchronization/0034-ntdll-Implement-NtOpenEvent.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 9eec3a23b2423759bf0e357a422ac0d410bd873f Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 00:42:15 -0500 -Subject: [PATCH 34/83] ntdll: Implement NtOpenEvent(). - ---- - dlls/ntdll/esync.c | 26 ++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 31 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index f014003fc..e6acc9eaf 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -413,6 +413,32 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - return ret; - } - -+NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr ) -+{ -+ enum esync_type type = ESYNC_AUTO_EVENT; -+ struct event *event; -+ NTSTATUS ret; -+ int fd; -+ -+ TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -+ -+ ret = open_esync( &type, &fd, handle, access, attr ); -+ if (!ret) -+ { -+ event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -+ if (!event) -+ return STATUS_NO_MEMORY; -+ -+ event->obj.type = type; -+ event->obj.fd = fd; -+ -+ add_to_list( *handle, &event->obj ); -+ } -+ -+ return ret; -+} -+ - NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - { - struct event *event = esync_get_object( handle ); -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index b0d756ec1..1af343ef4 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -34,6 +34,8 @@ extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 3b902e669..b39c17c64 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -398,6 +398,9 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT - - 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.20.1 - diff --git a/patches/eventfd_synchronization/0040-server-Create-eventfd-descriptors-for-timers.patch b/patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch similarity index 67% rename from patches/eventfd_synchronization/0040-server-Create-eventfd-descriptors-for-timers.patch rename to patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch index c600d22f..e2629a3d 100644 --- a/patches/eventfd_synchronization/0040-server-Create-eventfd-descriptors-for-timers.patch +++ b/patches/eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch @@ -1,40 +1,14 @@ -From 6c3029fe763d6c94016a038d016eb810ad8e38ef Mon Sep 17 00:00:00 2001 +From 9e3d043ea15a1814f2003b7c6ebe6968b51b7740 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. --- - dlls/ntdll/esync.c | 1 + - server/protocol.def | 1 + - server/timer.c | 18 +++++++++++++++++- - 3 files changed, 19 insertions(+), 1 deletion(-) + server/timer.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 17890f9e1f0..c1d8882d817 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -241,6 +241,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - esync = &mutex->obj; - break; - } -+ case ESYNC_AUTO_SERVER: - case ESYNC_MANUAL_SERVER: - case ESYNC_QUEUE: - esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -diff --git a/server/protocol.def b/server/protocol.def -index 0ab32aaca64..eb80c81d6e6 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4080,6 +4080,7 @@ enum esync_type - ESYNC_AUTO_EVENT, - ESYNC_MANUAL_EVENT, - ESYNC_MUTEX, -+ ESYNC_AUTO_SERVER, - ESYNC_MANUAL_SERVER, - ESYNC_QUEUE, - }; diff --git a/server/timer.c b/server/timer.c -index 2614e145c40..c3ebd3f52d3 100644 +index 319b9d142db..11fcdf3bae7 100644 --- a/server/timer.c +++ b/server/timer.c @@ -36,6 +36,7 @@ @@ -68,17 +42,18 @@ index 2614e145c40..c3ebd3f52d3 100644 timer_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ -@@ -99,6 +102,9 @@ static struct timer *create_timer( struct object *root, const struct unicode_str +@@ -100,6 +103,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; -@@ -172,6 +178,9 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period +@@ -173,6 +180,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; @@ -88,7 +63,7 @@ index 2614e145c40..c3ebd3f52d3 100644 } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; -@@ -205,6 +214,13 @@ static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) +@@ -207,6 +217,13 @@ static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) return timer->signaled; } @@ -103,5 +78,5 @@ index 2614e145c40..c3ebd3f52d3 100644 { struct timer *timer = (struct timer *)obj; -- -2.26.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0035-ntdll-Implement-NtOpenMutant.patch b/patches/eventfd_synchronization/0035-ntdll-Implement-NtOpenMutant.patch deleted file mode 100644 index 6b369f7d..00000000 --- a/patches/eventfd_synchronization/0035-ntdll-Implement-NtOpenMutant.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 143d6f220efa6b54571a5ef1b18f5faced8543af Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 00:44:54 -0500 -Subject: [PATCH 35/83] ntdll: Implement NtOpenMutant(). - ---- - dlls/ntdll/esync.c | 30 ++++++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 35 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index e6acc9eaf..9da300853 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -539,6 +539,36 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - return ret; - } - -+NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr ) -+{ -+ enum esync_type type = ESYNC_MUTEX; -+ struct mutex *mutex; -+ NTSTATUS ret; -+ int fd; -+ -+ TRACE("name %s.\n", debugstr_us(attr->ObjectName)); -+ -+ ret = open_esync( &type, &fd, handle, access, attr ); -+ if (!ret) -+ { -+ mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -+ if (!mutex) -+ return STATUS_NO_MEMORY; -+ -+ mutex->obj.type = ESYNC_MUTEX; -+ mutex->obj.fd = fd; -+ -+ FIXME("Attempt to open a mutex; this will not work.\n"); -+ mutex->tid = 0; -+ mutex->count = 0; -+ -+ add_to_list( *handle, &mutex->obj ); -+ } -+ -+ return ret; -+} -+ - NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - { - struct mutex *mutex = esync_get_object( handle ); -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index 1af343ef4..f79b9a06c 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -36,6 +36,8 @@ extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, -+ const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index b39c17c64..2f8d6fe5c 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -575,6 +575,9 @@ NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_A - - if ((status = validate_open_object_attributes( attr ))) return status; - -+ if (do_esync()) -+ return esync_open_mutex( handle, access, attr ); -+ - SERVER_START_REQ( open_mutex ) - { - req->access = access; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0045-server-ntdll-Implement-alertable-waits.patch b/patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch similarity index 53% rename from patches/eventfd_synchronization/0045-server-ntdll-Implement-alertable-waits.patch rename to patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch index 00efe887..dd4bfbf7 100644 --- a/patches/eventfd_synchronization/0045-server-ntdll-Implement-alertable-waits.patch +++ b/patches/eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch @@ -1,35 +1,33 @@ -From 81e9cb30bd1005500d3fd51962b6611540f91338 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 15 Jun 2018 14:12:22 -0500 -Subject: [PATCH] server, ntdll: Implement alertable waits. +From ec0fc4f9f1919616dcaecd4712749761d271c7c8 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. -We do this quite simply by waiting on an extra eventfd descriptor, which the server signals when a user APC is queued. --- - dlls/ntdll/esync.c | 95 +++++++++++++++++++++++++++++++++++------ - dlls/ntdll/ntdll_misc.h | 1 + - dlls/ntdll/thread.c | 2 + - server/esync.c | 20 +++++++-- - server/esync.h | 1 + - server/protocol.def | 5 +++ - server/thread.c | 13 ++++++ - server/thread.h | 1 + - 8 files changed, 121 insertions(+), 17 deletions(-) + 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/esync.c b/dlls/ntdll/esync.c -index 7504f9b2931e..15f99239fe9d 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -684,19 +684,43 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) - NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, +diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c +index d1a282c65e9..2a7c3865617 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -607,17 +607,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 = {0}; ++ static const LARGE_INTEGER zero; + struct esync *objs[MAXIMUM_WAIT_OBJECTS]; -- struct pollfd fds[MAXIMUM_WAIT_OBJECTS + 1]; -+ struct pollfd fds[MAXIMUM_WAIT_OBJECTS + 2]; +- struct pollfd fds[MAXIMUM_WAIT_OBJECTS]; ++ struct pollfd fds[MAXIMUM_WAIT_OBJECTS + 1]; int has_esync = 0, has_server = 0; -- DWORD pollcount = count; BOOL msgwait = FALSE; LONGLONG timeleft; LARGE_INTEGER now; @@ -37,8 +35,7 @@ index 7504f9b2931e..15f99239fe9d 100644 ULONGLONG end; int64_t value; ssize_t size; - int i, j; - int ret; + 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) @@ -47,7 +44,7 @@ index 7504f9b2931e..15f99239fe9d 100644 + sigset_t sigset; + int fd = -1; + -+ server_enter_uninterrupted_section( &fd_cache_section, &sigset ); ++ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + SERVER_START_REQ( get_esync_apc_fd ) + { + if (!(ret = wine_server_call( req ))) @@ -57,7 +54,7 @@ index 7504f9b2931e..15f99239fe9d 100644 + } + } + SERVER_END_REQ; -+ server_leave_uninterrupted_section( &fd_cache_section, &sigset ); ++ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + + ntdll_get_thread_data()->esync_apc_fd = fd; + } @@ -65,26 +62,18 @@ index 7504f9b2931e..15f99239fe9d 100644 NtQuerySystemTime( &now ); if (timeout) { -@@ -748,6 +772,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - if (msgwait) - TRACE(" or driver events (fd %d)", ntdll_get_thread_data()->esync_queue_fd); +@@ -656,6 +681,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"); - else -@@ -785,10 +812,17 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - } - if (msgwait) - { -- fds[count].fd = ntdll_get_thread_data()->esync_queue_fd; -- fds[count].events = POLLIN; -- pollcount++; -+ fds[i].fd = ntdll_get_thread_data()->esync_queue_fd; -+ fds[i].events = POLLIN; -+ i++; +@@ -692,12 +719,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) + { @@ -96,29 +85,22 @@ index 7504f9b2931e..15f99239fe9d 100644 while (1) { -@@ -848,10 +882,18 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - } - } - -- if (msgwait && (fds[count].revents & POLLIN)) -+ if (msgwait) -+ { -+ if (fds[i++].revents & POLLIN) -+ { -+ TRACE("Woken up by driver events.\n"); -+ return count - 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) - { -- TRACE("Woken up by driver events.\n"); -- return count - 1; -+ if (fds[i++].revents & POLLIN) ++ { ++ if (fds[pollcount - 1].revents & POLLIN) + goto userapc; - } - - /* If we got here, someone else stole (or reset, etc.) whatever -@@ -890,6 +932,14 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an ++ } ++ + /* Find out which object triggered the wait. */ + for (i = 0; i < count; i++) + { +@@ -771,6 +813,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; @@ -133,7 +115,7 @@ index 7504f9b2931e..15f99239fe9d 100644 for (i = 0; i < count; i++) { struct esync *obj = objs[i]; -@@ -905,9 +955,11 @@ tryagain: +@@ -786,9 +836,11 @@ tryagain: continue; } @@ -146,45 +128,31 @@ index 7504f9b2931e..15f99239fe9d 100644 if (fds[0].revents & (POLLHUP | POLLERR | POLLNVAL)) { -@@ -920,9 +972,11 @@ tryagain: - if (msgwait) - { - fds[0].fd = ntdll_get_thread_data()->esync_queue_fd; -- 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 we got here and we haven't timed out, that means all of the -@@ -934,10 +988,12 @@ tryagain: - } - if (msgwait) - { -- fds[count].fd = ntdll_get_thread_data()->esync_queue_fd; -- fds[count].events = POLLIN; -- pollcount++; -+ fds[i].fd = ntdll_get_thread_data()->esync_queue_fd; -+ fds[i].events = POLLIN; -+ i++; +@@ -804,10 +856,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, pollcount, 0 ); -@@ -1018,6 +1074,19 @@ err: +- 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++) +@@ -873,6 +927,19 @@ err: ERR("ppoll failed: %s\n", strerror(errno)); - return FILE_GetNtStatus(); + 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_wait(). */ ++ * 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 @@ -194,44 +162,36 @@ index 7504f9b2931e..15f99239fe9d 100644 + return ret; } - NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, -diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index e9262de93da9..f92fa9060103 100644 ---- a/dlls/ntdll/ntdll_misc.h -+++ b/dlls/ntdll/ntdll_misc.h -@@ -268,6 +268,7 @@ struct ntdll_thread_data - { - struct debug_info *debug_info; /* info for debugstr functions */ - int esync_queue_fd;/* fd to wait on for driver events */ + /* 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 c3ad0a41098..c2f215320ee 100644 +--- a/dlls/ntdll/unix/unix_private.h ++++ b/dlls/ntdll/unix/unix_private.h +@@ -57,6 +57,7 @@ struct ntdll_thread_data + struct list entry; /* entry in TEB list */ + PRTL_THREAD_START_ROUTINE start; /* thread entry point */ + void *param; /* thread entry point parameter */ + int esync_apc_fd; /* fd to wait on for user APCs */ - void *start_stack; /* stack for thread startup */ - int request_fd; /* fd for sending server requests */ - int reply_fd; /* fd for receiving server replies */ -diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c -index a3dd918fdf58..3b1b6daad981 100644 ---- a/dlls/ntdll/thread.c -+++ b/dlls/ntdll/thread.c -@@ -439,6 +439,7 @@ TEB *thread_init(void) + }; + + C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index d79e3de662e..6b83072b750 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -2555,6 +2555,7 @@ static void init_teb( TEB *teb, PEB *peb ) + thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; - thread_data->esync_queue_fd = -1; + thread_data->esync_apc_fd = -1; + list_add_head( &teb_list, &thread_data->entry ); + } - unix_funcs->dbg_init(); - unix_funcs->get_paths( &build_dir, &data_dir, &config_dir ); -@@ -747,6 +748,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle_ptr, ACCESS_MASK access, OBJECT - thread_data->wait_fd[1] = -1; - thread_data->start_stack = (char *)teb->Tib.StackBase; - thread_data->esync_queue_fd = -1; -+ thread_data->esync_apc_fd = -1; - - pthread_attr_init( &pthread_attr ); - pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, diff --git a/server/esync.c b/server/esync.c -index c68b2bc1fc05..a3cd1a8decf8 100644 +index 7b5b0761516..33a448d0a57 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -246,19 +246,25 @@ int esync_create_fd( int initval, int flags ) +@@ -348,19 +348,25 @@ int esync_create_fd( int initval, int flags ) #endif } @@ -261,7 +221,7 @@ index c68b2bc1fc05..a3cd1a8decf8 100644 } } -@@ -384,3 +390,9 @@ DECL_HANDLER(get_esync_fd) +@@ -498,3 +504,9 @@ DECL_HANDLER(get_esync_fd) release_object( obj ); } @@ -272,7 +232,7 @@ index c68b2bc1fc05..a3cd1a8decf8 100644 + send_client_fd( current->process, current->esync_apc_fd, current->id ); +} diff --git a/server/esync.h b/server/esync.h -index aeb58c5469c3..cea025d93088 100644 +index aeb58c5469c..cea025d9308 100644 --- a/server/esync.h +++ b/server/esync.h @@ -21,6 +21,7 @@ @@ -284,26 +244,22 @@ index aeb58c5469c3..cea025d93088 100644 void esync_clear( int fd ); diff --git a/server/protocol.def b/server/protocol.def -index 01f2207cc8af..9188893d7de6 100644 +index 5b8f66ffd80..a110c4c60a6 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -4070,6 +4070,11 @@ struct handle_info - unsigned int shm_idx; /* this object's index into the shm section */ +@@ -3714,3 +3714,7 @@ enum esync_type + @REQ(esync_msgwait) + int in_msgwait; /* are we in a message wait? */ @END - ++ +/* Retrieve the fd to wait on for user APCs. */ +@REQ(get_esync_apc_fd) -+@REPLY +@END -+ - enum esync_type - { - ESYNC_SEMAPHORE = 1, diff --git a/server/thread.c b/server/thread.c -index 9341261b580c..5677aa518da2 100644 +index d22555ca317..6bf4be04af5 100644 --- a/server/thread.c +++ b/server/thread.c -@@ -224,6 +224,7 @@ static inline void init_thread_structure( struct thread *thread ) +@@ -227,6 +227,7 @@ static inline void init_thread_structure( struct thread *thread ) thread->teb = 0; thread->entry_point = 0; thread->esync_fd = -1; @@ -311,7 +267,7 @@ index 9341261b580c..5677aa518da2 100644 thread->debug_ctx = NULL; thread->system_regs = 0; thread->queue = NULL; -@@ -362,7 +363,10 @@ struct thread *create_thread( int fd, struct process *process, const struct secu +@@ -363,7 +364,10 @@ struct thread *create_thread( int fd, struct process *process, const struct secu } if (do_esync()) @@ -322,21 +278,21 @@ index 9341261b580c..5677aa518da2 100644 set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */ add_process_thread( thread->process, thread ); -@@ -1153,8 +1157,13 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr +@@ -1150,8 +1154,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()) ++ if (do_esync() && queue == &thread->user_apc) + esync_wake_fd( thread->esync_apc_fd ); + } + return 1; } -@@ -1200,6 +1209,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system +@@ -1197,6 +1206,10 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system apc = LIST_ENTRY( ptr, struct thread_apc, entry ); list_remove( ptr ); } @@ -348,7 +304,7 @@ index 9341261b580c..5677aa518da2 100644 } diff --git a/server/thread.h b/server/thread.h -index 1b2973cba63e..9ed70aee8576 100644 +index f19080988e9..5faa2456a81 100644 --- a/server/thread.h +++ b/server/thread.h @@ -55,6 +55,7 @@ struct thread @@ -360,5 +316,5 @@ index 1b2973cba63e..9ed70aee8576 100644 unsigned int system_regs; /* which system regs have been set */ struct msg_queue *queue; /* message queue */ -- -2.26.2 +2.28.0 diff --git a/patches/eventfd_synchronization/0046-esync-Update-README.patch b/patches/eventfd_synchronization/0036-esync-Update-README.patch similarity index 96% rename from patches/eventfd_synchronization/0046-esync-Update-README.patch rename to patches/eventfd_synchronization/0036-esync-Update-README.patch index dbfa2b1f..fec3618d 100644 --- a/patches/eventfd_synchronization/0046-esync-Update-README.patch +++ b/patches/eventfd_synchronization/0036-esync-Update-README.patch @@ -1,14 +1,14 @@ -From b141d7ebda9f3440e96c8456dfedb83efb51d578 Mon Sep 17 00:00:00 2001 +From d00c4483de7260cae76a82291d179e8c33e5b732 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 10 Jun 2018 13:53:08 -0500 -Subject: [PATCH 46/83] esync: Update README. +Subject: [PATCH] esync: Update README. --- README.esync | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/README.esync b/README.esync -index 8fcb96901..627cc3f48 100644 +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 @@ -81,5 +81,5 @@ index 8fcb96901..627cc3f48 100644 This patchset was inspired by Daniel Santos' "hybrid synchronization" patchset. My idea was to create a framework whereby even contended waits could -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0036-ntdll-Record-the-current-count-of-a-semaphore-locall.patch b/patches/eventfd_synchronization/0036-ntdll-Record-the-current-count-of-a-semaphore-locall.patch deleted file mode 100644 index e77f7c94..00000000 --- a/patches/eventfd_synchronization/0036-ntdll-Record-the-current-count-of-a-semaphore-locall.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 52efa515c406f66dc16a82145ec116e90c64ecee Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 12:08:51 -0500 -Subject: [PATCH 36/83] ntdll: Record the current count of a semaphore locally. - -And check it against the maximum, and return it if requested. - -Of course, this won't work across processes. - -This should be thread-safe. ---- - dlls/ntdll/esync.c | 39 ++++++++++++++++++++++++++++++++++----- - 1 file changed, 34 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 9da300853..25e049291 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -90,6 +90,7 @@ struct semaphore - { - struct esync obj; - int max; -+ int count; - }; - - struct event -@@ -328,6 +329,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - semaphore->obj.type = ESYNC_SEMAPHORE; - semaphore->obj.fd = fd; - semaphore->max = max; -+ semaphore->count = initial; - - add_to_list( *handle, &semaphore->obj ); - } -@@ -356,6 +358,7 @@ NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - semaphore->obj.fd = fd; - - FIXME("Attempt to open a semaphore, this will not work.\n"); -+ semaphore->count = 0; - semaphore->max = 0xdeadbeef; - - add_to_list( *handle, &semaphore->obj ); -@@ -368,16 +371,27 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - { - struct semaphore *semaphore = esync_get_object( handle ); - uint64_t count64 = count; -+ ULONG current; - - TRACE("%p, %d, %p.\n", handle, count, prev); - - if (!semaphore) return STATUS_INVALID_HANDLE; - -- if (prev) -+ /* FIXME: This won't work across processes. In that case it may be best to -+ * use shared memory. */ -+ do - { -- FIXME("Can't write previous value.\n"); -- *prev = 1; -- } -+ 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( semaphore->obj.fd, &count64, sizeof(count64) ) == -1) - return FILE_GetNtStatus(); -@@ -794,6 +808,15 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - mutex->tid = GetCurrentThreadId(); - mutex->count = 1; - } -+ else if (obj->type == ESYNC_SEMAPHORE) -+ { -+ struct semaphore *semaphore = (struct semaphore *)obj; -+ /* 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. */ -+ InterlockedDecrement( &semaphore->count ); -+ } - return i; - } - } -@@ -932,7 +955,8 @@ tryagain: - } - - /* If we got here, we successfully waited on every object. */ -- /* Make sure to let ourselves know that we grabbed the mutexes. */ -+ /* Make sure to let ourselves know that we grabbed the mutexes -+ * and semaphores. */ - for (i = 0; i < count; i++) - { - if (objs[i]->type == ESYNC_MUTEX) -@@ -941,6 +965,11 @@ tryagain: - mutex->tid = GetCurrentThreadId(); - mutex->count++; - } -+ else if (objs[i]->type == ESYNC_SEMAPHORE) -+ { -+ struct semaphore *semaphore = (struct semaphore *)objs[i]; -+ InterlockedDecrement( &semaphore->count ); -+ } - } - TRACE("Wait successful.\n"); - return STATUS_SUCCESS; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0047-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 similarity index 85% rename from patches/eventfd_synchronization/0047-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch rename to patches/eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch index a1f1b6dc..f2afd441 100644 --- a/patches/eventfd_synchronization/0047-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 @@ -1,15 +1,15 @@ -From 5007a124ae988a9913c1e48656f67c3a2dc3b485 Mon Sep 17 00:00:00 2001 +From 4417ee6abe20066cb1bbc784c0705885a07b3966 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 13 Jun 2018 22:25:40 -0500 -Subject: [PATCH 47/83] kernel32/tests: Mark some existing tests as failing - under esync. +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 982a6ae10..befd7cdb5 100644 +index 2a47abf342c..ef900dcfc04 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -218,7 +218,8 @@ todo_wine @@ -31,5 +31,5 @@ index 982a6ae10..befd7cdb5 100644 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError()); -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0048-kernel32-tests-Add-some-semaphore-tests.patch b/patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch similarity index 95% rename from patches/eventfd_synchronization/0048-kernel32-tests-Add-some-semaphore-tests.patch rename to patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch index ec5ab7d6..5893a0c8 100644 --- a/patches/eventfd_synchronization/0048-kernel32-tests-Add-some-semaphore-tests.patch +++ b/patches/eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch @@ -1,14 +1,14 @@ -From 5708a3506461e879e20a05292b5826cb89938771 Mon Sep 17 00:00:00 2001 +From 775bf85e0e0614cbfe4494d7b8c47159cae5f47a Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 13 Jun 2018 22:40:47 -0500 -Subject: [PATCH 48/83] kernel32/tests: Add some semaphore tests. +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 befd7cdb5..b8c787d8f 100644 +index ef900dcfc04..26ccfdd4a54 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -577,7 +577,10 @@ static void test_event(void) @@ -124,5 +124,5 @@ index befd7cdb5..b8c787d8f 100644 static void test_waitable_timer(void) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0038-server-Alter-conditions-in-is_queue_hung.patch b/patches/eventfd_synchronization/0038-server-Alter-conditions-in-is_queue_hung.patch deleted file mode 100644 index bbd02d15..00000000 --- a/patches/eventfd_synchronization/0038-server-Alter-conditions-in-is_queue_hung.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0d9f118eb9601f98ff5f631effa3197477ab48b0 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 11 Jun 2018 16:43:24 -0500 -Subject: [PATCH 38/83] server: Alter conditions in is_queue_hung(). - -Unusually, I've elected not to guard this with do_esync(). I think this is a better way of checking for a hung queue in general, both because it's simpler and because it makes more sense: a queue is hung if it has messages it hasn't processed, not necessarily if it isn't actively waiting for messages. For example, a queue could be not associated with a window, and only waiting for messages when it makes sense to do so (due to some internal program logic). Or a thread could elect to poll its message queue with, say, GetQueueStatus(), and only get messages when there are messages to process. - -And, of course, this stops esync threads from being considered hung, since obviously the server has no idea that they are indeed waiting on their own queue. Normally nobody cares about this, but as of f6b0ce3c the server refuses to deliver hooks to a hung queue, and so we need to avoid a queue being wrongly considered hung. ---- - server/queue.c | 12 +----------- - 1 file changed, 1 insertion(+), 11 deletions(-) - -diff --git a/server/queue.c b/server/queue.c -index 91de4a3a8..e217a5e6a 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -975,17 +975,7 @@ static void cleanup_results( struct msg_queue *queue ) - /* check if the thread owning the queue is hung (not checking for messages) */ - static int is_queue_hung( struct msg_queue *queue ) - { -- struct wait_queue_entry *entry; -- -- if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC) -- return 0; /* less than 5 seconds since last get message -> not hung */ -- -- LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry ) -- { -- if (get_wait_queue_thread(entry)->queue == queue) -- return 0; /* thread is waiting on queue -> not hung */ -- } -- return 1; -+ return is_signaled( queue ) && (current_time - queue->last_get_msg > 5 * TICKS_PER_SEC); - } - - static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0049-kernel32-tests-Add-some-event-tests.patch b/patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch similarity index 96% rename from patches/eventfd_synchronization/0049-kernel32-tests-Add-some-event-tests.patch rename to patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch index f71a50d6..445c010b 100644 --- a/patches/eventfd_synchronization/0049-kernel32-tests-Add-some-event-tests.patch +++ b/patches/eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch @@ -1,14 +1,14 @@ -From 3e4feaed83e08132a424866386a54b778e1b021b Mon Sep 17 00:00:00 2001 +From 30a65d88cd062f09f88513c377d2c7780e92e05d Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 13 Jun 2018 22:59:37 -0500 -Subject: [PATCH 49/83] kernel32/tests: Add some event tests. +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 b8c787d8f..58972a4f2 100644 +index 26ccfdd4a54..ea54cb069df 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -464,12 +464,13 @@ static void test_slist(void) @@ -150,5 +150,5 @@ index b8c787d8f..58972a4f2 100644 static void test_semaphore(void) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0039-ntdll-server-Allow-DuplicateHandle-to-succeed-by-imp.patch b/patches/eventfd_synchronization/0039-ntdll-server-Allow-DuplicateHandle-to-succeed-by-imp.patch deleted file mode 100644 index 8d7759be..00000000 --- a/patches/eventfd_synchronization/0039-ntdll-server-Allow-DuplicateHandle-to-succeed-by-imp.patch +++ /dev/null @@ -1,106 +0,0 @@ -From fafd82460f1a8ee69feb9f2921889abd884d7926 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 14:33:38 -0500 -Subject: [PATCH 39/83] ntdll, server: Allow DuplicateHandle() to succeed by - implementing esync_get_esync_fd(). - -Note that this only works for events. ---- - dlls/ntdll/esync.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- - server/esync.c | 10 +++++++++- - 2 files changed, 51 insertions(+), 4 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 25e049291..4adf01a11 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -206,9 +206,48 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - - TRACE("Got fd %d for handle %p.\n", fd, handle); - -- esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -- esync->fd = fd; -- esync->type = type; -+ switch (type) -+ { -+ case ESYNC_SEMAPHORE: -+ { -+ struct semaphore *semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -+ semaphore->obj.type = ESYNC_SEMAPHORE; -+ semaphore->obj.fd = fd; -+ -+ FIXME("Attempt to duplicate a semaphore; this will not work.\n"); -+ semaphore->max = 0xdeadbeef; -+ semaphore->count = 0; -+ esync = &semaphore->obj; -+ break; -+ } -+ case ESYNC_AUTO_EVENT: -+ case ESYNC_MANUAL_EVENT: -+ { -+ struct event *event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -+ event->obj.type = type; -+ event->obj.fd = fd; -+ esync = &event->obj; -+ break; -+ } -+ case ESYNC_MUTEX: -+ { -+ struct mutex *mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -+ mutex->obj.type = type; -+ mutex->obj.fd = fd; -+ -+ FIXME("Attempt to duplicate a mutex; this will not work.\n"); -+ mutex->tid = 0; -+ mutex->count = 0; -+ esync = &mutex->obj; -+ break; -+ } -+ case ESYNC_MANUAL_SERVER: -+ case ESYNC_QUEUE: -+ esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -+ esync->fd = fd; -+ esync->type = type; -+ break; -+ } - - add_to_list( handle, esync ); - -diff --git a/server/esync.c b/server/esync.c -index 62e6df30b..5dd38c42a 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -60,6 +60,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 ); - -@@ -71,7 +72,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 */ -@@ -94,6 +95,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.20.1 - diff --git a/patches/eventfd_synchronization/0050-kernel32-tests-Add-some-mutex-tests.patch b/patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch similarity index 95% rename from patches/eventfd_synchronization/0050-kernel32-tests-Add-some-mutex-tests.patch rename to patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch index f58e03ab..553f295c 100644 --- a/patches/eventfd_synchronization/0050-kernel32-tests-Add-some-mutex-tests.patch +++ b/patches/eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch @@ -1,14 +1,14 @@ -From fd0423ea32b512123f2b60cb0ebcfc7e4f1cf037 Mon Sep 17 00:00:00 2001 +From 505384ad65984c3fc18c1c1a7b1fd39ecd0186f1 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 13 Jun 2018 23:32:04 -0500 -Subject: [PATCH 50/83] kernel32/tests: Add some mutex tests. +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 58972a4f2..0fb3fd70e 100644 +index ea54cb069df..790b7bfe797 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -177,8 +177,23 @@ static void test_signalandwait(void) @@ -122,5 +122,5 @@ index 58972a4f2..0fb3fd70e 100644 static void test_slist(void) -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0051-kernel32-tests-Add-some-tests-for-wait-timeouts.patch b/patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch similarity index 93% rename from patches/eventfd_synchronization/0051-kernel32-tests-Add-some-tests-for-wait-timeouts.patch rename to patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch index dfa1b429..ac107b05 100644 --- a/patches/eventfd_synchronization/0051-kernel32-tests-Add-some-tests-for-wait-timeouts.patch +++ b/patches/eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch @@ -1,4 +1,4 @@ -From 5e739bc4d78bbf6598a8feb7a8cf50e875f86e7f Mon Sep 17 00:00:00 2001 +From 0596227ece99953785e8165d9c983114da77721c 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. @@ -8,10 +8,10 @@ Subject: [PATCH] kernel32/tests: Add some tests for wait timeouts. 1 file changed, 68 insertions(+) diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 5fd758118fa..6b1d11a8a3c 100644 +index 790b7bfe797..6e4916f6bc3 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c -@@ -55,6 +55,7 @@ static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); +@@ -54,6 +54,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); @@ -19,7 +19,7 @@ index 5fd758118fa..6b1d11a8a3c 100644 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, -@@ -1481,11 +1482,15 @@ static HANDLE modify_handle(HANDLE handle, DWORD modify) +@@ -1480,11 +1481,15 @@ static HANDLE modify_handle(HANDLE handle, DWORD modify) return ULongToHandle(tmp); } @@ -35,7 +35,7 @@ index 5fd758118fa..6b1d11a8a3c 100644 DWORD ret; signaled = CreateEventW(NULL, TRUE, TRUE, NULL); -@@ -1570,6 +1575,68 @@ static void test_WaitForSingleObject(void) +@@ -1569,6 +1574,68 @@ static void test_WaitForSingleObject(void) status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status); @@ -104,7 +104,7 @@ index 5fd758118fa..6b1d11a8a3c 100644 CloseHandle(signaled); CloseHandle(nonsignaled); } -@@ -3003,6 +3070,7 @@ START_TEST(sync) +@@ -3037,6 +3104,7 @@ START_TEST(sync) pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); @@ -113,5 +113,5 @@ index 5fd758118fa..6b1d11a8a3c 100644 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); -- -2.17.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0041-server-Allocate-shared-memory-segments-for-semaphore.patch b/patches/eventfd_synchronization/0041-server-Allocate-shared-memory-segments-for-semaphore.patch deleted file mode 100644 index fac90112..00000000 --- a/patches/eventfd_synchronization/0041-server-Allocate-shared-memory-segments-for-semaphore.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 525b78c2da9801372ef32849871859ad4cd16db0 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 10 Jun 2018 23:12:16 -0500 -Subject: [PATCH] server: Allocate shared memory segments for semaphores and - mutexes. - -As has been described in the README, these two objects have state that can't -be expressed (or read from) the eventfd descriptor. Namely, for semaphores -we need to know the current lock count, and for mutexes we need to know the - owner tid and the recursion count. To make these work across processes, we -store them in a global shared memory section. - -This patch has no effect by itself; it's for separation. - -We use the WINEPREFIX dir to discriminate shm sections for simultaneously -running servers; this is based off of code in libwine (specifically -init_server_dir()). ---- - server/esync.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ - server/esync.h | 1 + - server/main.c | 4 +++ - server/protocol.def | 2 ++ - 4 files changed, 71 insertions(+) - -diff --git a/server/esync.c b/server/esync.c -index 5dd38c42a4f..fb9d02fc7d2 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -21,12 +21,20 @@ - #include "config.h" - #include "wine/port.h" - -+#include - #include - #include - #include - #ifdef HAVE_SYS_EVENTFD_H - # include - #endif -+#ifdef HAVE_SYS_MMAN_H -+# include -+#endif -+#ifdef HAVE_SYS_STAT_H -+# include -+#endif -+#include - - #include "ntstatus.h" - #define WIN32_NO_STATUS -@@ -52,11 +60,46 @@ int do_esync(void) - #endif - } - -+static char shm_name[29]; -+static int shm_fd; -+static off_t shm_size; -+ -+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_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 ); -+ if (shm_fd == -1) -+ perror( "shm_open" ); -+ -+ shm_size = sysconf( _SC_PAGESIZE ); -+ if (ftruncate( shm_fd, shm_size ) == -1) -+ perror( "ftruncate" ); -+ -+ 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 ); -@@ -146,6 +189,25 @@ static struct esync *create_esync( struct object *root, const struct unicode_str - return NULL; - } - esync->type = type; -+ if (type == ESYNC_SEMAPHORE || type == ESYNC_MUTEX) -+ { -+ /* 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 += sysconf( _SC_PAGESIZE ); -+ if (ftruncate( shm_fd, shm_size ) == -1) -+ { -+ fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -+ shm_name, shm_size ); -+ perror( "ftruncate" ); -+ } -+ } -+ } -+ else -+ esync->shm_idx = 0; - } - else - { -@@ -247,6 +309,7 @@ DECL_HANDLER(create_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 ); - } -@@ -278,6 +341,7 @@ DECL_HANDLER(open_esync) - } - - reply->type = esync->type; -+ reply->shm_idx = esync->shm_idx; - - send_client_fd( current->process, esync->fd, reply->handle ); - release_object( esync ); -diff --git a/server/esync.h b/server/esync.h -index 2687c72e419..aeb58c5469c 100644 ---- a/server/esync.h -+++ b/server/esync.h -@@ -19,6 +19,7 @@ - */ - - 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/main.c b/server/main.c -index 483a0c85580..ef4d3d7d835 100644 ---- a/server/main.c -+++ b/server/main.c -@@ -36,6 +36,7 @@ - #include "file.h" - #include "thread.h" - #include "request.h" -+#include "esync.h" - - /* command-line options */ - int debug_level = 0; -@@ -140,6 +141,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_scheduler(); -diff --git a/server/protocol.def b/server/protocol.def -index eb80c81d6e6..dde81a3ebcf 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4053,6 +4053,7 @@ struct handle_info - @REPLY - obj_handle_t handle; /* handle to the object */ - int type; /* type of esync object (see below) */ -+ unsigned int shm_idx; /* this object's index into the shm section */ - @END - - /* Open an esync object */ -@@ -4065,6 +4066,7 @@ struct handle_info - @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. */ --- -2.26.0 - diff --git a/patches/eventfd_synchronization/0059-kernel32-tests-Zigzag-test.patch b/patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch similarity index 94% rename from patches/eventfd_synchronization/0059-kernel32-tests-Zigzag-test.patch rename to patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch index 59cb0784..987cb2c2 100644 --- a/patches/eventfd_synchronization/0059-kernel32-tests-Zigzag-test.patch +++ b/patches/eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch @@ -1,4 +1,4 @@ -From a7cf9dff0dc87d7711df856971d1d6c2465ceba0 Mon Sep 17 00:00:00 2001 +From 5927f6063f981724d8b45031b9bd59aec465cb45 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. @@ -9,10 +9,10 @@ The primary function is to check for races. The secondary function is to measure 1 file changed, 79 insertions(+) diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c -index 5896211214f..f4307d1a5b6 100644 +index 6e4916f6bc3..0f072a5846e 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c -@@ -3044,6 +3044,84 @@ static void test_crit_section(void) +@@ -3078,6 +3078,84 @@ static void test_crit_section(void) ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo); } @@ -97,7 +97,7 @@ index 5896211214f..f4307d1a5b6 100644 START_TEST(sync) { char **argv; -@@ -3104,5 +3182,6 @@ START_TEST(sync) +@@ -3140,5 +3218,6 @@ START_TEST(sync) test_srwlock_example(); test_alertable_wait(); test_apc_deadlock(); @@ -105,5 +105,5 @@ index 5896211214f..f4307d1a5b6 100644 test_crit_section(); } -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0042-ntdll-Use-shared-memory-segments-to-store-semaphore-.patch b/patches/eventfd_synchronization/0042-ntdll-Use-shared-memory-segments-to-store-semaphore-.patch deleted file mode 100644 index 5bee62fc..00000000 --- a/patches/eventfd_synchronization/0042-ntdll-Use-shared-memory-segments-to-store-semaphore-.patch +++ /dev/null @@ -1,696 +0,0 @@ -From 3248f2b2ee3d8aeede1d3d51f8e3d570d982a69b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 11 Jun 2018 13:10:36 -0500 -Subject: [PATCH] ntdll: Use shared memory segments to store semaphore and - mutex state. - -This patch is pretty big, because it restructures the underlying esync -objects. Instead of wrapping a struct esync, the semaphore and mutex structs -are now contained within it, as a pointer to shared memory. This also means -that we can move a lot of common code to create_esync() and open_esync() -since now we don't have to allocate separate structures. ---- - dlls/ntdll/esync.c | 349 +++++++++++++++++++------------------------- - dlls/ntdll/esync.h | 1 + - dlls/ntdll/loader.c | 4 + - 3 files changed, 155 insertions(+), 199 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index c1d8882d817..ea71c960007 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - #ifdef HAVE_SYS_EVENTFD_H - # include - #endif -@@ -84,27 +85,75 @@ struct esync - { - enum esync_type type; /* defined in protocol.def */ - int fd; -+ void *shm; /* pointer to shm section */ - }; - - struct semaphore - { -- struct esync obj; - int max; - int count; - }; - --struct event --{ -- struct esync obj; --}; -- - struct mutex - { -- struct esync obj; - DWORD tid; - int count; /* recursion count */ - }; - -+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; -+ -+void esync_init(void) -+{ -+ struct stat st; -+ -+ 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) -+ ERR("Failed to initialize shared memory: %s\n", strerror( errno )); -+ -+ pagesize = sysconf( _SC_PAGESIZE ); -+ -+ shm_addrs = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * sizeof(shm_addrs[0]) ); -+ shm_addrs_size = 128; -+} -+ -+static void *get_shm( unsigned int idx ) -+{ -+ int entry = (idx * 8) / pagesize; -+ int offset = (idx * 8) % pagesize; -+ -+ if (entry >= shm_addrs_size) -+ { -+ shm_addrs_size *= 2; -+ if (!(shm_addrs = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, shm_addrs, shm_addrs_size ))) -+ ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_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 */ -+ } -+ -+ return (void *)((unsigned long)shm_addrs[entry] + offset); -+} -+ - /* 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. */ - -@@ -206,49 +255,13 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - - TRACE("Got fd %d for handle %p.\n", fd, handle); - -- switch (type) -- { -- case ESYNC_SEMAPHORE: -- { -- struct semaphore *semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -- semaphore->obj.type = ESYNC_SEMAPHORE; -- semaphore->obj.fd = fd; -- -- FIXME("Attempt to duplicate a semaphore; this will not work.\n"); -- semaphore->max = 0xdeadbeef; -- semaphore->count = 0; -- esync = &semaphore->obj; -- break; -- } -- case ESYNC_AUTO_EVENT: -- case ESYNC_MANUAL_EVENT: -- { -- struct event *event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -- event->obj.type = type; -- event->obj.fd = fd; -- esync = &event->obj; -- break; -- } -- case ESYNC_MUTEX: -- { -- struct mutex *mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -- mutex->obj.type = type; -- mutex->obj.fd = fd; -+ esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -+ esync->fd = fd; -+ esync->type = type; - -- FIXME("Attempt to duplicate a mutex; this will not work.\n"); -- mutex->tid = 0; -- mutex->count = 0; -- esync = &mutex->obj; -- break; -- } -- case ESYNC_AUTO_SERVER: -- case ESYNC_MANUAL_SERVER: -- case ESYNC_QUEUE: -- esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -- esync->fd = fd; -- esync->type = type; -- break; -- } -+ if (type == ESYNC_SEMAPHORE || type == ESYNC_MUTEX) -+ FIXME("Attempt to duplicate a semaphore or mutex; this will not work.\n"); -+ esync->shm = NULL; - - add_to_list( handle, esync ); - -@@ -276,16 +289,16 @@ NTSTATUS esync_close( HANDLE handle ) - return STATUS_INVALID_HANDLE; - } - --/* type is an in-out parameter; if the object already existed it returns the -- * actual type. */ --static NTSTATUS create_esync(enum esync_type *type, int *fd, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags) -+static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags ) - { - 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; - -@@ -297,32 +310,47 @@ static NTSTATUS create_esync(enum esync_type *type, int *fd, HANDLE *handle, - req->access = access; - req->initval = initval; - req->flags = flags; -- req->type = *type; -+ req->type = type; - 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; -- *fd = receive_fd( &fd_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_section, &sigset ); - -- TRACE("-> handle %p, fd %d.\n", *handle, *fd); -+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ { -+ struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) ); -+ if (!obj) return STATUS_NO_MEMORY; -+ -+ obj->type = type; -+ obj->fd = fd; -+ obj->shm = shm_idx ? get_shm( shm_idx ) : 0; -+ -+ add_to_list( *handle, obj ); -+ -+ TRACE("-> handle %p, fd %d, shm index %d.\n", *handle, fd, shm_idx); -+ } - - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return ret; - } - --static NTSTATUS open_esync( enum esync_type *type, int *fd, HANDLE *handle, -+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_section, &sigset ); - SERVER_START_REQ( open_esync ) -@@ -330,48 +358,55 @@ static NTSTATUS open_esync( enum esync_type *type, int *fd, HANDLE *handle, - req->access = access; - req->attributes = attr->Attributes; - req->rootdir = wine_server_obj_handle( attr->RootDirectory ); -- req->type = *type; -+ 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; -- *fd = receive_fd( &fd_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_section, &sigset ); - -- TRACE("-> handle %p, fd %d.\n", *handle, *fd); -+ if (!ret) -+ { -+ struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) ); -+ if (!obj) return STATUS_NO_MEMORY; -+ -+ obj->type = type; -+ obj->fd = fd; -+ obj->shm = shm_idx ? get_shm( shm_idx ) : 0; -+ -+ add_to_list( *handle, obj ); -+ -+ TRACE("-> handle %p, fd %d.\n", *handle, fd); -+ } - return ret; - } - - NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) - { -- enum esync_type type = ESYNC_SEMAPHORE; -- struct semaphore *semaphore; - NTSTATUS ret; -- int fd = -1; - - TRACE("name %s, initial %d, max %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial, max); - -- ret = create_esync( &type, &fd, handle, access, attr, initial, EFD_SEMAPHORE ); -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ ret = create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, EFD_SEMAPHORE ); -+ if (!ret) - { -- semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -- if (!semaphore) -- return STATUS_NO_MEMORY; -- -- semaphore->obj.type = ESYNC_SEMAPHORE; -- semaphore->obj.fd = fd; -+ /* Initialize the shared memory portion. -+ * Note we store max here (even though we don't need to) just to keep -+ * it the same size as the mutex's shm portion. */ -+ struct esync *obj = esync_get_object( *handle ); -+ struct semaphore *semaphore = obj->shm; - semaphore->max = max; - semaphore->count = initial; -- -- add_to_list( *handle, &semaphore->obj ); - } - - return ret; -@@ -380,45 +415,23 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -- enum esync_type type = ESYNC_SEMAPHORE; -- struct semaphore *semaphore; -- NTSTATUS ret; -- int fd = -1; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- ret = open_esync( &type, &fd, handle, access, attr ); -- if (!ret) -- { -- semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) ); -- if (!semaphore) -- return STATUS_NO_MEMORY; -- -- semaphore->obj.type = ESYNC_SEMAPHORE; -- semaphore->obj.fd = fd; -- -- FIXME("Attempt to open a semaphore, this will not work.\n"); -- semaphore->count = 0; -- semaphore->max = 0xdeadbeef; -- -- add_to_list( *handle, &semaphore->obj ); -- } -- -- return ret; -+ return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); - } - - NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - { -- struct semaphore *semaphore = esync_get_object( handle ); -+ struct esync *obj = esync_get_object( handle ); -+ struct semaphore *semaphore; - uint64_t count64 = count; - ULONG current; - - TRACE("%p, %d, %p.\n", handle, count, prev); - -- if (!semaphore) return STATUS_INVALID_HANDLE; -+ if (!obj) return STATUS_INVALID_HANDLE; -+ semaphore = obj->shm; - -- /* FIXME: This won't work across processes. In that case it may be best to -- * use shared memory. */ - do - { - current = semaphore->count; -@@ -433,7 +446,7 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - * 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( semaphore->obj.fd, &count64, sizeof(count64) ) == -1) -+ if (write( obj->fd, &count64, sizeof(count64) ) == -1) - return FILE_GetNtStatus(); - - return STATUS_SUCCESS; -@@ -443,64 +456,30 @@ 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); -- struct event *event; -- NTSTATUS ret; -- int fd; - - TRACE("name %s, %s-reset, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", - event_type == NotificationEvent ? "manual" : "auto", initial); - -- ret = create_esync( &type, &fd, handle, access, attr, initial, 0 ); -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -- { -- event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -- if (!event) -- return STATUS_NO_MEMORY; -- -- event->obj.type = type; /* note that the server might give us the real type */ -- event->obj.fd = fd; -- -- add_to_list( *handle, &event->obj); -- } -- -- return ret; -+ return create_esync( type, handle, access, attr, initial, 0 ); - } - - NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -- enum esync_type type = ESYNC_AUTO_EVENT; -- struct event *event; -- NTSTATUS ret; -- int fd; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- ret = open_esync( &type, &fd, handle, access, attr ); -- if (!ret) -- { -- event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) ); -- if (!event) -- return STATUS_NO_MEMORY; -- -- event->obj.type = type; -- event->obj.fd = fd; -- -- add_to_list( *handle, &event->obj ); -- } -- -- return ret; -+ return open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ - } - - NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - { -- struct event *event = esync_get_object( handle ); -+ struct esync *obj = esync_get_object( handle ); - static const uint64_t value = 1; - - TRACE("%p.\n", handle); - -- if (!event) return STATUS_INVALID_HANDLE; -+ if (!obj) return STATUS_INVALID_HANDLE; - - if (prev) - { -@@ -508,7 +487,7 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - *prev = 1; - } - -- if (write( event->obj.fd, &value, sizeof(value) ) == -1) -+ if (write( obj->fd, &value, sizeof(value) ) == -1) - return FILE_GetNtStatus(); - - return STATUS_SUCCESS; -@@ -516,12 +495,12 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - - NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - { -- struct event *event = esync_get_object( handle ); -+ struct esync *obj = esync_get_object( handle ); - static uint64_t value; - - TRACE("%p.\n", handle); - -- if (!event) return STATUS_INVALID_HANDLE; -+ if (!obj) return STATUS_INVALID_HANDLE; - - if (prev) - { -@@ -530,19 +509,19 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - } - - /* we don't care about the return value */ -- read( event->obj.fd, &value, sizeof(value) ); -+ read( obj->fd, &value, sizeof(value) ); - - return STATUS_SUCCESS; - } - - NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - { -- struct event *event = esync_get_object( handle ); -+ struct esync *obj = esync_get_object( handle ); - static uint64_t value = 1; - - TRACE("%p.\n", handle); - -- if (!event) return STATUS_INVALID_HANDLE; -+ if (!obj) return STATUS_INVALID_HANDLE; - - if (prev) - { -@@ -553,9 +532,9 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - /* 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( event->obj.fd, &value, sizeof(value) ) == -1) -+ if (write( obj->fd, &value, sizeof(value) ) == -1) - return FILE_GetNtStatus(); -- read( event->obj.fd, &value, sizeof(value) ); -+ read( obj->fd, &value, sizeof(value) ); - - return STATUS_SUCCESS; - } -@@ -563,31 +542,19 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) - { -- enum esync_type type = ESYNC_MUTEX; -- struct mutex *mutex; - NTSTATUS ret; -- int fd; - - TRACE("name %s, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial); - -- ret = create_esync( &type, &fd, handle, access, attr, initial ? 0 : 1, 0 ); -- if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) -+ ret = create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); -+ if (!ret) - { -- mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -- if (!mutex) -- return STATUS_NO_MEMORY; -- -- /* can't take ownership of the mutex if we didn't create it */ -- if (ret == STATUS_OBJECT_NAME_EXISTS) -- initial = FALSE; -- -- mutex->obj.type = ESYNC_MUTEX; -- mutex->obj.fd = fd; -+ /* Initialize the shared memory portion. */ -+ struct esync *obj = esync_get_object( *handle ); -+ struct mutex *mutex = obj->shm; - mutex->tid = initial ? GetCurrentThreadId() : 0; - mutex->count = initial ? 1 : 0; -- -- add_to_list( *handle, &mutex->obj); - } - - return ret; -@@ -596,41 +563,21 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -- enum esync_type type = ESYNC_MUTEX; -- struct mutex *mutex; -- NTSTATUS ret; -- int fd; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- ret = open_esync( &type, &fd, handle, access, attr ); -- if (!ret) -- { -- mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) ); -- if (!mutex) -- return STATUS_NO_MEMORY; -- -- mutex->obj.type = ESYNC_MUTEX; -- mutex->obj.fd = fd; -- -- FIXME("Attempt to open a mutex; this will not work.\n"); -- mutex->tid = 0; -- mutex->count = 0; -- -- add_to_list( *handle, &mutex->obj ); -- } -- -- return ret; -+ return open_esync( ESYNC_MUTEX, handle, access, attr ); - } - - NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - { -- struct mutex *mutex = esync_get_object( handle ); -+ struct esync *obj = esync_get_object( handle ); -+ struct mutex *mutex; - static const uint64_t value = 1; - - TRACE("%p, %p.\n", handle, prev); - -- if (!mutex) return STATUS_INVALID_HANDLE; -+ if (!obj) return STATUS_INVALID_HANDLE; -+ mutex = obj->shm; - - /* This is thread-safe, because the only thread that can change the tid to - * or from our tid is ours. */ -@@ -647,7 +594,7 @@ NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - * theirs. */ - mutex->tid = 0; - -- if (write( mutex->obj.fd, &value, sizeof(value) ) == -1) -+ if (write( obj->fd, &value, sizeof(value) ) == -1) - return FILE_GetNtStatus(); - } - -@@ -789,7 +736,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - /* 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; -+ struct mutex *mutex = obj->shm; - - if (mutex->tid == GetCurrentThreadId()) - { -@@ -844,13 +791,17 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - TRACE("Woken up by handle %p [%d].\n", handles[i], i); - if (obj->type == ESYNC_MUTEX) - { -- struct mutex *mutex = (struct mutex *)obj; -+ 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 = 1; - } - else if (obj->type == ESYNC_SEMAPHORE) - { -- struct semaphore *semaphore = (struct semaphore *)obj; -+ 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 -@@ -914,7 +865,7 @@ tryagain: - if (obj && obj->type == ESYNC_MUTEX) - { - /* It might be ours. */ -- struct mutex *mutex = (struct mutex *)obj; -+ struct mutex *mutex = obj->shm; - - if (mutex->tid == GetCurrentThreadId()) - continue; -@@ -967,7 +918,7 @@ tryagain: - { - case ESYNC_MUTEX: - { -- struct mutex *mutex = (struct mutex *)obj; -+ struct mutex *mutex = obj->shm; - if (mutex->tid == GetCurrentThreadId()) - break; - /* otherwise fall through */ -@@ -1001,13 +952,13 @@ tryagain: - { - if (objs[i]->type == ESYNC_MUTEX) - { -- struct mutex *mutex = (struct mutex *)objs[i]; -+ struct mutex *mutex = objs[i]->shm; - mutex->tid = GetCurrentThreadId(); - mutex->count++; - } - else if (objs[i]->type == ESYNC_SEMAPHORE) - { -- struct semaphore *semaphore = (struct semaphore *)objs[i]; -+ struct semaphore *semaphore = objs[i]->shm; - InterlockedDecrement( &semaphore->count ); - } - } -diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h -index f79b9a06c90..88f491e5ab4 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -19,6 +19,7 @@ - */ - - extern int do_esync(void) DECLSPEC_HIDDEN; -+extern void esync_init(void) DECLSPEC_HIDDEN; - extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index f7f9910daf6..752a0b3b622 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -51,6 +51,7 @@ - #include "wine/server.h" - #include "ntdll_misc.h" - #include "ddk/wdm.h" -+#include "esync.h" - - WINE_DEFAULT_DEBUG_CHANNEL(module); - WINE_DECLARE_DEBUG_CHANNEL(relay); -@@ -4647,6 +4648,9 @@ void __wine_process_init(void) - peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL ); - peb->LoaderLock = &loader_section; - -+ if (do_esync()) -+ esync_init(); -+ - init_unix_codepage(); - init_directories(); - init_user_process_params( info_size ); --- -2.26.2 - diff --git a/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch b/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch new file mode 100644 index 00000000..7b5350a7 --- /dev/null +++ b/patches/eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch @@ -0,0 +1,70 @@ +From 148a48dc487268a0b2d99304aee5ee4be271ded8 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 2a7c3865617..6837d0916be 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -425,6 +425,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 cb48e2cd022..599ed6dbd9b 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) DECLSPEC_HIDDEN; + extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_query_semaphore( HANDLE handle, void *info, ULONG *ret_len ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN; + + 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 4a97cdd32fd..27cc6b7723f 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -388,6 +388,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.28.0 + diff --git a/patches/eventfd_synchronization/0043-ntdll-Lock-creating-and-opening-objects-with-volatil.patch b/patches/eventfd_synchronization/0043-ntdll-Lock-creating-and-opening-objects-with-volatil.patch deleted file mode 100644 index 8c8c2b37..00000000 --- a/patches/eventfd_synchronization/0043-ntdll-Lock-creating-and-opening-objects-with-volatil.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 13a2d3a3d2f281751e7cd6ca252f49a39b82de33 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Fri, 15 Jun 2018 17:56:40 -0500 -Subject: [PATCH 43/83] ntdll: Lock creating and opening objects with volatile - state. - -Note that this also obviates using lock cmpxchg in get_shm(), but I think -it's best to leave that there; we don't really lose anything by it. ---- - dlls/ntdll/esync.c | 38 ++++++++++++++++++++++++++++++++++++-- - 1 file changed, 36 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index ce62446e6..6bfe24413 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -389,6 +389,15 @@ static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, - return ret; - } - -+RTL_CRITICAL_SECTION shm_init_section; -+static RTL_CRITICAL_SECTION_DEBUG critsect_debug = -+{ -+ 0, 0, &shm_init_section, -+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, -+ 0, 0, { (DWORD_PTR)(__FILE__ ": shm_init_section") } -+}; -+RTL_CRITICAL_SECTION shm_init_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -+ - NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) - { -@@ -397,6 +406,15 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - TRACE("name %s, initial %d, max %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial, max); - -+ /* We need this lock to protect against a potential (though unlikely) race: -+ * if a different process tries to open a named object and manages to use -+ * it between the time we get back from the server and the time we -+ * initialize the shared memory, it'll have uninitialize values for the -+ * object's state. That requires us to be REALLY slow, but we're not taking -+ * any chances. Synchronize on the CS here so that we're sure to be ready -+ * before anyone else can open the object. */ -+ RtlEnterCriticalSection( &shm_init_section ); -+ - ret = create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, EFD_SEMAPHORE ); - if (!ret) - { -@@ -409,15 +427,22 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - semaphore->count = initial; - } - -+ RtlLeaveCriticalSection( &shm_init_section ); -+ - return ret; - } - - NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -+ NTSTATUS ret; -+ - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); -+ RtlEnterCriticalSection( &shm_init_section ); -+ ret = open_esync( ESYNC_SEMAPHORE, handle, access, attr ); -+ RtlLeaveCriticalSection( &shm_init_section ); -+ return ret; - } - - NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) -@@ -547,6 +572,8 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - TRACE("name %s, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial); - -+ RtlEnterCriticalSection( &shm_init_section ); -+ - ret = create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); - if (!ret) - { -@@ -557,15 +584,22 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - mutex->count = initial ? 1 : 0; - } - -+ RtlLeaveCriticalSection( &shm_init_section ); -+ - return ret; - } - - NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -+ NTSTATUS ret; -+ - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- return open_esync( ESYNC_MUTEX, handle, access, attr ); -+ RtlEnterCriticalSection( &shm_init_section ); -+ ret = open_esync( ESYNC_MUTEX, handle, access, attr ); -+ RtlLeaveCriticalSection( &shm_init_section ); -+ return ret; - } - - NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch b/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch new file mode 100644 index 00000000..0e4f7be9 --- /dev/null +++ b/patches/eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch @@ -0,0 +1,71 @@ +From c22c32f977d17cf6e385d664ae5c52252f27f55a 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 6837d0916be..e6c331675f4 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -496,6 +496,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 599ed6dbd9b..8ac3924da2d 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 ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_reset_event( HANDLE handle ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; + +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index 27cc6b7723f..52b40c84cfc 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -581,6 +581,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.28.0 + diff --git a/patches/eventfd_synchronization/0044-server-ntdll-Pass-the-shared-memory-index-back-from-.patch b/patches/eventfd_synchronization/0044-server-ntdll-Pass-the-shared-memory-index-back-from-.patch deleted file mode 100644 index 11f58de2..00000000 --- a/patches/eventfd_synchronization/0044-server-ntdll-Pass-the-shared-memory-index-back-from-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 20207ace2ee21a22f2dc7095fd70364d54f53127 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 13 Jun 2018 15:08:26 -0500 -Subject: [PATCH 44/83] server, ntdll: Pass the shared memory index back from - get_esync_fd. - -This should let DuplicateHandle() work completely correctly for semaphores and mutexes. ---- - dlls/ntdll/esync.c | 6 +++--- - server/esync.c | 7 +++++++ - server/protocol.def | 1 + - 3 files changed, 11 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 6bfe24413..227dd3df0 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -214,6 +214,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - { - obj_handle_t fd_handle; - enum esync_type type; -+ unsigned int shm_idx; - struct esync *esync; - sigset_t sigset; - NTSTATUS ret; -@@ -231,6 +232,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - 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 ); - } -@@ -259,9 +261,7 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - esync->fd = fd; - esync->type = type; - -- if (type == ESYNC_SEMAPHORE || type == ESYNC_MUTEX) -- FIXME("Attempt to duplicate a semaphore or mutex; this will not work.\n"); -- esync->shm = NULL; -+ esync->shm = shm_idx ? get_shm( shm_idx ) : 0; - - add_to_list( handle, esync ); - -diff --git a/server/esync.c b/server/esync.c -index e9a1ec15e..5ef4dd282 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -364,6 +364,13 @@ DECL_HANDLER(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 -diff --git a/server/protocol.def b/server/protocol.def -index c2b554490..3037b8161 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4073,6 +4073,7 @@ struct handle_info - obj_handle_t handle; /* handle to the object */ - @REPLY - int type; /* esync type (defined below) */ -+ unsigned int shm_idx; /* this object's index into the shm section */ - @END - - enum esync_type --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch b/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch new file mode 100644 index 00000000..1cd1c24f --- /dev/null +++ b/patches/eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch @@ -0,0 +1,71 @@ +From b28111b0ed869637fd11d7a57440c1788bdc3a4b 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 e6c331675f4..13cdaf4f73e 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -567,6 +567,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 8ac3924da2d..18788fa273b 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 ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_query_mutex( HANDLE handle, void *info, ULONG *ret_len ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN; + + 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 52b40c84cfc..acec96c0a3c 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -696,6 +696,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.28.0 + diff --git a/patches/eventfd_synchronization/0064-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch b/patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch similarity index 79% rename from patches/eventfd_synchronization/0064-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch rename to patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch index bf221160..236602b0 100644 --- a/patches/eventfd_synchronization/0064-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch +++ b/patches/eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch @@ -1,8 +1,8 @@ -From 735941d777f8ab865de3d192bf2f878e556b9ca4 Mon Sep 17 00:00:00 2001 +From 620371ae80be978b427c6d13e8f7b059bd4bb900 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sat, 7 Jul 2018 12:57:47 +0200 -Subject: [PATCH 64/83] server: Create eventfd descriptors for pseudo-fd - objects and use them for named pipes. +Subject: [PATCH] server: Create eventfd descriptors for pseudo-fd objects and + use them for named pipes. --- server/fd.c | 22 ++++++++++++++++++++++ @@ -11,10 +11,10 @@ Subject: [PATCH 64/83] server: Create eventfd descriptors for pseudo-fd 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/server/fd.c b/server/fd.c -index a855c27d5..9e2f2c2cd 100644 +index d3b1e515b52..a7d81ec055b 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -101,6 +101,7 @@ +@@ -102,6 +102,7 @@ #include "handle.h" #include "process.h" #include "request.h" @@ -22,7 +22,7 @@ index a855c27d5..9e2f2c2cd 100644 #include "winternl.h" #include "winioctl.h" -@@ -195,6 +196,7 @@ struct fd +@@ -203,6 +204,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 */ @@ -30,8 +30,8 @@ index a855c27d5..9e2f2c2cd 100644 }; static void fd_dump( struct object *obj, int verbose ); -@@ -1500,6 +1502,9 @@ static void fd_destroy( struct object *obj ) - if (fd->unix_fd != -1) close( fd->unix_fd ); +@@ -1593,6 +1595,9 @@ static void fd_destroy( struct object *obj ) + free( fd->unlink_name ); free( fd->unix_name ); } + @@ -40,7 +40,7 @@ index a855c27d5..9e2f2c2cd 100644 } /* check if the desired access is possible without violating */ -@@ -1614,6 +1619,7 @@ static struct fd *alloc_fd_object(void) +@@ -1708,6 +1713,7 @@ static struct fd *alloc_fd_object(void) fd->poll_index = -1; fd->completion = NULL; fd->comp_flags = 0; @@ -48,7 +48,7 @@ index a855c27d5..9e2f2c2cd 100644 init_async_queue( &fd->read_q ); init_async_queue( &fd->write_q ); init_async_queue( &fd->wait_q ); -@@ -1651,11 +1657,15 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use +@@ -1746,11 +1752,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; @@ -64,7 +64,7 @@ index a855c27d5..9e2f2c2cd 100644 return fd; } -@@ -2011,6 +2021,9 @@ void set_fd_signaled( struct fd *fd, int signaled ) +@@ -2149,6 +2159,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 ); @@ -73,8 +73,8 @@ index a855c27d5..9e2f2c2cd 100644 + esync_clear( fd->esync_fd ); } - /* check if fd is signaled */ -@@ -2048,6 +2061,15 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) + /* handler for close_handle that refuses to close fd-associated handles in other processes */ +@@ -2180,6 +2193,15 @@ int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) return ret; } @@ -91,10 +91,10 @@ index a855c27d5..9e2f2c2cd 100644 unsigned int default_fd_map_access( struct object *obj, unsigned int access ) { diff --git a/server/file.h b/server/file.h -index 25561efc9..2bea2554b 100644 +index 477720f8b18..de260e29ddb 100644 --- a/server/file.h +++ b/server/file.h -@@ -103,6 +103,7 @@ extern int is_fd_signaled( struct fd *fd ); +@@ -102,6 +102,7 @@ extern void set_fd_signaled( struct fd *fd, int signaled ); extern char *dup_fd_name( struct fd *root, const char *name ); extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); @@ -103,10 +103,10 @@ index 25561efc9..2bea2554b 100644 extern int default_fd_get_poll_events( struct fd *fd ); extern void default_poll_event( struct fd *fd, int event ); diff --git a/server/named_pipe.c b/server/named_pipe.c -index aa3a8b7b7..dc8b9f635 100644 +index 9ab99d915b9..b438682d214 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c -@@ -161,7 +161,7 @@ static const struct object_ops pipe_server_ops = +@@ -163,7 +163,7 @@ static const struct object_ops pipe_server_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -115,7 +115,7 @@ index aa3a8b7b7..dc8b9f635 100644 no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ -@@ -204,7 +204,7 @@ static const struct object_ops pipe_client_ops = +@@ -207,7 +207,7 @@ static const struct object_ops pipe_client_ops = add_queue, /* add_queue */ remove_queue, /* remove_queue */ default_fd_signaled, /* signaled */ @@ -125,5 +125,5 @@ index aa3a8b7b7..dc8b9f635 100644 no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0066-esync-Update-README.patch b/patches/eventfd_synchronization/0047-esync-Update-README.patch similarity index 93% rename from patches/eventfd_synchronization/0066-esync-Update-README.patch rename to patches/eventfd_synchronization/0047-esync-Update-README.patch index bede0b45..edb79f68 100644 --- a/patches/eventfd_synchronization/0066-esync-Update-README.patch +++ b/patches/eventfd_synchronization/0047-esync-Update-README.patch @@ -1,14 +1,14 @@ -From 10f5229d4f0740c36e01f2e5ab35faefcec55eaa Mon Sep 17 00:00:00 2001 +From 2565f5c43a6acedee00a029947ed91d724ea0b67 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 4 Jul 2018 14:58:33 +0200 -Subject: [PATCH 66/83] esync: Update README. +Subject: [PATCH] esync: Update README. --- README.esync | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.esync b/README.esync -index 627cc3f48..30e241755 100644 +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 @@ -51,5 +51,5 @@ index 627cc3f48..30e241755 100644 these, except perhaps named pipes (which would honestly be rather difficult) and (maybe) timers. -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0067-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 similarity index 85% rename from patches/eventfd_synchronization/0067-esync-Add-note-about-file-limits-not-being-raised-wh.patch rename to patches/eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch index 41456e05..0de735aa 100644 --- a/patches/eventfd_synchronization/0067-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 @@ -1,15 +1,15 @@ -From 49055d312f46cb413b1cbbc47d88d64651331ec9 Mon Sep 17 00:00:00 2001 +From a92204fc7b6569c625a95bfed1a76c54b2998169 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 Jul 2018 12:56:50 -0700 -Subject: [PATCH 67/83] esync: Add note about file limits not being raised when - using systemd. +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 30e241755..7706f395e 100644 +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 @@ -37,5 +37,5 @@ index 30e241755..7706f395e 100644 \ No newline at end of file +--Zebediah Figura -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0069-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch b/patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch similarity index 83% rename from patches/eventfd_synchronization/0069-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch rename to patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch index b74f1cc6..56e30604 100644 --- a/patches/eventfd_synchronization/0069-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch +++ b/patches/eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch @@ -1,20 +1,20 @@ -From ecf0f52e7d1e3978aed20e585fe9068f8427d26d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 26 Jul 2018 10:01:54 -0600 -Subject: [PATCH 69/83] ntdll: Try to avoid poll() for uncontended objects. +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/esync.c | 60 ++++++++++++++++++++++++++++++++++++++-------- + dlls/ntdll/unix/esync.c | 60 ++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 10 deletions(-) -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 506d1c99d..4e5fcef8e 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -869,23 +869,63 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an +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) { @@ -30,7 +30,7 @@ index 506d1c99d..4e5fcef8e 100644 - /* 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 = obj->shm; +- struct mutex *mutex = (struct mutex *)obj; + switch (obj->type) + { + case ESYNC_MUTEX: @@ -89,5 +89,5 @@ index 506d1c99d..4e5fcef8e 100644 } -- -2.20.1 +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 new file mode 100644 index 00000000..79f99c8d --- /dev/null +++ b/patches/eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch @@ -0,0 +1,287 @@ +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/0075-esync-Update-README.patch b/patches/eventfd_synchronization/0051-esync-Update-README.patch similarity index 93% rename from patches/eventfd_synchronization/0075-esync-Update-README.patch rename to patches/eventfd_synchronization/0051-esync-Update-README.patch index 1b57edbb..5d584c0a 100644 --- a/patches/eventfd_synchronization/0075-esync-Update-README.patch +++ b/patches/eventfd_synchronization/0051-esync-Update-README.patch @@ -1,14 +1,14 @@ -From 930e29146eaee56a2e0a4aa1c122717e96ff1ec8 Mon Sep 17 00:00:00 2001 +From 3e93bc895e5d943d02b5dfaa0b80c73dcf53c1b8 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sat, 4 Aug 2018 15:18:24 -0500 -Subject: [PATCH 75/83] esync: Update README. +Subject: [PATCH] esync: Update README. --- README.esync | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.esync b/README.esync -index 7706f395e..b64bfefc1 100644 +index 7706f395ebd..b64bfefc1a3 100644 --- a/README.esync +++ b/README.esync @@ -5,7 +5,7 @@ with +esync. @@ -48,5 +48,5 @@ index 7706f395e..b64bfefc1 100644 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.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0052-ntdll-Go-through-the-server-if-necessary-when-perfor.patch b/patches/eventfd_synchronization/0052-ntdll-Go-through-the-server-if-necessary-when-perfor.patch deleted file mode 100644 index cd6becbf..00000000 --- a/patches/eventfd_synchronization/0052-ntdll-Go-through-the-server-if-necessary-when-perfor.patch +++ /dev/null @@ -1,182 +0,0 @@ -From f0c5814c083c825326b2e3d3bc03e688262f4012 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 19 Jun 2018 10:50:09 -0500 -Subject: [PATCH 52/83] ntdll: Go through the server if necessary when - performing event/semaphore/mutex ops. - -Because we might have a duplicated or inherited handle, and we won't know about it until we ask the server. ---- - dlls/ntdll/esync.c | 50 +++++++++++++++++++++++++++------------------- - 1 file changed, 29 insertions(+), 21 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 583174499..5eef7e3c8 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -197,7 +197,7 @@ static BOOL add_to_list( HANDLE handle, struct esync *obj ) - return TRUE; - } - --static void *esync_get_object( HANDLE handle ) -+static struct esync *get_cached_object( HANDLE handle ) - { - UINT_PTR entry, idx = handle_to_index( handle, &entry ); - -@@ -206,11 +206,14 @@ static void *esync_get_object( HANDLE handle ) - return esync_list[entry][idx]; - } - --/* Gets a waitable object. This is either a proper esync object (i.e. an event, -+/* 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_waitable_object( HANDLE handle, struct esync **obj ) -+ * message queue, etc.) -+ * -+ * Note that we have to make the server path available even for esync objects -+ * since we might be passed a duplicated or inherited handle. */ -+static NTSTATUS get_object( HANDLE handle, struct esync **obj ) - { - obj_handle_t fd_handle; - enum esync_type type; -@@ -220,11 +223,11 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj ) - NTSTATUS ret; - int fd; - -- if ((*obj = esync_get_object( handle ))) return STATUS_SUCCESS; -+ if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS; - - /* We need to try grabbing it from the server. */ - server_enter_uninterrupted_section( &fd_cache_section, &sigset ); -- if (!(esync = esync_get_object( handle ))) -+ if (!(esync = get_cached_object( handle ))) - { - SERVER_START_REQ( get_esync_fd ) - { -@@ -421,7 +424,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - /* Initialize the shared memory portion. - * Note we store max here (even though we don't need to) just to keep - * it the same size as the mutex's shm portion. */ -- struct esync *obj = esync_get_object( *handle ); -+ struct esync *obj = get_cached_object( *handle ); - struct semaphore *semaphore = obj->shm; - semaphore->max = max; - semaphore->count = initial; -@@ -447,14 +450,15 @@ NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - - NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - { -- struct esync *obj = esync_get_object( handle ); -+ struct esync *obj; - struct semaphore *semaphore; - uint64_t count64 = count; - ULONG current; -+ NTSTATUS ret; - - TRACE("%p, %d, %p.\n", handle, count, prev); - -- if (!obj) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj))) return ret; - semaphore = obj->shm; - - do -@@ -499,12 +503,13 @@ NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - - NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - { -- struct esync *obj = esync_get_object( handle ); - static const uint64_t value = 1; -+ struct esync *obj; -+ NTSTATUS ret; - - TRACE("%p.\n", handle); - -- if (!obj) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj ))) return ret; - - if (prev) - { -@@ -520,12 +525,13 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - - NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - { -- struct esync *obj = esync_get_object( handle ); - static uint64_t value; -+ struct esync *obj; -+ NTSTATUS ret; - - TRACE("%p.\n", handle); - -- if (!obj) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj ))) return ret; - - if (prev) - { -@@ -541,12 +547,13 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - - NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - { -- struct esync *obj = esync_get_object( handle ); - static uint64_t value = 1; -+ struct esync *obj; -+ NTSTATUS ret; - - TRACE("%p.\n", handle); - -- if (!obj) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( handle, &obj ))) return ret; - - if (prev) - { -@@ -578,7 +585,7 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - if (!ret) - { - /* Initialize the shared memory portion. */ -- struct esync *obj = esync_get_object( *handle ); -+ struct esync *obj = get_cached_object( *handle ); - struct mutex *mutex = obj->shm; - mutex->tid = initial ? GetCurrentThreadId() : 0; - mutex->count = initial ? 1 : 0; -@@ -604,13 +611,14 @@ NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, - - NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - { -- struct esync *obj = esync_get_object( handle ); -+ struct esync *obj; - struct mutex *mutex; - static const uint64_t value = 1; -+ NTSTATUS ret; - - TRACE("%p, %p.\n", handle, prev); - -- if (!obj) return STATUS_INVALID_HANDLE; -+ 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 -@@ -734,7 +742,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - - for (i = 0; i < count; i++) - { -- ret = get_waitable_object( handles[i], &objs[i] ); -+ ret = get_object( handles[i], &objs[i] ); - if (ret == STATUS_SUCCESS) - has_esync = 1; - else if (ret == STATUS_NOT_IMPLEMENTED) -@@ -1091,10 +1099,10 @@ userapc: - NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, - const LARGE_INTEGER *timeout ) - { -- struct esync *obj = esync_get_object( signal ); -+ struct esync *obj; - NTSTATUS ret; - -- if (!obj) return STATUS_INVALID_HANDLE; -+ if ((ret = get_object( signal, &obj ))) return ret; - - switch (obj->type) - { --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch b/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch new file mode 100644 index 00000000..dd6b7ce3 --- /dev/null +++ b/patches/eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch @@ -0,0 +1,76 @@ +From bb81fa475b3aa206fe1e8ff914d41de292aa9807 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 91a85253a83..d7511f39601 100644 +--- a/dlls/ntdll/unix/esync.c ++++ b/dlls/ntdll/unix/esync.c +@@ -607,6 +607,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 18788fa273b..188304f3be7 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 ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, + const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; ++extern NTSTATUS esync_pulse_event( HANDLE handle ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_query_event( HANDLE handle, void *info, ULONG *ret_len ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_reset_event( HANDLE handle ) DECLSPEC_HIDDEN; + extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN; +diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c +index acec96c0a3c..051c672bd12 100644 +--- a/dlls/ntdll/unix/sync.c ++++ b/dlls/ntdll/unix/sync.c +@@ -549,6 +549,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state ) + { + NTSTATUS ret; + ++ if (do_esync()) ++ return esync_pulse_event( handle ); ++ + SERVER_START_REQ( event_op ) + { + req->handle = wine_server_obj_handle( handle ); +-- +2.28.0 + diff --git a/patches/eventfd_synchronization/0083-esync-Update-README.patch b/patches/eventfd_synchronization/0053-esync-Update-README.patch similarity index 76% rename from patches/eventfd_synchronization/0083-esync-Update-README.patch rename to patches/eventfd_synchronization/0053-esync-Update-README.patch index bb2aaa28..e998b1b0 100644 --- a/patches/eventfd_synchronization/0083-esync-Update-README.patch +++ b/patches/eventfd_synchronization/0053-esync-Update-README.patch @@ -1,14 +1,14 @@ -From 3f08e4af150adc7e08c15a6836ca6bb8c71746ee Mon Sep 17 00:00:00 2001 +From 64d0157285ea05a7ea934d8567ce1a6087fb1d41 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 19 Aug 2018 13:40:05 -0500 -Subject: [PATCH 83/83] esync: Update README. +Subject: [PATCH] esync: Update README. --- README.esync | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.esync b/README.esync -index b64bfefc1..11d86563a 100644 +index b64bfefc1a3..11d86563a10 100644 --- a/README.esync +++ b/README.esync @@ -1,6 +1,5 @@ @@ -20,5 +20,5 @@ index b64bfefc1..11d86563a 100644 == BUGS AND LIMITATIONS == -- -2.20.1 +2.28.0 diff --git a/patches/eventfd_synchronization/0053-server-Create-eventfd-descriptors-for-console_input_.patch b/patches/eventfd_synchronization/0053-server-Create-eventfd-descriptors-for-console_input_.patch deleted file mode 100644 index aa97e143..00000000 --- a/patches/eventfd_synchronization/0053-server-Create-eventfd-descriptors-for-console_input_.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 3c9b318c047c0ec2397401ea329f59aa64690cf5 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 19 Jun 2018 11:27:58 -0500 -Subject: [PATCH 53/83] server: Create eventfd descriptors for - console_input_events objects. - ---- - server/console.c | 19 ++++++++++++++++++- - 1 file changed, 18 insertions(+), 1 deletion(-) - -diff --git a/server/console.c b/server/console.c -index 059839e06..c32270855 100644 ---- a/server/console.c -+++ b/server/console.c -@@ -38,6 +38,7 @@ - #include "unicode.h" - #include "wincon.h" - #include "winternl.h" -+#include "esync.h" - - struct screen_buffer; - struct console_input_events; -@@ -96,6 +97,7 @@ static const struct object_ops console_input_ops = - static void console_input_events_dump( struct object *obj, int verbose ); - static void console_input_events_destroy( struct object *obj ); - static int console_input_events_signaled( struct object *obj, struct wait_queue_entry *entry ); -+static int console_input_events_get_esync_fd( struct object *obj, enum esync_type *type ); - - struct console_input_events - { -@@ -103,6 +105,7 @@ struct console_input_events - int num_alloc; /* number of allocated events */ - int num_used; /* number of actually used events */ - struct console_renderer_event* events; -+ int esync_fd; /* esync file descriptor (signalled when events present) */ - }; - - static const struct object_ops console_input_events_ops = -@@ -113,7 +116,7 @@ static const struct object_ops console_input_events_ops = - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - console_input_events_signaled, /* signaled */ -- NULL, /* get_esync_fd */ -+ console_input_events_get_esync_fd,/* get_esync_fd */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ -@@ -253,6 +256,13 @@ static int console_input_events_signaled( struct object *obj, struct wait_queue_ - return (evts->num_used != 0); - } - -+static int console_input_events_get_esync_fd( struct object *obj, enum esync_type *type ) -+{ -+ struct console_input_events *evts = (struct console_input_events *)obj; -+ *type = ESYNC_MANUAL_SERVER; -+ return evts->esync_fd; -+} -+ - /* add an event to the console's renderer events list */ - static void console_input_events_append( struct console_input* console, - struct console_renderer_event* evt) -@@ -307,6 +317,9 @@ static void console_input_events_get( struct console_input_events* evts ) - (evts->num_used - num) * sizeof(evts->events[0]) ); - } - evts->num_used -= num; -+ -+ if (do_esync() && !evts->num_used) -+ esync_clear( evts->esync_fd ); - } - - static struct console_input_events *create_console_input_events(void) -@@ -316,6 +329,10 @@ static struct console_input_events *create_console_input_events(void) - if (!(evt = alloc_object( &console_input_events_ops ))) return NULL; - evt->num_alloc = evt->num_used = 0; - evt->events = NULL; -+ evt->esync_fd = -1; -+ -+ if (do_esync()) -+ evt->esync_fd = esync_create_fd( 0, 0 ); - return evt; - } - --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0054-server-Alter-conditions-in-is_queue_hung-again.patch b/patches/eventfd_synchronization/0054-server-Alter-conditions-in-is_queue_hung-again.patch deleted file mode 100644 index be05ffd3..00000000 --- a/patches/eventfd_synchronization/0054-server-Alter-conditions-in-is_queue_hung-again.patch +++ /dev/null @@ -1,52 +0,0 @@ -From ac4712c326cdda97942befa72a83142e10969697 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 20 Jun 2018 13:30:45 -0500 -Subject: [PATCH 54/83] server: Alter conditions in is_queue_hung(), again. - -Complications with SMTO_ABORTIFHUNG lead to implementing this function -exactly correctly. - -On Windows, a queue is not hung if you somehow process messages (doesn't -matter how), or if you call MsgWaitForMultipleObjects(). - -In a sense, Wine had this correct, except not exactly. Firstly, you can call -MsgWait(0, NULL, FALSE, 0, 0); Sleep(1000); in a loop and not be considered -hung; i.e. you don't have to be actively waiting on the queue, but can just -poll it. You also don't have to have a mask that lets in any events--but -just calling WaitForMultipleObjects() isn't enough. On the other hand, -calling MsgWait(0, NULL, FALSE, INFINITE, 0) will result in a hung queue. - -last_get_msg should probably be renamed, but nothing better comes to mind. ---- - server/queue.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/server/queue.c b/server/queue.c -index e217a5e6a..16ed7c5d3 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -975,7 +975,7 @@ static void cleanup_results( struct msg_queue *queue ) - /* check if the thread owning the queue is hung (not checking for messages) */ - static int is_queue_hung( struct msg_queue *queue ) - { -- return is_signaled( queue ) && (current_time - queue->last_get_msg > 5 * TICKS_PER_SEC); -+ return (current_time - queue->last_get_msg > 5 * TICKS_PER_SEC); - } - - static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ) -@@ -991,6 +991,12 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent - } - if (process->idle_event && !(queue->wake_mask & QS_SMRESULT)) set_event( process->idle_event ); - -+ /* On Windows, we are considered hung iff we have not somehow processed -+ * messages OR done a MsgWait call in the last 5 seconds. Note that in the -+ * latter case repeatedly waiting for 0 seconds is not hung, but waiting -+ * forever is hung, so this is correct. */ -+ queue->last_get_msg = current_time; -+ - if (queue->fd && list_empty( &obj->wait_queue )) /* first on the queue */ - set_fd_events( queue->fd, POLLIN ); - add_queue( obj, entry ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0084-server-Use-default_fd_get_esync_fd-for-directory-cha.patch b/patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch similarity index 84% rename from patches/eventfd_synchronization/0084-server-Use-default_fd_get_esync_fd-for-directory-cha.patch rename to patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch index bbd3be0f..4c1c345e 100644 --- a/patches/eventfd_synchronization/0084-server-Use-default_fd_get_esync_fd-for-directory-cha.patch +++ b/patches/eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch @@ -1,4 +1,4 @@ -From 770e803adbc13c78ee52c7e8435d651da854fcf1 Mon Sep 17 00:00:00 2001 +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 @@ -10,7 +10,7 @@ Subject: [PATCH] server: Create esync file descriptors for true file objects 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/change.c b/server/change.c -index 2be6a8360..9f07be705 100644 +index a79b6d61939..9c84f01180c 100644 --- a/server/change.c +++ b/server/change.c @@ -115,7 +115,7 @@ static const struct object_ops dir_ops = @@ -23,10 +23,10 @@ index 2be6a8360..9f07be705 100644 no_signal, /* signal */ dir_get_fd, /* get_fd */ diff --git a/server/fd.c b/server/fd.c -index 95f289718..9f51d065e 100644 +index a7d81ec055b..ea6ece2a111 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -1626,6 +1626,9 @@ static struct fd *alloc_fd_object(void) +@@ -1720,6 +1720,9 @@ static struct fd *alloc_fd_object(void) list_init( &fd->inode_entry ); list_init( &fd->locks ); @@ -37,5 +37,5 @@ index 95f289718..9f51d065e 100644 { release_object( fd ); -- -2.21.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0055-ntdll-Let-the-server-know-when-we-are-doing-a-messag.patch b/patches/eventfd_synchronization/0055-ntdll-Let-the-server-know-when-we-are-doing-a-messag.patch deleted file mode 100644 index 32b363ef..00000000 --- a/patches/eventfd_synchronization/0055-ntdll-Let-the-server-know-when-we-are-doing-a-messag.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 5262cc2c80ae65a0144dffb16072473149c70da7 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 20 Jun 2018 13:41:12 -0500 -Subject: [PATCH] ntdll: Let the server know when we are doing a message wait. - ---- - dlls/ntdll/esync.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 80f659d6fde..f2dc32f3a0e 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -753,11 +753,22 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - - if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE) - { -+ select_op_t select_op; -+ - /* Last object in the list is a queue, which means someone is using - * MsgWaitForMultipleObjects(). We have to wait not only for the server - * fd (signaled on send_message, etc.) but also the USER driver's fd - * (signaled on e.g. X11 events.) */ - msgwait = TRUE; -+ -+ /* We need to let the server know we are doing a message wait, for two -+ * reasons. First one is WaitForInputIdle(). Second one is checking for -+ * hung queues. Do it like this. */ -+ select_op.wait.op = SELECT_WAIT; -+ select_op.wait.handles[0] = wine_server_obj_handle( handles[count - 1] ); -+ ret = server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &zero ); -+ if (ret != STATUS_WAIT_0 && ret != STATUS_TIMEOUT) -+ ERR("Unexpected ret %#x\n", ret); - } - - if (has_esync && has_server) --- -2.26.0 - diff --git a/patches/eventfd_synchronization/0089-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch b/patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch similarity index 73% rename from patches/eventfd_synchronization/0089-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch rename to patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch index d6085595..019a88d2 100644 --- a/patches/eventfd_synchronization/0089-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch +++ b/patches/eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch @@ -1,21 +1,20 @@ -From c00917721a5076b90e3e61a7d326ef485c1f9dfb Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 17 Feb 2020 11:28:37 -0600 +From 5126b7e8cd315c7e85d84b897fd2d271d62d91c1 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. -Signed-off-by: Zebediah Figura --- - dlls/ntdll/esync.c | 31 ++++++++++++++++++++++++++----- - server/esync.c | 32 +++++++++++++++++++++++++++++--- - server/esync.h | 1 + - server/thread.c | 2 ++ - 4 files changed, 58 insertions(+), 8 deletions(-) + 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/esync.c b/dlls/ntdll/esync.c -index 87f303403..c2190f2fd 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -807,7 +807,7 @@ NTSTATUS esync_query_mutex( HANDLE handle, MUTANT_INFORMATION_CLASS class, +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()); @@ -24,7 +23,7 @@ index 87f303403..c2190f2fd 100644 if (ret_len) *ret_len = sizeof(*out); return STATUS_SUCCESS; -@@ -857,14 +857,19 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) +@@ -767,14 +767,19 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) return ret; } @@ -45,7 +44,7 @@ index 87f303403..c2190f2fd 100644 mutex->tid = GetCurrentThreadId(); mutex->count++; } -@@ -885,6 +890,8 @@ static void update_grabbed_object( struct esync *obj ) +@@ -795,6 +800,8 @@ static void update_grabbed_object( struct esync *obj ) * This might already be 0, but that's okay! */ event->signaled = 0; } @@ -54,7 +53,7 @@ index 87f303403..c2190f2fd 100644 } /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we -@@ -1018,7 +1025,13 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, +@@ -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)) { @@ -69,7 +68,7 @@ index 87f303403..c2190f2fd 100644 mutex->tid = GetCurrentThreadId(); mutex->count++; return i; -@@ -1136,7 +1149,8 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, +@@ -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); @@ -79,16 +78,16 @@ index 87f303403..c2190f2fd 100644 return i; } } -@@ -1255,6 +1269,8 @@ tryagain: +@@ -1120,6 +1134,8 @@ tryagain: ret = poll( fds, pollcount, 0 ); if (ret == pollcount) { + BOOL abandoned = FALSE; + /* Quick, grab everything. */ - for (i = 0; i < pollcount; i++) + for (i = 0; i < count; i++) { -@@ -1295,8 +1311,13 @@ tryagain: +@@ -1160,8 +1176,13 @@ tryagain: /* Make sure to let ourselves know that we grabbed the mutexes * and semaphores. */ for (i = 0; i < count; i++) @@ -104,10 +103,10 @@ index 87f303403..c2190f2fd 100644 return STATUS_SUCCESS; } diff --git a/server/esync.c b/server/esync.c -index 040e24e69..1b035bdb0 100644 +index 11785d28bab..d79be851c8f 100644 --- a/server/esync.c +++ b/server/esync.c -@@ -104,12 +104,15 @@ void esync_init(void) +@@ -105,12 +105,15 @@ void esync_init(void) atexit( shm_cleanup ); } @@ -115,18 +114,15 @@ index 040e24e69..1b035bdb0 100644 + struct esync { -- struct object obj; /* object header */ -- int fd; /* eventfd file descriptor */ -+ struct object obj; /* object header */ -+ int fd; /* eventfd file descriptor */ + struct object obj; /* object header */ + int fd; /* eventfd file descriptor */ enum esync_type type; -- unsigned int shm_idx; /* index into the shared memory section */ -+ unsigned int shm_idx; /* index into the shared memory section */ + 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 ); -@@ -168,6 +171,8 @@ static unsigned int esync_map_access( struct object *obj, unsigned int access ) +@@ -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; @@ -135,7 +131,7 @@ index 040e24e69..1b035bdb0 100644 close( esync->fd ); } -@@ -301,6 +306,7 @@ static struct esync *create_esync( struct object *root, const struct unicode_str +@@ -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; @@ -143,13 +139,12 @@ index 040e24e69..1b035bdb0 100644 break; } default: -@@ -447,6 +453,26 @@ void esync_reset_event( struct esync *esync ) +@@ -451,6 +457,25 @@ void esync_reset_event( struct esync *esync ) } } +void esync_abandon_mutexes( struct thread *thread ) +{ -+ unsigned int index = 0; + struct esync *esync; + + LIST_FOR_EACH_ENTRY( esync, &mutex_list, struct esync, mutex_entry ) @@ -171,7 +166,7 @@ index 040e24e69..1b035bdb0 100644 { struct esync *esync; diff --git a/server/esync.h b/server/esync.h -index cea025d93..125da8e9d 100644 +index cea025d9308..125da8e9d12 100644 --- a/server/esync.h +++ b/server/esync.h @@ -30,3 +30,4 @@ struct esync; @@ -180,10 +175,10 @@ index cea025d93..125da8e9d 100644 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 d1923b4e8..1d5bca525 100644 +index 6fb8684f5e0..f320f2b26e9 100644 --- a/server/thread.c +++ b/server/thread.c -@@ -1253,6 +1253,8 @@ void kill_thread( struct thread *thread, int violent_death ) +@@ -1328,6 +1328,8 @@ void kill_thread( struct thread *thread, int violent_death ) kill_console_processes( thread, 0 ); debug_exit_thread( thread ); abandon_mutexes( thread ); @@ -193,5 +188,5 @@ index d1923b4e8..1d5bca525 100644 { send_thread_signal( thread, SIGQUIT ); -- -2.25.0 +2.28.0 diff --git a/patches/eventfd_synchronization/0056-ntdll-Avoid-server_select-when-waiting-for-critical-.patch b/patches/eventfd_synchronization/0056-ntdll-Avoid-server_select-when-waiting-for-critical-.patch deleted file mode 100644 index 18b34e47..00000000 --- a/patches/eventfd_synchronization/0056-ntdll-Avoid-server_select-when-waiting-for-critical-.patch +++ /dev/null @@ -1,34 +0,0 @@ -From ffbf02d62296a0a0f56d3792bad1ff107d2ef725 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 20 Jun 2018 14:04:04 -0500 -Subject: [PATCH] ntdll: Avoid server_select() when waiting for critical - sections. - -There's no reason not to always use NtWaitForSingleObject(), so just do that. - -And of course this lets esync work right. ---- - dlls/ntdll/critsection.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c -index 1892d3abcb7..32907703730 100644 ---- a/dlls/ntdll/critsection.c -+++ b/dlls/ntdll/critsection.c -@@ -237,12 +237,9 @@ static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout ) - { - HANDLE sem = get_semaphore( crit ); - LARGE_INTEGER time; -- select_op_t select_op; - - time.QuadPart = timeout * (LONGLONG)-10000000; -- select_op.wait.op = SELECT_WAIT; -- select_op.wait.handles[0] = wine_server_obj_handle( sem ); -- ret = server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &time ); -+ ret = NtWaitForSingleObject( sem, FALSE, &time ); - } - return ret; - } --- -2.26.0 - diff --git a/patches/eventfd_synchronization/0057-user32-Remove-hooks-that-time-out.patch b/patches/eventfd_synchronization/0057-user32-Remove-hooks-that-time-out.patch deleted file mode 100644 index 600a3c5d..00000000 --- a/patches/eventfd_synchronization/0057-user32-Remove-hooks-that-time-out.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 9d4292cad821b6eb8a43a5fe122d1acb931b6897 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 20 Jun 2018 15:07:28 -0500 -Subject: [PATCH 57/83] user32: Remove hooks that time out. - -In accordance with Win7+ behaviour. ---- - dlls/user32/hook.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c -index 3aa7b33a8..79171fac0 100644 ---- a/dlls/user32/hook.c -+++ b/dlls/user32/hook.c -@@ -381,6 +381,7 @@ void *get_hook_proc( void *proc, const WCHAR *module, HMODULE *free_module ) - static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARAM lparam ) - { - DWORD_PTR ret = 0; -+ LRESULT lres; - - if (info->tid) - { -@@ -394,20 +395,24 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA - switch(info->id) - { - case WH_KEYBOARD_LL: -- MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, -- wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, -- get_ll_hook_timeout(), &ret ); -+ lres = MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, -+ wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); - break; - case WH_MOUSE_LL: -- MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, -- wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, -- get_ll_hook_timeout(), &ret ); -+ lres = MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, -+ wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); - break; - default: - ERR("Unknown hook id %d\n", info->id); - assert(0); - break; - } -+ -+ if (!lres && GetLastError() == ERROR_TIMEOUT) -+ { -+ TRACE("Hook %p timed out; removing it.\n", info->handle); -+ UnhookWindowsHookEx( info->handle ); -+ } - } - else if (info->proc) - { --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0058-server-Don-t-check-for-a-hung-queue-when-sending-low.patch b/patches/eventfd_synchronization/0058-server-Don-t-check-for-a-hung-queue-when-sending-low.patch deleted file mode 100644 index 68afc746..00000000 --- a/patches/eventfd_synchronization/0058-server-Don-t-check-for-a-hung-queue-when-sending-low.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5e533251f60d54e5660b81ff847f09408ed3d281 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 20 Jun 2018 15:10:08 -0500 -Subject: [PATCH] server: Don't check for a hung queue when sending low-level - hooks. - -Since user32 does this. - -This logic is independent of the SMTO_ABORTIFHUNG logic on Windows. In fact, IsHungAppWindow() uses yet another algorithm. ---- - server/queue.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/server/queue.c b/server/queue.c -index 16ed7c5d3dc..174a4ac09f9 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -1688,7 +1688,6 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa - - if (!(hook_thread = get_first_global_hook( id ))) return 0; - if (!(queue = hook_thread->queue)) return 0; -- if (is_queue_hung( queue )) return 0; - - if (!(msg = mem_alloc( sizeof(*msg) ))) return 0; - --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0060-server-Try-to-remove-a-pre-xisting-shm-file.patch b/patches/eventfd_synchronization/0060-server-Try-to-remove-a-pre-xisting-shm-file.patch deleted file mode 100644 index b9a588d5..00000000 --- a/patches/eventfd_synchronization/0060-server-Try-to-remove-a-pre-xisting-shm-file.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ada3afff191a9781b1109ef4a30b541c9bfeb09d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 1 Jul 2018 12:00:09 +0200 -Subject: [PATCH 60/83] =?UTF-8?q?server:=20Try=20to=20remove=20a=20pre?= - =?UTF-8?q?=C3=ABxisting=20shm=20file.?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This should have been removed even if wineserver was killed, but if someone -uses SIGKILL or something similar we should try to handle that gracefully. ---- - server/esync.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/server/esync.c b/server/esync.c -index 4fb42e6f9..a2f828173 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -84,6 +84,8 @@ void esync_init(void) - 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" ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0061-ntdll-Implement-NtQuerySemaphore.patch b/patches/eventfd_synchronization/0061-ntdll-Implement-NtQuerySemaphore.patch deleted file mode 100644 index de6b95f3..00000000 --- a/patches/eventfd_synchronization/0061-ntdll-Implement-NtQuerySemaphore.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 4bcee007d0380fe04426d68ca090f0300b03ddd0 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 4 Jul 2018 14:34:37 +0200 -Subject: [PATCH 61/83] ntdll: Implement NtQuerySemaphore(). - ---- - dlls/ntdll/esync.c | 26 ++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 31 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index d935a4af5..90241289d 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -481,6 +481,32 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_query_semaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) -+{ -+ struct esync *obj; -+ struct semaphore *semaphore; -+ SEMAPHORE_BASIC_INFORMATION *out = info; -+ NTSTATUS ret; -+ -+ TRACE("%p, %u, %p, %u, %p.\n", handle, class, info, len, ret_len); -+ -+ if (class != SemaphoreBasicInformation) -+ { -+ FIXME("(%p,%d,%u) Unknown class\n", handle, class, len); -+ return STATUS_INVALID_INFO_CLASS; -+ } -+ -+ 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/esync.h b/dlls/ntdll/esync.h -index 88f491e5a..39a4dfbbe 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -39,6 +39,8 @@ extern NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_query_semaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 2f8d6fe5c..95850d7a8 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -305,6 +305,9 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla - NTSTATUS ret; - SEMAPHORE_BASIC_INFORMATION *out = info; - -+ if (do_esync()) -+ return esync_query_semaphore( handle, class, info, len, ret_len ); -+ - TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len); - - if (class != SemaphoreBasicInformation) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0062-ntdll-Implement-NtQueryEvent.patch b/patches/eventfd_synchronization/0062-ntdll-Implement-NtQueryEvent.patch deleted file mode 100644 index 3571302a..00000000 --- a/patches/eventfd_synchronization/0062-ntdll-Implement-NtQueryEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 04d5bb8ddc3e77feb8b14fccbb3f605a35684d38 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 4 Jul 2018 14:40:30 +0200 -Subject: [PATCH 62/83] ntdll: Implement NtQueryEvent(). - ---- - dlls/ntdll/esync.c | 27 +++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 32 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 90241289d..62f5e9d97 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -597,6 +597,33 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_query_event( HANDLE handle, EVENT_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) -+{ -+ struct esync *obj; -+ EVENT_BASIC_INFORMATION *out = info; -+ struct pollfd fd; -+ NTSTATUS ret; -+ -+ TRACE("%p, %u, %p, %u, %p.\n", handle, class, info, len, ret_len); -+ -+ if (class != EventBasicInformation) -+ { -+ FIXME("(%p,%d,%u) Unknown class\n", handle, class, len); -+ return STATUS_INVALID_INFO_CLASS; -+ } -+ -+ 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/esync.h b/dlls/ntdll/esync.h -index 39a4dfbbe..7af338bbc 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -41,6 +41,8 @@ extern NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_query_semaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, - void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_query_event( HANDLE handle, EVENT_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 95850d7a8..2256bfc15 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -506,6 +506,9 @@ NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class, - NTSTATUS ret; - EVENT_BASIC_INFORMATION *out = info; - -+ if (do_esync()) -+ return esync_query_event( handle, class, info, len, ret_len ); -+ - TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len); - - if (class != EventBasicInformation) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0063-ntdll-Implement-NtQueryMutant.patch b/patches/eventfd_synchronization/0063-ntdll-Implement-NtQueryMutant.patch deleted file mode 100644 index 825433d6..00000000 --- a/patches/eventfd_synchronization/0063-ntdll-Implement-NtQueryMutant.patch +++ /dev/null @@ -1,79 +0,0 @@ -From c4616c8d0c79387d72a7a242ac1af0fff99e841f Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 4 Jul 2018 14:47:23 +0200 -Subject: [PATCH 63/83] ntdll: Implement NtQueryMutant(). - ---- - dlls/ntdll/esync.c | 27 +++++++++++++++++++++++++++ - dlls/ntdll/esync.h | 2 ++ - dlls/ntdll/sync.c | 3 +++ - 3 files changed, 32 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 62f5e9d97..0a1999162 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -696,6 +696,33 @@ NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) - return STATUS_SUCCESS; - } - -+NTSTATUS esync_query_mutex( HANDLE handle, MUTANT_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) -+{ -+ struct esync *obj; -+ struct mutex *mutex; -+ MUTANT_BASIC_INFORMATION *out = info; -+ NTSTATUS ret; -+ -+ TRACE("%p, %u, %p, %u, %p.\n", handle, class, info, len, ret_len); -+ -+ if (class != MutantBasicInformation) -+ { -+ FIXME("(%p,%d,%u) Unknown class\n", handle, class, len); -+ return STATUS_INVALID_INFO_CLASS; -+ } -+ -+ 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/esync.h b/dlls/ntdll/esync.h -index 7af338bbc..dd30b255b 100644 ---- a/dlls/ntdll/esync.h -+++ b/dlls/ntdll/esync.h -@@ -43,6 +43,8 @@ extern NTSTATUS esync_query_semaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLAS - void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; - extern NTSTATUS esync_query_event( HANDLE handle, EVENT_INFORMATION_CLASS class, - void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; -+extern NTSTATUS esync_query_mutex( HANDLE handle, MUTANT_INFORMATION_CLASS class, -+ void *info, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; - - extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, - BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; -diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c -index 2256bfc15..9a809f895 100644 ---- a/dlls/ntdll/sync.c -+++ b/dlls/ntdll/sync.c -@@ -629,6 +629,9 @@ NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class, - NTSTATUS ret; - MUTANT_BASIC_INFORMATION *out = info; - -+ if (do_esync()) -+ return esync_query_mutex( handle, class, info, len, ret_len ); -+ - TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len); - - if (class != MutantBasicInformation) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0065-ntdll-Cache-the-esync-struct-itself-instead-of-a-poi.patch b/patches/eventfd_synchronization/0065-ntdll-Cache-the-esync-struct-itself-instead-of-a-poi.patch deleted file mode 100644 index c3216b70..00000000 --- a/patches/eventfd_synchronization/0065-ntdll-Cache-the-esync-struct-itself-instead-of-a-poi.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 3e771ee17ee12068b93e4d400477a6c550d1746a Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 7 Jul 2018 15:10:53 +0200 -Subject: [PATCH 65/83] ntdll: Cache the esync struct itself instead of a - pointer to it. - -Now that the esync object has a constant size, we can perform this -optimization. ---- - dlls/ntdll/esync.c | 70 ++++++++++++++++------------------------------ - 1 file changed, 24 insertions(+), 46 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 0a1999162..3d0c17fd1 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -157,11 +157,11 @@ static void *get_shm( unsigned int idx ) - /* 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 128 -+#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 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 ) - { -@@ -170,7 +170,7 @@ static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry ) - return idx % ESYNC_LIST_BLOCK_SIZE; - } - --static BOOL add_to_list( HANDLE handle, struct esync *obj ) -+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 ); - -@@ -192,9 +192,12 @@ static BOOL add_to_list( HANDLE handle, struct esync *obj ) - } - } - -- obj = InterlockedExchangePointer((void **)&esync_list[entry][idx], obj); -- assert(!obj); -- return TRUE; -+ 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 struct esync *get_cached_object( HANDLE handle ) -@@ -202,8 +205,9 @@ 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]; -+ return &esync_list[entry][idx]; - } - - /* Gets an object. This is either a proper esync object (i.e. an event, -@@ -215,19 +219,18 @@ static struct esync *get_cached_object( HANDLE handle ) - * since we might be passed a duplicated or inherited handle. */ - 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; -- enum esync_type type; -- unsigned int shm_idx; -- struct esync *esync; - sigset_t sigset; -- NTSTATUS ret; -- int fd; -+ int fd = -1; - - if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS; - - /* We need to try grabbing it from the server. */ - server_enter_uninterrupted_section( &fd_cache_section, &sigset ); -- if (!(esync = get_cached_object( handle ))) -+ if (!(*obj = get_cached_object( handle ))) - { - SERVER_START_REQ( get_esync_fd ) - { -@@ -244,10 +247,9 @@ static NTSTATUS get_object( HANDLE handle, struct esync **obj ) - } - server_leave_uninterrupted_section( &fd_cache_section, &sigset ); - -- if (esync) -+ if (*obj) - { - /* We managed to grab it while in the CS; return it. */ -- *obj = esync; - return STATUS_SUCCESS; - } - -@@ -260,31 +262,21 @@ static NTSTATUS get_object( HANDLE handle, struct esync **obj ) - - TRACE("Got fd %d for handle %p.\n", fd, handle); - -- esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) ); -- esync->fd = fd; -- esync->type = type; -- -- esync->shm = shm_idx ? get_shm( shm_idx ) : 0; -- -- add_to_list( handle, esync ); -- -- *obj = esync; -+ *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 ); -- struct esync *obj; - - TRACE("%p.\n", handle); - - if (entry < ESYNC_LIST_ENTRIES && esync_list[entry]) - { -- if ((obj = InterlockedExchangePointer( (void **)&esync_list[entry][idx], 0 ))) -+ if (InterlockedExchange((int *)&esync_list[entry][idx].type, 0)) - { -- close( obj->fd ); -- RtlFreeHeap( GetProcessHeap(), 0, obj ); -+ close( esync_list[entry][idx].fd ); - return STATUS_SUCCESS; - } - } -@@ -330,14 +322,7 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, - - if (!ret || ret == STATUS_OBJECT_NAME_EXISTS) - { -- struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) ); -- if (!obj) return STATUS_NO_MEMORY; -- -- obj->type = type; -- obj->fd = fd; -- obj->shm = shm_idx ? get_shm( shm_idx ) : 0; -- -- add_to_list( *handle, obj ); -+ add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); - - TRACE("-> handle %p, fd %d, shm index %d.\n", *handle, fd, shm_idx); - } -@@ -378,14 +363,7 @@ static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, - - if (!ret) - { -- struct esync *obj = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*obj) ); -- if (!obj) return STATUS_NO_MEMORY; -- -- obj->type = type; -- obj->fd = fd; -- obj->shm = shm_idx ? get_shm( shm_idx ) : 0; -- -- add_to_list( *handle, obj ); -+ add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 ); - - TRACE("-> handle %p, fd %d.\n", *handle, fd); - } --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0068-ntdll-Ignore-pseudo-handles.patch b/patches/eventfd_synchronization/0068-ntdll-Ignore-pseudo-handles.patch deleted file mode 100644 index f6d5acf1..00000000 --- a/patches/eventfd_synchronization/0068-ntdll-Ignore-pseudo-handles.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c1003dbbc24a76415478209e46988ac0123ef915 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 26 Jul 2018 15:00:02 -0600 -Subject: [PATCH 68/83] ntdll: Ignore pseudo-handles. - ---- - dlls/ntdll/esync.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 3d0c17fd1..506d1c99d 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -228,6 +228,12 @@ static NTSTATUS get_object( HANDLE handle, struct esync **obj ) - - 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; -+ } -+ - /* We need to try grabbing it from the server. */ - server_enter_uninterrupted_section( &fd_cache_section, &sigset ); - if (!(*obj = get_cached_object( handle ))) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0070-ntdll-Store-an-event-s-signaled-state-internally.patch b/patches/eventfd_synchronization/0070-ntdll-Store-an-event-s-signaled-state-internally.patch deleted file mode 100644 index cb0b85e3..00000000 --- a/patches/eventfd_synchronization/0070-ntdll-Store-an-event-s-signaled-state-internally.patch +++ /dev/null @@ -1,414 +0,0 @@ -From 05b7e550b210c50deb5dbf31a50f96ebe0160c34 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Thu, 26 Jul 2018 11:20:44 -0600 -Subject: [PATCH 70/83] ntdll: Store an event's signaled state internally. - -This was way harder than I thought it would be... ---- - dlls/ntdll/esync.c | 237 +++++++++++++++++++++++++++++++++++---------- - server/esync.c | 26 +++-- - 2 files changed, 195 insertions(+), 68 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 4e5fcef8e..663b3658b 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -93,12 +93,21 @@ struct semaphore - int max; - int count; - }; -+C_ASSERT(sizeof(struct semaphore) == 8); - - struct mutex - { - DWORD tid; - int count; /* recursion count */ - }; -+C_ASSERT(sizeof(struct mutex) == 8); -+ -+struct event -+{ -+ int signaled; -+ int locked; -+}; -+C_ASSERT(sizeof(struct event) == 8); - - static char shm_name[29]; - static int shm_fd; -@@ -396,7 +405,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - /* We need this lock to protect against a potential (though unlikely) race: - * if a different process tries to open a named object and manages to use - * it between the time we get back from the server and the time we -- * initialize the shared memory, it'll have uninitialize values for the -+ * initialize the shared memory, it'll have uninitialized values for the - * object's state. That requires us to be REALLY slow, but we're not taking - * any chances. Synchronize on the CS here so that we're sure to be ready - * before anyone else can open the object. */ -@@ -495,40 +504,124 @@ 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); -+ NTSTATUS ret; - - 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 ); -+ RtlEnterCriticalSection( &shm_init_section ); -+ -+ ret = create_esync( type, handle, access, attr, initial, 0 ); -+ -+ if (!ret) -+ { -+ /* Initialize the shared memory portion. */ -+ struct esync *obj = get_cached_object( *handle ); -+ struct event *event = obj->shm; -+ event->signaled = initial; -+ event->locked = 0; -+ } -+ -+ RtlLeaveCriticalSection( &shm_init_section ); -+ -+ return ret; - } - - NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -+ NTSTATUS ret; -+ - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- return open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ -+ RtlEnterCriticalSection( &shm_init_section ); -+ ret = open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ -+ RtlLeaveCriticalSection( &shm_init_section ); -+ return ret; -+} -+ -+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. -+ * -+ * And of course if SetEvent() follows WaitFor() entirely, well, there's no -+ * problem at all. -+ */ -+ - NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - { - static const uint64_t value = 1; - struct esync *obj; -+ struct event *event; -+ LONG current; - NTSTATUS ret; - -- TRACE("%p.\n", handle); -+ TRACE("handle %p, prev %p.\n", handle, prev); - - if ((ret = get_object( handle, &obj ))) return ret; -+ event = obj->shm; -+ -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); - -- if (prev) -+ /* Only bother signaling the fd if we weren't already signaled. */ -+ if (!(current = InterlockedExchange( &event->signaled, 1 ))) - { -- FIXME("Can't write previous value.\n"); -- *prev = 1; -+ if (write( obj->fd, &value, sizeof(value) ) == -1) -+ return FILE_GetNtStatus(); - } - -- if (write( obj->fd, &value, sizeof(value) ) == -1) -- return FILE_GetNtStatus(); -+ if (prev) *prev = current; -+ -+ /* Release the spinlock. */ -+ event->locked = 0; - - return STATUS_SUCCESS; - } -@@ -537,20 +630,30 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - { - static uint64_t value; - struct esync *obj; -+ struct event *event; -+ LONG current; - NTSTATUS ret; - -- TRACE("%p.\n", handle); -+ TRACE("handle %p, prev %p.\n", handle, prev); - - if ((ret = get_object( handle, &obj ))) return ret; -+ event = obj->shm; -+ -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); - -- if (prev) -+ /* Only bother signaling the fd if we weren't already signaled. */ -+ if ((current = InterlockedExchange( &event->signaled, 0 ))) - { -- FIXME("Can't write previous value.\n"); -- *prev = 1; -+ /* we don't care about the return value */ -+ read( obj->fd, &value, sizeof(value) ); - } - -- /* we don't care about the return value */ -- read( obj->fd, &value, sizeof(value) ); -+ if (prev) *prev = current; -+ -+ /* Release the spinlock. */ -+ event->locked = 0; - - return STATUS_SUCCESS; - } -@@ -559,17 +662,18 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - { - static uint64_t value = 1; - struct esync *obj; -+ struct event *event; -+ LONG current; - NTSTATUS ret; - - TRACE("%p.\n", handle); - - if ((ret = get_object( handle, &obj ))) return ret; -+ event = obj->shm; - -- if (prev) -- { -- FIXME("Can't write previous value.\n"); -- *prev = 1; -- } -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); - - /* This isn't really correct; an application could miss the write. - * Unfortunately we can't really do much better. Fortunately this is rarely -@@ -578,6 +682,12 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - return FILE_GetNtStatus(); - read( obj->fd, &value, sizeof(value) ); - -+ current = InterlockedExchange( &event->signaled, 0 ); -+ if (prev) *prev = current; -+ -+ /* Release the spinlock. */ -+ event->locked = 0; -+ - return STATUS_SUCCESS; - } - -@@ -751,6 +861,35 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end ) - return ret; - } - -+static void update_grabbed_object( struct esync *obj ) -+{ -+ 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 -+ * 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. */ -+ InterlockedDecrement( &semaphore->count ); -+ } -+ 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(), for -+ * reasons described near esync_set_event(). */ -+ event->signaled = 0; -+ } -+} -+ - /* 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, -@@ -916,9 +1055,30 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - 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; -+ } -+ } -+ } - 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: -@@ -979,25 +1139,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - { - /* We found our object. */ - TRACE("Woken up by handle %p [%d].\n", handles[i], i); -- 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 = 1; -- } -- else if (obj->type == ESYNC_SEMAPHORE) -- { -- struct semaphore *semaphore = obj->shm; -- /* We don't have to worry about a race between this and read(); -- * the fact that we were able to grab it at all means the count -- * is nonzero, and if someone else grabbed it then the count -- * must have been >= 2, etc. */ -- InterlockedDecrement( &semaphore->count ); -- } -+ update_grabbed_object( obj ); - return i; - } - } -@@ -1161,19 +1303,8 @@ tryagain: - /* Make sure to let ourselves know that we grabbed the mutexes - * and semaphores. */ - for (i = 0; i < count; i++) -- { -- if (objs[i]->type == ESYNC_MUTEX) -- { -- struct mutex *mutex = objs[i]->shm; -- mutex->tid = GetCurrentThreadId(); -- mutex->count++; -- } -- else if (objs[i]->type == ESYNC_SEMAPHORE) -- { -- struct semaphore *semaphore = objs[i]->shm; -- InterlockedDecrement( &semaphore->count ); -- } -- } -+ update_grabbed_object( objs[i] ); -+ - TRACE("Wait successful.\n"); - return STATUS_SUCCESS; - } -diff --git a/server/esync.c b/server/esync.c -index a2f828173..847f1e974 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -192,25 +192,21 @@ static struct esync *create_esync( struct object *root, const struct unicode_str - return NULL; - } - esync->type = type; -- if (type == ESYNC_SEMAPHORE || type == ESYNC_MUTEX) -+ -+ /* 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) - { -- /* 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 += sysconf( _SC_PAGESIZE ); -+ if (ftruncate( shm_fd, shm_size ) == -1) - { -- /* Better expand the shm section. */ -- shm_size += sysconf( _SC_PAGESIZE ); -- if (ftruncate( shm_fd, shm_size ) == -1) -- { -- fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -- shm_name, shm_size ); -- perror( "ftruncate" ); -- } -+ fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -+ shm_name, shm_size ); -+ perror( "ftruncate" ); - } - } -- else -- esync->shm_idx = 0; - } - else - { --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0071-ntdll-Fix-growing-the-shm_addrs-array.patch b/patches/eventfd_synchronization/0071-ntdll-Fix-growing-the-shm_addrs-array.patch deleted file mode 100644 index bce26bd8..00000000 --- a/patches/eventfd_synchronization/0071-ntdll-Fix-growing-the-shm_addrs-array.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 332a9c67d3d400e6d127afce26f9e52114c50d5c Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 28 Jul 2018 12:09:40 -0500 -Subject: [PATCH 71/83] ntdll: Fix growing the shm_addrs array. - -Fixes an issue exposed by the last patch and visible in GTA V. Presumably -this didn't show up earlier because applications usually don't create large -numbers of semaphores or mutexes, and previously events didn't use shared -memory. ---- - dlls/ntdll/esync.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 663b3658b..a94a5aa6e 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -143,8 +143,9 @@ static void *get_shm( unsigned int idx ) - - if (entry >= shm_addrs_size) - { -- shm_addrs_size *= 2; -- if (!(shm_addrs = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, shm_addrs, shm_addrs_size ))) -+ shm_addrs_size = entry + 1; -+ if (!(shm_addrs = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, -+ shm_addrs, shm_addrs_size * sizeof(shm_addrs[0]) ))) - ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_size); - } - --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0072-server-Update-the-shared-memory-state-when-re-settin.patch b/patches/eventfd_synchronization/0072-server-Update-the-shared-memory-state-when-re-settin.patch deleted file mode 100644 index 63385ae5..00000000 --- a/patches/eventfd_synchronization/0072-server-Update-the-shared-memory-state-when-re-settin.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 599f4653ecd2bea798265f1e342c19bbcbb1162a Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 29 Jul 2018 13:36:42 -0500 -Subject: [PATCH 72/83] server: Update the shared memory state when (re)setting - an event. - ---- - server/esync.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 98 insertions(+), 6 deletions(-) - -diff --git a/server/esync.c b/server/esync.c -index 847f1e974..1fc9316b1 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -64,6 +64,9 @@ int do_esync(void) - 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) - { -@@ -90,7 +93,12 @@ void esync_init(void) - if (shm_fd == -1) - perror( "shm_open" ); - -- shm_size = sysconf( _SC_PAGESIZE ); -+ 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" ); - -@@ -199,7 +207,7 @@ static struct esync *create_esync( struct object *root, const struct unicode_str - while (esync->shm_idx * 8 >= shm_size) - { - /* Better expand the shm section. */ -- shm_size += sysconf( _SC_PAGESIZE ); -+ shm_size += pagesize; - if (ftruncate( shm_fd, shm_size ) == -1) - { - fprintf( stderr, "esync: couldn't expand %s to size %ld: ", -@@ -275,24 +283,108 @@ void esync_clear( int fd ) - read( fd, &value, sizeof(value) ); - } - -+/* Sadly, we need all of this infrastructure to keep the shm state in sync. */ -+ -+static void *get_shm( unsigned int idx ) -+{ -+ int entry = (idx * 8) / pagesize; -+ int offset = (idx * 8) % pagesize; -+ -+ if (entry >= shm_addrs_size) -+ { -+ if (!(shm_addrs = realloc( shm_addrs, (entry + 1) * 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, (entry + 1 - shm_addrs_size) * sizeof(shm_addrs[0]) ); -+ -+ shm_addrs_size = entry + 1; -+ } -+ -+ 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 (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 )) -+ munmap( addr, pagesize ); /* someone beat us to it */ -+ } -+ -+ return (void *)((unsigned long)shm_addrs[entry] + offset); -+} -+ -+struct event -+{ -+ int signaled; -+ int locked; -+}; -+C_ASSERT(sizeof(struct event) == 8); -+ -+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 ); -+ -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); -+ -+ if (!InterlockedExchange( &event->signaled, 1 )) -+ { -+ if (write( esync->fd, &value, sizeof(value) ) == -1) -+ perror( "esync: write" ); -+ } -+ -+ /* 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 ); -+ -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); -+ -+ /* Only bother signaling the fd if we weren't already signaled. */ -+ if (InterlockedExchange( &event->signaled, 0 )) -+ { -+ /* we don't care about the return value */ -+ read( esync->fd, &value, sizeof(value) ); -+ } -+ -+ /* Release the spinlock. */ -+ event->locked = 0; - } - - DECL_HANDLER(create_esync) --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0073-ntdll-Fix-a-missing-break-statement.patch b/patches/eventfd_synchronization/0073-ntdll-Fix-a-missing-break-statement.patch deleted file mode 100644 index 3223b069..00000000 --- a/patches/eventfd_synchronization/0073-ntdll-Fix-a-missing-break-statement.patch +++ /dev/null @@ -1,25 +0,0 @@ -From bcf741e2f08c2e571083796efef1aeab36d3daee Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 31 Jul 2018 11:54:39 -0500 -Subject: [PATCH 73/83] ntdll: Fix a missing break statement. - -Should fix #2, #3, #6. ---- - dlls/ntdll/esync.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index a94a5aa6e..3ab069da9 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -1068,6 +1068,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - return i; - } - } -+ break; - } - case ESYNC_MANUAL_EVENT: - { --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0074-ntdll-server-Abort-if-esync-is-enabled-for-the-serve.patch b/patches/eventfd_synchronization/0074-ntdll-server-Abort-if-esync-is-enabled-for-the-serve.patch deleted file mode 100644 index 63fa6123..00000000 --- a/patches/eventfd_synchronization/0074-ntdll-server-Abort-if-esync-is-enabled-for-the-serve.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 4863e6b323f7ecc1fceaff42a573cd0b9a07f3d5 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 4 Aug 2018 15:15:12 -0500 -Subject: [PATCH] ntdll, server: Abort if esync is enabled for the server but - not the client, and vice versa. - ---- - dlls/ntdll/esync.c | 28 +++++++++++++++++++++++++++- - dlls/ntdll/loader.c | 3 +-- - server/esync.c | 12 ++++++++++++ - 3 files changed, 40 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 0625de9fff0..522704f757f 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -115,10 +115,29 @@ static void **shm_addrs; - static int shm_addrs_size; /* length of the allocated shm_addrs array */ - static long pagesize; - -+static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags ); -+ - 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); - -@@ -128,7 +147,14 @@ void esync_init(void) - sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino ); - - if ((shm_fd = shm_open( shm_name, O_RDWR, 0644 )) == -1) -- ERR("Failed to initialize shared memory: %s\n", strerror( errno )); -+ { -+ /* 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 ); - -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index 752a0b3b622..36c5092a4b1 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -4648,8 +4648,7 @@ void __wine_process_init(void) - peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL ); - peb->LoaderLock = &loader_section; - -- if (do_esync()) -- esync_init(); -+ esync_init(); - - init_unix_codepage(); - init_directories(); -diff --git a/server/esync.c b/server/esync.c -index 11e5e482024..bc2ce61c9a2 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -394,6 +394,18 @@ DECL_HANDLER(create_esync) - 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_4 ); -+ return; -+ } -+ - if (!objattr) return; - - if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, req->type, sd ))) --- -2.26.2 - diff --git a/patches/eventfd_synchronization/0076-ntdll-Correctly-allocate-the-esync-handle-cache.patch b/patches/eventfd_synchronization/0076-ntdll-Correctly-allocate-the-esync-handle-cache.patch deleted file mode 100644 index fc41935c..00000000 --- a/patches/eventfd_synchronization/0076-ntdll-Correctly-allocate-the-esync-handle-cache.patch +++ /dev/null @@ -1,28 +0,0 @@ -From e66bb0ab91a9b83822edb9c1d3471c603848a3ab Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sat, 11 Aug 2018 10:45:43 -0500 -Subject: [PATCH 76/83] ntdll: Correctly allocate the esync handle cache. - -Fixes a regression introduced by 7b583a367ca05f961c1183a9647245ecd9f2160f. - -Should hopefully fix #7. ---- - dlls/ntdll/esync.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 1dd96c8e6..53a93f3cf 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -221,7 +221,7 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v - if (!entry) esync_list[0] = esync_list_initial_block; - else - { -- void *ptr = wine_anon_mmap( NULL, ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync *), -+ void *ptr = wine_anon_mmap( NULL, ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync), - PROT_READ | PROT_WRITE, 0 ); - if (ptr == MAP_FAILED) return FALSE; - esync_list[entry] = ptr; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0077-ntdll-server-Specify-EFD_SEMAPHORE-on-the-server-sid.patch b/patches/eventfd_synchronization/0077-ntdll-server-Specify-EFD_SEMAPHORE-on-the-server-sid.patch deleted file mode 100644 index e4e3b3c0..00000000 --- a/patches/eventfd_synchronization/0077-ntdll-server-Specify-EFD_SEMAPHORE-on-the-server-sid.patch +++ /dev/null @@ -1,153 +0,0 @@ -From d743c7745d1fcdf53f9575bf903a6af88b23f776 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 29 Jul 2018 16:53:58 -0500 -Subject: [PATCH 77/83] ntdll, server: Specify EFD_SEMAPHORE on the server - side. - -This just makes things cleaner; since we already pass the type to the server -there's no reason to pass this as well. ---- - dlls/ntdll/esync.c | 20 ++++++-------------- - server/esync.c | 11 ++++++++--- - server/protocol.def | 1 - - 3 files changed, 14 insertions(+), 18 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 53a93f3cf..4f418b211 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -33,9 +33,6 @@ - #include - #include - #include --#ifdef HAVE_SYS_EVENTFD_H --# include --#endif - #ifdef HAVE_SYS_MMAN_H - # include - #endif -@@ -52,10 +49,6 @@ - #include "ntdll_misc.h" - #include "esync.h" - --#ifndef EFD_SEMAPHORE --#define EFD_SEMAPHORE 1 --#endif -- - WINE_DEFAULT_DEBUG_CHANNEL(esync); - - int do_esync(void) -@@ -116,7 +109,7 @@ static int shm_addrs_size; /* length of the allocated shm_addrs array */ - static long pagesize; - - static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags ); -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval ); - - void esync_init(void) - { -@@ -128,7 +121,7 @@ void esync_init(void) - HANDLE handle; - NTSTATUS ret; - -- ret = create_esync( 0, &handle, 0, NULL, 0, 0 ); -+ ret = create_esync( 0, &handle, 0, NULL, 0 ); - if (ret != STATUS_NOT_IMPLEMENTED) - { - ERR("Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.\n"); -@@ -327,7 +320,7 @@ NTSTATUS esync_close( HANDLE handle ) - } - - static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int flags ) -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval ) - { - NTSTATUS ret; - data_size_t len; -@@ -346,7 +339,6 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, - { - req->access = access; - req->initval = initval; -- req->flags = flags; - req->type = type; - wine_server_add_data( req, objattr, len ); - ret = wine_server_call( req ); -@@ -438,7 +430,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - * before anyone else can open the object. */ - RtlEnterCriticalSection( &shm_init_section ); - -- ret = create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, EFD_SEMAPHORE ); -+ ret = create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial ); - if (!ret) - { - /* Initialize the shared memory portion. -@@ -539,7 +531,7 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access, - - RtlEnterCriticalSection( &shm_init_section ); - -- ret = create_esync( type, handle, access, attr, initial, 0 ); -+ ret = create_esync( type, handle, access, attr, initial ); - - if (!ret) - { -@@ -755,7 +747,7 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - - RtlEnterCriticalSection( &shm_init_section ); - -- ret = create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1, 0 ); -+ ret = create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1 ); - if (!ret) - { - /* Initialize the shared memory portion. */ -diff --git a/server/esync.c b/server/esync.c -index cb4de2daa..f5556e91c 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -180,7 +180,7 @@ static int type_matches( enum esync_type type1, enum esync_type type2 ) - } - - static struct esync *create_esync( struct object *root, const struct unicode_str *name, -- unsigned int attr, int initval, int flags, enum esync_type type, -+ unsigned int attr, int initval, enum esync_type type, - const struct security_descriptor *sd ) - { - #ifdef HAVE_SYS_EVENTFD_H -@@ -190,8 +190,13 @@ static struct esync *create_esync( struct object *root, const struct unicode_str - { - 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 | EFD_CLOEXEC | EFD_NONBLOCK ); -+ esync->fd = eventfd( initval, flags ); - if (esync->fd == -1) - { - perror( "eventfd" ); -@@ -409,7 +414,7 @@ DECL_HANDLER(create_esync) - - if (!objattr) return; - -- if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, req->type, sd ))) -+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->type, sd ))) - { - if (get_error() == STATUS_OBJECT_NAME_EXISTS) - reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes ); -diff --git a/server/protocol.def b/server/protocol.def -index f55da3a0e..220c7c407 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4046,7 +4046,6 @@ struct handle_info - @REQ(create_esync) - unsigned int access; /* wanted access rights */ - int initval; /* initial value */ -- int flags; /* flags (EFD_SEMAPHORE or 0) */ - int type; /* type of esync object (see below) */ - VARARG(objattr,object_attributes); /* object attributes */ - @REPLY --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0078-ntdll-server-Initialize-the-shared-memory-portion-on.patch b/patches/eventfd_synchronization/0078-ntdll-server-Initialize-the-shared-memory-portion-on.patch deleted file mode 100644 index 4198ad1e..00000000 --- a/patches/eventfd_synchronization/0078-ntdll-server-Initialize-the-shared-memory-portion-on.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 943e5341b06b05129e2f909b48e446141a6d976d Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 29 Jul 2018 16:50:08 -0500 -Subject: [PATCH 78/83] ntdll, server: Initialize the shared memory portion on - the server side. - -Simply using a CS only prevents this race within one process. ---- - dlls/ntdll/esync.c | 100 ++++---------------------------- - server/esync.c | 135 +++++++++++++++++++++++++++++--------------- - server/protocol.def | 1 + - 3 files changed, 101 insertions(+), 135 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 4f418b211..b84b7b83c 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -109,7 +109,7 @@ static int shm_addrs_size; /* length of the allocated shm_addrs array */ - static long pagesize; - - static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval ); -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int max ); - - void esync_init(void) - { -@@ -121,7 +121,7 @@ void esync_init(void) - HANDLE handle; - NTSTATUS ret; - -- ret = create_esync( 0, &handle, 0, NULL, 0 ); -+ 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"); -@@ -320,7 +320,7 @@ NTSTATUS esync_close( HANDLE handle ) - } - - static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, -- ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval ) -+ ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int initval, int max ) - { - NTSTATUS ret; - data_size_t len; -@@ -340,6 +340,7 @@ static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, - 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) -@@ -404,60 +405,21 @@ static NTSTATUS open_esync( enum esync_type type, HANDLE *handle, - return ret; - } - --RTL_CRITICAL_SECTION shm_init_section; --static RTL_CRITICAL_SECTION_DEBUG critsect_debug = --{ -- 0, 0, &shm_init_section, -- { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, -- 0, 0, { (DWORD_PTR)(__FILE__ ": shm_init_section") } --}; --RTL_CRITICAL_SECTION shm_init_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -- - NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) - { -- NTSTATUS ret; -- - TRACE("name %s, initial %d, max %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial, max); - -- /* We need this lock to protect against a potential (though unlikely) race: -- * if a different process tries to open a named object and manages to use -- * it between the time we get back from the server and the time we -- * initialize the shared memory, it'll have uninitialized values for the -- * object's state. That requires us to be REALLY slow, but we're not taking -- * any chances. Synchronize on the CS here so that we're sure to be ready -- * before anyone else can open the object. */ -- RtlEnterCriticalSection( &shm_init_section ); -- -- ret = create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial ); -- if (!ret) -- { -- /* Initialize the shared memory portion. -- * Note we store max here (even though we don't need to) just to keep -- * it the same size as the mutex's shm portion. */ -- struct esync *obj = get_cached_object( *handle ); -- struct semaphore *semaphore = obj->shm; -- semaphore->max = max; -- semaphore->count = initial; -- } -- -- RtlLeaveCriticalSection( &shm_init_section ); -- -- return ret; -+ return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max ); - } - - NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -- NTSTATUS ret; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- RtlEnterCriticalSection( &shm_init_section ); -- ret = open_esync( ESYNC_SEMAPHORE, handle, access, attr ); -- RtlLeaveCriticalSection( &shm_init_section ); -- return ret; -+ return open_esync( ESYNC_SEMAPHORE, handle, access, attr ); - } - - NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) -@@ -523,41 +485,20 @@ 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); -- NTSTATUS ret; - - TRACE("name %s, %s-reset, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", - event_type == NotificationEvent ? "manual" : "auto", initial); - -- RtlEnterCriticalSection( &shm_init_section ); -- -- ret = create_esync( type, handle, access, attr, initial ); -- -- if (!ret) -- { -- /* Initialize the shared memory portion. */ -- struct esync *obj = get_cached_object( *handle ); -- struct event *event = obj->shm; -- event->signaled = initial; -- event->locked = 0; -- } -- -- RtlLeaveCriticalSection( &shm_init_section ); -- -- return ret; -+ return create_esync( type, handle, access, attr, initial, 0 ); - } - - NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr ) - { -- NTSTATUS ret; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- RtlEnterCriticalSection( &shm_init_section ); -- ret = open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ -- RtlLeaveCriticalSection( &shm_init_section ); -- return ret; -+ return open_esync( ESYNC_AUTO_EVENT, handle, access, attr ); /* doesn't matter which */ - } - - static inline void small_pause(void) -@@ -740,39 +681,18 @@ NTSTATUS esync_query_event( HANDLE handle, EVENT_INFORMATION_CLASS class, - NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access, - const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) - { -- NTSTATUS ret; -- - TRACE("name %s, initial %d.\n", - attr ? debugstr_us(attr->ObjectName) : "", initial); - -- RtlEnterCriticalSection( &shm_init_section ); -- -- ret = create_esync( ESYNC_MUTEX, handle, access, attr, initial ? 0 : 1 ); -- if (!ret) -- { -- /* Initialize the shared memory portion. */ -- struct esync *obj = get_cached_object( *handle ); -- struct mutex *mutex = obj->shm; -- mutex->tid = initial ? GetCurrentThreadId() : 0; -- mutex->count = initial ? 1 : 0; -- } -- -- RtlLeaveCriticalSection( &shm_init_section ); -- -- return ret; -+ 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 ) - { -- NTSTATUS ret; -- - TRACE("name %s.\n", debugstr_us(attr->ObjectName)); - -- RtlEnterCriticalSection( &shm_init_section ); -- ret = open_esync( ESYNC_MUTEX, handle, access, attr ); -- RtlLeaveCriticalSection( &shm_init_section ); -- return ret; -+ return open_esync( ESYNC_MUTEX, handle, access, attr ); - } - - NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) -diff --git a/server/esync.c b/server/esync.c -index f5556e91c..19e614a89 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -179,8 +179,63 @@ static int type_matches( enum esync_type type1, enum esync_type type2 ) - (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) -+ { -+ if (!(shm_addrs = realloc( shm_addrs, (entry + 1) * 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, (entry + 1 - shm_addrs_size) * sizeof(shm_addrs[0]) ); -+ -+ shm_addrs_size = entry + 1; -+ } -+ -+ 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 (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 )) -+ munmap( addr, pagesize ); /* someone beat us to it */ -+ } -+ -+ return (void *)((unsigned long)shm_addrs[entry] + offset); -+} -+ -+struct semaphore -+{ -+ int max; -+ int count; -+}; -+C_ASSERT(sizeof(struct semaphore) == 8); -+ -+struct mutex -+{ -+ DWORD tid; -+ int count; /* recursion count */ -+}; -+C_ASSERT(sizeof(struct mutex) == 8); -+ -+struct event -+{ -+ int signaled; -+ int locked; -+}; -+C_ASSERT(sizeof(struct event) == 8); -+ - static struct esync *create_esync( struct object *root, const struct unicode_str *name, -- unsigned int attr, int initval, enum esync_type type, -+ unsigned int attr, int initval, int max, enum esync_type type, - const struct security_descriptor *sd ) - { - #ifdef HAVE_SYS_EVENTFD_H -@@ -220,6 +275,38 @@ static struct esync *create_esync( struct object *root, const struct unicode_str - perror( "ftruncate" ); - } - } -+ -+ /* Initialize the shared memory portion. We want to do this on the -+ * server side to avoid a potential though unlikely race whereby -+ * the same object is opened and used between the time it's created -+ * and the time its shared memory portion is initialized. */ -+ switch (type) -+ { -+ case ESYNC_SEMAPHORE: -+ { -+ struct semaphore *semaphore = get_shm( esync->shm_idx ); -+ semaphore->max = max; -+ semaphore->count = initval; -+ break; -+ } -+ case ESYNC_AUTO_EVENT: -+ case ESYNC_MANUAL_EVENT: -+ { -+ struct event *event = get_shm( esync->shm_idx ); -+ event->signaled = initval ? 1 : 0; -+ event->locked = 0; -+ break; -+ } -+ case ESYNC_MUTEX: -+ { -+ struct mutex *mutex = get_shm( esync->shm_idx ); -+ mutex->tid = initval ? 0 : current->id; -+ mutex->count = initval ? 0 : 1; -+ break; -+ } -+ default: -+ assert( 0 ); -+ } - } - else - { -@@ -288,49 +375,6 @@ void esync_clear( int fd ) - read( fd, &value, sizeof(value) ); - } - --/* Sadly, we need all of this infrastructure to keep the shm state in sync. */ -- --static void *get_shm( unsigned int idx ) --{ -- int entry = (idx * 8) / pagesize; -- int offset = (idx * 8) % pagesize; -- -- if (entry >= shm_addrs_size) -- { -- if (!(shm_addrs = realloc( shm_addrs, (entry + 1) * 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, (entry + 1 - shm_addrs_size) * sizeof(shm_addrs[0]) ); -- -- shm_addrs_size = entry + 1; -- } -- -- 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 (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 )) -- munmap( addr, pagesize ); /* someone beat us to it */ -- } -- -- return (void *)((unsigned long)shm_addrs[entry] + offset); --} -- --struct event --{ -- int signaled; -- int locked; --}; --C_ASSERT(sizeof(struct event) == 8); -- - static inline void small_pause(void) - { - #ifdef __i386__ -@@ -414,7 +458,8 @@ DECL_HANDLER(create_esync) - - if (!objattr) return; - -- if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->type, sd ))) -+ 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 ); -diff --git a/server/protocol.def b/server/protocol.def -index 220c7c407..dbb8770df 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4047,6 +4047,7 @@ struct handle_info - unsigned int access; /* wanted access rights */ - int initval; /* initial value */ - int type; /* type of esync object (see below) */ -+ int max; /* maximum count on a semaphore */ - VARARG(objattr,object_attributes); /* object attributes */ - @REPLY - obj_handle_t handle; /* handle to the object */ --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0079-ntdll-server-Revert-to-old-implementation-of-hung-qu.patch b/patches/eventfd_synchronization/0079-ntdll-server-Revert-to-old-implementation-of-hung-qu.patch deleted file mode 100644 index 7518ef57..00000000 --- a/patches/eventfd_synchronization/0079-ntdll-server-Revert-to-old-implementation-of-hung-qu.patch +++ /dev/null @@ -1,197 +0,0 @@ -From d67891b541cfcd5107805b088f20d3b8ca7f7d00 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 13 Aug 2018 21:35:06 -0500 -Subject: [PATCH] ntdll, server: Revert to old implementation of hung queue - detection. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -By manually notifying the server every time we enter and exit a message wait. - -The hung queue logic keeps breaking. In the case of bug #9 it was breaking -because we were waiting for more than 5 seconds on our queue and then someone -sent us a message with SMTO_ABORTIFHUNG. Just stop fighting against the -server and try to coƶperate with it instead. It takes two extra server calls, -but ideally the GUI thread isn't going to be in the same sort of performance- -critical code that this patchset was written for. ---- - dlls/ntdll/esync.c | 53 ++++++++++++++++++++++++++++++++++----------- - server/protocol.def | 6 ++++- - server/queue.c | 35 ++++++++++++++++++++++++------ - 3 files changed, 73 insertions(+), 21 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 2cdfcca4f04..9c7e8deea85 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -831,8 +831,8 @@ 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, -- BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, -+ BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) - { - static const LARGE_INTEGER zero = {0}; - -@@ -895,22 +895,11 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an - - if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE) - { -- select_op_t select_op; -- - /* Last object in the list is a queue, which means someone is using - * MsgWaitForMultipleObjects(). We have to wait not only for the server - * fd (signaled on send_message, etc.) but also the USER driver's fd - * (signaled on e.g. X11 events.) */ - msgwait = TRUE; -- -- /* We need to let the server know we are doing a message wait, for two -- * reasons. First one is WaitForInputIdle(). Second one is checking for -- * hung queues. Do it like this. */ -- select_op.wait.op = SELECT_WAIT; -- select_op.wait.handles[0] = wine_server_obj_handle( handles[count - 1] ); -- ret = server_wait( &select_op, offsetof( select_op_t, wait.handles[1] ), 0, &zero ); -- if (ret != STATUS_WAIT_0 && ret != STATUS_TIMEOUT) -- ERR("Unexpected ret %#x\n", ret); - } - - if (has_esync && has_server) -@@ -1283,6 +1272,44 @@ userapc: - return ret; - } - -+/* We need to let the server know when we are doing a message wait, and when we -+ * are done with one, so that all of the code surrounding hung queues works. -+ * We also need this for WaitForInputIdle(). */ -+static void server_set_msgwait( int in_msgwait ) -+{ -+ SERVER_START_REQ( esync_msgwait ) -+ { -+ req->in_msgwait = in_msgwait; -+ wine_server_call( req ); -+ } -+ SERVER_END_REQ; -+} -+ -+/* This is a very thin wrapper around the proper implementation above. The -+ * purpose is to make sure the server knows when we are doing a message wait. -+ * This is separated into a wrapper function since there are at least a dozen -+ * exit paths from esync_wait_objects(). */ -+NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, -+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) -+{ -+ BOOL msgwait = FALSE; -+ struct esync *obj; -+ NTSTATUS ret; -+ -+ if (!get_object( handles[count - 1], &obj ) && obj->type == ESYNC_QUEUE) -+ { -+ msgwait = TRUE; -+ server_set_msgwait( 1 ); -+ } -+ -+ ret = __esync_wait_objects( count, handles, wait_any, alertable, timeout ); -+ -+ if (msgwait) -+ server_set_msgwait( 0 ); -+ -+ return ret; -+} -+ - NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, - const LARGE_INTEGER *timeout ) - { -diff --git a/server/protocol.def b/server/protocol.def -index ab5e205462d..2260f432311 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -4085,7 +4085,11 @@ struct handle_info - - /* Retrieve the fd to wait on for user APCs. */ - @REQ(get_esync_apc_fd) --@REPLY -+@END -+ -+/* Notify the server that we are doing a message wait (or done with one). */ -+@REQ(esync_msgwait) -+ int in_msgwait; /* are we in a message wait? */ - @END - - enum esync_type -diff --git a/server/queue.c b/server/queue.c -index c365eacb9e0..2b780deb112 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -126,6 +126,7 @@ struct msg_queue - struct thread *thread; /* reference to the thread owning the queue */ - struct fd *fd; /* optional file descriptor to poll */ - int esync_fd; /* esync file descriptor (signalled on message) */ -+ int esync_in_msgwait; /* our thread is currently waiting on us */ - unsigned int wake_bits; /* wakeup bits */ - unsigned int wake_mask; /* wakeup mask */ - unsigned int changed_bits; /* changed wakeup bits */ -@@ -996,7 +997,21 @@ static void cleanup_results( struct msg_queue *queue ) - /* check if the thread owning the queue is hung (not checking for messages) */ - static int is_queue_hung( struct msg_queue *queue ) - { -- return (current_time - queue->last_get_msg > 5 * TICKS_PER_SEC); -+ struct wait_queue_entry *entry; -+ -+ if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC) -+ return 0; /* less than 5 seconds since last get message -> not hung */ -+ -+ LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry ) -+ { -+ 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; - } - - static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ) -@@ -1012,12 +1027,6 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent - } - if (process->idle_event && !(queue->wake_mask & QS_SMRESULT)) set_event( process->idle_event ); - -- /* On Windows, we are considered hung iff we have not somehow processed -- * messages OR done a MsgWait call in the last 5 seconds. Note that in the -- * latter case repeatedly waiting for 0 seconds is not hung, but waiting -- * forever is hung, so this is correct. */ -- queue->last_get_msg = current_time; -- - if (queue->fd && list_empty( &obj->wait_queue )) /* first on the queue */ - set_fd_events( queue->fd, POLLIN ); - add_queue( obj, entry ); -@@ -1728,6 +1737,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa - - if (!(hook_thread = get_first_global_hook( id ))) return 0; - if (!(queue = hook_thread->queue)) return 0; -+ if (is_queue_hung( queue )) return 0; - - if (!(msg = mem_alloc( sizeof(*msg) ))) return 0; - -@@ -3432,3 +3442,14 @@ DECL_HANDLER(get_rawinput_devices) - - set_reply_data_ptr( devices, device_count * sizeof (*devices) ); - } -+ -+DECL_HANDLER(esync_msgwait) -+{ -+ struct msg_queue *queue = get_current_queue(); -+ -+ if (!queue) return; -+ queue->esync_in_msgwait = req->in_msgwait; -+ -+ if (current->process->idle_event && !(queue->wake_mask & QS_SMRESULT)) -+ set_event( current->process->idle_event ); -+} --- -2.26.0 - diff --git a/patches/eventfd_synchronization/0080-ntdll-Fix-a-couple-of-misplaced-global-variables.patch b/patches/eventfd_synchronization/0080-ntdll-Fix-a-couple-of-misplaced-global-variables.patch deleted file mode 100644 index f264c015..00000000 --- a/patches/eventfd_synchronization/0080-ntdll-Fix-a-couple-of-misplaced-global-variables.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 5f1c5d0a6ab0171bee767562ada00b04ceb98596 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 14 Aug 2018 20:00:54 -0500 -Subject: [PATCH 80/83] ntdll: Fix a couple of misplaced global variables. - -There's no reason these should be global, and in particular, this means that esync_pulse_event() might end up writing 0, which raises the likelihood of a missed wakeup from "probable" to "certain". - -Fixes #10. ---- - dlls/ntdll/esync.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 501175c1d..597cb8fa8 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -588,7 +588,7 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - - NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - { -- static uint64_t value; -+ uint64_t value; - struct esync *obj; - struct event *event; - LONG current; -@@ -620,7 +620,7 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - - NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - { -- static uint64_t value = 1; -+ uint64_t value = 1; - struct esync *obj; - struct event *event; - LONG current; --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0081-ntdll-Yield-during-PulseEvent.patch b/patches/eventfd_synchronization/0081-ntdll-Yield-during-PulseEvent.patch deleted file mode 100644 index adea6190..00000000 --- a/patches/eventfd_synchronization/0081-ntdll-Yield-during-PulseEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 25b0902552205d767139b8eea4e448faa8b67fec Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 19 Aug 2018 12:50:57 -0500 -Subject: [PATCH 81/83] ntdll: Yield during PulseEvent(). - -May help with #10, although the real fix there is just not to use esync. ---- - dlls/ntdll/esync.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 597cb8fa8..d9b5b1a70 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -640,6 +640,11 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) - * used (and publicly deprecated). */ - if (write( obj->fd, &value, sizeof(value) ) == -1) - return FILE_GetNtStatus(); -+ -+ /* 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) ); - - current = InterlockedExchange( &event->signaled, 0 ); --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0082-ntdll-server-Check-the-value-of-WINEESYNC-instead-of.patch b/patches/eventfd_synchronization/0082-ntdll-server-Check-the-value-of-WINEESYNC-instead-of.patch deleted file mode 100644 index d4c26d1a..00000000 --- a/patches/eventfd_synchronization/0082-ntdll-server-Check-the-value-of-WINEESYNC-instead-of.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 785a0e353a59eeea347c5e3543e2e6c6af456c6b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Sun, 19 Aug 2018 12:54:33 -0500 -Subject: [PATCH 82/83] ntdll, server: Check the value of WINEESYNC instead of - just the presence. - -People keep getting tripped up by this. ---- - dlls/ntdll/esync.c | 2 +- - server/esync.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index d9b5b1a70..776fc484d 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -57,7 +57,7 @@ int do_esync(void) - static int do_esync_cached = -1; - - if (do_esync_cached == -1) -- do_esync_cached = (getenv("WINEESYNC") != NULL); -+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); - - return do_esync_cached; - #else -diff --git a/server/esync.c b/server/esync.c -index 19e614a89..4521993d4 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -53,7 +53,7 @@ int do_esync(void) - static int do_esync_cached = -1; - - if (do_esync_cached == -1) -- do_esync_cached = (getenv("WINEESYNC") != NULL); -+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC")); - - return do_esync_cached; - #else --- -2.20.1 - diff --git a/patches/eventfd_synchronization/0085-server-Only-signal-the-APC-fd-for-user-APCs.patch b/patches/eventfd_synchronization/0085-server-Only-signal-the-APC-fd-for-user-APCs.patch deleted file mode 100644 index 259618a5..00000000 --- a/patches/eventfd_synchronization/0085-server-Only-signal-the-APC-fd-for-user-APCs.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9e4df70f7282b04849153b3fa2edf15dc24eaf4f Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 23 Jul 2019 18:39:06 -0500 -Subject: [PATCH] server: Only signal the APC fd for user APCs. - -Otherwise we might incorrectly return WAIT_IO_COMPLETION to the user when a system APC runs. ---- - server/thread.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/server/thread.c b/server/thread.c -index fc751c2cb..2e77e5ff2 100644 ---- a/server/thread.c -+++ b/server/thread.c -@@ -1057,7 +1057,7 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr - { - wake_thread( thread ); - -- if (do_esync()) -+ if (do_esync() && queue == &thread->user_apc) - esync_wake_fd( thread->esync_apc_fd ); - } - --- -2.23.0 - diff --git a/patches/eventfd_synchronization/0086-ntdll-Check-the-APC-fd-first.patch b/patches/eventfd_synchronization/0086-ntdll-Check-the-APC-fd-first.patch deleted file mode 100644 index 6dfd55c7..00000000 --- a/patches/eventfd_synchronization/0086-ntdll-Check-the-APC-fd-first.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 836f1b6b0560bd178efb8d52900b4b136f87ae30 Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Tue, 23 Jul 2019 17:22:20 -0500 -Subject: [PATCH] ntdll: Check the APC fd first. - ---- - dlls/ntdll/esync.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index fc621ccfb..0adb4ad77 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -1046,6 +1046,14 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, - 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++) - { -@@ -1089,11 +1097,6 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, - return count - 1; - } - } -- if (alertable) -- { -- if (fds[i++].revents & POLLIN) -- goto userapc; -- } - - /* If we got here, someone else stole (or reset, etc.) whatever - * we were waiting for. So keep waiting. */ --- -2.23.0 - diff --git a/patches/eventfd_synchronization/0087-ntdll-esync-Lock-accessing-the-shm_addrs-array.patch b/patches/eventfd_synchronization/0087-ntdll-esync-Lock-accessing-the-shm_addrs-array.patch deleted file mode 100644 index 771d8556..00000000 --- a/patches/eventfd_synchronization/0087-ntdll-esync-Lock-accessing-the-shm_addrs-array.patch +++ /dev/null @@ -1,52 +0,0 @@ -From c1804983dc8e9509c088c35914212cda1bd5a48a Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Wed, 7 Aug 2019 17:14:54 -0500 -Subject: [PATCH] ntdll/esync: Lock accessing the shm_addrs array. - ---- - dlls/ntdll/esync.c | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 0adb4ad77..2f030c141 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -155,10 +155,22 @@ void esync_init(void) - shm_addrs_size = 128; - } - -+static RTL_CRITICAL_SECTION shm_addrs_section; -+static RTL_CRITICAL_SECTION_DEBUG shm_addrs_debug = -+{ -+ 0, 0, &shm_addrs_section, -+ { &shm_addrs_debug.ProcessLocksList, &shm_addrs_debug.ProcessLocksList }, -+ 0, 0, { (DWORD_PTR)(__FILE__ ": shm_addrs_section") } -+}; -+static RTL_CRITICAL_SECTION shm_addrs_section = { &shm_addrs_debug, -1, 0, 0, 0, 0 }; -+ - static void *get_shm( unsigned int idx ) - { - int entry = (idx * 8) / pagesize; - int offset = (idx * 8) % pagesize; -+ void *ret; -+ -+ RtlEnterCriticalSection(&shm_addrs_section); - - if (entry >= shm_addrs_size) - { -@@ -180,7 +192,11 @@ static void *get_shm( unsigned int idx ) - munmap( addr, pagesize ); /* someone beat us to it */ - } - -- return (void *)((unsigned long)shm_addrs[entry] + offset); -+ ret = (void *)((unsigned long)shm_addrs[entry] + offset); -+ -+ RtlLeaveCriticalSection(&shm_addrs_section); -+ -+ return ret; - } - - /* We'd like lookup to be fast. To that end, we use a static list indexed by handle. --- -2.23.0 - diff --git a/patches/eventfd_synchronization/0088-ntdll-Get-rid-of-the-per-event-spinlock-for-auto-res.patch b/patches/eventfd_synchronization/0088-ntdll-Get-rid-of-the-per-event-spinlock-for-auto-res.patch deleted file mode 100644 index ddff504a..00000000 --- a/patches/eventfd_synchronization/0088-ntdll-Get-rid-of-the-per-event-spinlock-for-auto-res.patch +++ /dev/null @@ -1,206 +0,0 @@ -From c41dc5b8c422be3914cd31c239ec586a091b8a3b Mon Sep 17 00:00:00 2001 -From: Zebediah Figura -Date: Mon, 10 Jun 2019 11:25:34 -0400 -Subject: [PATCH] ntdll: Get rid of the per-event spinlock for auto-reset - events. - -It's not necessary. Much like semaphores, the shm state is just a hint. ---- - dlls/ntdll/esync.c | 74 +++++++++++++++++++++++++++++++++++----------- - server/esync.c | 32 +++++++++++++------- - 2 files changed, 78 insertions(+), 28 deletions(-) - -diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c -index 2f030c141..87f303403 100644 ---- a/dlls/ntdll/esync.c -+++ b/dlls/ntdll/esync.c -@@ -570,6 +570,14 @@ static inline void small_pause(void) - * problem at all. - */ - -+/* 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, LONG *prev ) - { - static const uint64_t value = 1; -@@ -583,21 +591,36 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) - if ((ret = get_object( handle, &obj ))) return ret; - event = obj->shm; - -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -+ 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. */ - - /* Only bother signaling the fd if we weren't already signaled. */ -- if (!(current = InterlockedExchange( &event->signaled, 1 ))) -+ if (!(current = InterlockedExchange( &event->signaled, 1 )) || obj->type == ESYNC_AUTO_EVENT) - { - if (write( obj->fd, &value, sizeof(value) ) == -1) -- return FILE_GetNtStatus(); -+ ERR("write: %s\n", strerror(errno)); - } - - if (prev) *prev = current; - -- /* Release the spinlock. */ -- event->locked = 0; -+ if (obj->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Release the spinlock. */ -+ event->locked = 0; -+ } - - return STATUS_SUCCESS; - } -@@ -615,21 +638,34 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) - if ((ret = get_object( handle, &obj ))) return ret; - event = obj->shm; - -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -+ if (obj->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); -+ } - -- /* Only bother signaling the fd if we weren't already signaled. */ -- if ((current = InterlockedExchange( &event->signaled, 0 ))) -+ /* 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 ((current = InterlockedExchange( &event->signaled, 0 )) || obj->type == ESYNC_AUTO_EVENT) - { -- /* we don't care about the return value */ -- read( obj->fd, &value, sizeof(value) ); -+ if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN) -+ { -+ ERR("read: %s\n", strerror(errno)); -+ } - } - - if (prev) *prev = current; - -- /* Release the spinlock. */ -- event->locked = 0; -+ if (obj->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Release the spinlock. */ -+ event->locked = 0; -+ } - - return STATUS_SUCCESS; - } -@@ -844,8 +880,9 @@ static void update_grabbed_object( struct esync *obj ) - 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(), for -- * reasons described near esync_set_event(). */ -+ /* 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; - } - } -@@ -1094,6 +1131,7 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, - } - else - { -+ /* FIXME: Could we check the poll or shm state first? Should we? */ - if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value)) - { - /* We found our object. */ -diff --git a/server/esync.c b/server/esync.c -index 4521993d4..84d0951cb 100644 ---- a/server/esync.c -+++ b/server/esync.c -@@ -396,9 +396,12 @@ void esync_set_event( struct esync *esync ) - if (debug_level) - fprintf( stderr, "esync_set_event() fd=%d\n", esync->fd ); - -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -+ if (esync->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); -+ } - - if (!InterlockedExchange( &event->signaled, 1 )) - { -@@ -406,8 +409,11 @@ void esync_set_event( struct esync *esync ) - perror( "esync: write" ); - } - -- /* Release the spinlock. */ -- event->locked = 0; -+ if (esync->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Release the spinlock. */ -+ event->locked = 0; -+ } - } - - void esync_reset_event( struct esync *esync ) -@@ -421,9 +427,12 @@ void esync_reset_event( struct esync *esync ) - if (debug_level) - fprintf( stderr, "esync_reset_event() fd=%d\n", esync->fd ); - -- /* Acquire the spinlock. */ -- while (InterlockedCompareExchange( &event->locked, 1, 0 )) -- small_pause(); -+ if (esync->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Acquire the spinlock. */ -+ while (InterlockedCompareExchange( &event->locked, 1, 0 )) -+ small_pause(); -+ } - - /* Only bother signaling the fd if we weren't already signaled. */ - if (InterlockedExchange( &event->signaled, 0 )) -@@ -432,8 +441,11 @@ void esync_reset_event( struct esync *esync ) - read( esync->fd, &value, sizeof(value) ); - } - -- /* Release the spinlock. */ -- event->locked = 0; -+ if (esync->type == ESYNC_MANUAL_EVENT) -+ { -+ /* Release the spinlock. */ -+ event->locked = 0; -+ } - } - - DECL_HANDLER(create_esync) --- -2.23.0 - diff --git a/patches/eventfd_synchronization/definition b/patches/eventfd_synchronization/definition index f32566c3..c0b18001 100644 --- a/patches/eventfd_synchronization/definition +++ b/patches/eventfd_synchronization/definition @@ -1,9 +1,5 @@ Fixes: [36692] Many multi-threaded applications have poor performance due to heavy use of synchronization primitives -# Note: the following dependencies are essentially artificial; in particular -# these patches do not make use of the Staging shared memory infrastructure. -Depends: server-Shared_Memory Depends: server-Realtime_Priority -Depends: advapi32-Token_Integrity_Level Depends: ntdll-Junction_Points -Depends: user32-rawinput-mouse -Disabled: true \ No newline at end of file +Depends: server-PeekMessage +Depends: server-Signal_Thread diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 17f1833b..ded5339b 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -51,7 +51,7 @@ usage() # Get the upstream commit sha upstream_commit() { - echo "de679af492ed93d70c99dff7f7cfc01cc8f25eb0" + echo "0c249e6125fc9dc6ee86b4ef6ae0d9fa2fc6291b" } # Show version information @@ -126,6 +126,7 @@ patch_enable_all () enable_dwrite_FontFallback="$1" enable_dxdiagn_Enumerate_DirectSound="$1" enable_dxdiagn_GetChildContainer_Leaf_Nodes="$1" + enable_eventfd_synchronization="$1" enable_explorer_Video_Registry_Key="$1" enable_fonts_Missing_Fonts="$1" enable_gdi32_rotation="$1" @@ -468,6 +469,9 @@ patch_enable () dxdiagn-GetChildContainer_Leaf_Nodes) enable_dxdiagn_GetChildContainer_Leaf_Nodes="$2" ;; + eventfd_synchronization) + enable_eventfd_synchronization="$2" + ;; explorer-Video_Registry_Key) enable_explorer_Video_Registry_Key="$2" ;; @@ -1621,17 +1625,6 @@ if test "$enable_ntdll_NtDevicePath" -eq 1; then enable_ntdll_Pipe_SpecialCharacters=1 fi -if test "$enable_ntdll_Junction_Points" -eq 1; then - if test "$enable_ntdll_DOS_Attributes" -gt 1; then - abort "Patchset ntdll-DOS_Attributes disabled, but ntdll-Junction_Points depends on that." - fi - if test "$enable_ntdll_NtQueryEaFile" -gt 1; then - abort "Patchset ntdll-NtQueryEaFile disabled, but ntdll-Junction_Points depends on that." - fi - enable_ntdll_DOS_Attributes=1 - enable_ntdll_NtQueryEaFile=1 -fi - if test "$enable_ntdll_Builtin_Prot" -eq 1; then if test "$enable_ntdll_WRITECOPY" -gt 1; then abort "Patchset ntdll-WRITECOPY disabled, but ntdll-Builtin_Prot depends on that." @@ -1660,6 +1653,36 @@ if test "$enable_kernel32_CopyFileEx" -eq 1; then enable_ntdll_FileDispositionInformation=1 fi +if test "$enable_eventfd_synchronization" -eq 1; then + if test "$enable_ntdll_Junction_Points" -gt 1; then + abort "Patchset ntdll-Junction_Points disabled, but eventfd_synchronization depends on that." + fi + if test "$enable_server_PeekMessage" -gt 1; then + abort "Patchset server-PeekMessage disabled, but eventfd_synchronization depends on that." + fi + if test "$enable_server_Realtime_Priority" -gt 1; then + abort "Patchset server-Realtime_Priority disabled, but eventfd_synchronization depends on that." + fi + if test "$enable_server_Signal_Thread" -gt 1; then + abort "Patchset server-Signal_Thread disabled, but eventfd_synchronization depends on that." + fi + enable_ntdll_Junction_Points=1 + enable_server_PeekMessage=1 + enable_server_Realtime_Priority=1 + enable_server_Signal_Thread=1 +fi + +if test "$enable_ntdll_Junction_Points" -eq 1; then + if test "$enable_ntdll_DOS_Attributes" -gt 1; then + abort "Patchset ntdll-DOS_Attributes disabled, but ntdll-Junction_Points depends on that." + fi + if test "$enable_ntdll_NtQueryEaFile" -gt 1; then + abort "Patchset ntdll-NtQueryEaFile disabled, but ntdll-Junction_Points depends on that." + fi + enable_ntdll_DOS_Attributes=1 + enable_ntdll_NtQueryEaFile=1 +fi + if test "$enable_dxdiagn_GetChildContainer_Leaf_Nodes" -eq 1; then if test "$enable_dxdiagn_Enumerate_DirectSound" -gt 1; then abort "Patchset dxdiagn-Enumerate_DirectSound disabled, but dxdiagn-GetChildContainer_Leaf_Nodes depends on that." @@ -2419,6 +2442,185 @@ if test "$enable_dxdiagn_GetChildContainer_Leaf_Nodes" -eq 1; then patch_apply dxdiagn-GetChildContainer_Leaf_Nodes/0001-dxdiagn-Calling-GetChildContainer-with-an-empty-stri.patch fi +# Patchset ntdll-DOS_Attributes +# | +# | This patchset fixes the following Wine bugs: +# | * [#9158] Support for DOS hidden/system file attributes +# | * [#15679] cygwin symlinks not working in wine +# | +# | Modified files: +# | * configure.ac, dlls/ntdll/tests/directory.c, dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c +# | +if test "$enable_ntdll_DOS_Attributes" -eq 1; then + patch_apply ntdll-DOS_Attributes/0001-ntdll-Implement-retrieving-DOS-attributes-in-fd_-get.patch + patch_apply ntdll-DOS_Attributes/0003-ntdll-Implement-storing-DOS-attributes-in-NtSetInfor.patch + patch_apply ntdll-DOS_Attributes/0004-ntdll-Implement-storing-DOS-attributes-in-NtCreateFi.patch + patch_apply ntdll-DOS_Attributes/0005-libport-Add-support-for-Mac-OS-X-style-extended-attr.patch + patch_apply ntdll-DOS_Attributes/0006-libport-Add-support-for-FreeBSD-style-extended-attri.patch + patch_apply ntdll-DOS_Attributes/0007-ntdll-Perform-the-Unix-style-hidden-file-check-withi.patch + patch_apply ntdll-DOS_Attributes/0008-ntdll-Always-store-SAMBA_XATTR_DOS_ATTRIB-when-path-.patch +fi + +# Patchset ntdll-NtQueryEaFile +# | +# | Modified files: +# | * dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c +# | +if test "$enable_ntdll_NtQueryEaFile" -eq 1; then + patch_apply ntdll-NtQueryEaFile/0001-ntdll-Improve-stub-of-NtQueryEaFile.patch +fi + +# Patchset ntdll-Junction_Points +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile +# | +# | This patchset fixes the following Wine bugs: +# | * [#12401] NET Framework 2.0, 3.0, 4.0 installers and other apps that make use of GAC API for managed assembly +# | installation on NTFS filesystems need reparse point/junction API support +# | (FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT) +# | * [#44948] Multiple apps (Spine (Mod starter for Gothic), MS Office 365 installer) need CreateSymbolicLinkW implementation +# | +# | Modified files: +# | * configure.ac, dlls/kernel32/tests/path.c, dlls/kernelbase/file.c, dlls/msvcp120/tests/msvcp120.c, +# | dlls/msvcp140/tests/msvcp140.c, dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c, include/Makefile.in, include/ntifs.h, +# | include/winternl.h, programs/cmd/builtins.c, programs/cmd/directory.c, server/fd.c, server/protocol.def +# | +if test "$enable_ntdll_Junction_Points" -eq 1; then + patch_apply ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch + patch_apply ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch + patch_apply ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch + patch_apply ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch + patch_apply ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch + patch_apply ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch + patch_apply ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch + patch_apply ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch + patch_apply ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch + patch_apply ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch + patch_apply ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch + patch_apply ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch + patch_apply ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch + patch_apply ntdll-Junction_Points/0015-kernel32-Set-error-code-when-attempting-to-delete-fi.patch + patch_apply ntdll-Junction_Points/0016-server-Properly-handle-file-symlink-deletion.patch + patch_apply ntdll-Junction_Points/0017-ntdll-Always-report-symbolic-links-as-containing-zer.patch + patch_apply ntdll-Junction_Points/0018-ntdll-Find-dangling-symlinks-quickly.patch + patch_apply ntdll-Junction_Points/0019-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch + patch_apply ntdll-Junction_Points/0020-kernel32-Add-reparse-support-to-FindNextFile.patch + patch_apply ntdll-Junction_Points/0021-wcmd-Display-reparse-point-type-in-directory-listing.patch + patch_apply ntdll-Junction_Points/0022-wcmd-Show-reparse-point-target-in-directory-listing.patch + patch_apply ntdll-Junction_Points/0023-wcmd-Add-junction-point-support-to-mklink.patch + patch_apply ntdll-Junction_Points/0024-server-Fix-obtaining-information-about-a-symlink.patch +fi + +# Patchset server-PeekMessage +# | +# | This patchset fixes the following Wine bugs: +# | * [#28884] GetMessage should remove already seen messages with higher priority +# | +# | Modified files: +# | * dlls/user32/tests/msg.c, server/queue.c +# | +if test "$enable_server_PeekMessage" -eq 1; then + patch_apply server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch +fi + +# Patchset server-Realtime_Priority +# | +# | Modified files: +# | * server/Makefile.in, server/main.c, server/scheduler.c, server/thread.c, server/thread.h +# | +if test "$enable_server_Realtime_Priority" -eq 1; then + patch_apply server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch +fi + +# Patchset server-Signal_Thread +# | +# | Modified files: +# | * server/thread.c, server/thread.h +# | +if test "$enable_server_Signal_Thread" -eq 1; then + patch_apply server-Signal_Thread/0001-server-Do-not-signal-thread-until-it-is-really-gone.patch +fi + +# Patchset eventfd_synchronization +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, server-PeekMessage, server-Realtime_Priority, server- +# | Signal_Thread +# | +# | This patchset fixes the following Wine bugs: +# | * [#36692] Many multi-threaded applications have poor performance due to heavy use of synchronization primitives +# | +# | Modified files: +# | * README.esync, configure, configure.ac, dlls/kernel32/tests/sync.c, dlls/ntdll/Makefile.in, dlls/ntdll/unix/esync.c, +# | dlls/ntdll/unix/esync.h, dlls/ntdll/unix/loader.c, dlls/ntdll/unix/server.c, dlls/ntdll/unix/sync.c, +# | dlls/ntdll/unix/unix_private.h, dlls/ntdll/unix/virtual.c, dlls/rpcrt4/rpc_server.c, include/config.h.in, +# | server/Makefile.in, server/async.c, server/atom.c, server/change.c, server/clipboard.c, server/completion.c, +# | server/console.c, server/debugger.c, server/device.c, server/directory.c, server/esync.c, server/esync.h, +# | server/event.c, server/fd.c, server/file.c, server/file.h, server/handle.c, server/hook.c, server/mailslot.c, +# | server/main.c, server/mapping.c, server/mutex.c, server/named_pipe.c, server/object.h, server/process.c, +# | server/process.h, server/protocol.def, server/queue.c, server/registry.c, server/request.c, server/semaphore.c, +# | server/serial.c, server/signal.c, server/sock.c, server/symlink.c, server/thread.c, server/thread.h, server/timer.c, +# | server/token.c, server/winstation.c +# | +if test "$enable_eventfd_synchronization" -eq 1; then + patch_apply eventfd_synchronization/0001-configure-Check-for-sys-eventfd.h-ppoll-and-shm_open.patch + patch_apply eventfd_synchronization/0002-server-Create-server-objects-for-eventfd-based-synch.patch + patch_apply eventfd_synchronization/0003-ntdll-Create-eventfd-based-objects-for-semaphores.patch + patch_apply eventfd_synchronization/0004-ntdll-Implement-NtReleaseSemaphore.patch + patch_apply eventfd_synchronization/0005-ntdll-Implement-NtClose.patch + patch_apply eventfd_synchronization/0006-ntdll-Implement-NtWaitForMultipleObjects.patch + patch_apply eventfd_synchronization/0007-ntdll-server-Implement-NtCreateEvent.patch + patch_apply eventfd_synchronization/0008-ntdll-Implement-NtSetEvent.patch + patch_apply eventfd_synchronization/0009-ntdll-Implement-NtResetEvent.patch + patch_apply eventfd_synchronization/0010-ntdll-Implement-waiting-on-manual-reset-events.patch + patch_apply eventfd_synchronization/0011-server-Add-an-object-operation-to-grab-the-esync-fil.patch + patch_apply eventfd_synchronization/0012-server-Add-a-request-to-get-the-eventfd-file-descrip.patch + patch_apply eventfd_synchronization/0013-server-Create-eventfd-file-descriptors-for-process-o.patch + patch_apply eventfd_synchronization/0014-ntdll-server-Implement-waiting-on-server-bound-objec.patch + patch_apply eventfd_synchronization/0015-server-Create-eventfd-file-descriptors-for-event-obj.patch + patch_apply eventfd_synchronization/0016-server-Allow-re-setting-esync-events-on-the-server-s.patch + patch_apply eventfd_synchronization/0017-ntdll-Try-again-if-poll-returns-EINTR.patch + patch_apply eventfd_synchronization/0018-server-Create-eventfd-file-descriptors-for-thread-ob.patch + patch_apply eventfd_synchronization/0019-rpcrt4-Avoid-closing-the-server-thread-handle-while-.patch + patch_apply eventfd_synchronization/0020-server-Create-eventfd-file-descriptors-for-message-q.patch + patch_apply eventfd_synchronization/0021-server-ntdll-Implement-message-waits.patch + patch_apply eventfd_synchronization/0022-server-Create-eventfd-descriptors-for-device-manager.patch + patch_apply eventfd_synchronization/0023-ntdll-server-Implement-NtCreateMutant.patch + patch_apply eventfd_synchronization/0024-ntdll-Implement-NtReleaseMutant.patch + patch_apply eventfd_synchronization/0025-ntdll-Implement-waiting-on-mutexes.patch + patch_apply eventfd_synchronization/0026-ntdll-Implement-wait-all.patch + patch_apply eventfd_synchronization/0027-esync-Add-a-README.patch + patch_apply eventfd_synchronization/0028-ntdll-Implement-NtSignalAndWaitForSingleObject.patch + patch_apply eventfd_synchronization/0029-ntdll-Implement-NtOpenSemaphore.patch + patch_apply eventfd_synchronization/0030-ntdll-Implement-NtOpenEvent.patch + patch_apply eventfd_synchronization/0031-ntdll-Implement-NtOpenMutant.patch + patch_apply eventfd_synchronization/0032-server-Implement-esync_map_access.patch + patch_apply eventfd_synchronization/0033-server-Implement-NtDuplicateObject.patch + patch_apply eventfd_synchronization/0034-server-Create-eventfd-descriptors-for-timers.patch + patch_apply eventfd_synchronization/0035-ntdll-server-Implement-alertable-waits.patch + patch_apply eventfd_synchronization/0036-esync-Update-README.patch + patch_apply eventfd_synchronization/0037-kernel32-tests-Mark-some-existing-tests-as-failing-u.patch + patch_apply eventfd_synchronization/0038-kernel32-tests-Add-some-semaphore-tests.patch + patch_apply eventfd_synchronization/0039-kernel32-tests-Add-some-event-tests.patch + patch_apply eventfd_synchronization/0040-kernel32-tests-Add-some-mutex-tests.patch + patch_apply eventfd_synchronization/0041-kernel32-tests-Add-some-tests-for-wait-timeouts.patch + patch_apply eventfd_synchronization/0042-kernel32-tests-Zigzag-test.patch + patch_apply eventfd_synchronization/0043-ntdll-Implement-NtQuerySemaphore.patch + patch_apply eventfd_synchronization/0044-ntdll-Implement-NtQueryEvent.patch + patch_apply eventfd_synchronization/0045-ntdll-Implement-NtQueryMutant.patch + patch_apply eventfd_synchronization/0046-server-Create-eventfd-descriptors-for-pseudo-fd-obje.patch + patch_apply eventfd_synchronization/0047-esync-Update-README.patch + patch_apply eventfd_synchronization/0048-esync-Add-note-about-file-limits-not-being-raised-wh.patch + patch_apply eventfd_synchronization/0049-ntdll-Try-to-avoid-poll-for-uncontended-objects.patch + patch_apply eventfd_synchronization/0050-ntdll-server-Try-to-avoid-poll-for-signaled-events.patch + patch_apply eventfd_synchronization/0051-esync-Update-README.patch + patch_apply eventfd_synchronization/0052-ntdll-Implement-NtPulseEvent.patch + patch_apply eventfd_synchronization/0053-esync-Update-README.patch + patch_apply eventfd_synchronization/0054-server-Create-esync-file-descriptors-for-true-file-o.patch + patch_apply eventfd_synchronization/0055-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch +fi + # Patchset explorer-Video_Registry_Key # | # | Modified files: @@ -2945,25 +3147,6 @@ if test "$enable_ntdll_CriticalSection" -eq 1; then patch_apply ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch fi -# Patchset ntdll-DOS_Attributes -# | -# | This patchset fixes the following Wine bugs: -# | * [#9158] Support for DOS hidden/system file attributes -# | * [#15679] cygwin symlinks not working in wine -# | -# | Modified files: -# | * configure.ac, dlls/ntdll/tests/directory.c, dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c -# | -if test "$enable_ntdll_DOS_Attributes" -eq 1; then - patch_apply ntdll-DOS_Attributes/0001-ntdll-Implement-retrieving-DOS-attributes-in-fd_-get.patch - patch_apply ntdll-DOS_Attributes/0003-ntdll-Implement-storing-DOS-attributes-in-NtSetInfor.patch - patch_apply ntdll-DOS_Attributes/0004-ntdll-Implement-storing-DOS-attributes-in-NtCreateFi.patch - patch_apply ntdll-DOS_Attributes/0005-libport-Add-support-for-Mac-OS-X-style-extended-attr.patch - patch_apply ntdll-DOS_Attributes/0006-libport-Add-support-for-FreeBSD-style-extended-attri.patch - patch_apply ntdll-DOS_Attributes/0007-ntdll-Perform-the-Unix-style-hidden-file-check-withi.patch - patch_apply ntdll-DOS_Attributes/0008-ntdll-Always-store-SAMBA_XATTR_DOS_ATTRIB-when-path-.patch -fi - # Patchset ntdll-Dealloc_Thread_Stack # | # | Modified files: @@ -3053,57 +3236,6 @@ if test "$enable_ntdll_Interrupt_0x2e" -eq 1; then patch_apply ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch fi -# Patchset ntdll-NtQueryEaFile -# | -# | Modified files: -# | * dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c -# | -if test "$enable_ntdll_NtQueryEaFile" -eq 1; then - patch_apply ntdll-NtQueryEaFile/0001-ntdll-Improve-stub-of-NtQueryEaFile.patch -fi - -# Patchset ntdll-Junction_Points -# | -# | This patchset has the following (direct or indirect) dependencies: -# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile -# | -# | This patchset fixes the following Wine bugs: -# | * [#12401] NET Framework 2.0, 3.0, 4.0 installers and other apps that make use of GAC API for managed assembly -# | installation on NTFS filesystems need reparse point/junction API support -# | (FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT) -# | * [#44948] Multiple apps (Spine (Mod starter for Gothic), MS Office 365 installer) need CreateSymbolicLinkW implementation -# | -# | Modified files: -# | * configure.ac, dlls/kernel32/tests/path.c, dlls/kernelbase/file.c, dlls/msvcp120/tests/msvcp120.c, -# | dlls/msvcp140/tests/msvcp140.c, dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c, include/Makefile.in, include/ntifs.h, -# | include/winternl.h, programs/cmd/builtins.c, programs/cmd/directory.c, server/fd.c, server/protocol.def -# | -if test "$enable_ntdll_Junction_Points" -eq 1; then - patch_apply ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch - patch_apply ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch - patch_apply ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch - patch_apply ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch - patch_apply ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch - patch_apply ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch - patch_apply ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch - patch_apply ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch - patch_apply ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch - patch_apply ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch - patch_apply ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch - patch_apply ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch - patch_apply ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch - patch_apply ntdll-Junction_Points/0015-kernel32-Set-error-code-when-attempting-to-delete-fi.patch - patch_apply ntdll-Junction_Points/0016-server-Properly-handle-file-symlink-deletion.patch - patch_apply ntdll-Junction_Points/0017-ntdll-Always-report-symbolic-links-as-containing-zer.patch - patch_apply ntdll-Junction_Points/0018-ntdll-Find-dangling-symlinks-quickly.patch - patch_apply ntdll-Junction_Points/0019-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch - patch_apply ntdll-Junction_Points/0020-kernel32-Add-reparse-support-to-FindNextFile.patch - patch_apply ntdll-Junction_Points/0021-wcmd-Display-reparse-point-type-in-directory-listing.patch - patch_apply ntdll-Junction_Points/0022-wcmd-Show-reparse-point-target-in-directory-listing.patch - patch_apply ntdll-Junction_Points/0023-wcmd-Add-junction-point-support-to-mklink.patch - patch_apply ntdll-Junction_Points/0024-server-Fix-obtaining-information-about-a-symlink.patch -fi - # Patchset ntdll-Manifest_Range # | # | This patchset fixes the following Wine bugs: @@ -3657,27 +3789,6 @@ if test "$enable_server_Object_Types" -eq 1; then patch_apply server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch fi -# Patchset server-PeekMessage -# | -# | This patchset fixes the following Wine bugs: -# | * [#28884] GetMessage should remove already seen messages with higher priority -# | -# | Modified files: -# | * dlls/user32/tests/msg.c, server/queue.c -# | -if test "$enable_server_PeekMessage" -eq 1; then - patch_apply server-PeekMessage/0001-server-Fix-handling-of-GetMessage-after-previous-Pee.patch -fi - -# Patchset server-Realtime_Priority -# | -# | Modified files: -# | * server/Makefile.in, server/main.c, server/scheduler.c, server/thread.c, server/thread.h -# | -if test "$enable_server_Realtime_Priority" -eq 1; then - patch_apply server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch -fi - # Patchset server-Registry_Notifications # | # | Modified files: @@ -3688,15 +3799,6 @@ if test "$enable_server_Registry_Notifications" -eq 1; then patch_apply server-Registry_Notifications/0002-server-Introduce-refcounting-for-registry-notificati.patch fi -# Patchset server-Signal_Thread -# | -# | Modified files: -# | * server/thread.c, server/thread.h -# | -if test "$enable_server_Signal_Thread" -eq 1; then - patch_apply server-Signal_Thread/0001-server-Do-not-signal-thread-until-it-is-really-gone.patch -fi - # Patchset setupapi-DiskSpaceList # | # | Modified files: