From e6e0ef574ce53d5b5e94068ae9dc137c2c7dee92 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] 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 351da1a7cb2..da26d27cbc8 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 00000000000..f93535b7b4c
--- /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 c4cb041f293..ed03210a5f5 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 */
 
@@ -67,6 +68,7 @@ static struct security_descriptor *process_get_sd( struct object *obj );
 static void process_poll_event( struct fd *fd, int event );
 static struct list *process_get_kernel_obj_list( struct object *obj );
 static void process_destroy( struct object *obj );
+static int process_get_esync_fd( struct object *obj );
 static void terminate_process( struct process *process, struct thread *skip, int exit_code );
 
 static const struct object_ops process_ops =
@@ -77,7 +79,7 @@ static const struct object_ops process_ops =
     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 */
@@ -531,6 +533,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->kernel_object );
     list_init( &process->thread_list );
     list_init( &process->locks );
@@ -575,6 +578,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
     }
     if (!process->handles || !process->token) goto error;
 
+    if (do_esync())
+        process->esync_fd = esync_create_fd( 0, 0 );
+
     set_fd_events( process->msg_fd, POLLIN );  /* start listening to events */
     return process;
 
@@ -623,6 +629,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 */
@@ -647,6 +656,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 41267a27df5..02765f2f122 100644
--- a/server/process.h
+++ b/server/process.h
@@ -97,6 +97,7 @@ struct process
     const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */
     const struct rawinput_device *rawinput_kbd;   /* rawinput keyboard device, if any */
     struct list          kernel_object;   /* list of kernel object pointers */
+    int                  esync_fd;        /* esync file descriptor (signaled on exit) */
 };
 
 struct process_snapshot
-- 
2.20.1

