mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
eventfd_synchronization: Add patch set.
This commit is contained in:
parent
8ce5fe8929
commit
553986fdfb
@ -0,0 +1,54 @@
|
||||
From 2cc1bac9dcbe9d52e395baea3811bfbb38c1ec0b 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 01/83] 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 | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index b2c614726..b44729df7 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -505,6 +505,7 @@ AC_CHECK_HEADERS(\
|
||||
sys/elf32.h \
|
||||
sys/epoll.h \
|
||||
sys/event.h \
|
||||
+ sys/eventfd.h \
|
||||
sys/exec_elf.h \
|
||||
sys/filio.h \
|
||||
sys/inotify.h \
|
||||
@@ -2245,6 +2246,7 @@ AC_CHECK_FUNCS(\
|
||||
pipe2 \
|
||||
poll \
|
||||
port_create \
|
||||
+ ppoll \
|
||||
prctl \
|
||||
pread \
|
||||
proc_pidinfo \
|
||||
@@ -2317,6 +2319,16 @@ AC_SEARCH_LIBS(clock_gettime, rt,
|
||||
test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")])
|
||||
LIBS=$ac_save_LIBS
|
||||
|
||||
+dnl Check for shm_open which may be in -lrt
|
||||
+if test "$ac_cv_header_sys_mman_h" = "yes" -a "x$RT_LIBS" = "x"
|
||||
+then
|
||||
+ 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")])
|
||||
+fi
|
||||
+LIBS=$ac_save_LIBS
|
||||
+
|
||||
dnl **** Check for OpenLDAP ***
|
||||
if test "x$with_ldap" != "xno"
|
||||
then
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,189 @@
|
||||
From ed20373cc262b783cd7e04641618a732f33e8a51 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 02/83] server: Create server objects for eventfd-based
|
||||
synchronization objects.
|
||||
|
||||
---
|
||||
server/Makefile.in | 1 +
|
||||
server/esync.c | 137 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
server/protocol.def | 10 ++++
|
||||
3 files changed, 148 insertions(+)
|
||||
create mode 100644 server/esync.c
|
||||
|
||||
diff --git a/server/Makefile.in b/server/Makefile.in
|
||||
index d2715e8cb..4f8f10cd5 100644
|
||||
--- a/server/Makefile.in
|
||||
+++ b/server/Makefile.in
|
||||
@@ -11,6 +11,7 @@ C_SRCS = \
|
||||
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 000000000..147fb7724
|
||||
--- /dev/null
|
||||
+++ b/server/esync.c
|
||||
@@ -0,0 +1,137 @@
|
||||
+/*
|
||||
+ * 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 "wine/port.h"
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdarg.h>
|
||||
+#ifdef HAVE_SYS_EVENTFD_H
|
||||
+# include <sys/eventfd.h>
|
||||
+#endif
|
||||
+
|
||||
+#include "ntstatus.h"
|
||||
+#define WIN32_NO_STATUS
|
||||
+#include "windef.h"
|
||||
+#include "winternl.h"
|
||||
+
|
||||
+#include "handle.h"
|
||||
+#include "request.h"
|
||||
+#include "file.h"
|
||||
+
|
||||
+struct esync
|
||||
+{
|
||||
+ struct object obj; /* object header */
|
||||
+ int fd; /* eventfd file descriptor */
|
||||
+};
|
||||
+
|
||||
+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 */
|
||||
+ esync_dump, /* dump */
|
||||
+ no_get_type, /* get_type */
|
||||
+ no_add_queue, /* add_queue */
|
||||
+ NULL, /* remove_queue */
|
||||
+ NULL, /* signaled */
|
||||
+ NULL, /* satisfied */
|
||||
+ no_signal, /* signal */
|
||||
+ no_get_fd, /* get_fd */
|
||||
+ no_map_access, /* map_access */
|
||||
+ default_get_sd, /* get_sd */
|
||||
+ default_set_sd, /* set_sd */
|
||||
+ 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 );
|
||||
+}
|
||||
+
|
||||
+struct esync *create_esync( struct object *root, const struct unicode_str *name,
|
||||
+ unsigned int attr, int initval, int flags,
|
||||
+ 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)
|
||||
+ {
|
||||
+ /* initialize it if it didn't already exist */
|
||||
+ esync->fd = eventfd( initval, flags | EFD_CLOEXEC | EFD_NONBLOCK );
|
||||
+ if (esync->fd == -1)
|
||||
+ {
|
||||
+ perror( "eventfd" );
|
||||
+ file_set_error();
|
||||
+ release_object( esync );
|
||||
+ 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 (!objattr) return;
|
||||
+
|
||||
+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, 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 );
|
||||
+
|
||||
+ send_client_fd( current->process, esync->fd, reply->handle );
|
||||
+ release_object( esync );
|
||||
+ }
|
||||
+
|
||||
+ if (root) release_object( root );
|
||||
+}
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index c3751e609..a56f098ab 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -4041,3 +4041,13 @@ struct handle_info
|
||||
@REQ(resume_process)
|
||||
obj_handle_t handle; /* process handle */
|
||||
@END
|
||||
+
|
||||
+/* Create a new eventfd-based synchronization object */
|
||||
+@REQ(create_esync)
|
||||
+ unsigned int access; /* wanted access rights */
|
||||
+ int initval; /* initial value */
|
||||
+ int flags; /* flags (EFD_SEMAPHORE or 0) */
|
||||
+ VARARG(objattr,object_attributes); /* object attributes */
|
||||
+@REPLY
|
||||
+ obj_handle_t handle; /* handle to the object */
|
||||
+@END
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,292 @@
|
||||
From 4df197cdb567f731bec385786ccda35499d656b4 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 7 Jun 2018 20:29:21 -0500
|
||||
Subject: [PATCH 03/83] ntdll: Create eventfd-based objects for semaphores.
|
||||
|
||||
This patch break things, of course. That is fine. Its purpose is to prevent a Massive Patch Munge.
|
||||
|
||||
---
|
||||
dlls/ntdll/Makefile.in | 1 +
|
||||
dlls/ntdll/esync.c | 141 ++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 32 +++++++++
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
dlls/ntdll/server.c | 7 +-
|
||||
dlls/ntdll/sync.c | 5 ++
|
||||
6 files changed, 184 insertions(+), 3 deletions(-)
|
||||
create mode 100644 dlls/ntdll/esync.c
|
||||
create mode 100644 dlls/ntdll/esync.h
|
||||
|
||||
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
|
||||
index ed4bb94e4..b75e8308a 100644
|
||||
--- a/dlls/ntdll/Makefile.in
|
||||
+++ b/dlls/ntdll/Makefile.in
|
||||
@@ -15,6 +15,7 @@ C_SRCS = \
|
||||
directory.c \
|
||||
env.c \
|
||||
error.c \
|
||||
+ esync.c \
|
||||
exception.c \
|
||||
file.c \
|
||||
handletable.c \
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
new file mode 100644
|
||||
index 000000000..da35bdf85
|
||||
--- /dev/null
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -0,0 +1,141 @@
|
||||
+/*
|
||||
+ * 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 <assert.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <stdlib.h>
|
||||
+#ifdef HAVE_SYS_EVENTFD_H
|
||||
+# include <sys/eventfd.h>
|
||||
+#endif
|
||||
+
|
||||
+#include "ntstatus.h"
|
||||
+#define WIN32_NO_STATUS
|
||||
+#define NONAMELESSUNION
|
||||
+#include "windef.h"
|
||||
+#include "winternl.h"
|
||||
+#include "wine/server.h"
|
||||
+#include "wine/debug.h"
|
||||
+
|
||||
+#include "ntdll_misc.h"
|
||||
+#include "esync.h"
|
||||
+
|
||||
+#ifndef EFD_SEMAPHORE
|
||||
+#define EFD_SEMAPHORE 1
|
||||
+#endif
|
||||
+
|
||||
+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") != NULL);
|
||||
+
|
||||
+ return do_esync_cached;
|
||||
+#else
|
||||
+ static int once;
|
||||
+ if (!once++)
|
||||
+ FIXME("eventfd not supported on this platform.\n");
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+enum esync_type
|
||||
+{
|
||||
+ ESYNC_SEMAPHORE = 1,
|
||||
+};
|
||||
+
|
||||
+struct esync
|
||||
+{
|
||||
+ enum esync_type type;
|
||||
+ int fd;
|
||||
+};
|
||||
+
|
||||
+struct semaphore
|
||||
+{
|
||||
+ struct esync obj;
|
||||
+ int max;
|
||||
+};
|
||||
+
|
||||
+static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
|
||||
+ const OBJECT_ATTRIBUTES *attr, int initval, int flags)
|
||||
+{
|
||||
+ NTSTATUS ret;
|
||||
+ data_size_t len;
|
||||
+ struct object_attributes *objattr;
|
||||
+ obj_handle_t fd_handle;
|
||||
+ sigset_t sigset;
|
||||
+
|
||||
+ if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
|
||||
+
|
||||
+ /* We have to synchronize on the fd cache CS so that our calls to
|
||||
+ * receive_fd don't race with theirs. */
|
||||
+ server_enter_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+ SERVER_START_REQ( create_esync )
|
||||
+ {
|
||||
+ req->access = access;
|
||||
+ req->initval = initval;
|
||||
+ req->flags = flags;
|
||||
+ wine_server_add_data( req, objattr, len );
|
||||
+ ret = wine_server_call( req );
|
||||
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
|
||||
+ {
|
||||
+ *handle = wine_server_ptr_handle( reply->handle );
|
||||
+ *fd = receive_fd( &fd_handle );
|
||||
+ assert( wine_server_ptr_handle(fd_handle) == *handle );
|
||||
+ }
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ server_leave_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+
|
||||
+ TRACE("-> handle %p, fd %d.\n", *handle, *fd);
|
||||
+
|
||||
+ RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
|
||||
+{
|
||||
+ struct semaphore *semaphore;
|
||||
+ NTSTATUS ret;
|
||||
+ int fd = -1;
|
||||
+
|
||||
+ TRACE("name %s, initial %d, max %d.\n",
|
||||
+ attr ? debugstr_us(attr->ObjectName) : "<no name>", initial, max);
|
||||
+
|
||||
+ ret = create_esync( &fd, handle, access, attr, initial, EFD_SEMAPHORE );
|
||||
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
|
||||
+ {
|
||||
+ semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) );
|
||||
+ if (!semaphore)
|
||||
+ return STATUS_NO_MEMORY;
|
||||
+
|
||||
+ semaphore->obj.type = ESYNC_SEMAPHORE;
|
||||
+ semaphore->obj.fd = fd;
|
||||
+ semaphore->max = max;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
new file mode 100644
|
||||
index 000000000..1a88170cf
|
||||
--- /dev/null
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -0,0 +1,32 @@
|
||||
+/*
|
||||
+ * 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) DECLSPEC_HIDDEN;
|
||||
+
|
||||
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
|
||||
+
|
||||
+
|
||||
+/* We have to synchronize on the fd cache CS so that our calls to receive_fd
|
||||
+ * don't race with theirs. It looks weird, I know.
|
||||
+ *
|
||||
+ * If we weren't trying to avoid touching the code I'd rename the CS to
|
||||
+ * "server_fd_section" or something similar. */
|
||||
+extern RTL_CRITICAL_SECTION fd_cache_section;
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 17d87cd52..dad0996c4 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -107,6 +107,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *
|
||||
extern int server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
extern int server_get_unix_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
||||
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
|
||||
+extern int receive_fd( obj_handle_t *handle ) DECLSPEC_HIDDEN;
|
||||
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
|
||||
data_size_t *ret_len ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
|
||||
index d2d238968..dcb355a65 100644
|
||||
--- a/dlls/ntdll/server.c
|
||||
+++ b/dlls/ntdll/server.c
|
||||
@@ -81,6 +81,7 @@
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
#include "ntdll_misc.h"
|
||||
+#include "esync.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(server);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
@@ -120,14 +121,14 @@ sigset_t server_block_set; /* signals to block during server calls */
|
||||
static int fd_socket = -1; /* socket to exchange file descriptors with the server */
|
||||
static pid_t server_pid;
|
||||
|
||||
-static RTL_CRITICAL_SECTION fd_cache_section;
|
||||
+RTL_CRITICAL_SECTION fd_cache_section;
|
||||
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
{
|
||||
0, 0, &fd_cache_section,
|
||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") }
|
||||
};
|
||||
-static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
+RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
/* atomically exchange a 64-bit value */
|
||||
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
|
||||
@@ -773,7 +774,7 @@ void CDECL 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/sync.c b/dlls/ntdll/sync.c
|
||||
index b74bebf08..c259267fb 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -59,7 +59,9 @@
|
||||
#include "winternl.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
+
|
||||
#include "ntdll_misc.h"
|
||||
+#include "esync.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
|
||||
@@ -248,6 +250,9 @@ NTSTATUS WINAPI NtCreateSemaphore( OUT PHANDLE SemaphoreHandle,
|
||||
if (MaximumCount <= 0 || InitialCount < 0 || InitialCount > MaximumCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
+ if (do_esync())
|
||||
+ return esync_create_semaphore( SemaphoreHandle, access, attr, InitialCount, MaximumCount );
|
||||
+
|
||||
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
|
||||
|
||||
SERVER_START_REQ( create_semaphore )
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,123 @@
|
||||
From 3f6f2c22a0ee8e7c9067b74aef67018ed0739484 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 7 Jun 2018 20:45:57 -0500
|
||||
Subject: [PATCH 04/83] ntdll: Store esync objects locally.
|
||||
|
||||
Slight tweak for optimization: return UINT_PTR instead, and remove a useless
|
||||
cmpxchg.
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 61 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index da35bdf85..2bb85d910 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
+#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
@@ -26,6 +27,9 @@
|
||||
#ifdef HAVE_SYS_EVENTFD_H
|
||||
# include <sys/eventfd.h>
|
||||
#endif
|
||||
+#ifdef HAVE_SYS_MMAN_H
|
||||
+# include <sys/mman.h>
|
||||
+#endif
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
@@ -34,6 +38,7 @@
|
||||
#include "winternl.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
+#include "wine/library.h"
|
||||
|
||||
#include "ntdll_misc.h"
|
||||
#include "esync.h"
|
||||
@@ -78,6 +83,59 @@ struct semaphore
|
||||
int max;
|
||||
};
|
||||
|
||||
+/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
|
||||
+ * This is copied and adapted from the fd cache code. */
|
||||
+
|
||||
+#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync *))
|
||||
+#define ESYNC_LIST_ENTRIES 128
|
||||
+
|
||||
+static struct esync * *esync_list[ESYNC_LIST_ENTRIES];
|
||||
+static struct esync * esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];
|
||||
+
|
||||
+static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
|
||||
+{
|
||||
+ UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1;
|
||||
+ *entry = idx / ESYNC_LIST_BLOCK_SIZE;
|
||||
+ return idx % ESYNC_LIST_BLOCK_SIZE;
|
||||
+}
|
||||
+
|
||||
+static BOOL add_to_list( HANDLE handle, struct esync *obj )
|
||||
+{
|
||||
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
|
||||
+
|
||||
+ if (entry >= ESYNC_LIST_ENTRIES)
|
||||
+ {
|
||||
+ FIXME( "too many allocated handles, not caching %p\n", handle );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!esync_list[entry]) /* do we need to allocate a new block of entries? */
|
||||
+ {
|
||||
+ if (!entry) esync_list[0] = esync_list_initial_block;
|
||||
+ else
|
||||
+ {
|
||||
+ void *ptr = wine_anon_mmap( NULL, ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync *),
|
||||
+ PROT_READ | PROT_WRITE, 0 );
|
||||
+ if (ptr == MAP_FAILED) return FALSE;
|
||||
+ esync_list[entry] = ptr;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ obj = interlocked_xchg_ptr((void **)&esync_list[entry][idx], obj);
|
||||
+ assert(!obj);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static void *esync_get_object( HANDLE handle )
|
||||
+{
|
||||
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
|
||||
+
|
||||
+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
|
||||
+
|
||||
+ return esync_list[entry][idx];
|
||||
+}
|
||||
+
|
||||
+
|
||||
static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, int initval, int flags)
|
||||
{
|
||||
@@ -115,7 +173,7 @@ static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
+NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
|
||||
{
|
||||
struct semaphore *semaphore;
|
||||
@@ -135,6 +193,8 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
semaphore->obj.type = ESYNC_SEMAPHORE;
|
||||
semaphore->obj.fd = fd;
|
||||
semaphore->max = max;
|
||||
+
|
||||
+ add_to_list( *handle, &semaphore->obj );
|
||||
}
|
||||
|
||||
return ret;
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,78 @@
|
||||
From eb0273dfd273f1f6c48db45b444ec318fe514699 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 7 Jun 2018 21:02:14 -0500
|
||||
Subject: [PATCH 05/83] ntdll: Implement NtReleaseSemaphore().
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 22 ++++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 1 +
|
||||
dlls/ntdll/sync.c | 4 ++++
|
||||
3 files changed, 27 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 2bb85d910..bca95b9b2 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
+#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_SYS_EVENTFD_H
|
||||
# include <sys/eventfd.h>
|
||||
@@ -199,3 +200,24 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
|
||||
+{
|
||||
+ struct semaphore *semaphore = esync_get_object( handle );
|
||||
+ uint64_t count64 = count;
|
||||
+
|
||||
+ TRACE("%p, %d, %p.\n", handle, count, prev);
|
||||
+
|
||||
+ if (!semaphore) return STATUS_INVALID_HANDLE;
|
||||
+
|
||||
+ if (prev)
|
||||
+ {
|
||||
+ FIXME("Can't write previous value.\n");
|
||||
+ *prev = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (write( semaphore->obj.fd, &count64, sizeof(count64) ) == -1)
|
||||
+ return FILE_GetNtStatus();
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index 1a88170cf..fec0b68e8 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -22,6 +22,7 @@ extern int do_esync(void) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
||||
/* We have to synchronize on the fd cache CS so that our calls to receive_fd
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index c259267fb..93052ddb5 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -333,6 +333,10 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
|
||||
NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, PULONG previous )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
+
|
||||
+ if (do_esync())
|
||||
+ return esync_release_semaphore( handle, count, previous );
|
||||
+
|
||||
SERVER_START_REQ( release_semaphore )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,78 @@
|
||||
From d101cc56af09470319046d570891e861d0a6154a Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 7 Jun 2018 21:07:51 -0500
|
||||
Subject: [PATCH 06/83] ntdll: Close esync objects.
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 19 +++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 1 +
|
||||
dlls/ntdll/om.c | 4 ++++
|
||||
3 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index bca95b9b2..f7a427425 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -136,6 +136,25 @@ static void *esync_get_object( HANDLE handle )
|
||||
return esync_list[entry][idx];
|
||||
}
|
||||
|
||||
+NTSTATUS esync_close( HANDLE handle )
|
||||
+{
|
||||
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
|
||||
+ struct esync *obj;
|
||||
+
|
||||
+ TRACE("%p.\n", handle);
|
||||
+
|
||||
+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
|
||||
+ {
|
||||
+ if ((obj = interlocked_xchg_ptr( (void **)&esync_list[entry][idx], 0 )))
|
||||
+ {
|
||||
+ close( obj->fd );
|
||||
+ RtlFreeHeap( GetProcessHeap(), 0, obj );
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return STATUS_INVALID_HANDLE;
|
||||
+}
|
||||
|
||||
static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, int initval, int flags)
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index fec0b68e8..a22618de8 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
extern int do_esync(void) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
|
||||
index b9fe302b1..ef2cb8b94 100644
|
||||
--- a/dlls/ntdll/om.c
|
||||
+++ b/dlls/ntdll/om.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "windef.h"
|
||||
#include "winternl.h"
|
||||
#include "ntdll_misc.h"
|
||||
+#include "esync.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/unicode.h"
|
||||
@@ -446,6 +447,9 @@ NTSTATUS close_handle( HANDLE handle )
|
||||
NTSTATUS ret;
|
||||
int fd = server_remove_fd_from_cache( handle );
|
||||
|
||||
+ if (do_esync())
|
||||
+ esync_close( handle );
|
||||
+
|
||||
SERVER_START_REQ( close_handle )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,225 @@
|
||||
From f3596cd66ac694d4a7633f91bc53a2f44b2608cc Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Thu, 7 Jun 2018 21:23:52 -0500
|
||||
Subject: [PATCH 07/83] ntdll: Implement waiting on esync objects.
|
||||
|
||||
This is the most basic case: WAIT_ANY. We use poll() (actually ppoll(), for
|
||||
the better granularity) to select on all of the handles that we can.
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 161 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 3 +
|
||||
dlls/ntdll/sync.c | 7 ++
|
||||
3 files changed, 171 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index f7a427425..0950d8b5a 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -22,6 +22,13 @@
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
+#include <errno.h>
|
||||
+#ifdef HAVE_POLL_H
|
||||
+#include <poll.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_POLL_H
|
||||
+# include <sys/poll.h>
|
||||
+#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -240,3 +247,157 @@ 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 );
|
||||
+}
|
||||
+
|
||||
+/* 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 ret;
|
||||
+ int i;
|
||||
+
|
||||
+ 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++)
|
||||
+ {
|
||||
+ objs[i] = esync_get_object( handles[i] );
|
||||
+ if (objs[i])
|
||||
+ has_esync = 1;
|
||||
+ else
|
||||
+ has_server = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (has_esync && has_server)
|
||||
+ {
|
||||
+ FIXME("Can't wait on esync and server objects at the same time!\n");
|
||||
+ /* Wait on just the eventfds; it's the best we can do. */
|
||||
+ }
|
||||
+ else if (has_server)
|
||||
+ {
|
||||
+ /* It's just server objects, so delegate to the server. */
|
||||
+ return STATUS_NOT_IMPLEMENTED;
|
||||
+ }
|
||||
+
|
||||
+ if (TRACE_ON(esync))
|
||||
+ {
|
||||
+ TRACE("Waiting for %s of %d handles:", wait_any ? "any" : "all", count);
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ DPRINTF(" %p", handles[i]);
|
||||
+
|
||||
+ if (!timeout)
|
||||
+ DPRINTF(", timeout = INFINITE.\n");
|
||||
+ else
|
||||
+ {
|
||||
+ timeleft = update_timeout( end );
|
||||
+ DPRINTF(", 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++)
|
||||
+ {
|
||||
+ if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
+ {
|
||||
+ ERR("Polling on fd %d returned %#x.\n", fds[i].fd, fds[i].revents);
|
||||
+ return STATUS_INVALID_HANDLE;
|
||||
+ }
|
||||
+
|
||||
+ if (objs[i])
|
||||
+ {
|
||||
+ 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);
|
||||
+ 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 FILE_GetNtStatus();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Wait-all not implemented.\n");
|
||||
+ return STATUS_NOT_IMPLEMENTED;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index a22618de8..8f7f9b030 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -25,6 +25,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
|
||||
+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
+
|
||||
|
||||
/* We have to synchronize on the fd cache CS so that our calls to receive_fd
|
||||
* don't race with theirs. It looks weird, I know.
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 93052ddb5..40bc619a2 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -1089,6 +1089,13 @@ static NTSTATUS wait_objects( DWORD count, const HANDLE *handles,
|
||||
|
||||
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.20.1
|
||||
|
@ -0,0 +1,100 @@
|
||||
From 0ab9981b2309831fb12ee778e026cb1b4651dab6 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 15:33:46 -0500
|
||||
Subject: [PATCH 08/83] ntdll: Create esync objects for events.
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 2 ++
|
||||
dlls/ntdll/sync.c | 3 +++
|
||||
3 files changed, 39 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 0950d8b5a..ace2f4a45 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -77,6 +77,8 @@ int do_esync(void)
|
||||
enum esync_type
|
||||
{
|
||||
ESYNC_SEMAPHORE = 1,
|
||||
+ ESYNC_AUTO_EVENT,
|
||||
+ ESYNC_MANUAL_EVENT,
|
||||
};
|
||||
|
||||
struct esync
|
||||
@@ -91,6 +93,11 @@ struct semaphore
|
||||
int max;
|
||||
};
|
||||
|
||||
+struct event
|
||||
+{
|
||||
+ struct esync obj;
|
||||
+};
|
||||
+
|
||||
/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
|
||||
* This is copied and adapted from the fd cache code. */
|
||||
|
||||
@@ -248,6 +255,33 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
+NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial )
|
||||
+{
|
||||
+ struct event *event;
|
||||
+ NTSTATUS ret;
|
||||
+ int fd;
|
||||
+
|
||||
+ TRACE("name %s, %s-reset, initial %d.\n",
|
||||
+ attr ? debugstr_us(attr->ObjectName) : "<no name>",
|
||||
+ type == NotificationEvent ? "manual" : "auto", initial);
|
||||
+
|
||||
+ ret = create_esync( &fd, handle, access, attr, initial, 0 );
|
||||
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
|
||||
+ {
|
||||
+ event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) );
|
||||
+ if (!event)
|
||||
+ return STATUS_NO_MEMORY;
|
||||
+
|
||||
+ event->obj.type = (type == NotificationEvent ? ESYNC_MANUAL_EVENT : ESYNC_AUTO_EVENT);
|
||||
+ event->obj.fd = fd;
|
||||
+
|
||||
+ add_to_list( *handle, &event->obj);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#define TICKSPERSEC 10000000
|
||||
#define TICKSPERMSEC 10000
|
||||
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index 8f7f9b030..32a259e39 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -24,6 +24,8 @@ extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
|
||||
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 40bc619a2..6f0e72125 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -365,6 +365,9 @@ NTSTATUS WINAPI NtCreateEvent( PHANDLE EventHandle, ACCESS_MASK DesiredAccess,
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
+ if (do_esync())
|
||||
+ return esync_create_event( EventHandle, DesiredAccess, attr, type, InitialState );
|
||||
+
|
||||
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
|
||||
|
||||
SERVER_START_REQ( create_event )
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,73 @@
|
||||
From b3f22ae85154f22532b66362a2399592d755ce33 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 15:41:01 -0500
|
||||
Subject: [PATCH 09/83] ntdll: Implement NtSetEvent().
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 21 +++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 1 +
|
||||
dlls/ntdll/sync.c | 4 ++++
|
||||
3 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index ace2f4a45..62c56af75 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -282,6 +282,27 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
|
||||
+{
|
||||
+ struct event *event = esync_get_object( handle );
|
||||
+ static const uint64_t value = 1;
|
||||
+
|
||||
+ TRACE("%p.\n", handle);
|
||||
+
|
||||
+ if (!event) return STATUS_INVALID_HANDLE;
|
||||
+
|
||||
+ if (prev)
|
||||
+ {
|
||||
+ FIXME("Can't write previous value.\n");
|
||||
+ *prev = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (write( event->obj.fd, &value, sizeof(value) ) == -1)
|
||||
+ return FILE_GetNtStatus();
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
#define TICKSPERSEC 10000000
|
||||
#define TICKSPERMSEC 10000
|
||||
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index 32a259e39..ba1c89665 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -26,6 +26,7 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
|
||||
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
|
||||
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 6f0e72125..1e1e381b4 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -417,6 +417,10 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT
|
||||
NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
+
|
||||
+ if (do_esync())
|
||||
+ return esync_set_event( handle, prev_state );
|
||||
+
|
||||
SERVER_START_REQ( event_op )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,73 @@
|
||||
From 022deba562034611dccefaf2af504861e391fe7c Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 15:44:49 -0500
|
||||
Subject: [PATCH 10/83] ntdll: Implement NtResetEvent().
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 21 +++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 1 +
|
||||
dlls/ntdll/sync.c | 4 ++++
|
||||
3 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 62c56af75..9e091819a 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -303,6 +303,27 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
+NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
|
||||
+{
|
||||
+ struct event *event = esync_get_object( handle );
|
||||
+ static uint64_t value;
|
||||
+
|
||||
+ TRACE("%p.\n", handle);
|
||||
+
|
||||
+ if (!event) return STATUS_INVALID_HANDLE;
|
||||
+
|
||||
+ if (prev)
|
||||
+ {
|
||||
+ FIXME("Can't write previous value.\n");
|
||||
+ *prev = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* we don't care about the return value */
|
||||
+ read( event->obj.fd, &value, sizeof(value) );
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
#define TICKSPERSEC 10000000
|
||||
#define TICKSPERMSEC 10000
|
||||
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index ba1c89665..8d2b4683e 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -27,6 +27,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
|
||||
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
|
||||
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 1e1e381b4..4be641eb5 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -438,6 +438,10 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
|
||||
NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
+
|
||||
+ if (do_esync())
|
||||
+ return esync_reset_event( handle, prev_state );
|
||||
+
|
||||
SERVER_START_REQ( event_op )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,76 @@
|
||||
From 728fb6100bab81223baad2815878fccfe7fe17a6 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 15:47:16 -0500
|
||||
Subject: [PATCH 11/83] ntdll: Implement NtPulseEvent().
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 25 +++++++++++++++++++++++++
|
||||
dlls/ntdll/esync.h | 1 +
|
||||
dlls/ntdll/sync.c | 3 +++
|
||||
3 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 9e091819a..1055e11ae 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -324,6 +324,31 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
+NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev )
|
||||
+{
|
||||
+ struct event *event = esync_get_object( handle );
|
||||
+ static uint64_t value = 1;
|
||||
+
|
||||
+ TRACE("%p.\n", handle);
|
||||
+
|
||||
+ if (!event) return STATUS_INVALID_HANDLE;
|
||||
+
|
||||
+ if (prev)
|
||||
+ {
|
||||
+ FIXME("Can't write previous value.\n");
|
||||
+ *prev = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* This isn't really correct; an application could miss the write.
|
||||
+ * Unfortunately we can't really do much better. Fortunately this is rarely
|
||||
+ * used (and publicly deprecated). */
|
||||
+ if (write( event->obj.fd, &value, sizeof(value) ) == -1)
|
||||
+ return FILE_GetNtStatus();
|
||||
+ read( event->obj.fd, &value, sizeof(value) );
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
#define TICKSPERSEC 10000000
|
||||
#define TICKSPERMSEC 10000
|
||||
|
||||
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
|
||||
index 8d2b4683e..551257fbc 100644
|
||||
--- a/dlls/ntdll/esync.h
|
||||
+++ b/dlls/ntdll/esync.h
|
||||
@@ -28,6 +28,7 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
|
||||
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 4be641eb5..74b50cbc7 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -474,6 +474,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
|
||||
+ if (do_esync())
|
||||
+ return esync_pulse_event( handle, prev_state );
|
||||
+
|
||||
SERVER_START_REQ( event_op )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,46 @@
|
||||
From ba99a79e4ed4be4525e14aec71eaf52421580c32 Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 15:55:39 -0500
|
||||
Subject: [PATCH 12/83] ntdll: Implement waiting on events.
|
||||
|
||||
More specifically, implement waiting on manual-reset events. Auto-reset events already worked.
|
||||
|
||||
---
|
||||
dlls/ntdll/esync.c | 20 ++++++++++++++++----
|
||||
1 file changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 1055e11ae..7a384dc61 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -471,11 +471,23 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
|
||||
int64_t value;
|
||||
ssize_t size;
|
||||
|
||||
- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
|
||||
+ if (objs[i]->type == ESYNC_MANUAL_EVENT)
|
||||
{
|
||||
- /* We found our object. */
|
||||
- TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
- return i;
|
||||
+ /* Don't grab the object, just check if it's signaled. */
|
||||
+ if (fds[i].revents & POLLIN)
|
||||
+ {
|
||||
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
+ return i;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
|
||||
+ {
|
||||
+ /* We found our object. */
|
||||
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
+ return i;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.20.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
||||
From 74d7000943e1037303294332b415b0b4b5e8291c 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 14/83] server: Add a request to get the eventfd file
|
||||
descriptor associated with a waitable handle.
|
||||
|
||||
---
|
||||
server/esync.c | 28 ++++++++++++++++++++++++++++
|
||||
server/protocol.def | 6 ++++++
|
||||
2 files changed, 34 insertions(+)
|
||||
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index f3a139da4..351da1a7c 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -136,3 +136,31 @@ 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;
|
||||
+ 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 );
|
||||
+ 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 a56f098ab..5f2d77bc7 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -4051,3 +4051,9 @@ struct handle_info
|
||||
@REPLY
|
||||
obj_handle_t handle; /* handle to the object */
|
||||
@END
|
||||
+
|
||||
+/* Retrieve the esync fd for an object. */
|
||||
+@REQ(get_esync_fd)
|
||||
+ obj_handle_t handle; /* handle to the object */
|
||||
+@REPLY
|
||||
+@END
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,178 @@
|
||||
From 4473e26d9c3177ee7a42f023fcbe48edc672f9bc Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 18:57:12 -0500
|
||||
Subject: [PATCH 15/83] server: Create eventfd file descriptors for process
|
||||
objects.
|
||||
|
||||
---
|
||||
server/esync.c | 33 +++++++++++++++++++++++++++++++++
|
||||
server/esync.h | 22 ++++++++++++++++++++++
|
||||
server/process.c | 17 ++++++++++++++++-
|
||||
server/process.h | 1 +
|
||||
4 files changed, 72 insertions(+), 1 deletion(-)
|
||||
create mode 100644 server/esync.h
|
||||
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index 351da1a7c..da26d27cb 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -35,6 +35,21 @@
|
||||
#include "handle.h"
|
||||
#include "request.h"
|
||||
#include "file.h"
|
||||
+#include "esync.h"
|
||||
+
|
||||
+int do_esync(void)
|
||||
+{
|
||||
+#ifdef HAVE_SYS_EVENTFD_H
|
||||
+ static int do_esync_cached = -1;
|
||||
+
|
||||
+ if (do_esync_cached == -1)
|
||||
+ do_esync_cached = (getenv("WINEESYNC") != NULL);
|
||||
+
|
||||
+ return do_esync_cached;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
|
||||
struct esync
|
||||
{
|
||||
@@ -112,6 +127,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
|
||||
#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
|
||||
new file mode 100644
|
||||
index 000000000..f93535b7b
|
||||
--- /dev/null
|
||||
+++ b/server/esync.h
|
||||
@@ -0,0 +1,22 @@
|
||||
+/*
|
||||
+ * eventfd-based synchronization objects
|
||||
+ *
|
||||
+ * Copyright (C) 2018 Zebediah Figura
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Lesser General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2.1 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public
|
||||
+ * License along with this library; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
+ */
|
||||
+
|
||||
+extern int do_esync(void);
|
||||
+int esync_create_fd( int initval, int flags );
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index a96972e6b..0bb220dba 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "request.h"
|
||||
#include "user.h"
|
||||
#include "security.h"
|
||||
+#include "esync.h"
|
||||
|
||||
/* process structure */
|
||||
|
||||
@@ -66,6 +67,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access
|
||||
static struct security_descriptor *process_get_sd( struct object *obj );
|
||||
static void process_poll_event( struct fd *fd, int event );
|
||||
static void process_destroy( struct object *obj );
|
||||
+static int process_get_esync_fd( struct object *obj );
|
||||
static void terminate_process( struct process *process, struct thread *skip, int exit_code );
|
||||
|
||||
static const struct object_ops process_ops =
|
||||
@@ -76,7 +78,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 */
|
||||
@@ -529,6 +531,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
|
||||
process->trace_data = 0;
|
||||
process->rawinput_mouse = NULL;
|
||||
process->rawinput_kbd = NULL;
|
||||
+ process->esync_fd = -1;
|
||||
list_init( &process->thread_list );
|
||||
list_init( &process->locks );
|
||||
list_init( &process->asyncs );
|
||||
@@ -572,6 +575,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
|
||||
}
|
||||
if (!process->handles || !process->token) goto error;
|
||||
|
||||
+ if (do_esync())
|
||||
+ process->esync_fd = esync_create_fd( 0, 0 );
|
||||
+
|
||||
set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */
|
||||
return process;
|
||||
|
||||
@@ -620,6 +626,9 @@ static void process_destroy( struct object *obj )
|
||||
if (process->id) free_ptid( process->id );
|
||||
if (process->token) release_object( process->token );
|
||||
free( process->dir_cache );
|
||||
+
|
||||
+ if (do_esync())
|
||||
+ close( process->esync_fd );
|
||||
}
|
||||
|
||||
/* dump a process on stdout for debugging purposes */
|
||||
@@ -643,6 +652,12 @@ 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 )
|
||||
+{
|
||||
+ struct process *process = (struct process *)obj;
|
||||
+ return process->esync_fd;
|
||||
+}
|
||||
+
|
||||
static unsigned int process_map_access( struct object *obj, unsigned int access )
|
||||
{
|
||||
if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
|
||||
diff --git a/server/process.h b/server/process.h
|
||||
index ea2809194..f8fd12833 100644
|
||||
--- a/server/process.h
|
||||
+++ b/server/process.h
|
||||
@@ -96,6 +96,7 @@ struct process
|
||||
struct list rawinput_devices;/* list of registered rawinput devices */
|
||||
const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */
|
||||
const struct rawinput_device *rawinput_kbd; /* rawinput keyboard device, if any */
|
||||
+ int esync_fd; /* esync file descriptor (signaled on exit) */
|
||||
};
|
||||
|
||||
struct process_snapshot
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,192 @@
|
||||
From 4f6cb6b5955df87982491aed1fd23e18051d095a Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Fri, 8 Jun 2018 19:25:05 -0500
|
||||
Subject: [PATCH 16/83] ntdll, server: Implement waiting on server-bound
|
||||
objects.
|
||||
|
||||
The code here is sort of self-explanatory, but since I split it up over
|
||||
several patches I'll provide a quick explanation. The basic principle is
|
||||
that we can create an eventfd descriptor for any synchronizable handle, and
|
||||
signal it on the server side whenever a wakeup would be triggered. This means
|
||||
not only that we can wait simultaneously on esync primitives and on other
|
||||
primitives, but that we can do it all in "user-mode", i.e. without having to
|
||||
make a server call.
|
||||
|
||||
With this patch we break waiting on svcctl.exe.
|
||||
---
|
||||
dlls/ntdll/esync.c | 68 +++++++++++++++++++++++++++++++++++++++++++---
|
||||
server/esync.c | 16 +++++++++++
|
||||
server/esync.h | 1 +
|
||||
server/thread.c | 4 +++
|
||||
4 files changed, 85 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 7a384dc61..23b03b23b 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -79,6 +79,7 @@ enum esync_type
|
||||
ESYNC_SEMAPHORE = 1,
|
||||
ESYNC_AUTO_EVENT,
|
||||
ESYNC_MANUAL_EVENT,
|
||||
+ ESYNC_MANUAL_SERVER,
|
||||
};
|
||||
|
||||
struct esync
|
||||
@@ -150,6 +151,63 @@ static void *esync_get_object( HANDLE handle )
|
||||
return esync_list[entry][idx];
|
||||
}
|
||||
|
||||
+/* Gets a waitable object. This is either a proper esync object (i.e. an event,
|
||||
+ * semaphore, etc. created using create_esync) or a generic synchronizable
|
||||
+ * server-side object which the server will signal (e.g. a process, thread,
|
||||
+ * message queue, etc.) */
|
||||
+static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj )
|
||||
+{
|
||||
+ obj_handle_t fd_handle;
|
||||
+ struct esync *esync;
|
||||
+ sigset_t sigset;
|
||||
+ NTSTATUS ret;
|
||||
+ int fd;
|
||||
+
|
||||
+ if ((*obj = esync_get_object( handle ))) return STATUS_SUCCESS;
|
||||
+
|
||||
+ /* We need to try grabbing it from the server. */
|
||||
+ server_enter_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+ if (!(esync = esync_get_object( handle )))
|
||||
+ {
|
||||
+ SERVER_START_REQ( get_esync_fd )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( handle );
|
||||
+ if (!(ret = wine_server_call( req )))
|
||||
+ {
|
||||
+ fd = receive_fd( &fd_handle );
|
||||
+ assert( wine_server_ptr_handle(fd_handle) == handle );
|
||||
+ }
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ }
|
||||
+ server_leave_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+
|
||||
+ if (esync)
|
||||
+ {
|
||||
+ /* We managed to grab it while in the CS; return it. */
|
||||
+ *obj = esync;
|
||||
+ return STATUS_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ WARN("Failed to retrieve fd for handle %p, status %#x.\n", handle, ret);
|
||||
+ *obj = NULL;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ TRACE("Got fd %d for handle %p.\n", fd, handle);
|
||||
+
|
||||
+ esync = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*esync) );
|
||||
+ esync->fd = fd;
|
||||
+ esync->type = ESYNC_MANUAL_SERVER;
|
||||
+
|
||||
+ add_to_list( handle, esync );
|
||||
+
|
||||
+ *obj = esync;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
NTSTATUS esync_close( HANDLE handle )
|
||||
{
|
||||
UINT_PTR entry, idx = handle_to_index( handle, &entry );
|
||||
@@ -410,11 +468,13 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
- objs[i] = esync_get_object( handles[i] );
|
||||
- if (objs[i])
|
||||
+ ret = get_waitable_object( handles[i], &objs[i] );
|
||||
+ if (ret == STATUS_SUCCESS)
|
||||
has_esync = 1;
|
||||
- else
|
||||
+ else if (ret == STATUS_NOT_IMPLEMENTED)
|
||||
has_server = 1;
|
||||
+ else
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
if (has_esync && has_server)
|
||||
@@ -471,7 +531,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
|
||||
int64_t value;
|
||||
ssize_t size;
|
||||
|
||||
- if (objs[i]->type == ESYNC_MANUAL_EVENT)
|
||||
+ if (objs[i]->type == ESYNC_MANUAL_EVENT || objs[i]->type == ESYNC_MANUAL_SERVER)
|
||||
{
|
||||
/* Don't grab the object, just check if it's signaled. */
|
||||
if (fds[i].revents & POLLIN)
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index da26d27cb..96bf6a57f 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
+#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_SYS_EVENTFD_H
|
||||
@@ -145,6 +146,21 @@ int esync_create_fd( int initval, int flags )
|
||||
#endif
|
||||
}
|
||||
|
||||
+/* Wake up a server-side esync object. */
|
||||
+void esync_wake_up( struct object *obj )
|
||||
+{
|
||||
+ static const uint64_t value = 1;
|
||||
+ int fd;
|
||||
+
|
||||
+ if (obj->ops->get_esync_fd)
|
||||
+ {
|
||||
+ fd = obj->ops->get_esync_fd( obj );
|
||||
+
|
||||
+ if (write( fd, &value, sizeof(value) ) == -1)
|
||||
+ perror( "esync: write" );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
DECL_HANDLER(create_esync)
|
||||
{
|
||||
struct esync *esync;
|
||||
diff --git a/server/esync.h b/server/esync.h
|
||||
index f93535b7b..bbfe0aef8 100644
|
||||
--- a/server/esync.h
|
||||
+++ b/server/esync.h
|
||||
@@ -20,3 +20,4 @@
|
||||
|
||||
extern int do_esync(void);
|
||||
int esync_create_fd( int initval, int flags );
|
||||
+void esync_wake_up( struct object *obj );
|
||||
diff --git a/server/thread.c b/server/thread.c
|
||||
index cf401f79b..ae00c89da 100644
|
||||
--- a/server/thread.c
|
||||
+++ b/server/thread.c
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "request.h"
|
||||
#include "user.h"
|
||||
#include "security.h"
|
||||
+#include "esync.h"
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
@@ -940,6 +941,9 @@ void wake_up( struct object *obj, int max )
|
||||
struct list *ptr;
|
||||
int ret;
|
||||
|
||||
+ if (do_esync())
|
||||
+ esync_wake_up( obj );
|
||||
+
|
||||
LIST_FOR_EACH( ptr, &obj->wait_queue )
|
||||
{
|
||||
struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,144 @@
|
||||
From da31b19b8edb1c270fe3735ac2f5d54132c3007c 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 17/83] server: Create eventfd file descriptors for event
|
||||
objects.
|
||||
|
||||
We still need this, since there are some events which the server signals.
|
||||
|
||||
This lets system processes shut down.
|
||||
|
||||
---
|
||||
server/esync.c | 8 ++++++++
|
||||
server/esync.h | 1 +
|
||||
server/event.c | 28 ++++++++++++++++++++++++++--
|
||||
3 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index 96bf6a57f..406c1a557 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -161,6 +161,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 bbfe0aef8..054a77190 100644
|
||||
--- a/server/esync.h
|
||||
+++ b/server/esync.h
|
||||
@@ -21,3 +21,4 @@
|
||||
extern int do_esync(void);
|
||||
int esync_create_fd( int initval, int flags );
|
||||
void esync_wake_up( struct object *obj );
|
||||
+void esync_clear( int fd );
|
||||
diff --git a/server/event.c b/server/event.c
|
||||
index f78c12d26..12724c581 100644
|
||||
--- a/server/event.c
|
||||
+++ b/server/event.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "thread.h"
|
||||
#include "request.h"
|
||||
#include "security.h"
|
||||
+#include "esync.h"
|
||||
|
||||
struct event
|
||||
{
|
||||
@@ -42,15 +43,18 @@ 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 struct object_type *event_get_type( struct object *obj );
|
||||
static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
|
||||
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
|
||||
+static int event_get_esync_fd( struct object *obj );
|
||||
static unsigned int event_map_access( struct object *obj, unsigned int access );
|
||||
static int event_signal( struct object *obj, unsigned int access);
|
||||
static struct list *event_get_kernel_obj_list( struct object *obj );
|
||||
+static void event_destroy( struct object *obj );
|
||||
|
||||
static const struct object_ops event_ops =
|
||||
{
|
||||
@@ -60,7 +64,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 */
|
||||
@@ -73,7 +77,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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -126,6 +130,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;
|
||||
@@ -154,6 +161,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 )
|
||||
@@ -177,6 +187,12 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
|
||||
return event->signaled;
|
||||
}
|
||||
|
||||
+static int event_get_esync_fd( struct object *obj )
|
||||
+{
|
||||
+ struct event *event = (struct event *)obj;
|
||||
+ return event->esync_fd;
|
||||
+}
|
||||
+
|
||||
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry )
|
||||
{
|
||||
struct event *event = (struct event *)obj;
|
||||
@@ -214,6 +230,14 @@ static struct list *event_get_kernel_obj_list( struct object *obj )
|
||||
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.20.1
|
||||
|
@ -0,0 +1,117 @@
|
||||
From 06935535827e6ce33ce77ae9c17165d4623b22ec 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 18/83] 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 406c1a557..4f7ff6bda 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -61,7 +61,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 */
|
||||
esync_dump, /* dump */
|
||||
@@ -169,6 +169,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 054a77190..2687c72e4 100644
|
||||
--- a/server/esync.h
|
||||
+++ b/server/esync.h
|
||||
@@ -22,3 +22,9 @@ extern int do_esync(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 12724c581..62d8bf7d3 100644
|
||||
--- a/server/event.c
|
||||
+++ b/server/event.c
|
||||
@@ -140,6 +140,10 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -153,6 +157,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 );
|
||||
@@ -160,6 +170,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
|
||||
|
@ -0,0 +1,69 @@
|
||||
From fe2e94200cfb6a88e82b9261f2d8a05a6fae0cbe 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 19/83] 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/esync.c | 32 +++++++++++++++++++++-----------
|
||||
1 file changed, 21 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 23b03b23b..0655ab779 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -423,22 +423,32 @@ static LONGLONG update_timeout( ULONGLONG end )
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
|
||||
--
|
||||
2.20.1
|
||||
|
@ -0,0 +1,88 @@
|
||||
From 69c158267facd8919329e71e082e872031ee4054 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 20/83] server: Create eventfd file descriptors for thread
|
||||
objects.
|
||||
|
||||
---
|
||||
server/thread.c | 16 +++++++++++++++-
|
||||
server/thread.h | 1 +
|
||||
2 files changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/server/thread.c b/server/thread.c
|
||||
index ae00c89da..e82d71f67 100644
|
||||
--- a/server/thread.c
|
||||
+++ b/server/thread.c
|
||||
@@ -133,6 +133,7 @@ static const struct object_ops thread_apc_ops =
|
||||
static void dump_thread( struct object *obj, int verbose );
|
||||
static struct object_type *thread_get_type( struct object *obj );
|
||||
static int thread_signaled( struct object *obj, struct wait_queue_entry *entry );
|
||||
+static int thread_get_esync_fd( struct object *obj );
|
||||
static unsigned int thread_map_access( struct object *obj, unsigned int access );
|
||||
static void thread_poll_event( struct fd *fd, int event );
|
||||
static void destroy_thread( struct object *obj );
|
||||
@@ -145,7 +146,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 */
|
||||
@@ -185,6 +186,7 @@ static inline void init_thread_structure( struct thread *thread )
|
||||
thread->suspend_context = NULL;
|
||||
thread->teb = 0;
|
||||
thread->entry_point = 0;
|
||||
+ thread->esync_fd = -1;
|
||||
thread->debug_ctx = NULL;
|
||||
thread->debug_event = NULL;
|
||||
thread->debug_break = 0;
|
||||
@@ -292,6 +294,9 @@ struct thread *create_thread( int fd, struct process *process, const struct secu
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ 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;
|
||||
@@ -364,6 +369,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 */
|
||||
@@ -388,6 +396,12 @@ 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 )
|
||||
+{
|
||||
+ struct thread *thread = (struct thread *)obj;
|
||||
+ return thread->esync_fd;
|
||||
+}
|
||||
+
|
||||
static unsigned int thread_map_access( struct object *obj, unsigned int access )
|
||||
{
|
||||
if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT;
|
||||
diff --git a/server/thread.h b/server/thread.h
|
||||
index bfd818ce2..4913577f7 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) */
|
||||
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
||||
struct debug_event *debug_event; /* debug event being sent to debugger */
|
||||
int debug_break; /* debug breakpoint pending? */
|
||||
--
|
||||
2.20.1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user