Alexandre Julliard : server: Reuse existing file descriptor objects for duplicate file mappings.

Alexandre Julliard julliard at winehq.org
Tue Apr 19 12:08:18 CDT 2011


Module: wine
Branch: master
Commit: 200f8d958f43c9985240c0e14b27a9ea10efdfb3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=200f8d958f43c9985240c0e14b27a9ea10efdfb3

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Apr 19 17:19:31 2011 +0200

server: Reuse existing file descriptor objects for duplicate file mappings.

---

 server/fd.c      |   14 ++++++++++++++
 server/file.h    |    1 +
 server/mapping.c |   11 +++++++----
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/server/fd.c b/server/fd.c
index 1743952..fd0e2fc 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1670,6 +1670,20 @@ failed:
     return NULL;
 }
 
+/* find an existing fd object that can be reused for a mapping */
+struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access, unsigned int sharing )
+{
+    struct fd *fd_ptr;
+
+    if (!fd->inode) return NULL;
+
+    LIST_FOR_EACH_ENTRY( fd_ptr, &fd->inode->open, struct fd, inode_entry )
+        if (fd_ptr->access == access && fd_ptr->sharing == sharing)
+            return (struct fd *)grab_object( fd_ptr );
+
+    return NULL;
+}
+
 /* set the status to return when the fd has no associated unix fd */
 void set_no_fd_status( struct fd *fd, unsigned int status )
 {
diff --git a/server/file.h b/server/file.h
index 218b553..ead356d 100644
--- a/server/file.h
+++ b/server/file.h
@@ -61,6 +61,7 @@ extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
                                        int unix_fd, struct object *user, unsigned int options );
 extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
                                  unsigned int options );
+extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access, unsigned int sharing );
 extern void *get_fd_user( struct fd *fd );
 extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
 extern unsigned int get_fd_options( struct fd *fd );
diff --git a/server/mapping.c b/server/mapping.c
index 733dc89..f37016f 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -496,6 +496,7 @@ static struct object *create_mapping( struct directory *root, const struct unico
 
     if (handle)
     {
+        const unsigned int sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
         unsigned int mapping_access = FILE_MAPPING_ACCESS;
 
         if (!(protect & VPROT_COMMITTED))
@@ -509,14 +510,16 @@ static struct object *create_mapping( struct directory *root, const struct unico
         /* file sharing rules for mappings are different so we use magic the access rights */
         if (protect & VPROT_IMAGE) mapping_access |= FILE_MAPPING_IMAGE;
         else if (protect & VPROT_WRITE) mapping_access |= FILE_MAPPING_WRITE;
-        mapping->fd = dup_fd_object( fd, mapping_access,
-                                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                                     FILE_SYNCHRONOUS_IO_NONALERT );
+
+        if (!(mapping->fd = get_fd_object_for_mapping( fd, mapping_access, sharing )))
+        {
+            mapping->fd = dup_fd_object( fd, mapping_access, sharing, FILE_SYNCHRONOUS_IO_NONALERT );
+            if (mapping->fd) set_fd_user( mapping->fd, &mapping_fd_ops, NULL );
+        }
         release_object( file );
         release_object( fd );
         if (!mapping->fd) goto error;
 
-        set_fd_user( mapping->fd, &mapping_fd_ops, &mapping->obj );
         if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error;
         if (protect & VPROT_IMAGE)
         {




More information about the wine-cvs mailing list