Module: wine Branch: master Commit: 200f8d958f43c9985240c0e14b27a9ea10efdfb3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=200f8d958f43c9985240c0e14b...
Author: Alexandre Julliard julliard@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) {