From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 195 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 143 insertions(+), 52 deletions(-)
diff --git a/server/event.c b/server/event.c index 8d4a78d988a..b5dff9b5b49 100644 --- a/server/event.c +++ b/server/event.c @@ -50,32 +50,133 @@ struct type_descr event_type = }, };
+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 */ +}; + +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 const struct object_ops event_sync_ops = +{ + sizeof(struct event_sync), /* size */ + &no_type, /* type */ + event_sync_dump, /* dump */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + event_sync_signaled, /* signaled */ + event_sync_satisfied, /* satisfied */ + event_sync_signal, /* signal */ + no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ + default_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + no_destroy /* destroy */ +}; + +static struct object *create_event_sync( int manual, int signaled ) +{ + struct event_sync *event; + + if (!(event = alloc_object( &event_sync_ops ))) return NULL; + event->manual = manual; + event->signaled = signaled; + + return &event->obj; +} + +static void signal_sync( struct object *obj ) +{ + struct event_sync *event = (struct event_sync *)obj; + assert( obj->ops == &event_sync_ops ); + + event->signaled = 1; + /* wake up all waiters if manual reset, a single one otherwise */ + wake_up( &event->obj, !event->manual ); +} + +static void reset_sync( struct object *obj ) +{ + struct event_sync *event = (struct event_sync *)obj; + assert( obj->ops == &event_sync_ops ); + + event->signaled = 0; +} + +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 ); +} + +static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry ) +{ + struct event_sync *event = (struct event_sync *)obj; + assert( obj->ops == &event_sync_ops ); + return event->signaled; +} + +static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ) +{ + 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) event->signaled = 0; +} + +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 (!(access & EVENT_MODIFY_STATE)) + { + set_error( STATUS_ACCESS_DENIED ); + return 0; + } + signal_sync( &event->obj ); + return 1; +} + struct event { struct object obj; /* object header */ + struct object *sync; /* event sync object */ 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 ); -static int event_signaled( struct object *obj, struct wait_queue_entry *entry ); -static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ); -static int event_signal( struct object *obj, unsigned int access); +static struct object *event_get_sync( struct object *obj ); static struct list *event_get_kernel_obj_list( struct object *obj ); +static void event_destroy( struct object *obj );
static const struct object_ops event_ops = { sizeof(struct event), /* size */ &event_type, /* type */ event_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - event_signaled, /* signaled */ - event_satisfied, /* satisfied */ - event_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + event_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -86,7 +187,7 @@ static const struct object_ops event_ops = no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + event_destroy, /* destroy */ };
@@ -149,9 +250,14 @@ 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 = NULL; list_init( &event->kernel_object ); - event->manual_reset = manual_reset; - event->signaled = initial_state; + + if (!(event->sync = create_event_sync( manual_reset, initial_state ))) + { + release_object( event ); + return NULL; + } } } return event; @@ -162,67 +268,42 @@ 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 ) -{ - event->signaled = 1; - /* wake up all waiters if manual reset, a single one otherwise */ - wake_up( &event->obj, !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->sync ); }
void reset_event( struct event *event ) { - event->signaled = 0; + reset_sync( event->sync ); }
static void event_dump( struct object *obj, int verbose ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops ); - fprintf( stderr, "Event manual=%d signaled=%d\n", - event->manual_reset, event->signaled ); + event->sync->ops->dump( event->sync, verbose ); }
-static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *event_get_sync( struct object *obj ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops ); - return event->signaled; + return grab_object( event->sync ); }
-static void event_satisfied( struct object *obj, struct wait_queue_entry *entry ) +static struct list *event_get_kernel_obj_list( struct object *obj ) { struct event *event = (struct event *)obj; - assert( obj->ops == &event_ops ); - /* Reset if it's an auto-reset event */ - if (!event->manual_reset) event->signaled = 0; + return &event->kernel_object; }
-static int event_signal( struct object *obj, unsigned int access ) +static void event_destroy( struct object *obj ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops );
- if (!(access & EVENT_MODIFY_STATE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } - set_event( event ); - return 1; -} - -static struct list *event_get_kernel_obj_list( struct object *obj ) -{ - struct event *event = (struct event *)obj; - return &event->kernel_object; + if (event->sync) release_object( event->sync ); }
struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name, @@ -315,14 +396,21 @@ 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 ); + sync->signaled = 1; + /* wake up all waiters if manual reset, a single one otherwise */ + wake_up( &sync->obj, !sync->manual ); + sync->signaled = 0; break; case SET_EVENT: set_event( event ); @@ -340,12 +428,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; + reply->state = sync->signaled;
release_object( event ); }