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

