You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-12-15 08:03:15 -08:00
Rebase against 01269452e0fbb1f081d506bd64996590a553e2b9.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user