Rebase against 01269452e0fbb1f081d506bd64996590a553e2b9.

This commit is contained in:
Elizabeth Figura
2025-10-03 16:39:15 -05:00
parent 9c06e8eab3
commit 38d4b8ca78
66 changed files with 39 additions and 7790 deletions

View File

@@ -1,85 +0,0 @@
From 6c64a33f908b9fade24fe11d89533a70fdce352f Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Wed, 13 Jun 2018 10:44:49 -0500
Subject: [PATCH] configure: Check for sys/eventfd.h, ppoll(), and shm_open().
We use ppoll() instead of poll() for the better time granularity.
Although perhaps we shouldn't since the server doesn't do this.
---
configure.ac | 8 ++++++++
include/config.h.in | 11 ++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index eb7f8223b51..388ac14dc8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -411,6 +411,7 @@ AC_CHECK_HEADERS(\
sys/cdio.h \
sys/epoll.h \
sys/event.h \
+ sys/eventfd.h \
sys/extattr.h \
sys/filio.h \
sys/ipc.h \
@@ -2079,6 +2080,7 @@ AC_CHECK_FUNCS(\
port_create \
posix_fadvise \
posix_fallocate \
+ ppoll \
prctl \
sched_getcpu \
sched_yield \
@@ -2100,6 +2102,12 @@ AC_SEARCH_LIBS(clock_gettime, rt,
test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")])
LIBS=$ac_save_LIBS
+ac_save_LIBS=$LIBS
+AC_SEARCH_LIBS(shm_open, rt,
+ [AC_DEFINE(HAVE_SHM_OPEN, 1, [Define to 1 if you have the `shm_open' function.])
+ test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")])
+LIBS=$ac_save_LIBS
+
AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity,
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[#include <sched.h>]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no]))
diff --git a/include/config.h.in b/include/config.h.in
index 6033d8674f3..563b63a92df 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -321,6 +321,9 @@
/* Define to 1 if you have the 'posix_fallocate' function. */
#undef HAVE_POSIX_FALLOCATE
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
/* Define to 1 if you have the 'prctl' function. */
#undef HAVE_PRCTL
@@ -381,7 +384,10 @@
/* Define to 1 if 'interface_id' is a member of 'sg_io_hdr_t'. */
#undef HAVE_SG_IO_HDR_T_INTERFACE_ID
-/* Define to 1 if 'si_fd' is a member of 'siginfo_t'. */
+/* Define to 1 if you have the `shm_open' function. */
+#undef HAVE_SHM_OPEN
+
+/* Define to 1 if `si_fd' is a member of `siginfo_t'. */
#undef HAVE_SIGINFO_T_SI_FD
/* Define to 1 if you have the 'sigprocmask' function. */
@@ -510,6 +516,9 @@
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
+/* Define to 1 if you have the <sys/eventfd.h> header file. */
+#undef HAVE_SYS_EVENTFD_H
+
/* Define to 1 if you have the <sys/event.h> header file. */
#undef HAVE_SYS_EVENT_H
--
2.45.2

View File

@@ -1,446 +0,0 @@
From da832ae3626406e9aee5f9f78bce01f2a0d49691 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 20:09:59 -0500
Subject: [PATCH] server: Create server objects for eventfd-based
synchronization objects.
---
server/Makefile.in | 1 +
server/esync.c | 318 ++++++++++++++++++++++++++++++++++++++++++++
server/esync.h | 24 ++++
server/main.c | 4 +
server/protocol.def | 24 ++++
5 files changed, 371 insertions(+)
create mode 100644 server/esync.c
create mode 100644 server/esync.h
diff --git a/server/Makefile.in b/server/Makefile.in
index 7e571ac2ba6..9632c4e694f 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -11,6 +11,7 @@ SOURCES = \
debugger.c \
device.c \
directory.c \
+ esync.c \
event.c \
fd.c \
file.c \
diff --git a/server/esync.c b/server/esync.c
new file mode 100644
index 00000000000..35b4833fd4c
--- /dev/null
+++ b/server/esync.c
@@ -0,0 +1,318 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_SYS_EVENTFD_H
+# include <sys/eventfd.h>
+#endif
+#include <sys/mman.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <unistd.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+
+#include "handle.h"
+#include "request.h"
+#include "file.h"
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
+
+ return do_esync_cached;
+#else
+ return 0;
+#endif
+}
+
+static char shm_name[29];
+static int shm_fd;
+static off_t shm_size;
+static void **shm_addrs;
+static int shm_addrs_size; /* length of the allocated shm_addrs array */
+static long pagesize;
+
+static void shm_cleanup(void)
+{
+ close( shm_fd );
+ if (shm_unlink( shm_name ) == -1)
+ perror( "shm_unlink" );
+}
+
+void esync_init(void)
+{
+ struct stat st;
+
+ if (fstat( config_dir_fd, &st ) == -1)
+ fatal_error( "cannot stat config dir\n" );
+
+ if (st.st_ino != (unsigned long)st.st_ino)
+ sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino );
+ else
+ sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino );
+
+ shm_unlink( shm_name );
+
+ shm_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 );
+ if (shm_fd == -1)
+ perror( "shm_open" );
+
+ pagesize = sysconf( _SC_PAGESIZE );
+
+ shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
+ shm_addrs_size = 128;
+
+ shm_size = pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ perror( "ftruncate" );
+
+ fprintf( stderr, "esync: up and running.\n" );
+
+ atexit( shm_cleanup );
+}
+
+struct esync
+{
+ struct object obj; /* object header */
+ int fd; /* eventfd file descriptor */
+ enum esync_type type;
+ unsigned int shm_idx; /* index into the shared memory section */
+};
+
+static void esync_dump( struct object *obj, int verbose );
+static void esync_destroy( struct object *obj );
+
+static const struct object_ops esync_ops =
+{
+ sizeof(struct esync), /* size */
+ &no_type, /* type */
+ esync_dump, /* dump */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ default_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ default_get_full_name, /* get_full_name */
+ no_lookup_name, /* lookup_name */
+ directory_link_name, /* link_name */
+ default_unlink_name, /* unlink_name */
+ no_open_file, /* open_file */
+ no_kernel_obj_list, /* get_kernel_obj_list */
+ no_close_handle, /* close_handle */
+ esync_destroy /* destroy */
+};
+
+static void esync_dump( struct object *obj, int verbose )
+{
+ struct esync *esync = (struct esync *)obj;
+ assert( obj->ops == &esync_ops );
+ fprintf( stderr, "esync fd=%d\n", esync->fd );
+}
+
+static void esync_destroy( struct object *obj )
+{
+ struct esync *esync = (struct esync *)obj;
+ close( esync->fd );
+}
+
+static int type_matches( enum esync_type type1, enum esync_type type2 )
+{
+ return (type1 == type2) ||
+ ((type1 == ESYNC_AUTO_EVENT || type1 == ESYNC_MANUAL_EVENT) &&
+ (type2 == ESYNC_AUTO_EVENT || type2 == ESYNC_MANUAL_EVENT));
+}
+
+static void *get_shm( unsigned int idx )
+{
+ int entry = (idx * 8) / pagesize;
+ int offset = (idx * 8) % pagesize;
+
+ if (entry >= shm_addrs_size)
+ {
+ int new_size = max(shm_addrs_size * 2, entry + 1);
+
+ if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) )))
+ fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 );
+
+ memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) );
+
+ shm_addrs_size = new_size;
+ }
+
+ if (!shm_addrs[entry])
+ {
+ void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
+ if (addr == (void *)-1)
+ {
+ fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize );
+ perror( "mmap" );
+ }
+
+ if (debug_level)
+ fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr );
+
+ if (__sync_val_compare_and_swap( &shm_addrs[entry], 0, addr ))
+ munmap( addr, pagesize ); /* someone beat us to it */
+ }
+
+ return (void *)((unsigned long)shm_addrs[entry] + offset);
+}
+
+struct semaphore
+{
+ int max;
+ int count;
+};
+C_ASSERT(sizeof(struct semaphore) == 8);
+
+struct esync *create_esync( struct object *root, const struct unicode_str *name,
+ unsigned int attr, int initval, int max, enum esync_type type,
+ const struct security_descriptor *sd )
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ struct esync *esync;
+
+ if ((esync = create_named_object( root, &esync_ops, name, attr, sd )))
+ {
+ if (get_error() != STATUS_OBJECT_NAME_EXISTS)
+ {
+ int flags = EFD_CLOEXEC | EFD_NONBLOCK;
+
+ if (type == ESYNC_SEMAPHORE)
+ flags |= EFD_SEMAPHORE;
+
+ /* initialize it if it didn't already exist */
+ esync->fd = eventfd( initval, flags );
+ if (esync->fd == -1)
+ {
+ perror( "eventfd" );
+ file_set_error();
+ release_object( esync );
+ return NULL;
+ }
+ esync->type = type;
+
+ /* Use the fd as index, since that'll be unique across all
+ * processes, but should hopefully end up also allowing reuse. */
+ esync->shm_idx = esync->fd + 1; /* we keep index 0 reserved */
+ while (esync->shm_idx * 8 >= shm_size)
+ {
+ /* Better expand the shm section. */
+ shm_size += pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ {
+ fprintf( stderr, "esync: couldn't expand %s to size %ld: ",
+ shm_name, (long)shm_size );
+ perror( "ftruncate" );
+ }
+ }
+
+ /* Initialize the shared memory portion. We want to do this on the
+ * server side to avoid a potential though unlikely race whereby
+ * the same object is opened and used between the time it's created
+ * and the time its shared memory portion is initialized. */
+ switch (type)
+ {
+ case ESYNC_SEMAPHORE:
+ {
+ struct semaphore *semaphore = get_shm( esync->shm_idx );
+ semaphore->max = max;
+ semaphore->count = initval;
+ break;
+ }
+ default:
+ assert( 0 );
+ }
+ }
+ else
+ {
+ /* validate the type */
+ if (!type_matches( type, esync->type ))
+ {
+ release_object( &esync->obj );
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ return NULL;
+ }
+ }
+ }
+ return esync;
+#else
+ /* FIXME: Provide a fallback implementation using pipe(). */
+ set_error( STATUS_NOT_IMPLEMENTED );
+ return NULL;
+#endif
+}
+
+DECL_HANDLER(create_esync)
+{
+ struct esync *esync;
+ struct unicode_str name;
+ struct object *root;
+ const struct security_descriptor *sd;
+ const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
+
+ if (!do_esync())
+ {
+ set_error( STATUS_NOT_IMPLEMENTED );
+ return;
+ }
+
+ if (!req->type)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (!objattr) return;
+
+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->max, req->type, sd )))
+ {
+ if (get_error() == STATUS_OBJECT_NAME_EXISTS)
+ reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes );
+ else
+ reply->handle = alloc_handle_no_access_check( current->process, esync,
+ req->access, objattr->attributes );
+
+ reply->type = esync->type;
+ reply->shm_idx = esync->shm_idx;
+ send_client_fd( current->process, esync->fd, reply->handle );
+ release_object( esync );
+ }
+
+ if (root) release_object( root );
+}
diff --git a/server/esync.h b/server/esync.h
new file mode 100644
index 00000000000..00f9e638d83
--- /dev/null
+++ b/server/esync.h
@@ -0,0 +1,24 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <unistd.h>
+
+extern int do_esync(void);
+void esync_init(void);
diff --git a/server/main.c b/server/main.c
index e014ec535ff..052667b4c6b 100644
--- a/server/main.c
+++ b/server/main.c
@@ -34,6 +34,7 @@
#include "thread.h"
#include "request.h"
#include "unicode.h"
+#include "esync.h"
/* command-line options */
int debug_level = 0;
@@ -229,6 +230,9 @@ int main( int argc, char *argv[] )
sock_init();
open_master_socket();
+ if (do_esync())
+ esync_init();
+
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
set_current_time();
init_signals();
diff --git a/server/protocol.def b/server/protocol.def
index fa4ca4aaa9e..a9ee996a8ab 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4080,6 +4080,29 @@ struct handle_info
obj_handle_t handle; /* next thread handle */
@END
+enum esync_type
+{
+ ESYNC_SEMAPHORE = 1,
+ ESYNC_AUTO_EVENT,
+ ESYNC_MANUAL_EVENT,
+ ESYNC_MUTEX,
+ ESYNC_AUTO_SERVER,
+ ESYNC_MANUAL_SERVER,
+ ESYNC_QUEUE,
+};
+
+/* Create a new eventfd-based synchronization object */
+@REQ(create_esync)
+ unsigned int access; /* wanted access rights */
+ int initval; /* initial value */
+ int type; /* type of esync object */
+ int max; /* maximum count on a semaphore */
+ VARARG(objattr,object_attributes); /* object attributes */
+@REPLY
+ obj_handle_t handle; /* handle to the object */
+ int type; /* actual type (may be different for events) */
+ unsigned int shm_idx;
+@END
/* Setup keyboard auto-repeat */
@REQ(set_keyboard_repeat)
@@ -4089,3 +4112,4 @@ struct handle_info
@REPLY
int enable; /* previous state of auto-repeat enable */
@END
+
--
2.47.2

