From 5eddf968dfe301274c53a11f1f4d28e8b77fdb87 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Sat, 9 Jun 2018 15:39:37 -0500
Subject: [PATCH] server: Create eventfd descriptors for device manager
 objects.

We don't have to worry about synchronization here because
wine_ntoskrnl_main_loop() is only ever called from one thread per winedevice
process.

This lets drivers like mountmgr finally work, and so winecfg can open the
Drives tab.
---
 server/device.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/server/device.c b/server/device.c
index a6bfa06eb..5f82daa73 100644
--- a/server/device.c
+++ b/server/device.c
@@ -39,6 +39,7 @@
 #include "handle.h"
 #include "request.h"
 #include "process.h"
+#include "esync.h"
 
 /* IRP object */
 
@@ -92,10 +93,12 @@ struct device_manager
     struct list            requests;       /* list of pending irps across all devices */
     struct irp_call       *current_call;   /* call currently executed on client side */
     struct wine_rb_tree    kernel_objects; /* map of objects that have client side pointer associated */
+    int                    esync_fd;       /* esync file descriptor */
 };
 
 static void device_manager_dump( struct object *obj, int verbose );
 static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry );
+static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type );
 static void device_manager_destroy( struct object *obj );
 
 static const struct object_ops device_manager_ops =
@@ -106,7 +109,7 @@ static const struct object_ops device_manager_ops =
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     device_manager_signaled,          /* signaled */
-    NULL,                             /* get_esync_fd */
+    device_manager_get_esync_fd,      /* get_esync_fd */
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
@@ -694,6 +697,9 @@ static void delete_file( struct device_file *file )
     /* terminate all pending requests */
     LIST_FOR_EACH_ENTRY_SAFE( irp, next, &file->requests, struct irp_call, dev_entry )
     {
+        if (do_esync() && file->device->manager && list_empty( &file->device->manager->requests ))
+            esync_clear( file->device->manager->esync_fd );
+
         list_remove( &irp->mgr_entry );
         set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 );
     }
@@ -726,6 +732,13 @@ static int device_manager_signaled( struct object *obj, struct wait_queue_entry
     return !list_empty( &manager->requests );
 }
 
+static int device_manager_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+    struct device_manager *manager = (struct device_manager *)obj;
+    *type = ESYNC_MANUAL_SERVER;
+    return manager->esync_fd;
+}
+
 static void device_manager_destroy( struct object *obj )
 {
     struct device_manager *manager = (struct device_manager *)obj;
@@ -760,6 +773,9 @@ static void device_manager_destroy( struct object *obj )
         assert( !irp->file && !irp->async );
         release_object( irp );
     }
+
+    if (do_esync())
+        close( manager->esync_fd );
 }
 
 static struct device_manager *create_device_manager(void)
@@ -772,6 +788,9 @@ static struct device_manager *create_device_manager(void)
         list_init( &manager->devices );
         list_init( &manager->requests );
         wine_rb_init( &manager->kernel_objects, compare_kernel_object );
+
+        if (do_esync())
+            manager->esync_fd = esync_create_fd( 0, 0 );
     }
     return manager;
 }
@@ -930,6 +949,9 @@ DECL_HANDLER(get_next_device_request)
                 /* we already own the object if it's only on manager queue */
                 if (irp->file) grab_object( irp );
                 manager->current_call = irp;
+
+                if (do_esync() && list_empty( &manager->requests ))
+                    esync_clear( manager->esync_fd );
             }
             else close_handle( current->process, reply->next );
         }
-- 
2.21.0

