From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 31 +++++++++++++++++-------------- server/inproc_sync.c | 16 +++++++++++++++- server/mutex.c | 7 +++++-- server/object.c | 2 +- server/object.h | 6 +++--- server/semaphore.c | 7 +++++-- server/thread.c | 2 +- 7 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/server/event.c b/server/event.c index 3bbf92f18e5..3dc324df0ec 100644 --- a/server/event.c +++ b/server/event.c @@ -60,7 +60,7 @@ struct event_sync static void event_sync_dump( struct object *obj, int verbose ); static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry ); static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ); -static int event_sync_signal( struct object *obj, unsigned int access ); +static int event_sync_signal( struct object *obj, unsigned int access, int signal );
static const struct object_ops event_sync_ops = { @@ -129,16 +129,14 @@ static int event_sync_signaled( struct object *obj, struct wait_queue_entry *ent return event->signaled; }
-void signal_sync( struct event_sync *event ) +void signal_sync( struct event_sync *sync ) { - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual ); + sync->obj.ops->signal( &sync->obj, 0, 1 ); }
-void reset_sync( struct event_sync *event ) +void reset_sync( struct event_sync *sync ) { - event->signaled = 0; + sync->obj.ops->signal( &sync->obj, 0, 0 ); }
static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ) @@ -146,14 +144,16 @@ static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *e struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); /* Reset if it's an auto-reset event */ - if (!event->manual) reset_sync( event ); + if (!event->manual) event->signaled = 0; }
-static int event_sync_signal( struct object *obj, unsigned int access ) +static int event_sync_signal( struct object *obj, unsigned int access, int signal ) { struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); - signal_sync( event ); + + /* wake up all waiters if manual reset, a single one otherwise */ + if ((event->signaled = !!signal)) wake_up( &event->obj, !event->manual ); return 1; }
@@ -166,7 +166,7 @@ struct event
static void event_dump( struct object *obj, int verbose ); static struct object *event_get_sync( struct object *obj ); -static int event_signal( struct object *obj, unsigned int access); +static int event_signal( struct object *obj, unsigned int access, int signal ); static struct list *event_get_kernel_obj_list( struct object *obj ); static void event_destroy( struct object *obj );
@@ -297,18 +297,21 @@ static struct object *event_get_sync( struct object *obj ) return grab_object( event->sync ); }
-static int event_signal( struct object *obj, unsigned int access ) +static int event_signal( struct object *obj, unsigned int access, int signal ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops );
+ assert( event->sync->obj.ops == &event_sync_ops ); /* never called with inproc syncs */ + assert( signal == -1 ); /* always called from signal_object */ + if (!(access & EVENT_MODIFY_STATE)) { set_error( STATUS_ACCESS_DENIED ); return 0; } - set_event( event ); - return 1; + + return event_sync_signal( &event->sync->obj, 0, 1 ); }
static struct list *event_get_kernel_obj_list( struct object *obj ) diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 435c58947f3..54342fc3e2a 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -60,6 +60,7 @@ struct inproc_sync };
static void inproc_sync_dump( struct object *obj, int verbose ); +static int inproc_sync_signal( struct object *obj, unsigned int access, int signal ); static void inproc_sync_destroy( struct object *obj );
static const struct object_ops inproc_sync_ops = @@ -71,7 +72,7 @@ static const struct object_ops inproc_sync_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + inproc_sync_signal, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -126,6 +127,19 @@ void reset_inproc_sync( struct inproc_sync *sync ) ioctl( sync->fd, NTSYNC_IOC_EVENT_RESET, &count ); }
+static int inproc_sync_signal( struct object *obj, unsigned int access, int signal ) +{ + struct inproc_sync *sync = (struct inproc_sync *)obj; + assert( obj->ops == &inproc_sync_ops ); + + assert( sync->type == INPROC_SYNC_INTERNAL ); /* never called for mutex / semaphore */ + assert( signal == 0 || signal == 1 ); /* never called from signal_object */ + + if (signal) signal_inproc_sync( sync ); + else reset_inproc_sync( sync ); + return 1; +} + static void inproc_sync_destroy( struct object *obj ) { struct inproc_sync *sync = (struct inproc_sync *)obj; diff --git a/server/mutex.c b/server/mutex.c index e370d301472..3fa8c021330 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -174,7 +174,7 @@ struct mutex
static void mutex_dump( struct object *obj, int verbose ); static struct object *mutex_get_sync( struct object *obj ); -static int mutex_signal( struct object *obj, unsigned int access ); +static int mutex_signal( struct object *obj, unsigned int access, int signal ); static void mutex_destroy( struct object *obj );
static const struct object_ops mutex_ops = @@ -251,11 +251,14 @@ static struct object *mutex_get_sync( struct object *obj ) return grab_object( mutex->sync ); }
-static int mutex_signal( struct object *obj, unsigned int access ) +static int mutex_signal( struct object *obj, unsigned int access, int signal ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops );
+ assert( mutex->sync->obj.ops == &mutex_sync_ops ); /* never called with inproc syncs */ + assert( signal == -1 ); /* always called from signal_object */ + if (!(access & SYNCHRONIZE)) { set_error( STATUS_ACCESS_DENIED ); diff --git a/server/object.c b/server/object.c index 356956aad6a..694835a6a51 100644 --- a/server/object.c +++ b/server/object.c @@ -630,7 +630,7 @@ void no_satisfied( struct object *obj, struct wait_queue_entry *entry ) { }
-int no_signal( struct object *obj, unsigned int access ) +int no_signal( struct object *obj, unsigned int access, int signal ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); return 0; diff --git a/server/object.h b/server/object.h index d604f70d100..4cc169b827c 100644 --- a/server/object.h +++ b/server/object.h @@ -80,8 +80,8 @@ struct object_ops int (*signaled)(struct object *,struct wait_queue_entry *); /* wait satisfied */ void (*satisfied)(struct object *,struct wait_queue_entry *); - /* signal an object */ - int (*signal)(struct object *, unsigned int); + /* signal/reset an object */ + int (*signal)(struct object *,unsigned int,int); /* return an fd object that can be used to read/write from the object */ struct fd *(*get_fd)(struct object *); /* return a sync that can be used to wait/signal the object */ @@ -170,7 +170,7 @@ extern struct object *find_object( const struct namespace *namespace, const stru extern struct object *find_object_index( const struct namespace *namespace, unsigned int index ); extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); extern void no_satisfied( struct object *obj, struct wait_queue_entry *entry ); -extern int no_signal( struct object *obj, unsigned int access ); +extern int no_signal( struct object *obj, unsigned int access, int signal ); extern struct fd *no_get_fd( struct object *obj ); extern struct object *default_get_sync( struct object *obj ); static inline struct object *get_obj_sync( struct object *obj ) { return obj->ops->get_sync( obj ); } diff --git a/server/semaphore.c b/server/semaphore.c index 4b31bfe806c..771115e62fd 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -148,7 +148,7 @@ struct semaphore
static void semaphore_dump( struct object *obj, int verbose ); static struct object *semaphore_get_sync( struct object *obj ); -static int semaphore_signal( struct object *obj, unsigned int access ); +static int semaphore_signal( struct object *obj, unsigned int access, int signal ); static void semaphore_destroy( struct object *obj );
static const struct object_ops semaphore_ops = @@ -218,11 +218,14 @@ static struct object *semaphore_get_sync( struct object *obj ) return grab_object( sem->sync ); }
-static int semaphore_signal( struct object *obj, unsigned int access ) +static int semaphore_signal( struct object *obj, unsigned int access, int signal ) { struct semaphore *sem = (struct semaphore *)obj; assert( obj->ops == &semaphore_ops );
+ assert( sem->sync->obj.ops == &semaphore_sync_ops ); /* never called with inproc syncs */ + assert( signal == -1 ); /* always called from signal_object */ + if (!(access & SEMAPHORE_MODIFY_STATE)) { set_error( STATUS_ACCESS_DENIED ); diff --git a/server/thread.c b/server/thread.c index 8bd1e0cff3b..83ee9a47794 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1269,7 +1269,7 @@ static int signal_object( obj_handle_t handle ) obj = get_handle_obj( current->process, handle, 0, NULL ); if (obj) { - ret = obj->ops->signal( obj, get_handle_access( current->process, handle )); + ret = obj->ops->signal( obj, get_handle_access( current->process, handle ), -1 ); release_object( obj ); } return ret;