View File

@@ -1,425 +0,0 @@
From 955a93ac10d1328e293fbf033e28107f98c43c7f Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:09:22 -0500
Subject: [PATCH] ntdll: Create eventfd-based objects for semaphores.
---
dlls/ntdll/Makefile.in | 1 +
dlls/ntdll/unix/esync.c | 270 +++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 35 +++++
dlls/ntdll/unix/loader.c | 2 +
dlls/ntdll/unix/server.c | 4 +-
dlls/ntdll/unix/sync.c | 4 +
server/esync.c | 1 +
7 files changed, 315 insertions(+), 2 deletions(-)
create mode 100644 dlls/ntdll/unix/esync.c
create mode 100644 dlls/ntdll/unix/esync.h
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 74e6da5bb56..a2b498759a9 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -48,6 +48,7 @@ SOURCES = \
unix/cdrom.c \
unix/debug.c \
unix/env.c \
+ unix/esync.c \
unix/file.c \
unix/loader.c \
unix/loadorder.c \
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
new file mode 100644
index 00000000000..7be4e03fa34
--- /dev/null
+++ b/dlls/ntdll/unix/esync.c
@@ -0,0 +1,270 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "wine/server.h"
+#include "wine/debug.h"
+
+#include "unix_private.h"
+#include "esync.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(esync);
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
+
+ return do_esync_cached;
+#else
+ static int once;
+ if (!once++)
+ FIXME("eventfd not supported on this platform.\n");
+ return 0;
+#endif
+}
+
+struct esync
+{
+ enum esync_type type;
+ int fd;
+ void *shm;
+};
+
+struct semaphore
+{
+ int max;
+ int count;
+};
+C_ASSERT(sizeof(struct semaphore) == 8);
+
+static char shm_name[29];
+static int shm_fd;
+static void **shm_addrs;
+static int shm_addrs_size; /* length of the allocated shm_addrs array */
+static long pagesize;
+
+static pthread_mutex_t shm_addrs_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void *get_shm( unsigned int idx )
+{
+ int entry = (idx * 8) / pagesize;
+ int offset = (idx * 8) % pagesize;
+ void *ret;
+
+ pthread_mutex_lock( &shm_addrs_mutex );
+
+ if (entry >= shm_addrs_size)
+ {
+ int new_size = max(shm_addrs_size * 2, entry + 1);
+
+ if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) )))
+ ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_size);
+ memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) );
+ shm_addrs_size = new_size;
+ }
+
+ if (!shm_addrs[entry])
+ {
+ void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
+ if (addr == (void *)-1)
+ ERR("Failed to map page %d (offset %#lx).\n", entry, entry * pagesize);
+
+ TRACE("Mapping page %d at %p.\n", entry, addr);
+
+ if (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 ))
+ munmap( addr, pagesize ); /* someone beat us to it */
+ }
+
+ ret = (void *)((unsigned long)shm_addrs[entry] + offset);
+
+ pthread_mutex_unlock( &shm_addrs_mutex );
+
+ return ret;
+}
+
+/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
+ * This is copied and adapted from the fd cache code. */
+
+#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync))
+#define ESYNC_LIST_ENTRIES 256
+
+static struct esync *esync_list[ESYNC_LIST_ENTRIES];
+static struct esync esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];
+
+static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
+{
+ UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1;
+ *entry = idx / ESYNC_LIST_BLOCK_SIZE;
+ return idx % ESYNC_LIST_BLOCK_SIZE;
+}
+
+static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, void *shm )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES)
+ {
+ FIXME( "too many allocated handles, not caching %p\n", handle );
+ return FALSE;
+ }
+
+ if (!esync_list[entry]) /* do we need to allocate a new block of entries? */
+ {
+ if (!entry) esync_list[0] = esync_list_initial_block;
+ else
+ {
+ void *ptr = anon_mmap_alloc( ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync),
+ PROT_READ | PROT_WRITE );
+ if (ptr == MAP_FAILED) return FALSE;
+ esync_list[entry] = ptr;
+ }
+ }
+
+ if (!InterlockedCompareExchange( (int *)&esync_list[entry][idx].type, type, 0 ))
+ {
+ esync_list[entry][idx].fd = fd;
+ esync_list[entry][idx].shm = shm;
+ }
+ return &esync_list[entry][idx];
+}
+
+static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, int initval, int max )
+{
+ NTSTATUS ret;
+ data_size_t len;
+ struct object_attributes *objattr;
+ obj_handle_t fd_handle;
+ unsigned int shm_idx;
+ sigset_t sigset;
+ int fd;
+
+ if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
+
+ /* We have to synchronize on the fd cache CS so that our calls to
+ * receive_fd don't race with theirs. */
+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
+ SERVER_START_REQ( create_esync )
+ {
+ req->access = access;
+ req->initval = initval;
+ req->type = type;
+ req->max = max;
+ wine_server_add_data( req, objattr, len );
+ ret = wine_server_call( req );
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+ {
+ *handle = wine_server_ptr_handle( reply->handle );
+ type = reply->type;
+ shm_idx = reply->shm_idx;
+ fd = receive_fd( &fd_handle );
+ assert( wine_server_ptr_handle(fd_handle) == *handle );
+ }
+ }
+ SERVER_END_REQ;
+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+ {
+ add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );
+ TRACE("-> handle %p, fd %d.\n", *handle, fd);
+ }
+
+ free( objattr );
+ return ret;
+}
+
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
+{
+ TRACE("name %s, initial %d, max %d.\n",
+ attr ? debugstr_us(attr->ObjectName) : "<no name>", initial, max);
+
+ return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max );
+}
+
+void esync_init(void)
+{
+ struct stat st;
+
+ if (!do_esync())
+ {
+ /* make sure the server isn't running with WINEESYNC */
+ HANDLE handle;
+ NTSTATUS ret;
+
+ ret = create_esync( 0, &handle, 0, NULL, 0, 0 );
+ if (ret != STATUS_NOT_IMPLEMENTED)
+ {
+ ERR("Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.\n");
+ exit(1);
+ }
+
+ return;
+ }
+
+ if (stat( config_dir, &st ) == -1)
+ ERR("Cannot stat %s\n", config_dir);
+
+ if (st.st_ino != (unsigned long)st.st_ino)
+ sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino );
+ else
+ sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino );
+
+ if ((shm_fd = shm_open( shm_name, O_RDWR, 0644 )) == -1)
+ {
+ /* probably the server isn't running with WINEESYNC, tell the user and bail */
+ if (errno == ENOENT)
+ ERR("Failed to open esync shared memory file; make sure no stale wineserver instances are running without WINEESYNC.\n");
+ else
+ ERR("Failed to initialize shared memory: %s\n", strerror( errno ));
+ exit(1);
+ }
+
+ pagesize = sysconf( _SC_PAGESIZE );
+
+ shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
+ shm_addrs_size = 128;
+}
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
new file mode 100644
index 00000000000..5fec18860f8
--- /dev/null
+++ b/dlls/ntdll/unix/esync.h
@@ -0,0 +1,35 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int do_esync(void);
+extern void esync_init(void);
+
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
+
+
+/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
+ * don't race with theirs. It looks weird, I know.
+ *
+ * If we weren't trying to avoid touching the code I'd rename the mutex to
+ * "server_fd_mutex" or something similar. */
+extern pthread_mutex_t fd_cache_mutex;
+
+extern int receive_fd( obj_handle_t *handle );
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index aa120ae38ec..fdda50575d1 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -87,6 +87,7 @@
#include "winioctl.h"
#include "winternl.h"
#include "unix_private.h"
+#include "esync.h"
#include "wine/list.h"
#include "ntsyscalls.h"
#include "wine/debug.h"
@@ -1790,6 +1791,7 @@ static void start_main_thread(void)
signal_alloc_thread( teb );
dbg_init();
startup_info_size = server_init_process();
+ esync_init();
virtual_map_user_shared_data();
init_cpu_info();
init_files();
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 7211457387c..cd8dbbdcc10 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */
static int fd_socket = -1; /* socket to exchange file descriptors with the server */
static int initial_cwd = -1;
static pid_t server_pid;
-static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
/* atomically exchange a 64-bit value */
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
@@ -918,7 +918,7 @@ void wine_server_send_fd( int fd )
*
* Receive a file descriptor passed from the server.
*/
-static int receive_fd( obj_handle_t *handle )
+int receive_fd( obj_handle_t *handle )
{
struct iovec vec;
struct msghdr msghdr;
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index bfbcaf4a851..f21ceb80298 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -63,6 +63,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
+#include "esync.h"
WINE_DEFAULT_DEBUG_CHANNEL(sync);
@@ -272,6 +273,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
+ if (do_esync())
+ return esync_create_semaphore( handle, access, attr, initial, max );
+
SERVER_START_REQ( create_semaphore )
{
req->access = access;
diff --git a/server/esync.c b/server/esync.c
index 35b4833fd4c..75ef586df30 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -41,6 +41,7 @@
#include "handle.h"
#include "request.h"
#include "file.h"
+#include "esync.h"
int do_esync(void)
{
--
2.42.0

View File

@@ -1,108 +0,0 @@
From d8135b1bdafffc23be62c216edda9ac280045753 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:16:34 -0500
Subject: [PATCH] ntdll: Implement NtReleaseSemaphore().
---
dlls/ntdll/unix/esync.c | 43 +++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 3 +++
3 files changed, 47 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 7be4e03fa34..e8da4bd311b 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifdef HAVE_SYS_STAT_H
@@ -170,6 +171,16 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v
return &esync_list[entry][idx];
}
+static struct esync *get_cached_object( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
+ if (!esync_list[entry][idx].type) return NULL;
+
+ return &esync_list[entry][idx];
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
@@ -225,6 +236,38 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max );
}
+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
+{
+ struct esync *obj;
+ struct semaphore *semaphore;
+ uint64_t count64 = count;
+ ULONG current;
+
+ TRACE("%p, %d, %p.\n", handle, count, prev);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ semaphore = obj->shm;
+
+ do
+ {
+ current = semaphore->count;
+
+ if (count + current > semaphore->max)
+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED;
+ } while (InterlockedCompareExchange( &semaphore->count, count + current, current ) != current);
+
+ if (prev) *prev = current;
+
+ /* We don't have to worry about a race between increasing the count and
+ * write(). The fact that we were able to increase the count means that we
+ * have permission to actually write that many releases to the semaphore. */
+
+ if (write( obj->fd, &count64, sizeof(count64) ) == -1)
+ return errno_to_status( errno );
+
+ return STATUS_SUCCESS;
+}
+
void esync_init(void)
{
struct stat st;
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 5fec18860f8..cbaaed3e308 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -23,6 +23,7 @@ extern void esync_init(void);
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev );
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index f21ceb80298..c85f985b4f3 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -358,6 +358,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
{
unsigned int ret;
+ if (do_esync())
+ return esync_release_semaphore( handle, count, previous );
+
SERVER_START_REQ( release_semaphore )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

View File

@@ -1,77 +0,0 @@
From e57a0ae8ff11195fa4a29aa1c1ccc250c0036073 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:20:44 -0500
Subject: [PATCH] ntdll: Implement NtClose().
---
dlls/ntdll/unix/esync.c | 18 ++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/server.c | 4 ++++
3 files changed, 23 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index e8da4bd311b..e031e9cb94f 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -181,6 +181,24 @@ static struct esync *get_cached_object( HANDLE handle )
return &esync_list[entry][idx];
}
+NTSTATUS esync_close( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ TRACE("%p.\n", handle);
+
+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
+ {
+ if (InterlockedExchange((int *)&esync_list[entry][idx].type, 0))
+ {
+ close( esync_list[entry][idx].fd );
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_HANDLE;
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index cbaaed3e308..c63491dcaad 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -20,6 +20,7 @@
extern int do_esync(void);
extern void esync_init(void);
+extern NTSTATUS esync_close( HANDLE handle );
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index cd8dbbdcc10..00d665d9e62 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -79,6 +79,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
+#include "esync.h"
#include "ddk/wdm.h"
WINE_DEFAULT_DEBUG_CHANNEL(server);
@@ -1839,6 +1840,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
* retrieve it again */
fd = remove_fd_from_cache( handle );
+ if (do_esync())
+ esync_close( handle );
+
SERVER_START_REQ( close_handle )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

View File

@@ -1,243 +0,0 @@
From 4865ed639a87ee06ffcf6a7a74b6c97ef448e7ab Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:34:42 -0500
Subject: [PATCH] ntdll: Implement NtWaitForMultipleObjects().
---
dlls/ntdll/unix/esync.c | 172 ++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 3 +
dlls/ntdll/unix/sync.c | 7 ++
3 files changed, 182 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index e031e9cb94f..85db837f16b 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -24,6 +24,10 @@
#include "config.h"
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -34,6 +38,12 @@
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
#include <sys/types.h>
#include <unistd.h>
@@ -286,6 +296,168 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return STATUS_SUCCESS;
}
+#define TICKSPERSEC 10000000
+#define TICKSPERMSEC 10000
+
+static LONGLONG update_timeout( ULONGLONG end )
+{
+ LARGE_INTEGER now;
+ LONGLONG timeleft;
+
+ NtQuerySystemTime( &now );
+ timeleft = end - now.QuadPart;
+ if (timeleft < 0) timeleft = 0;
+ return timeleft;
+}
+
+static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end )
+{
+ if (end)
+ {
+ LONGLONG timeleft = update_timeout( *end );
+
+#ifdef HAVE_PPOLL
+ /* We use ppoll() if available since the time granularity is better. */
+ struct timespec tmo_p;
+ tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
+ tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;
+ return ppoll( fds, nfds, &tmo_p, NULL );
+#else
+ return poll( fds, nfds, timeleft / TICKSPERMSEC );
+#endif
+ }
+ else
+ return poll( fds, nfds, -1 );
+}
+
+static void update_grabbed_object( struct esync *obj )
+{
+ if (obj->type == ESYNC_SEMAPHORE)
+ {
+ struct semaphore *semaphore = obj->shm;
+ /* We don't have to worry about a race between this and read(); the
+ * fact that we were able to grab it at all means the count is nonzero,
+ * and if someone else grabbed it then the count must have been >= 2,
+ * etc. */
+ InterlockedExchangeAdd( &semaphore->count, -1 );
+ }
+}
+
+/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
+ * need to delegate to server_select(). */
+NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
+ BOOLEAN alertable, const LARGE_INTEGER *timeout )
+{
+ struct esync *objs[MAXIMUM_WAIT_OBJECTS];
+ struct pollfd fds[MAXIMUM_WAIT_OBJECTS];
+ int has_esync = 0, has_server = 0;
+ LONGLONG timeleft;
+ LARGE_INTEGER now;
+ ULONGLONG end;
+ int i, ret;
+
+ NtQuerySystemTime( &now );
+ if (timeout)
+ {
+ if (timeout->QuadPart == TIMEOUT_INFINITE)
+ timeout = NULL;
+ else if (timeout->QuadPart >= 0)
+ end = timeout->QuadPart;
+ else
+ end = now.QuadPart - timeout->QuadPart;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if ((objs[i] = get_cached_object( handles[i] )))
+ has_esync = 1;
+ else
+ has_server = 1;
+ }
+
+ if (has_esync && has_server)
+ FIXME("Can't wait on esync and server objects at the same time!\n");
+ else if (has_server)
+ return STATUS_NOT_IMPLEMENTED;
+
+ if (TRACE_ON(esync))
+ {
+ TRACE("Waiting for %s of %d handles:", wait_any ? "any" : "all", count);
+ for (i = 0; i < count; i++)
+ TRACE(" %p", handles[i]);
+
+ if (!timeout)
+ TRACE(", timeout = INFINITE.\n");
+ else
+ {
+ timeleft = update_timeout( end );
+ TRACE(", timeout = %ld.%07ld sec.\n",
+ (long) timeleft / TICKSPERSEC, (long) timeleft % TICKSPERSEC);
+ }
+ }
+
+ if (wait_any || count == 1)
+ {
+ for (i = 0; i < count; i++)
+ {
+ fds[i].fd = objs[i] ? objs[i]->fd : -1;
+ fds[i].events = POLLIN;
+ }
+
+ while (1)
+ {
+ ret = do_poll( fds, count, timeout ? &end : NULL );
+ if (ret > 0)
+ {
+ /* Find out which object triggered the wait. */
+ for (i = 0; i < count; i++)
+ {
+ struct esync *obj = objs[i];
+
+ if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ ERR("Polling on fd %d returned %#x.\n", fds[i].fd, fds[i].revents);
+ return STATUS_INVALID_HANDLE;
+ }
+
+ if (obj)
+ {
+ int64_t value;
+ ssize_t size;
+
+ if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
+ {
+ /* We found our object. */
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
+ update_grabbed_object( obj );
+ return i;
+ }
+ }
+ }
+
+ /* If we got here, someone else stole (or reset, etc.) whatever
+ * we were waiting for. So keep waiting. */
+ NtQuerySystemTime( &now );
+ }
+ else if (ret == 0)
+ {
+ TRACE("Wait timed out.\n");
+ return STATUS_TIMEOUT;
+ }
+ else
+ {
+ ERR("ppoll failed: %s\n", strerror( errno ));
+ return errno_to_status( errno );
+ }
+ }
+ }
+ else
+ {
+ FIXME("Wait-all not implemented.\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
+
void esync_init(void)
{
struct stat st;
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index c63491dcaad..92b609ebd27 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev );
+extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
+ BOOLEAN alertable, const LARGE_INTEGER *timeout );
+
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
* don't race with theirs. It looks weird, I know.
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index dd938c95873..4361813e628 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -1588,6 +1588,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
+ if (do_esync())
+ {
+ NTSTATUS ret = esync_wait_objects( count, handles, wait_any, alertable, timeout );
+ if (ret != STATUS_NOT_IMPLEMENTED)
+ return ret;
+ }
+
if (alertable) flags |= SELECT_ALERTABLE;
select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
--
2.43.0

View File

@@ -1,129 +0,0 @@
From 9c2870d27349ce3548c84ff1f7b5825b5c398296 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:40:43 -0500
Subject: [PATCH] ntdll, server: Implement NtCreateEvent().
---
dlls/ntdll/unix/esync.c | 27 +++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 3 +++
dlls/ntdll/unix/sync.c | 4 ++++
server/esync.c | 15 +++++++++++++++
4 files changed, 49 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 75ceb95bc66..06842f0c8f5 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -88,6 +88,13 @@ struct semaphore
};
C_ASSERT(sizeof(struct semaphore) == 8);
+struct event
+{
+ int signaled;
+ int locked;
+};
+C_ASSERT(sizeof(struct event) == 8);
+
static char shm_name[29];
static int shm_fd;
static void **shm_addrs;
@@ -294,6 +301,18 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return STATUS_SUCCESS;
}
+NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE event_type, BOOLEAN initial )
+{
+ enum esync_type type = (event_type == SynchronizationEvent ? ESYNC_AUTO_EVENT : ESYNC_MANUAL_EVENT);
+
+ TRACE("name %s, %s-reset, initial %d.\n",
+ attr ? debugstr_us(attr->ObjectName) : "<no name>",
+ event_type == NotificationEvent ? "manual" : "auto", initial);
+
+ return create_esync( type, handle, access, attr, initial, 0 );
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
@@ -339,6 +358,14 @@ static void update_grabbed_object( struct esync *obj )
* etc. */
InterlockedExchangeAdd( &semaphore->count, -1 );
}
+ else if (obj->type == ESYNC_AUTO_EVENT)
+ {
+ struct event *event = obj->shm;
+ /* We don't have to worry about a race between this and read(), since
+ * this is just a hint, and the real state is in the kernel object.
+ * This might already be 0, but that's okay! */
+ event->signaled = 0;
+ }
}
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 92b609ebd27..7bb963faf51 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev );
+extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial );
+
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout );
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 79141999e33..161c170f59c 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -387,6 +387,10 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_
*handle = 0;
if (type != NotificationEvent && type != SynchronizationEvent) return STATUS_INVALID_PARAMETER;
+
+ if (do_esync())
+ return esync_create_event( handle, access, attr, type, state );
+
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
SERVER_START_REQ( create_event )
diff --git a/server/esync.c b/server/esync.c
index 75ef586df30..6a63c0dd5e9 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -201,6 +201,13 @@ struct semaphore
};
C_ASSERT(sizeof(struct semaphore) == 8);
+struct event
+{
+ int signaled;
+ int locked;
+};
+C_ASSERT(sizeof(struct event) == 8);
+
struct esync *create_esync( struct object *root, const struct unicode_str *name,
unsigned int attr, int initval, int max, enum esync_type type,
const struct security_descriptor *sd )
@@ -256,6 +263,14 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
semaphore->count = initval;
break;
}
+ case ESYNC_AUTO_EVENT:
+ case ESYNC_MANUAL_EVENT:
+ {
+ struct event *event = get_shm( esync->shm_idx );
+ event->signaled = initval ? 1 : 0;
+ event->locked = 0;
+ break;
+ }
default:
assert( 0 );
}
--
2.42.0

