From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 19 +++++++++++++------ server/fd.c | 45 +++++++++++++++++++++++++-------------------- server/object.h | 4 ++++ 3 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/server/event.c b/server/event.c index b5dff9b5b49..3a228f2898f 100644 --- a/server/event.c +++ b/server/event.c @@ -55,6 +55,7 @@ struct event_sync struct object obj; /* object header */ unsigned int manual : 1; /* is it a manual reset event? */ unsigned int signaled : 1; /* event has been signaled */ + unsigned int internal : 1; /* sync is an internal sync */ };
static void event_sync_dump( struct object *obj, int verbose ); @@ -87,18 +88,19 @@ static const struct object_ops event_sync_ops = no_destroy /* destroy */ };
-static struct object *create_event_sync( int manual, int signaled ) +struct object *create_event_sync( int manual, int signaled, int internal ) { struct event_sync *event;
if (!(event = alloc_object( &event_sync_ops ))) return NULL; event->manual = manual; event->signaled = signaled; + event->internal = internal;
return &event->obj; }
-static void signal_sync( struct object *obj ) +void signal_sync( struct object *obj ) { struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); @@ -108,7 +110,7 @@ static void signal_sync( struct object *obj ) wake_up( &event->obj, !event->manual ); }
-static void reset_sync( struct object *obj ) +void reset_sync( struct object *obj ) { struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); @@ -120,8 +122,8 @@ static void event_sync_dump( struct object *obj, int verbose ) { struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); - fprintf( stderr, "Event manual=%d signaled=%d\n", - event->manual, event->signaled ); + fprintf( stderr, "Event manual=%d signaled=%d internal=%d\n", + event->manual, event->signaled, event->internal ); }
static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -144,6 +146,11 @@ static int event_sync_signal( struct object *obj, unsigned int access ) struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops );
+ if (event->internal) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return 0; + } if (!(access & EVENT_MODIFY_STATE)) { set_error( STATUS_ACCESS_DENIED ); @@ -253,7 +260,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name, event->sync = NULL; list_init( &event->kernel_object );
- if (!(event->sync = create_event_sync( manual_reset, initial_state ))) + if (!(event->sync = create_event_sync( manual_reset, initial_state, 0 ))) { release_object( event ); return NULL; diff --git a/server/fd.c b/server/fd.c index 94fa3e2dae7..0424c0ab510 100644 --- a/server/fd.c +++ b/server/fd.c @@ -128,6 +128,7 @@ struct closed_fd struct fd { struct object obj; /* object header */ + struct object *sync; /* sync object for wait/signal */ const struct fd_ops *fd_ops; /* file descriptor operations */ struct inode *inode; /* inode that this fd belongs to */ struct list inode_entry; /* entry in inode fd list */ @@ -145,7 +146,6 @@ struct fd int unix_fd; /* unix file descriptor */ unsigned int no_fd_status;/* status to return when unix_fd is -1 */ unsigned int cacheable :1;/* can the fd be cached on the client side? */ - unsigned int signaled :1; /* is the fd signaled? */ unsigned int fs_locks :1; /* can we use filesystem locks for this fd? */ int poll_index; /* index of fd in poll array */ struct async_queue read_q; /* async readers of this fd */ @@ -157,7 +157,7 @@ struct fd };
static void fd_dump( struct object *obj, int verbose ); -static int fd_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *fd_get_sync( struct object *obj ); static void fd_destroy( struct object *obj );
static const struct object_ops fd_ops = @@ -165,13 +165,13 @@ static const struct object_ops fd_ops = sizeof(struct fd), /* size */ &no_type, /* type */ fd_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -1565,6 +1565,12 @@ static void fd_dump( struct object *obj, int verbose ) fprintf( stderr, "\n" ); }
+static struct object *fd_get_sync( struct object *obj ) +{ + struct fd *fd = (struct fd *)obj; + return grab_object( fd->sync ); +} + static void fd_destroy( struct object *obj ) { struct fd *fd = (struct fd *)obj; @@ -1589,6 +1595,7 @@ static void fd_destroy( struct object *obj ) if (fd->unix_fd != -1) close( fd->unix_fd ); free( fd->unix_name ); } + if (fd->sync) release_object( fd->sync ); }
/* check if the desired access is possible without violating */ @@ -1702,7 +1709,6 @@ static struct fd *alloc_fd_object(void) fd->nt_name = NULL; fd->nt_namelen = 0; fd->cacheable = 0; - fd->signaled = 1; fd->fs_locks = 1; fd->poll_index = -1; fd->completion = NULL; @@ -1713,7 +1719,8 @@ static struct fd *alloc_fd_object(void) list_init( &fd->inode_entry ); list_init( &fd->locks );
- if ((fd->poll_index = add_poll_user( fd )) == -1) + if ((fd->poll_index = add_poll_user( fd )) == -1 || + !(fd->sync = create_event_sync( 1, 1, 1 ))) { release_object( fd ); return NULL; @@ -1742,7 +1749,6 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use fd->nt_namelen = 0; fd->unix_fd = -1; fd->cacheable = 0; - fd->signaled = 1; fd->fs_locks = 0; fd->poll_index = -1; fd->completion = NULL; @@ -1753,6 +1759,12 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use init_async_queue( &fd->wait_q ); list_init( &fd->inode_entry ); list_init( &fd->locks ); + + if (!(fd->sync = create_event_sync( 1, 1, 1 ))) + { + release_object( fd ); + return NULL; + } return fd; }
@@ -2156,8 +2168,8 @@ int is_fd_removable( struct fd *fd ) void set_fd_signaled( struct fd *fd, int signaled ) { if (fd->comp_flags & FILE_SKIP_SET_EVENT_ON_HANDLE) return; - fd->signaled = signaled; - if (signaled) wake_up( &fd->obj, 0 ); + if (signaled) signal_sync( fd->sync ); + else reset_sync( fd->sync ); }
/* check if events are pending and if yes return which one(s) */ @@ -2174,13 +2186,6 @@ int check_fd_events( struct fd *fd, int events ) return pfd.revents; }
-static int fd_signaled( struct object *obj, struct wait_queue_entry *entry ) -{ - struct fd *fd = (struct fd *)obj; - assert( obj->ops == &fd_ops ); - return fd->signaled; -} - /* default get_sync() routine for objects that poll() on an fd */ struct object *default_fd_get_sync( struct object *obj ) { diff --git a/server/object.h b/server/object.h index 513d1906020..33d918a77f7 100644 --- a/server/object.h +++ b/server/object.h @@ -218,6 +218,10 @@ static inline void *mem_append( void *ptr, const void *src, data_size_t len ) struct event; struct keyed_event;
+extern struct object *create_event_sync( int manual, int signaled, int internal ); +extern void signal_sync( struct object *obj ); +extern void reset_sync( struct object *obj ); + extern struct event *create_event( struct object *root, const struct unicode_str *name, unsigned int attr, int manual_reset, int initial_state, const struct security_descriptor *sd );