From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 69 +++++++++++++++++++++++++++++++------------------ server/object.c | 12 +++++++++ server/object.h | 2 ++ 3 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/server/event.c b/server/event.c index f0565757670..500d95bb8e0 100644 --- a/server/event.c +++ b/server/event.c @@ -50,13 +50,18 @@ struct type_descr event_type = }, };
+struct event_sync +{ + struct sync sync; /* sync header */ + unsigned int manual_reset :1; /* is it a manual reset event? */ + unsigned int signaled :1; /* event has been signaled */ +}; + struct event { struct object obj; /* object header */ struct sync *sync; /* object sync */ struct list kernel_object; /* list of kernel object pointers */ - int manual_reset; /* is it a manual reset event? */ - int signaled; /* event has been signaled */ };
static void event_dump( struct object *obj, int verbose ); @@ -69,7 +74,7 @@ static struct list *event_get_kernel_obj_list( struct object *obj );
static const struct sync_ops event_sync_ops = { - sizeof(struct sync), /* size */ + sizeof(struct event_sync), /* size */ sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ @@ -155,6 +160,15 @@ static const struct object_ops keyed_event_ops = keyed_event_destroy, /* destroy */ };
+static struct sync *create_event_sync( int manual_reset, int initial_state ) +{ + struct event_sync *event; + + event = (struct event_sync *)alloc_sync( &event_sync_ops ); + event->manual_reset = manual_reset; + event->signaled = initial_state; + return &event->sync; +}
struct event *create_event( struct object *root, const struct unicode_str *name, unsigned int attr, int manual_reset, int initial_state, @@ -167,10 +181,8 @@ struct event *create_event( struct object *root, const struct unicode_str *name, if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - event->sync = alloc_sync( &event_sync_ops ); + event->sync = create_event_sync( manual_reset, initial_state ); list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; } } return event; @@ -181,32 +193,32 @@ struct event *get_event_obj( struct process *process, obj_handle_t handle, unsig return (struct event *)get_handle_obj( process, handle, access, &event_ops ); }
-static void pulse_event( struct event *event ) +static void pulse_event( struct event_sync *event ) { event->signaled = 1; /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); + sync_wake_up( &event->sync, !event->manual_reset ); event->signaled = 0; }
void set_event( struct event *event ) { - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !event->manual_reset ); + signal_sync( &event->obj ); }
void reset_event( struct event *event ) { - event->signaled = 0; + reset_sync( &event->obj ); }
static void event_dump( struct object *obj, int verbose ) { struct event *event = (struct event *)obj; + struct event_sync *sync = (struct event_sync *)event->sync; assert( obj->ops == &event_ops ); + assert( event->sync->ops == &event_sync_ops ); fprintf( stderr, "Event manual=%d signaled=%d\n", - event->manual_reset, event->signaled ); + sync->manual_reset, sync->signaled ); }
static struct sync *event_get_sync( struct object *obj ) @@ -225,23 +237,23 @@ static void event_destroy( struct object *obj )
static int event_signaled( struct sync *sync, struct object *obj, struct wait_queue_entry *entry ) { - struct event *event = (struct event *)obj; - assert( obj->ops == &event_ops ); + struct event_sync *event = (struct event_sync *)sync; + assert( sync->ops == &event_sync_ops ); return event->signaled; }
static void event_satisfied( struct sync *sync, struct object *obj, struct wait_queue_entry *entry ) { - struct event *event = (struct event *)obj; - assert( obj->ops == &event_ops ); + struct event_sync *event = (struct event_sync *)sync; + assert( sync->ops == &event_sync_ops ); /* Reset if it's an auto-reset event */ if (!event->manual_reset) event->signaled = 0; }
static int event_signal( struct sync *sync, struct object *obj, int signal, unsigned int access ) { - struct event *event = (struct event *)obj; - assert( obj->ops == &event_ops ); + struct event_sync *event = (struct event_sync *)sync; + assert( sync->ops == &event_sync_ops );
if (signal == SIGNAL_SELECT && !(access & EVENT_MODIFY_STATE)) { @@ -249,8 +261,8 @@ static int event_signal( struct sync *sync, struct object *obj, int signal, unsi return 0; }
- assert( signal == SIGNAL_SELECT ); - set_event( event ); + /* wake up all waiters if manual reset, a single one otherwise */ + if ((event->signaled = !!signal)) sync_wake_up( &event->sync, !event->manual_reset ); return 1; }
@@ -365,14 +377,18 @@ DECL_HANDLER(open_event) /* do an event operation */ DECL_HANDLER(event_op) { + struct event_sync *sync; struct event *event;
if (!(event = get_event_obj( current->process, req->handle, EVENT_MODIFY_STATE ))) return; - reply->state = event->signaled; + sync = (struct event_sync *)event->sync; + assert( event->sync->ops == &event_sync_ops ); + + reply->state = sync->signaled; switch(req->op) { case PULSE_EVENT: - pulse_event( event ); + pulse_event( sync ); break; case SET_EVENT: set_event( event ); @@ -390,12 +406,15 @@ DECL_HANDLER(event_op) /* return details about the event */ DECL_HANDLER(query_event) { + struct event_sync *sync; struct event *event;
if (!(event = get_event_obj( current->process, req->handle, EVENT_QUERY_STATE ))) return; + sync = (struct event_sync *)event->sync; + assert( event->sync->ops == &event_sync_ops );
- reply->manual_reset = event->manual_reset; - reply->state = event->signaled; + reply->manual_reset = sync->manual_reset; + reply->state = sync->signaled;
release_object( event ); } diff --git a/server/object.c b/server/object.c index 1704bea1b98..a38078d09bd 100644 --- a/server/object.c +++ b/server/object.c @@ -675,6 +675,18 @@ int no_signal( struct sync *sync, struct object *obj, int signal, unsigned int a return 0; }
+int signal_sync( struct object *obj ) +{ + struct sync *sync = obj->ops->get_sync( obj ); + return sync->ops->signal( sync, obj, 1, 0 ); +} + +int reset_sync( struct object *obj ) +{ + struct sync *sync = obj->ops->get_sync( obj ); + return sync->ops->signal( sync, obj, 0, 0 ); +} + void sync_destroy( struct sync *obj ) { struct sync *sync = (struct sync *)obj; diff --git a/server/object.h b/server/object.h index e822106d86e..2571e0d54b7 100644 --- a/server/object.h +++ b/server/object.h @@ -192,6 +192,8 @@ extern struct object *find_object_index( const struct namespace *namespace, unsi extern int no_add_queue( struct sync *sync, struct object *obj, struct wait_queue_entry *entry ); extern void no_satisfied( struct sync *sync, struct object *obj, struct wait_queue_entry *entry ); extern int no_signal( struct sync *sync, struct object *obj, int signal, unsigned int access ); +extern int signal_sync( struct object *obj ); +extern int reset_sync( struct object *obj ); extern void sync_destroy( struct sync *obj ); extern struct fd *no_get_fd( struct object *obj ); extern struct sync *no_get_sync( struct object *obj );