View File

@@ -1,69 +0,0 @@
From e2ab736b2e8b98268bdf840a460ee54b8388328e Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:46:24 -0500
Subject: [PATCH] ntdll: Implement NtSetEvent().
---
dlls/ntdll/unix/esync.c | 15 +++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 4 ++++
3 files changed, 20 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 06842f0c8f5..3bb7f2daf8f 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -313,6 +313,21 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
return create_esync( type, handle, access, attr, initial, 0 );
}
+NTSTATUS esync_set_event( HANDLE handle )
+{
+ static const uint64_t value = 1;
+ struct esync *obj;
+
+ TRACE("%p.\n", handle);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+
+ if (write( obj->fd, &value, sizeof(value) ) == -1)
+ ERR("write: %s\n", strerror(errno));
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 7bb963faf51..d92165214d6 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial );
+extern NTSTATUS esync_set_event( HANDLE handle );
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout );
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 161c170f59c..706d381d7c7 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -439,8 +439,12 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT
*/
NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
{
+ /* This comment is a dummy to make sure this patch applies in the right place. */
unsigned int ret;
+ if (do_esync())
+ return esync_set_event( handle );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

View File

@@ -1,70 +0,0 @@
From 98024ae21fbeb4f86c89000bd7953cf192c833ef Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:51:21 -0500
Subject: [PATCH] ntdll: Implement NtResetEvent().
---
dlls/ntdll/unix/esync.c | 15 +++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 5 +++++
3 files changed, 21 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 3bb7f2daf8f..8ee0c99c5d9 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -328,6 +328,21 @@ NTSTATUS esync_set_event( HANDLE handle )
return STATUS_SUCCESS;
}
+NTSTATUS esync_reset_event( HANDLE handle )
+{
+ uint64_t value;
+ struct esync *obj;
+
+ TRACE("%p.\n", handle);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+
+ if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN)
+ ERR("read: %s\n", strerror(errno));
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index d92165214d6..6e5d6233a2e 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial );
+extern NTSTATUS esync_reset_event( HANDLE handle );
extern NTSTATUS esync_set_event( HANDLE handle );
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 706d381d7c7..fdf4215039b 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -462,8 +462,13 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
*/
NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
{
+ /* This comment is a dummy to make sure this patch applies in the right place. */
unsigned int ret;
+ if (do_esync())
+ return esync_reset_event( handle );
+
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

View File

@@ -1,59 +0,0 @@
From 4a9eff3f22bfe2c6463e3064ec862617d5dd07d7 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:57:42 -0500
Subject: [PATCH] ntdll: Implement waiting on manual-reset events.
---
dlls/ntdll/unix/esync.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 80eb3773ee4..f4c27796189 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -36,12 +36,7 @@
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
-#ifdef HAVE_POLL_H
#include <poll.h>
-#endif
-#ifdef HAVE_SYS_POLL_H
-# include <sys/poll.h>
-#endif
#include <sys/types.h>
#include <unistd.h>
@@ -481,12 +476,24 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
int64_t value;
ssize_t size;
- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
+ if (obj->type == ESYNC_MANUAL_EVENT)
+ {
+ /* Don't grab the object, just check if it's signaled. */
+ if (fds[i].revents & POLLIN)
+ {
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
+ return i;
+ }
+ }
+ else
{
- /* We found our object. */
- TRACE("Woken up by handle %p [%d].\n", handles[i], i);
- update_grabbed_object( obj );
- return i;
+ if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
+ {
+ /* We found our object. */
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
+ update_grabbed_object( obj );
+ return i;
+ }
}
}
}
--
2.33.0

