Instead of https://gitlab.winehq.org/wine/wine/-/merge_requests/7815, for https://gitlab.winehq.org/wine/wine/-/merge_requests/7226, this only split the sync ops to a separate vtable and let objects delegate theirs to a separate object.
This starts using a event-like interface for most objects, leaving the decision regarding if/how to split sync themselves / integrate inproc syncs for later.
-- v9: server: Use an event sync for fd objects. server: Introduce a new event sync object. server: Redirect fd-based objects sync to the fd. server: Add an operation to retrieve an object sync. server: Move object grab/release out of (add|remove)_queue. server: Move signal access checks outside of the objects.
From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 10 ++-------- server/mutex.c | 9 ++------- server/object.c | 3 +-- server/object.h | 4 ++-- server/semaphore.c | 10 ++-------- server/thread.c | 25 ++++++++++++++++++++++++- 6 files changed, 33 insertions(+), 28 deletions(-)
diff --git a/server/event.c b/server/event.c index ad7c09acc99..894ebdf3ae3 100644 --- a/server/event.c +++ b/server/event.c @@ -61,7 +61,7 @@ struct event 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 int event_signal( struct object *obj ); static struct list *event_get_kernel_obj_list( struct object *obj );
static const struct object_ops event_ops = @@ -203,16 +203,10 @@ static void event_satisfied( struct object *obj, struct wait_queue_entry *entry if (!event->manual_reset) event->signaled = 0; }
-static int event_signal( struct object *obj, unsigned int access ) +static int event_signal( 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; } diff --git a/server/mutex.c b/server/mutex.c index af0efe72132..8dbbc466397 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -63,7 +63,7 @@ static void mutex_dump( struct object *obj, int verbose ); static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ); static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void mutex_destroy( struct object *obj ); -static int mutex_signal( struct object *obj, unsigned int access ); +static int mutex_signal( struct object *obj );
static const struct object_ops mutex_ops = { @@ -170,16 +170,11 @@ static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry mutex->abandoned = 0; }
-static int mutex_signal( struct object *obj, unsigned int access ) +static int mutex_signal( struct object *obj ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops );
- if (!(access & SYNCHRONIZE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } if (!mutex->count || (mutex->owner != current)) { set_error( STATUS_MUTANT_NOT_OWNED ); diff --git a/server/object.c b/server/object.c index cd368ef724a..8d8dcd6485e 100644 --- a/server/object.c +++ b/server/object.c @@ -627,9 +627,8 @@ 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 ) { - set_error( STATUS_OBJECT_TYPE_MISMATCH ); return 0; }
diff --git a/server/object.h b/server/object.h index 1058f9bfb0a..da858d61196 100644 --- a/server/object.h +++ b/server/object.h @@ -81,7 +81,7 @@ struct object_ops /* wait satisfied */ void (*satisfied)(struct object *,struct wait_queue_entry *); /* signal an object */ - int (*signal)(struct object *, unsigned int); + int (*signal)(struct object *); /* return an fd object that can be used to read/write from the object */ struct fd *(*get_fd)(struct object *); /* map access rights to the specific rights for this object */ @@ -168,7 +168,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 ); extern struct fd *no_get_fd( struct object *obj ); extern unsigned int default_map_access( struct object *obj, unsigned int access ); extern struct security_descriptor *default_get_sd( struct object *obj ); diff --git a/server/semaphore.c b/server/semaphore.c index 53b42a886df..727597f6c44 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -60,7 +60,7 @@ struct semaphore static void semaphore_dump( struct object *obj, int verbose ); static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ); static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry ); -static int semaphore_signal( struct object *obj, unsigned int access ); +static int semaphore_signal( struct object *obj );
static const struct object_ops semaphore_ops = { @@ -154,16 +154,10 @@ static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *en sem->count--; }
-static int semaphore_signal( struct object *obj, unsigned int access ) +static int semaphore_signal( struct object *obj ) { struct semaphore *sem = (struct semaphore *)obj; assert( obj->ops == &semaphore_ops ); - - if (!(access & SEMAPHORE_MODIFY_STATE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } return release_semaphore( sem, 1, NULL ); }
diff --git a/server/thread.c b/server/thread.c index ffc016bfa56..63c0fdb905b 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1184,6 +1184,27 @@ static void thread_timeout( void *ptr ) wake_thread( thread ); }
+/* check if an event flag, a semaphore or a mutex can be signaled */ +static unsigned int check_signal_object( struct object *obj, unsigned int access ) +{ + if (obj->ops->type == &event_type) + { + if (access & EVENT_MODIFY_STATE) return STATUS_SUCCESS; + return STATUS_ACCESS_DENIED; + } + if (obj->ops->type == &semaphore_type) + { + if (access & SEMAPHORE_MODIFY_STATE) return STATUS_SUCCESS; + return STATUS_ACCESS_DENIED; + } + if (obj->ops->type == &mutex_type) + { + if (access & SYNCHRONIZE) return STATUS_SUCCESS; + return STATUS_ACCESS_DENIED; + } + return STATUS_OBJECT_TYPE_MISMATCH; +} + /* try signaling an event flag, a semaphore or a mutex */ static int signal_object( obj_handle_t handle ) { @@ -1193,7 +1214,9 @@ 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 )); + unsigned int status, access = get_handle_access( current->process, handle ); + if ((status = check_signal_object( obj, access ))) set_error( status ); + else ret = obj->ops->signal( obj ); release_object( obj ); } return ret;
From: Rémi Bernon rbernon@codeweavers.com
--- server/thread.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/server/thread.c b/server/thread.c index 63c0fdb905b..e138c5eb5e8 100644 --- a/server/thread.c +++ b/server/thread.c @@ -922,8 +922,6 @@ int resume_thread( struct thread *thread ) /* add a thread to an object wait queue; return 1 if OK, 0 on error */ int add_queue( struct object *obj, struct wait_queue_entry *entry ) { - grab_object( obj ); - entry->obj = obj; list_add_tail( &obj->wait_queue, &entry->entry ); return 1; } @@ -932,7 +930,6 @@ int add_queue( struct object *obj, struct wait_queue_entry *entry ) void remove_queue( struct object *obj, struct wait_queue_entry *entry ) { list_remove( &entry->entry ); - release_object( obj ); }
struct thread *get_wait_queue_thread( struct wait_queue_entry *entry ) @@ -987,7 +984,11 @@ static unsigned int end_wait( struct thread *thread, unsigned int status ) if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0; } for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) + { entry->obj->ops->remove_queue( entry->obj, entry ); + release_object( entry->obj ); + entry->obj = NULL; + } if (wait->user) remove_timeout_user( wait->user ); free( wait ); return status; @@ -1024,6 +1025,7 @@ static int wait_on( const union select_op *select_op, unsigned int count, struct return 0; }
+ grab_object( (entry->obj = obj) ); if (obj == (struct object *)current->queue) idle = 1; }
From: Rémi Bernon rbernon@codeweavers.com
--- server/async.c | 2 ++ server/atom.c | 1 + server/change.c | 1 + server/clipboard.c | 1 + server/completion.c | 2 ++ server/console.c | 7 ++++++ server/debugger.c | 2 ++ server/device.c | 4 ++++ server/directory.c | 2 ++ server/event.c | 2 ++ server/fd.c | 4 ++++ server/file.c | 1 + server/handle.c | 1 + server/hook.c | 1 + server/mailslot.c | 4 ++++ server/mapping.c | 3 +++ server/mutex.c | 1 + server/named_pipe.c | 6 +++++ server/object.c | 7 ++++++ server/object.h | 4 ++++ server/process.c | 3 +++ server/queue.c | 2 ++ server/registry.c | 1 + server/request.c | 1 + server/semaphore.c | 1 + server/serial.c | 1 + server/signal.c | 1 + server/sock.c | 3 +++ server/symlink.c | 1 + server/thread.c | 55 +++++++++++++++++++++++++++++++++++++++------ server/timer.c | 1 + server/token.c | 1 + server/window.c | 1 + server/winstation.c | 2 ++ 34 files changed, 123 insertions(+), 7 deletions(-)
diff --git a/server/async.c b/server/async.c index d2d929c9709..1ed241dcb65 100644 --- a/server/async.c +++ b/server/async.c @@ -81,6 +81,7 @@ static const struct object_ops async_ops = async_satisfied, /* satisfied */ no_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 */ @@ -701,6 +702,7 @@ static const struct object_ops iosb_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/atom.c b/server/atom.c index ff0799f5880..d93f1568588 100644 --- a/server/atom.c +++ b/server/atom.c @@ -82,6 +82,7 @@ static const struct object_ops atom_table_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/change.c b/server/change.c index f42ce066340..a6f367b8075 100644 --- a/server/change.c +++ b/server/change.c @@ -115,6 +115,7 @@ static const struct object_ops dir_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ dir_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ dir_get_sd, /* get_sd */ dir_set_sd, /* set_sd */ diff --git a/server/clipboard.c b/server/clipboard.c index 91f159bc7c9..59a50354b48 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -79,6 +79,7 @@ static const struct object_ops clipboard_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/completion.c b/server/completion.c index 99680ae0680..fd623b36d5a 100644 --- a/server/completion.c +++ b/server/completion.c @@ -95,6 +95,7 @@ static const struct object_ops completion_wait_ops = completion_wait_satisfied, /* satisfied */ no_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 */ @@ -169,6 +170,7 @@ static const struct object_ops completion_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/console.c b/server/console.c index de6f4e73e31..aa7ec863605 100644 --- a/server/console.c +++ b/server/console.c @@ -87,6 +87,7 @@ static const struct object_ops console_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ console_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -164,6 +165,7 @@ static const struct object_ops console_server_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ console_server_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -233,6 +235,7 @@ static const struct object_ops screen_buffer_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ screen_buffer_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -282,6 +285,7 @@ static const struct object_ops console_device_ops = no_satisfied, /* satisfied */ no_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 */ @@ -321,6 +325,7 @@ static const struct object_ops console_input_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ console_input_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -380,6 +385,7 @@ static const struct object_ops console_output_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ console_output_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -438,6 +444,7 @@ static const struct object_ops console_connection_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ console_connection_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/debugger.c b/server/debugger.c index 39a740e07e5..43d01fbf246 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -89,6 +89,7 @@ static const struct object_ops debug_event_ops = no_satisfied, /* satisfied */ no_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 */ @@ -117,6 +118,7 @@ static const struct object_ops debug_obj_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/device.c b/server/device.c index 1f93cca437d..7dc5e868d88 100644 --- a/server/device.c +++ b/server/device.c @@ -69,6 +69,7 @@ static const struct object_ops irp_call_ops = NULL, /* satisfied */ no_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 */ @@ -109,6 +110,7 @@ static const struct object_ops device_manager_ops = no_satisfied, /* satisfied */ no_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 */ @@ -166,6 +168,7 @@ static const struct object_ops device_ops = no_satisfied, /* satisfied */ no_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 */ @@ -218,6 +221,7 @@ static const struct object_ops device_file_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ device_file_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/directory.c b/server/directory.c index fd689c561bc..c8dc3d1901d 100644 --- a/server/directory.c +++ b/server/directory.c @@ -72,6 +72,7 @@ static const struct object_ops object_type_ops = NULL, /* satisfied */ no_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 */ @@ -122,6 +123,7 @@ static const struct object_ops directory_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/event.c b/server/event.c index 894ebdf3ae3..7bd1ed21e06 100644 --- a/server/event.c +++ b/server/event.c @@ -75,6 +75,7 @@ static const struct object_ops event_ops = event_satisfied, /* satisfied */ event_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 */ @@ -122,6 +123,7 @@ static const struct object_ops keyed_event_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/fd.c b/server/fd.c index bb0e90d99d0..f6d232edd82 100644 --- a/server/fd.c +++ b/server/fd.c @@ -170,6 +170,7 @@ static const struct object_ops fd_ops = NULL, /* satisfied */ no_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 */ @@ -211,6 +212,7 @@ static const struct object_ops device_ops = NULL, /* satisfied */ no_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 */ @@ -251,6 +253,7 @@ static const struct object_ops inode_ops = NULL, /* satisfied */ no_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 */ @@ -293,6 +296,7 @@ static const struct object_ops file_lock_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/file.c b/server/file.c index 8f6566a0077..4b94a75823a 100644 --- a/server/file.c +++ b/server/file.c @@ -97,6 +97,7 @@ static const struct object_ops file_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ file_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ file_get_sd, /* get_sd */ file_set_sd, /* set_sd */ diff --git a/server/handle.c b/server/handle.c index 8968df73647..141298ba4b7 100644 --- a/server/handle.c +++ b/server/handle.c @@ -129,6 +129,7 @@ static const struct object_ops handle_table_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/hook.c b/server/hook.c index ffe7206369e..88566253945 100644 --- a/server/hook.c +++ b/server/hook.c @@ -84,6 +84,7 @@ static const struct object_ops hook_table_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/mailslot.c b/server/mailslot.c index c54281c2101..f98fc4c0075 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -84,6 +84,7 @@ static const struct object_ops mailslot_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ mailslot_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ mailslot_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -145,6 +146,7 @@ static const struct object_ops mail_writer_ops = NULL, /* satisfied */ no_signal, /* signal */ mail_writer_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ mail_writer_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -210,6 +212,7 @@ static const struct object_ops mailslot_device_ops = no_satisfied, /* satisfied */ no_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 */ @@ -240,6 +243,7 @@ static const struct object_ops mailslot_device_file_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ mailslot_device_file_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/mapping.c b/server/mapping.c index 247b28cf6f5..7ece32b0231 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -70,6 +70,7 @@ static const struct object_ops ranges_ops = NULL, /* satisfied */ no_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 */ @@ -106,6 +107,7 @@ static const struct object_ops shared_map_ops = NULL, /* satisfied */ no_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 */ @@ -179,6 +181,7 @@ static const struct object_ops mapping_ops = NULL, /* satisfied */ no_signal, /* signal */ mapping_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/mutex.c b/server/mutex.c index 8dbbc466397..01de17864e1 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -76,6 +76,7 @@ static const struct object_ops mutex_ops = mutex_satisfied, /* satisfied */ mutex_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 */ diff --git a/server/named_pipe.c b/server/named_pipe.c index 6e4ae371a1b..b167c9b7083 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -122,6 +122,7 @@ static const struct object_ops named_pipe_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ named_pipe_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -170,6 +171,7 @@ static const struct object_ops pipe_server_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ pipe_end_get_sd, /* get_sd */ pipe_end_set_sd, /* set_sd */ @@ -214,6 +216,7 @@ static const struct object_ops pipe_client_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ pipe_end_get_sd, /* get_sd */ pipe_end_set_sd, /* set_sd */ @@ -261,6 +264,7 @@ static const struct object_ops named_pipe_device_ops = no_satisfied, /* satisfied */ no_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 */ @@ -292,6 +296,7 @@ static const struct object_ops named_pipe_device_file_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ named_pipe_device_file_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -342,6 +347,7 @@ static const struct object_ops named_pipe_dir_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ named_pipe_dir_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/object.c b/server/object.c index 8d8dcd6485e..3743e2c9609 100644 --- a/server/object.c +++ b/server/object.c @@ -111,6 +111,7 @@ static const struct object_ops apc_reserve_ops = no_satisfied, /* satisfied */ no_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 */ @@ -135,6 +136,7 @@ static const struct object_ops completion_reserve_ops = no_satisfied, /* satisfied */ no_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 */ @@ -638,6 +640,11 @@ struct fd *no_get_fd( struct object *obj ) return NULL; }
+struct object *default_get_sync( struct object *obj ) +{ + return grab_object( obj ); +} + unsigned int default_map_access( struct object *obj, unsigned int access ) { return map_access( access, &obj->ops->type->mapping ); diff --git a/server/object.h b/server/object.h index da858d61196..7fdc7e56f5c 100644 --- a/server/object.h +++ b/server/object.h @@ -84,6 +84,8 @@ struct object_ops int (*signal)(struct object *); /* 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 */ + struct object *(*get_sync)(struct object *); /* map access rights to the specific rights for this object */ unsigned int (*map_access)(struct object *, unsigned int); /* returns the security descriptor of the object */ @@ -170,6 +172,8 @@ 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 ); 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 ); } extern unsigned int default_map_access( struct object *obj, unsigned int access ); extern struct security_descriptor *default_get_sd( struct object *obj ); extern int default_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info ); diff --git a/server/process.c b/server/process.c index b161e3394ba..124f294d543 100644 --- a/server/process.c +++ b/server/process.c @@ -108,6 +108,7 @@ static const struct object_ops process_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ process_map_access, /* map_access */ process_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -159,6 +160,7 @@ static const struct object_ops startup_info_ops = no_satisfied, /* satisfied */ no_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 */ @@ -220,6 +222,7 @@ static const struct object_ops job_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/queue.c b/server/queue.c index b4b6069f927..bc0d7820d4a 100644 --- a/server/queue.c +++ b/server/queue.c @@ -168,6 +168,7 @@ static const struct object_ops msg_queue_ops = msg_queue_satisfied, /* satisfied */ no_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 */ @@ -205,6 +206,7 @@ static const struct object_ops thread_input_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/registry.c b/server/registry.c index c60c737feff..dc03a564736 100644 --- a/server/registry.c +++ b/server/registry.c @@ -183,6 +183,7 @@ static const struct object_ops key_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ key_map_access, /* map_access */ key_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/request.c b/server/request.c index 2254315b79e..835ea30cec3 100644 --- a/server/request.c +++ b/server/request.c @@ -92,6 +92,7 @@ static const struct object_ops master_socket_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/semaphore.c b/server/semaphore.c index 727597f6c44..8123befcccf 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -73,6 +73,7 @@ static const struct object_ops semaphore_ops = semaphore_satisfied, /* satisfied */ semaphore_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 */ diff --git a/server/serial.c b/server/serial.c index 209f2e9174e..fc0939e402b 100644 --- a/server/serial.c +++ b/server/serial.c @@ -94,6 +94,7 @@ static const struct object_ops serial_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ serial_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/signal.c b/server/signal.c index 19b76d44c16..078951af6e4 100644 --- a/server/signal.c +++ b/server/signal.c @@ -65,6 +65,7 @@ static const struct object_ops handler_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/sock.c b/server/sock.c index e064f867ff4..0dd0f308337 100644 --- a/server/sock.c +++ b/server/sock.c @@ -489,6 +489,7 @@ static const struct object_ops sock_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ sock_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -3698,6 +3699,7 @@ static const struct object_ops ifchange_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ ifchange_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -3919,6 +3921,7 @@ static const struct object_ops socket_device_ops = no_satisfied, /* satisfied */ no_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 */ diff --git a/server/symlink.c b/server/symlink.c index 74b60162c01..b597b38ec1a 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -74,6 +74,7 @@ static const struct object_ops symlink_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/thread.c b/server/thread.c index e138c5eb5e8..93440cb8ce5 100644 --- a/server/thread.c +++ b/server/thread.c @@ -109,6 +109,7 @@ static const struct object_ops thread_apc_ops = no_satisfied, /* satisfied */ no_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 */ @@ -151,6 +152,7 @@ static const struct object_ops context_ops = no_satisfied, /* satisfied */ no_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 */ @@ -200,6 +202,7 @@ static const struct object_ops thread_ops = no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ thread_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -957,6 +960,44 @@ void set_wait_status( struct wait_queue_entry *entry, int status ) entry->wait->status = status; }
+static void object_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ) +{ + struct object *sync = get_obj_sync( obj ); + sync->ops->satisfied( sync, entry ); + release_object( sync ); +} + +static void object_sync_remove_queue( struct object *obj, struct wait_queue_entry *entry ) +{ + struct object *sync = get_obj_sync( obj ); + sync->ops->remove_queue( sync, entry ); + release_object( sync ); +} + +static int object_sync_add_queue( struct object *obj, struct wait_queue_entry *entry ) +{ + struct object *sync = get_obj_sync( obj ); + int ret = sync->ops->add_queue( sync, entry ); + release_object( sync ); + return ret; +} + +static int object_sync_signaled( struct object *obj, struct wait_queue_entry *entry ) +{ + struct object *sync = get_obj_sync( obj ); + int ret = sync->ops->signaled( sync, entry ); + release_object( sync ); + return ret; +} + +static int object_sync_signal( struct object *obj ) +{ + struct object *sync = get_obj_sync( obj ); + int ret = sync->ops->signal( sync ); + release_object( sync ); + return ret; +} + /* finish waiting */ static unsigned int end_wait( struct thread *thread, unsigned int status ) { @@ -973,19 +1014,19 @@ static unsigned int end_wait( struct thread *thread, unsigned int status ) if (wait->select == SELECT_WAIT_ALL) { for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) - entry->obj->ops->satisfied( entry->obj, entry ); + object_sync_satisfied( entry->obj, entry ); } else { entry = wait->queues + status; - entry->obj->ops->satisfied( entry->obj, entry ); + object_sync_satisfied( entry->obj, entry ); } status = wait->status; if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0; } for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) { - entry->obj->ops->remove_queue( entry->obj, entry ); + object_sync_remove_queue( entry->obj, entry ); release_object( entry->obj ); entry->obj = NULL; } @@ -1018,7 +1059,7 @@ static int wait_on( const union select_op *select_op, unsigned int count, struct { struct object *obj = objects[i]; entry->wait = wait; - if (!obj->ops->add_queue( obj, entry )) + if (!object_sync_add_queue( obj, entry )) { wait->count = i; end_wait( current, get_error() ); @@ -1073,13 +1114,13 @@ static int check_wait( struct thread *thread ) /* Note: we must check them all anyway, as some objects may * want to do something when signaled, even if others are not */ for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) - not_ok |= !entry->obj->ops->signaled( entry->obj, entry ); + not_ok |= !object_sync_signaled( entry->obj, entry ); if (!not_ok) return STATUS_WAIT_0; } else { for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) - if (entry->obj->ops->signaled( entry->obj, entry )) return i; + if (object_sync_signaled( entry->obj, entry )) return i; }
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC; @@ -1218,7 +1259,7 @@ static int signal_object( obj_handle_t handle ) { unsigned int status, access = get_handle_access( current->process, handle ); if ((status = check_signal_object( obj, access ))) set_error( status ); - else ret = obj->ops->signal( obj ); + else ret = object_sync_signal( obj ); release_object( obj ); } return ret; diff --git a/server/timer.c b/server/timer.c index b0b6ec81535..4ad4ca19072 100644 --- a/server/timer.c +++ b/server/timer.c @@ -79,6 +79,7 @@ static const struct object_ops timer_ops = timer_satisfied, /* satisfied */ no_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 */ diff --git a/server/token.c b/server/token.c index 7e20c670a16..f51778e0e19 100644 --- a/server/token.c +++ b/server/token.c @@ -148,6 +148,7 @@ static const struct object_ops token_ops = NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ token_set_sd, /* set_sd */ diff --git a/server/window.c b/server/window.c index f7f9d5e517f..ffec6a907fe 100644 --- a/server/window.c +++ b/server/window.c @@ -110,6 +110,7 @@ static const struct object_ops window_ops = NULL, /* satisfied */ no_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 */ diff --git a/server/winstation.c b/server/winstation.c index b3746090ccf..bb5596f9a03 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -79,6 +79,7 @@ static const struct object_ops winstation_ops = NULL, /* satisfied */ no_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 */ @@ -119,6 +120,7 @@ static const struct object_ops desktop_ops = NULL, /* satisfied */ no_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 */
From: Rémi Bernon rbernon@codeweavers.com
--- server/change.c | 12 ++++++------ server/device.c | 12 ++++++------ server/fd.c | 26 +++++++++++++++--------- server/file.c | 12 ++++++------ server/file.h | 2 +- server/mailslot.c | 24 +++++++++++------------ server/named_pipe.c | 48 ++++++++++++++++++++++----------------------- server/serial.c | 12 ++++++------ server/sock.c | 12 ++++++------ 9 files changed, 84 insertions(+), 76 deletions(-)
diff --git a/server/change.c b/server/change.c index a6f367b8075..1f451be64f0 100644 --- a/server/change.c +++ b/server/change.c @@ -109,13 +109,13 @@ static const struct object_ops dir_ops = sizeof(struct dir), /* size */ &file_type, /* type */ dir_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ dir_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ dir_get_sd, /* get_sd */ dir_set_sd, /* set_sd */ diff --git a/server/device.c b/server/device.c index 7dc5e868d88..ba306af7bb1 100644 --- a/server/device.c +++ b/server/device.c @@ -215,13 +215,13 @@ static const struct object_ops device_file_ops = sizeof(struct device_file), /* size */ &file_type, /* type */ device_file_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ device_file_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/fd.c b/server/fd.c index f6d232edd82..94fa3e2dae7 100644 --- a/server/fd.c +++ b/server/fd.c @@ -157,6 +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 void fd_destroy( struct object *obj );
static const struct object_ops fd_ops = @@ -164,10 +165,10 @@ static const struct object_ops fd_ops = sizeof(struct fd), /* size */ &no_type, /* type */ fd_dump, /* dump */ - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ - NULL, /* satisfied */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + fd_signaled, /* signaled */ + no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ @@ -2156,7 +2157,7 @@ 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->user, 0 ); + if (signaled) wake_up( &fd->obj, 0 ); }
/* check if events are pending and if yes return which one(s) */ @@ -2173,13 +2174,20 @@ int check_fd_events( struct fd *fd, int events ) return pfd.revents; }
-/* default signaled() routine for objects that poll() on an fd */ -int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ) +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 ) { struct fd *fd = get_obj_fd( obj ); - int ret = fd->signaled; + struct object *sync = get_obj_sync( &fd->obj ); release_object( fd ); - return ret; + return sync; }
int default_fd_get_poll_events( struct fd *fd ) diff --git a/server/file.c b/server/file.c index 4b94a75823a..b3840381d06 100644 --- a/server/file.c +++ b/server/file.c @@ -91,13 +91,13 @@ static const struct object_ops file_ops = sizeof(struct file), /* size */ &file_type, /* type */ file_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ file_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ file_get_sd, /* get_sd */ file_set_sd, /* set_sd */ diff --git a/server/file.h b/server/file.h index 59b73c0245c..f282e66835a 100644 --- a/server/file.h +++ b/server/file.h @@ -108,7 +108,7 @@ extern void set_fd_signaled( struct fd *fd, int signaled ); extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(free) __WINE_MALLOC; extern void get_nt_name( struct fd *fd, struct unicode_str *name );
-extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); +extern struct object *default_fd_get_sync( struct object *obj ); extern int default_fd_get_poll_events( struct fd *fd ); extern void default_poll_event( struct fd *fd, int event ); extern void fd_cancel_async( struct fd *fd, struct async *async ); diff --git a/server/mailslot.c b/server/mailslot.c index f98fc4c0075..cbeb6363060 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -78,13 +78,13 @@ static const struct object_ops mailslot_ops = sizeof(struct mailslot), /* size */ &file_type, /* type */ mailslot_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ mailslot_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ mailslot_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -237,13 +237,13 @@ static const struct object_ops mailslot_device_file_ops = sizeof(struct mailslot_device_file), /* size */ &file_type, /* type */ mailslot_device_file_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ mailslot_device_file_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/named_pipe.c b/server/named_pipe.c index b167c9b7083..af0ab2ce7ae 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -165,13 +165,13 @@ static const struct object_ops pipe_server_ops = sizeof(struct pipe_server), /* size */ &file_type, /* type */ pipe_server_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ pipe_end_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ pipe_end_get_sd, /* get_sd */ pipe_end_set_sd, /* set_sd */ @@ -210,13 +210,13 @@ static const struct object_ops pipe_client_ops = sizeof(struct pipe_end), /* size */ &file_type, /* type */ pipe_client_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ pipe_end_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ pipe_end_get_sd, /* get_sd */ pipe_end_set_sd, /* set_sd */ @@ -290,13 +290,13 @@ static const struct object_ops named_pipe_device_file_ops = sizeof(struct named_pipe_device_file), /* size */ &file_type, /* type */ named_pipe_device_file_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ named_pipe_device_file_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -341,13 +341,13 @@ static const struct object_ops named_pipe_dir_ops = sizeof(struct named_pipe_device_file), /* size */ &file_type, /* type */ named_pipe_dir_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ named_pipe_dir_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/serial.c b/server/serial.c index fc0939e402b..40150080ce1 100644 --- a/server/serial.c +++ b/server/serial.c @@ -88,13 +88,13 @@ static const struct object_ops serial_ops = sizeof(struct serial), /* size */ &file_type, /* type */ serial_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ serial_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ diff --git a/server/sock.c b/server/sock.c index 0dd0f308337..b9b3743e030 100644 --- a/server/sock.c +++ b/server/sock.c @@ -483,13 +483,13 @@ static const struct object_ops sock_ops = sizeof(struct sock), /* size */ &file_type, /* type */ sock_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - default_fd_signaled, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* signal */ sock_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */
From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 183 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 137 insertions(+), 46 deletions(-)
diff --git a/server/event.c b/server/event.c index 7bd1ed21e06..d5a2aedb9a6 100644 --- a/server/event.c +++ b/server/event.c @@ -50,32 +50,127 @@ 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 ); + +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 ) +{ + struct event_sync *event = (struct event_sync *)obj; + assert( obj->ops == &event_sync_ops ); + 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 ); +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 +181,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 +244,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,61 +262,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 ) +static void event_destroy( struct object *obj ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops ); - 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, @@ -309,14 +390,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 ); @@ -334,12 +422,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 ); }
From: Rémi Bernon rbernon@codeweavers.com
--- server/event.c | 6 +++--- server/fd.c | 56 ++++++++++++++++++++++++++++--------------------- server/object.h | 4 ++++ 3 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/server/event.c b/server/event.c index d5a2aedb9a6..aba0fd4d2b3 100644 --- a/server/event.c +++ b/server/event.c @@ -87,7 +87,7 @@ 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 ) { struct event_sync *event;
@@ -98,7 +98,7 @@ static struct object *create_event_sync( int manual, int signaled ) 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 +108,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 ); diff --git a/server/fd.c b/server/fd.c index 94fa3e2dae7..faf617cabad 100644 --- a/server/fd.c +++ b/server/fd.c @@ -129,6 +129,7 @@ struct fd { struct object obj; /* object header */ const struct fd_ops *fd_ops; /* file descriptor operations */ + struct object *sync; /* sync object for wait/signal */ struct inode *inode; /* inode that this fd belongs to */ struct list inode_entry; /* entry in inode fd list */ struct closed_fd *closed; /* structure to store the unix fd at destroy time */ @@ -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 */ @@ -1689,6 +1696,7 @@ static struct fd *alloc_fd_object(void) if (!fd) return NULL;
fd->fd_ops = NULL; + fd->sync = NULL; fd->user = NULL; fd->inode = NULL; fd->closed = NULL; @@ -1702,7 +1710,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,12 +1720,14 @@ 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) - { - release_object( fd ); - return NULL; - } + if (!(fd->sync = create_event_sync( 1, 1 ))) goto error; + if ((fd->poll_index = add_poll_user( fd )) == -1) goto error; + return fd; + +error: + release_object( fd ); + return NULL; }
/* allocate a pseudo fd object, for objects that need to behave like files but don't have a unix fd */ @@ -1729,6 +1738,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use if (!fd) return NULL;
fd->fd_ops = fd_user_ops; + fd->sync = NULL; fd->user = user; fd->inode = NULL; fd->closed = NULL; @@ -1742,7 +1752,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 +1762,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 ))) + { + release_object( fd ); + return NULL; + } return fd; }
@@ -2156,8 +2171,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 +2189,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 7fdc7e56f5c..86c0c954af5 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 ); +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 );
Thanks! I could think of multiple ways to do this:
1) Add a input parameter to `get_sync` to indicate that the sync is retrieved for client-side signaling, and check whether this is allowed in every get_sync implementations. This however isn't future proof for inproc syncs, as they will be retrieved once and cached on the client-side, we need a way to inspect what is allowed or not.
2) Add an output parameter to `get_sync`, to retrieve whether the sync is internal or not, or to retrieve some allowed `access` mask, then use that when `select` tries to signal the object. Having an `internal` flag seemed a bit too specific, while an `access` parameter still didn't allow to check for access rights because of different object types rights / or check for object type itself and mismach easily.
3) Move the access checks out of the individual object signal methods, and implement the checks directly in `signal_object`, inspecting the object types and mapping access directly. As `signal_object` already lists the expected object types in its comment it seems alright to check the object types here.
I went with 3) and moved the signal checks out of the individual objects and into a specific `check_signal_object` helper. Later on, with inproc syncs, we can use that same helper when syncs are retrieved to be cached, and check the status to tell what the client will be allowed to do with the objects.
Is this still not right? For ntsync we will need a way to introspect the object capabilities anyway, I don't see many more options there. Would an output parameter to `get_sync` considered better?