View File

@@ -1,83 +0,0 @@
From 2f23f37d5a1ba0d59d367729d96285ac7c470e8d Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 18:55:49 -0500
Subject: [PATCH] server: Add a request to get the eventfd file descriptor
associated with a waitable handle.
---
server/esync.c | 37 +++++++++++++++++++++++++++++++++++++
server/protocol.def | 9 ++++++++-
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/server/esync.c b/server/esync.c
index f95dc5a391f..85f7f1e060f 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -333,3 +333,40 @@ DECL_HANDLER(create_esync)
if (root) release_object( root );
}
+
+/* Retrieve a file descriptor for an esync object which will be signaled by the
+ * server. The client should only read from (i.e. wait on) this object. */
+DECL_HANDLER(get_esync_fd)
+{
+ struct object *obj;
+ enum esync_type type;
+ int fd;
+
+ if (!(obj = get_handle_obj( current->process, req->handle, SYNCHRONIZE, NULL )))
+ return;
+
+ if (obj->ops->get_esync_fd)
+ {
+ fd = obj->ops->get_esync_fd( obj, &type );
+ reply->type = type;
+ if (obj->ops == &esync_ops)
+ {
+ struct esync *esync = (struct esync *)obj;
+ reply->shm_idx = esync->shm_idx;
+ }
+ else
+ reply->shm_idx = 0;
+ send_client_fd( current->process, fd, req->handle );
+ }
+ else
+ {
+ if (debug_level)
+ {
+ fprintf( stderr, "%04x: esync: can't wait on object: ", current->id );
+ obj->ops->dump( obj, 0 );
+ }
+ set_error( STATUS_NOT_IMPLEMENTED );
+ }
+
+ release_object( obj );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 03bc0aeb11e..4ab6b97ba93 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3902,6 +3902,14 @@ enum esync_type
unsigned int shm_idx;
@END
+/* Retrieve the esync fd for an object. */
+@REQ(get_esync_fd)
+ obj_handle_t handle; /* handle to the object */
+@REPLY
+ int type;
+ unsigned int shm_idx;
+@END
+
/* Setup keyboard auto-repeat */
@REQ(set_keyboard_repeat)
int enable; /* whether to enable auto-repeat */
@@ -3910,4 +3918,3 @@ enum esync_type
@REPLY
int enable; /* previous state of auto-repeat enable */
@END
-
--
2.43.0

View File

@@ -1,134 +0,0 @@
From ce164f9c292bc93ad50055bdb0a786e8a8770afa Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 15:11:12 -0500
Subject: [PATCH] server: Create eventfd file descriptors for process objects.
---
server/esync.c | 18 ++++++++++++++++++
server/esync.h | 1 +
server/process.c | 16 +++++++++++++++-
server/process.h | 1 +
4 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/server/esync.c b/server/esync.c
index 85f7f1e060f..44214e5fe02 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -295,6 +295,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
#endif
}
+/* Create a file descriptor for an existing handle.
+ * Caller must close the handle when it's done; it's not linked to an esync
+ * server object in any way. */
+int esync_create_fd( int initval, int flags )
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ int fd;
+
+ fd = eventfd( initval, flags | EFD_CLOEXEC | EFD_NONBLOCK );
+ if (fd == -1)
+ perror( "eventfd" );
+
+ return fd;
+#else
+ return -1;
+#endif
+}
+
DECL_HANDLER(create_esync)
{
struct esync *esync;
diff --git a/server/esync.h b/server/esync.h
index 00f9e638d83..8522d8a69ae 100644
--- a/server/esync.h
+++ b/server/esync.h
@@ -22,3 +22,4 @@
extern int do_esync(void);
void esync_init(void);
+int esync_create_fd( int initval, int flags );
diff --git a/server/process.c b/server/process.c
index 3c5a58b7b03..30555d516c8 100644
--- a/server/process.c
+++ b/server/process.c
@@ -63,6 +63,7 @@
#include "request.h"
#include "user.h"
#include "security.h"
+#include "esync.h"
/* process object */
@@ -95,6 +96,7 @@ static struct security_descriptor *process_get_sd( struct object *obj );
static void process_poll_event( struct fd *fd, int event );
static struct list *process_get_kernel_obj_list( struct object *obj );
static void process_destroy( struct object *obj );
+static int process_get_esync_fd( struct object *obj, enum esync_type *type );
static void terminate_process( struct process *process, struct thread *skip, int exit_code );
static const struct object_ops process_ops =
@@ -105,7 +107,7 @@ static const struct object_ops process_ops =
add_queue, /* add_queue */
remove_queue, /* remove_queue */
process_signaled, /* signaled */
- NULL, /* get_esync_fd */
+ process_get_esync_fd, /* get_esync_fd */
no_satisfied, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
@@ -689,6 +691,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
process->rawinput_kbd = NULL;
memset( &process->image_info, 0, sizeof(process->image_info) );
list_init( &process->rawinput_entry );
+ process->esync_fd = -1;
list_init( &process->kernel_object );
list_init( &process->thread_list );
list_init( &process->locks );
@@ -739,6 +742,9 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla
if (!process->handles || !process->token) goto error;
process->session_id = token_get_session_id( process->token );
+ if (do_esync())
+ process->esync_fd = esync_create_fd( 0, 0 );
+
set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */
return process;
@@ -787,6 +793,7 @@ static void process_destroy( struct object *obj )
free( process->rawinput_devices );
free( process->dir_cache );
free( process->image );
+ if (do_esync()) close( process->esync_fd );
}
/* dump a process on stdout for debugging purposes */
@@ -804,6 +811,13 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry
return !process->running_threads;
}
+static int process_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+ struct process *process = (struct process *)obj;
+ *type = ESYNC_MANUAL_SERVER;
+ return process->esync_fd;
+}
+
static unsigned int process_map_access( struct object *obj, unsigned int access )
{
access = default_map_access( obj, access );
diff --git a/server/process.h b/server/process.h
index 96814ab7cf8..ec74ba0490a 100644
--- a/server/process.h
+++ b/server/process.h
@@ -86,6 +86,7 @@ struct process
struct list rawinput_entry; /* entry in the rawinput process list */
struct list kernel_object; /* list of kernel object pointers */
struct pe_image_info image_info; /* main exe image info */
+ int esync_fd; /* esync file descriptor (signaled on exit) */
};
/* process functions */
--
2.45.2

View File

@@ -1,236 +0,0 @@
From 0ef3de9bd3b51a1e37c50fd75ceb3db6ea24abd0 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 15:19:37 -0500
Subject: [PATCH] ntdll, server: Implement waiting on server-bound objects.
The code here is sort of self-explanatory, but since I split it up over
several patches I'll provide a quick explanation. The basic principle is
that we can create an eventfd descriptor for any synchronizable handle, and
signal it on the server side whenever a wakeup would be triggered. This means
not only that we can wait simultaneously on esync primitives and on other
primitives, but that we can do it all in "user-mode", i.e. without having to
make a server call.
With this patch we break waiting on svcctl.exe.
---
dlls/ntdll/unix/esync.c | 84 ++++++++++++++++++++++++++++++++++++++---
server/esync.c | 16 ++++++++
server/esync.h | 1 +
server/named_pipe.c | 1 +
server/thread.c | 4 ++
5 files changed, 100 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 65ef70acd36..b0168f5cde5 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -193,6 +193,72 @@ static struct esync *get_cached_object( HANDLE handle )
return &esync_list[entry][idx];
}
+/* Gets an object. This is either a proper esync object (i.e. an event,
+ * semaphore, etc. created using create_esync) or a generic synchronizable
+ * server-side object which the server will signal (e.g. a process, thread,
+ * message queue, etc.) */
+static NTSTATUS get_object( HANDLE handle, struct esync **obj )
+{
+ NTSTATUS ret = STATUS_SUCCESS;
+ enum esync_type type = 0;
+ unsigned int shm_idx = 0;
+ obj_handle_t fd_handle;
+ sigset_t sigset;
+ int fd = -1;
+
+ if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS;
+
+ if ((INT_PTR)handle < 0)
+ {
+ /* We can deal with pseudo-handles, but it's just easier this way */
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (!handle)
+ {
+ /* Shadow of the Tomb Raider really likes passing in NULL handles to
+ * various functions. Concerning, but let's avoid a server call. */
+ return STATUS_INVALID_HANDLE;
+ }
+
+ /* We need to try grabbing it from the server. */
+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
+ if (!(*obj = get_cached_object( handle )))
+ {
+ SERVER_START_REQ( get_esync_fd )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ if (!(ret = wine_server_call( req )))
+ {
+ type = reply->type;
+ shm_idx = reply->shm_idx;
+ fd = receive_fd( &fd_handle );
+ assert( wine_server_ptr_handle(fd_handle) == handle );
+ }
+ }
+ SERVER_END_REQ;
+ }
+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+ if (*obj)
+ {
+ /* We managed to grab it while in the CS; return it. */
+ return STATUS_SUCCESS;
+ }
+
+ if (ret)
+ {
+ WARN("Failed to retrieve fd for handle %p, status %#x.\n", handle, ret);
+ *obj = NULL;
+ return ret;
+ }
+
+ TRACE("Got fd %d for handle %p.\n", fd, handle);
+
+ *obj = add_to_list( handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );
+ return ret;
+}
+
NTSTATUS esync_close( HANDLE handle )
{
UINT_PTR entry, idx = handle_to_index( handle, &entry );
@@ -272,10 +338,11 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
struct semaphore *semaphore;
uint64_t count64 = count;
ULONG current;
+ NTSTATUS ret;
TRACE("%p, %d, %p.\n", handle, count, prev);
- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ if ((ret = get_object( handle, &obj))) return ret;
semaphore = obj->shm;
do
@@ -314,10 +381,11 @@ NTSTATUS esync_set_event( HANDLE handle )
{
static const uint64_t value = 1;
struct esync *obj;
+ NTSTATUS ret;
TRACE("%p.\n", handle);
- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ if ((ret = get_object( handle, &obj))) return ret;
if (write( obj->fd, &value, sizeof(value) ) == -1)
ERR("write: %s\n", strerror(errno));
@@ -329,10 +397,11 @@ NTSTATUS esync_reset_event( HANDLE handle )
{
uint64_t value;
struct esync *obj;
+ NTSTATUS ret;
TRACE("%p.\n", handle);
- if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ if ((ret = get_object( handle, &obj))) return ret;
if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN)
ERR("read: %s\n", strerror(errno));
@@ -421,10 +490,13 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
for (i = 0; i < count; i++)
{
- if ((objs[i] = get_cached_object( handles[i] )))
+ ret = get_object( handles[i], &objs[i] );
+ if (ret == STATUS_SUCCESS)
has_esync = 1;
- else
+ else if (ret == STATUS_NOT_IMPLEMENTED)
has_server = 1;
+ else
+ return ret;
}
if (has_esync && has_server)
@@ -477,7 +549,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
int64_t value;
ssize_t size;
- if (obj->type == ESYNC_MANUAL_EVENT)
+ if (obj->type == ESYNC_MANUAL_EVENT || obj->type == ESYNC_MANUAL_SERVER)
{
/* Don't grab the object, just check if it's signaled. */
if (fds[i].revents & POLLIN)
diff --git a/server/esync.c b/server/esync.c
index 44214e5fe02..60e98936455 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -313,6 +313,22 @@ int esync_create_fd( int initval, int flags )
#endif
}
+/* Wake up a server-side esync object. */
+void esync_wake_up( struct object *obj )
+{
+ static const uint64_t value = 1;
+ enum esync_type dummy;
+ int fd;
+
+ if (obj->ops->get_esync_fd)
+ {
+ fd = obj->ops->get_esync_fd( obj, &dummy );
+
+ if (write( fd, &value, sizeof(value) ) == -1)
+ perror( "esync: write" );
+ }
+}
+
DECL_HANDLER(create_esync)
{
struct esync *esync;
diff --git a/server/esync.h b/server/esync.h
index 8522d8a69ae..1241e6d9f1a 100644
--- a/server/esync.h
+++ b/server/esync.h
@@ -23,3 +23,4 @@
extern int do_esync(void);
void esync_init(void);
int esync_create_fd( int initval, int flags );
+void esync_wake_up( struct object *obj );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 68fa8953cca..1535c5188ec 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -344,6 +344,7 @@ static const struct object_ops named_pipe_dir_ops =
add_queue, /* add_queue */
remove_queue, /* remove_queue */
default_fd_signaled, /* signaled */
+ NULL, /* get_esync_fd */
no_satisfied, /* satisfied */
no_signal, /* signal */
named_pipe_dir_get_fd, /* get_fd */
diff --git a/server/thread.c b/server/thread.c
index 339cdfec1fa..4262b841fca 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -50,6 +50,7 @@
#include "request.h"
#include "user.h"
#include "security.h"
+#include "esync.h"
/* thread queues */
@@ -1073,6 +1074,9 @@ void wake_up( struct object *obj, int max )
struct list *ptr;
int ret;
+ if (do_esync())
+ esync_wake_up( obj );
+
LIST_FOR_EACH( ptr, &obj->wait_queue )
{
struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
--
2.45.2

View File

@@ -1,141 +0,0 @@
From dcb50e04b4ec205f4a6688c71a23cb2863cffce6 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 21:01:24 -0500
Subject: [PATCH] server: Create eventfd file descriptors for event objects.
We still need this, since there are some events which the server signals.
This lets system processes shut down.
---
server/esync.c | 8 ++++++++
server/esync.h | 1 +
server/event.c | 29 +++++++++++++++++++++++++++--
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/server/esync.c b/server/esync.c
index 6696119b207..8cb46c4f2ce 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -329,6 +329,14 @@ void esync_wake_up( struct object *obj )
}
}
+void esync_clear( int fd )
+{
+ uint64_t value;
+
+ /* we don't care about the return value */
+ read( fd, &value, sizeof(value) );
+}
+
DECL_HANDLER(create_esync)
{
struct esync *esync;
diff --git a/server/esync.h b/server/esync.h
index 1241e6d9f1a..d259b5f604d 100644
--- a/server/esync.h
+++ b/server/esync.h
@@ -24,3 +24,4 @@ extern int do_esync(void);
void esync_init(void);
int esync_create_fd( int initval, int flags );
void esync_wake_up( struct object *obj );
+void esync_clear( int fd );
diff --git a/server/event.c b/server/event.c
index c727bfdd1ba..f1a88e3d23f 100644
--- a/server/event.c
+++ b/server/event.c
@@ -35,6 +35,7 @@
#include "thread.h"
#include "request.h"
#include "security.h"
+#include "esync.h"
static const WCHAR event_name[] = {'E','v','e','n','t'};
@@ -56,13 +57,16 @@ struct event
struct list kernel_object; /* list of kernel object pointers */
int manual_reset; /* is it a manual reset event? */
int signaled; /* event has been signaled */
+ int esync_fd; /* esync file descriptor */
};
static void event_dump( struct object *obj, int verbose );
static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
+static int event_get_esync_fd( struct object *obj, enum esync_type *type );
static int event_signal( struct object *obj, unsigned int access);
static struct list *event_get_kernel_obj_list( struct object *obj );
+static void event_destroy( struct object *obj );
static const struct object_ops event_ops =
{
@@ -72,7 +76,7 @@ static const struct object_ops event_ops =
add_queue, /* add_queue */
remove_queue, /* remove_queue */
event_signaled, /* signaled */
- NULL, /* get_esync_fd */
+ event_get_esync_fd, /* get_esync_fd */
event_satisfied, /* satisfied */
event_signal, /* signal */
no_get_fd, /* get_fd */
@@ -86,7 +90,7 @@ static const struct object_ops event_ops =
no_open_file, /* open_file */
event_get_kernel_obj_list, /* get_kernel_obj_list */
no_close_handle, /* close_handle */
- no_destroy /* destroy */
+ event_destroy /* destroy */
};
@@ -152,6 +156,9 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
list_init( &event->kernel_object );
event->manual_reset = manual_reset;
event->signaled = initial_state;
+
+ if (do_esync())
+ event->esync_fd = esync_create_fd( initial_state, 0 );
}
}
return event;
@@ -180,6 +187,9 @@ void set_event( struct event *event )
void reset_event( struct event *event )
{
event->signaled = 0;
+
+ if (do_esync())
+ esync_clear( event->esync_fd );
}
static void event_dump( struct object *obj, int verbose )
@@ -197,6 +207,13 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
return event->signaled;
}
+static int event_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+ struct event *event = (struct event *)obj;
+ *type = event->manual_reset ? ESYNC_MANUAL_SERVER : ESYNC_AUTO_SERVER;
+ return event->esync_fd;
+}
+
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry )
{
struct event *event = (struct event *)obj;
@@ -225,6 +242,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj )
return &event->kernel_object;
}
+static void event_destroy( struct object *obj )
+{
+ struct event *event = (struct event *)obj;
+
+ if (do_esync())
+ close( event->esync_fd );
+}
+
struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
unsigned int attr, const struct security_descriptor *sd )
{
--
2.35.1

View File

@@ -1,115 +0,0 @@
From 949b61856a56c339cbe6f8ec88a34902e200ae8e Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 21:43:37 -0500
Subject: [PATCH] server: Allow (re)setting esync events on the server side.
Some server calls pass an event handle, most notably asyncs. We need to be
able to handle these correctly. Accordingly we pass them along to esync if
it turns out the underlying object is actually an esync object.
In an ideal world we'd just convert all instances of events on the server
side to use esyncs instead. But we want to keep esync perfectly configurable,
so this is how we do it.
---
server/esync.c | 22 +++++++++++++++++++++-
server/esync.h | 6 ++++++
server/event.c | 15 +++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/server/esync.c b/server/esync.c
index 975e5d2ddd6..ac59779a454 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -116,7 +116,7 @@ struct esync
static void esync_dump( struct object *obj, int verbose );
static void esync_destroy( struct object *obj );
-static const struct object_ops esync_ops =
+const struct object_ops esync_ops =
{
sizeof(struct esync), /* size */
&no_type, /* type */
@@ -339,6 +339,26 @@ void esync_clear( int fd )
read( fd, &value, sizeof(value) );
}
+/* Server-side event support. */
+void esync_set_event( struct esync *esync )
+{
+ static const uint64_t value = 1;
+
+ assert( esync->obj.ops == &esync_ops );
+ if (write( esync->fd, &value, sizeof(value) ) == -1)
+ perror( "esync: write" );
+}
+
+void esync_reset_event( struct esync *esync )
+{
+ static uint64_t value = 1;
+
+ assert( esync->obj.ops == &esync_ops );
+
+ /* we don't care about the return value */
+ read( esync->fd, &value, sizeof(value) );
+}
+
DECL_HANDLER(create_esync)
{
struct esync *esync;
diff --git a/server/esync.h b/server/esync.h
index fcbfd0989bb..aeb58c5469c 100644
--- a/server/esync.h
+++ b/server/esync.h
@@ -23,3 +23,9 @@ void esync_init(void);
int esync_create_fd( int initval, int flags );
void esync_wake_up( struct object *obj );
void esync_clear( int fd );
+
+struct esync;
+
+extern const struct object_ops esync_ops;
+void esync_set_event( struct esync *esync );
+void esync_reset_event( struct esync *esync );
diff --git a/server/event.c b/server/event.c
index 78d90dac5d6..bc2948c30aa 100644
--- a/server/event.c
+++ b/server/event.c
@@ -154,6 +154,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access )
{
+ struct object *obj;
+ if (do_esync() && (obj = get_handle_obj( process, handle, access, &esync_ops)))
+ return (struct event *)obj; /* even though it's not an event */
+
return (struct event *)get_handle_obj( process, handle, access, &event_ops );
}
@@ -167,6 +171,12 @@ void pulse_event( struct event *event )
void set_event( struct event *event )
{
+ if (do_esync() && event->obj.ops == &esync_ops)
+ {
+ esync_set_event( (struct esync *)event );
+ return;
+ }
+
event->signaled = 1;
/* wake up all waiters if manual reset, a single one otherwise */
wake_up( &event->obj, !event->manual_reset );
@@ -174,6 +184,11 @@ void set_event( struct event *event )
void reset_event( struct event *event )
{
+ if (do_esync() && event->obj.ops == &esync_ops)
+ {
+ esync_reset_event( (struct esync *)event );
+ return;
+ }
event->signaled = 0;
if (do_esync())
--
2.20.1

View File

@@ -1,68 +0,0 @@
From 07f3e8af59a9083ecd5abe31a48670a18dac2e84 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 21:58:37 -0500
Subject: [PATCH] ntdll: Try again if poll() returns EINTR.
I originally had this return STATUS_USER_APC, but that isn't correct. The
server code here is a bit confusing, but only the thread that waits *during*
the suspend should receive STATUS_USER_APC (and I imagine that it really
should receive STATUS_KERNEL_APC instead). The thread that is suspended
should just keep on waiting.
Besides, we could be suspended for reasons other than to deliver a system
APC.
---
dlls/ntdll/unix/esync.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 6fd195df759..fcbe563bb5a 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -431,22 +431,32 @@ static LONGLONG update_timeout( ULONGLONG end )
static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end )
{
- if (end)
+ int ret;
+
+ do
{
- LONGLONG timeleft = update_timeout( *end );
+ if (end)
+ {
+ LONGLONG timeleft = update_timeout( *end );
#ifdef HAVE_PPOLL
- /* We use ppoll() if available since the time granularity is better. */
- struct timespec tmo_p;
- tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
- tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;
- return ppoll( fds, nfds, &tmo_p, NULL );
+ /* We use ppoll() if available since the time granularity is better. */
+ struct timespec tmo_p;
+ tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
+ tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;
+ ret = ppoll( fds, nfds, &tmo_p, NULL );
#else
- return poll( fds, nfds, timeleft / TICKSPERMSEC );
+ ret = poll( fds, nfds, timeleft / TICKSPERMSEC );
#endif
- }
- else
- return poll( fds, nfds, -1 );
+ }
+ else
+ ret = poll( fds, nfds, -1 );
+
+ /* If we receive EINTR we were probably suspended (SIGUSR1), possibly for a
+ * system APC. The right thing to do is just try again. */
+ } while (ret < 0 && errno == EINTR);
+
+ return ret;
}
static void update_grabbed_object( struct esync *obj )
--
2.28.0

View File

@@ -1,88 +0,0 @@
From f72b878cf5dcf8f20d485f7b3e75d86e303393e7 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 22:04:29 -0500
Subject: [PATCH] server: Create eventfd file descriptors for thread objects.
---
server/thread.c | 17 ++++++++++++++++-
server/thread.h | 1 +
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/server/thread.c b/server/thread.c
index e7795c21136..ef5b3fbf313 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -186,6 +186,7 @@ struct type_descr thread_type =
static void dump_thread( struct object *obj, int verbose );
static int thread_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int thread_get_esync_fd( struct object *obj, enum esync_type *type );
static unsigned int thread_map_access( struct object *obj, unsigned int access );
static void thread_poll_event( struct fd *fd, int event );
static struct list *thread_get_kernel_obj_list( struct object *obj );
@@ -199,7 +200,7 @@ static const struct object_ops thread_ops =
add_queue, /* add_queue */
remove_queue, /* remove_queue */
thread_signaled, /* signaled */
- NULL, /* get_esync_fd */
+ thread_get_esync_fd, /* get_esync_fd */
no_satisfied, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
@@ -239,6 +240,7 @@ static inline void init_thread_structure( struct thread *thread )
thread->context = NULL;
thread->teb = 0;
thread->entry_point = 0;
+ thread->esync_fd = -1;
thread->system_regs = 0;
thread->queue = NULL;
thread->wait = NULL;
@@ -385,6 +387,9 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
}
}
+ if (do_esync())
+ thread->esync_fd = esync_create_fd( 0, 0 );
+
set_fd_events( thread->request_fd, POLLIN ); /* start listening to events */
add_process_thread( thread->process, thread );
return thread;
@@ -464,6 +469,9 @@ static void destroy_thread( struct object *obj )
if (thread->exit_poll) remove_timeout_user( thread->exit_poll );
if (thread->id) free_ptid( thread->id );
if (thread->token) release_object( thread->token );
+
+ if (do_esync())
+ close( thread->esync_fd );
}
/* dump a thread on stdout for debugging purposes */
@@ -482,6 +490,13 @@ static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
return mythread->state == TERMINATED && !mythread->exit_poll;
}
+static int thread_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+ struct thread *thread = (struct thread *)obj;
+ *type = ESYNC_MANUAL_SERVER;
+ return thread->esync_fd;
+}
+
static unsigned int thread_map_access( struct object *obj, unsigned int access )
{
access = default_map_access( obj, access );
diff --git a/server/thread.h b/server/thread.h
index 077ab0929ba..99904557d44 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -54,6 +54,7 @@ struct thread
struct process *process;
thread_id_t id; /* thread id */
struct list mutex_list; /* list of currently owned mutexes */
+ int esync_fd; /* esync file descriptor (signalled on exit) */
unsigned int system_regs; /* which system regs have been set */
struct msg_queue *queue; /* message queue */
struct thread_wait *wait; /* current wait condition if sleeping */
--
2.30.2

View File

@@ -1,48 +0,0 @@
From b3b91529f2e57720b52553dd0477c6077ab1a04b Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 23:30:17 -0500
Subject: [PATCH] rpcrt4: Avoid closing the server thread handle while it is
being waited on.
This, or something like this, should go upstream. This is invalid behaviour.
---
dlls/rpcrt4/rpc_server.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index cb62c59e368..2fd1e1bc4b4 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -699,10 +699,6 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
}
LeaveCriticalSection(&cps->cs);
- EnterCriticalSection(&listen_cs);
- CloseHandle(cps->server_thread);
- cps->server_thread = NULL;
- LeaveCriticalSection(&listen_cs);
TRACE("done\n");
return 0;
}
@@ -1570,7 +1566,10 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry)
{
if ((wait_thread = protseq->server_thread))
+ {
+ protseq->server_thread = NULL;
break;
+ }
}
LeaveCriticalSection(&server_cs);
if (!wait_thread)
@@ -1579,6 +1578,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
TRACE("waiting for thread %lu\n", GetThreadId(wait_thread));
LeaveCriticalSection(&listen_cs);
WaitForSingleObject(wait_thread, INFINITE);
+ CloseHandle(wait_thread);
EnterCriticalSection(&listen_cs);
}
if (listen_done_event == event)
--
2.34.1

View File

@@ -1,130 +0,0 @@
From 52be83d9a557eec924a964944e6b926fb1e347ad Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 16:01:56 -0500
Subject: [PATCH] server: Create eventfd file descriptors for message queues.
---
server/queue.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/server/queue.c b/server/queue.c
index a3479055ed4..08635c047b2 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -45,6 +45,7 @@
#include "process.h"
#include "request.h"
#include "user.h"
+#include "esync.h"
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
@@ -135,6 +136,7 @@ struct msg_queue
int keystate_lock; /* owns an input keystate lock */
queue_shm_t *shared; /* queue in session shared memory */
unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */
+ int esync_fd; /* esync file descriptor (signalled on message) */
};
struct hotkey
@@ -151,6 +153,7 @@ static void msg_queue_dump( struct object *obj, int verbose );
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type );
static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry );
static void msg_queue_destroy( struct object *obj );
static void msg_queue_poll_event( struct fd *fd, int event );
@@ -166,7 +169,7 @@ static const struct object_ops msg_queue_ops =
msg_queue_add_queue, /* add_queue */
msg_queue_remove_queue, /* remove_queue */
msg_queue_signaled, /* signaled */
- NULL, /* get_esync_fd */
+ msg_queue_get_esync_fd, /* get_esync_fd */
msg_queue_satisfied, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
@@ -317,6 +320,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->last_get_msg = current_time;
queue->keystate_lock = 0;
queue->ignore_post_msg = 0;
+ queue->esync_fd = -1;
list_init( &queue->send_result );
list_init( &queue->callback_result );
list_init( &queue->pending_timers );
@@ -339,6 +343,9 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
}
SHARED_WRITE_END;
+ if (do_esync())
+ queue->esync_fd = esync_create_fd( 0, 0 );
+
thread->queue = queue;
if ((desktop = get_thread_desktop( thread, 0 )))
@@ -753,6 +760,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
if (queue->keystate_lock) unlock_input_keystate( queue->input );
queue->keystate_lock = 0;
}
+
+ if (do_esync() && !is_signaled( queue ))
+ esync_clear( queue->esync_fd );
}
/* check if message is matched by the filter */
@@ -1335,6 +1345,13 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr
return ret || is_signaled( queue );
}
+static int msg_queue_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ *type = ESYNC_QUEUE;
+ return queue->esync_fd;
+}
+
static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry )
{
struct msg_queue *queue = (struct msg_queue *)obj;
@@ -1391,6 +1408,7 @@ static void msg_queue_destroy( struct object *obj )
if (queue->hooks) release_object( queue->hooks );
if (queue->fd) release_object( queue->fd );
if (queue->shared) free_shared_object( queue->shared );
+ if (do_esync()) close( queue->esync_fd );
}
static void msg_queue_poll_event( struct fd *fd, int event )
@@ -3181,6 +3199,9 @@ DECL_HANDLER(set_queue_mask)
}
else wake_up( &queue->obj, 0 );
}
+
+ if (do_esync() && !is_signaled( queue ))
+ esync_clear( queue->esync_fd );
}
}
@@ -3201,6 +3222,9 @@ DECL_HANDLER(get_queue_status)
shared->changed_bits &= ~req->clear_bits;
}
SHARED_WRITE_END;
+
+ if (do_esync() && !is_signaled( queue ))
+ esync_clear( queue->esync_fd );
}
else reply->wake_bits = reply->changed_bits = 0;
}
@@ -3469,6 +3493,10 @@ DECL_HANDLER(get_message)
SHARED_WRITE_END;
set_error( STATUS_PENDING ); /* FIXME */
+
+ if (do_esync() && !is_signaled( queue ))
+ esync_clear( queue->esync_fd );
+
return;
found_msg:
--
2.47.2

Some files were not shown because too many files have changed in this diff Show More