From: Rémi Bernon rbernon@codeweavers.com
--- server/async.c | 8 ++++-- server/completion.c | 17 +++++++++--- server/console.c | 40 +++++++++++++++++++------- server/debugger.c | 17 +++++++++--- server/device.c | 9 ++++-- server/event.c | 38 ++++++++++++++++++++----- server/fd.c | 29 ++++++++++++++----- server/file.h | 2 +- server/mutex.c | 17 ++++++++---- server/object.c | 68 ++++++++++++++++++++++++++++++++++++++++++--- server/object.h | 14 ++++++++-- server/process.c | 24 ++++++++++++---- server/process.h | 1 + server/queue.c | 22 ++++++++++----- server/semaphore.c | 17 ++++++++++-- server/thread.c | 47 ++++++++++++++++++------------- server/thread.h | 1 + server/timer.c | 8 ++++-- 18 files changed, 294 insertions(+), 85 deletions(-)
diff --git a/server/async.c b/server/async.c index 50c4bcf58c2..399fb530789 100644 --- a/server/async.c +++ b/server/async.c @@ -37,6 +37,7 @@ struct async { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct thread *thread; /* owning thread */ struct list queue_entry; /* entry in async queue list */ struct list process_entry; /* entry in process list */ @@ -73,6 +74,8 @@ static void async_destroy( struct object *obj );
static const struct sync_ops async_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ async_signaled, /* signaled */ @@ -116,7 +119,7 @@ static struct sync *async_get_sync( struct object *obj ) { struct async *async = (struct async *)obj; assert( obj->ops == &async_ops ); - return &async->obj.sync; + return async->sync; }
static int async_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -172,6 +175,7 @@ static void async_destroy( struct object *obj ) if (async->event) release_object( async->event ); if (async->iosb) release_object( async->iosb ); release_object( async->thread ); + release_sync( async->sync ); }
/* notifies client thread of new status of its async request */ @@ -274,7 +278,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const struct a if (event) release_object( event ); return NULL; } - async->obj.sync.ops = &async_sync_ops; + async->sync = alloc_sync( &async_sync_ops ); async->thread = (struct thread *)grab_object( thread ); async->event = event; async->data = *data; diff --git a/server/completion.c b/server/completion.c index 052112866a4..cf3588c4267 100644 --- a/server/completion.c +++ b/server/completion.c @@ -63,6 +63,7 @@ struct comp_msg struct completion_wait { struct object obj; + struct sync *sync; obj_handle_t handle; struct completion *completion; struct thread *thread; @@ -73,6 +74,7 @@ struct completion_wait struct completion { struct object obj; + struct sync *sync; struct list queue; struct list wait_queue; unsigned int depth; @@ -87,6 +89,8 @@ static void completion_wait_destroy( struct object * );
static const struct sync_ops completion_wait_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_wait_signaled, /* signaled */ @@ -118,6 +122,7 @@ static void completion_wait_destroy( struct object *obj ) { struct completion_wait *wait = (struct completion_wait *)obj; free( wait->msg ); + release_sync( wait->sync ); }
static void completion_wait_dump( struct object *obj, int verbose ) @@ -132,7 +137,7 @@ static struct sync *completion_wait_get_sync( struct object *obj ) { struct completion_wait *wait = (struct completion_wait *)obj; assert( obj->ops == &completion_wait_ops ); - return &wait->obj.sync; + return wait->sync; }
static int completion_wait_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -173,6 +178,8 @@ static void completion_destroy( struct object * );
static const struct sync_ops completion_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ completion_signaled, /* signaled */ @@ -209,6 +216,8 @@ static void completion_destroy( struct object *obj) { free( tmp ); } + + release_sync( completion->sync ); }
static void completion_dump( struct object *obj, int verbose ) @@ -223,7 +232,7 @@ static struct sync *completion_get_sync( struct object *obj ) { struct completion *completion = (struct completion *)obj; assert( obj->ops == &completion_ops ); - return &completion->obj.sync; + return completion->sync; }
static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -275,7 +284,7 @@ static struct completion_wait *create_completion_wait( struct thread *thread ) struct completion_wait *wait;
if (!(wait = alloc_object( &completion_wait_ops ))) return NULL; - wait->obj.sync.ops = &completion_wait_sync_ops; + wait->sync = alloc_sync( &completion_wait_sync_ops ); wait->completion = NULL; wait->thread = thread; wait->msg = NULL; @@ -297,7 +306,7 @@ static struct completion *create_completion( struct object *root, const struct u { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { - completion->obj.sync.ops = &completion_sync_ops; + completion->sync = alloc_sync( &completion_sync_ops ); list_init( &completion->queue ); list_init( &completion->wait_queue ); completion->depth = 0; diff --git a/server/console.c b/server/console.c index 8ee1690551b..9b0e7e2e63a 100644 --- a/server/console.c +++ b/server/console.c @@ -53,6 +53,7 @@ struct history_line struct console { struct object obj; /* object header */ + struct sync *sync; /* object sync */ int signaled; /* is console signaled */ struct thread *renderer; /* console renderer thread */ struct screen_buffer *active; /* active screen buffer */ @@ -79,6 +80,8 @@ static int console_add_queue( struct object *obj, struct wait_queue_entry *entry
static const struct sync_ops console_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ console_add_queue, /* add_queue */ remove_queue, /* remove_queue */ console_signaled, /* signaled */ @@ -140,6 +143,7 @@ struct console_host_ioctl struct console_server { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct fd *fd; /* pseudo-fd for ioctls */ struct console *console; /* attached console */ struct list queue; /* ioctl queue */ @@ -162,6 +166,8 @@ static struct object *console_server_open_file( struct object *obj, unsigned int
static const struct sync_ops console_server_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ console_server_signaled, /* signaled */ @@ -220,6 +226,7 @@ struct font_info struct screen_buffer { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list entry; /* entry in list of all screen buffers */ struct console *input; /* associated console input */ unsigned int id; /* buffer id */ @@ -237,6 +244,8 @@ static struct object *screen_buffer_open_file( struct object *obj, unsigned int
static const struct sync_ops screen_buffer_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ screen_buffer_signaled, /* signaled */ @@ -312,6 +321,7 @@ static const struct object_ops console_device_ops = struct console_input { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct fd *fd; /* pseudo-fd */ struct list entry; /* entry in console->inputs */ struct console *console; /* associated console at creation time */ @@ -327,6 +337,8 @@ static void console_input_destroy( struct object *obj );
static const struct sync_ops console_input_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ console_input_signaled, /* signaled */ @@ -377,6 +389,7 @@ static const struct fd_ops console_input_fd_ops = struct console_output { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct fd *fd; /* pseudo-fd */ struct list entry; /* entry in console->outputs */ struct console *console; /* associated console at creation time */ @@ -392,6 +405,8 @@ static void console_output_destroy( struct object *obj );
static const struct sync_ops console_output_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ console_output_signaled, /* signaled */ @@ -525,7 +540,7 @@ static struct sync *console_get_sync( struct object *obj ) { struct console *console = (struct console *)obj; assert( obj->ops == &console_ops ); - return &console->obj.sync; + return console->sync; }
static enum server_fd_type console_get_fd_type( struct fd *fd ) @@ -565,7 +580,7 @@ static struct object *create_console(void) struct console *console;
if (!(console = alloc_object( &console_ops ))) return NULL; - console->obj.sync.ops = &console_sync_ops; + console->sync = alloc_sync( &console_sync_ops ); console->renderer = NULL; console->signaled = 0; console->active = NULL; @@ -670,7 +685,7 @@ static struct object *create_screen_buffer( struct console *console ) }
if (!(screen_buffer = alloc_object( &screen_buffer_ops ))) return NULL; - screen_buffer->obj.sync.ops = &screen_buffer_sync_ops; + screen_buffer->sync = alloc_sync( &screen_buffer_sync_ops ); screen_buffer->id = ++console->last_id; screen_buffer->input = console; init_async_queue( &screen_buffer->ioctl_q ); @@ -805,6 +820,7 @@ static void console_destroy( struct object *obj ) free_async_queue( &console->read_q ); if (console->fd) release_object( console->fd ); + release_sync( console->sync ); }
static struct object *create_console_connection( struct console *console ) @@ -881,6 +897,7 @@ static void screen_buffer_destroy( struct object *obj ) } if (screen_buffer->fd) release_object( screen_buffer->fd ); free_async_queue( &screen_buffer->ioctl_q ); + release_sync( screen_buffer->sync ); }
static int screen_buffer_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -911,7 +928,7 @@ static struct sync *screen_buffer_get_sync( struct object *obj ) { struct screen_buffer *screen_buffer = (struct screen_buffer *)obj; assert( obj->ops == &screen_buffer_ops ); - return &screen_buffer->obj.sync; + return screen_buffer->sync; }
static void console_server_dump( struct object *obj, int verbose ) @@ -926,6 +943,7 @@ static void console_server_destroy( struct object *obj ) assert( obj->ops == &console_server_ops ); disconnect_console_server( server ); if (server->fd) release_object( server->fd ); + release_sync( server->sync ); }
static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, @@ -984,7 +1002,7 @@ static struct sync *console_server_get_sync( struct object *obj ) { struct console_server *server = (struct console_server *)obj; assert( obj->ops == &console_server_ops ); - return &server->obj.sync; + return server->sync; }
static struct object *console_server_open_file( struct object *obj, unsigned int access, @@ -998,7 +1016,7 @@ static struct object *create_console_server( void ) struct console_server *server;
if (!(server = alloc_object( &console_server_ops ))) return NULL; - server->obj.sync.ops = &console_server_sync_ops; + server->sync = alloc_sync( &console_server_sync_ops ); server->console = NULL; server->busy = 0; server->once_input = 0; @@ -1379,7 +1397,7 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
name->len = 0; if (!(console_input = alloc_object( &console_input_ops ))) return NULL; - console_input->obj.sync.ops = &console_input_sync_ops; + console_input->sync = alloc_sync( &console_input_sync_ops ); console_input->fd = alloc_pseudo_fd( &console_input_fd_ops, &console_input->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!console_input->fd) @@ -1404,7 +1422,7 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni
name->len = 0; if (!(console_output = alloc_object( &console_output_ops ))) return NULL; - console_output->obj.sync.ops = &console_output_sync_ops; + console_output->sync = alloc_sync( &console_output_sync_ops ); console_output->fd = alloc_pseudo_fd( &console_output_fd_ops, &console_output->obj, FILE_SYNCHRONOUS_IO_NONALERT ); if (!console_output->fd) @@ -1486,7 +1504,7 @@ static struct sync *console_input_get_sync( struct object *obj ) { struct console_input *console_input = (struct console_input *)obj; assert( obj->ops == &console_input_ops ); - return &console_input->obj.sync; + return console_input->sync; }
static struct object *console_input_open_file( struct object *obj, unsigned int access, @@ -1502,6 +1520,7 @@ static void console_input_destroy( struct object *obj ) assert( obj->ops == &console_input_ops ); if (console_input->fd) release_object( console_input->fd ); if (console_input->console) list_remove( &console_input->entry ); + release_sync( console_input->sync ); }
static void console_input_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) @@ -1564,7 +1583,7 @@ static struct sync *console_output_get_sync( struct object *obj ) { struct console_output *console_output = (struct console_output *)obj; assert( obj->ops == &console_output_ops ); - return &console_output->obj.sync; + return console_output->sync; }
static struct object *console_output_open_file( struct object *obj, unsigned int access, @@ -1580,6 +1599,7 @@ static void console_output_destroy( struct object *obj ) assert( obj->ops == &console_output_ops ); if (console_output->fd) release_object( console_output->fd ); if (console_output->console) list_remove( &console_output->entry ); + release_sync( console_output->sync ); }
static void console_output_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) diff --git a/server/debugger.c b/server/debugger.c index 8024556d77d..576a751823d 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -43,6 +43,7 @@ enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_DELAYED, EVENT_CONTINUE struct debug_event { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list entry; /* entry in event queue */ struct thread *sender; /* thread which sent this event */ struct file *file; /* file object for events that need one */ @@ -69,6 +70,7 @@ struct type_descr debug_obj_type = struct debug_obj { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ }; @@ -81,6 +83,8 @@ static void debug_event_destroy( struct object *obj );
static const struct sync_ops debug_event_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ debug_event_signaled, /* signaled */ @@ -115,6 +119,8 @@ static void debug_obj_destroy( struct object *obj );
static const struct sync_ops debug_obj_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ debug_obj_signaled, /* signaled */ @@ -315,7 +321,7 @@ static struct sync *debug_event_get_sync( struct object *obj ) { struct debug_event *debug_event = (struct debug_event *)obj; assert( obj->ops == &debug_event_ops ); - return &debug_event->obj.sync; + return debug_event->sync; }
static int debug_event_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -332,6 +338,7 @@ static void debug_event_destroy( struct object *obj )
if (event->file) release_object( event->file ); release_object( event->sender ); + release_sync( event->sync ); }
static void debug_obj_dump( struct object *obj, int verbose ) @@ -346,7 +353,7 @@ static struct sync *debug_obj_get_sync( struct object *obj ) { struct debug_obj *debug_obj = (struct debug_obj *)obj; assert( obj->ops == &debug_obj_ops ); - return &debug_obj->obj.sync; + return debug_obj->sync; }
static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -368,6 +375,8 @@ static void debug_obj_destroy( struct object *obj ) /* free all pending events */ while ((ptr = list_head( &debug_obj->event_queue ))) unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry )); + + release_sync( debug_obj->sync ); }
struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -385,7 +394,7 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { - debug_obj->obj.sync.ops = &debug_obj_sync_ops; + debug_obj->sync = alloc_sync( &debug_obj_sync_ops ); debug_obj->flags = flags; list_init( &debug_obj->event_queue ); } @@ -454,7 +463,7 @@ static struct debug_event *alloc_debug_event( struct thread *thread, int code, c
/* build the event */ if (!(event = alloc_object( &debug_event_ops ))) return NULL; - event->obj.sync.ops = &debug_event_sync_ops; + event->sync = alloc_sync( &debug_event_sync_ops ); event->state = EVENT_QUEUED; event->sender = (struct thread *)grab_object( thread ); event->file = NULL; diff --git a/server/device.c b/server/device.c index f7109d2d470..62dd7b70d07 100644 --- a/server/device.c +++ b/server/device.c @@ -84,6 +84,7 @@ static const struct object_ops irp_call_ops = struct device_manager { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list devices; /* list of devices */ struct list requests; /* list of pending irps across all devices */ struct irp_call *current_call; /* call currently executed on client side */ @@ -97,6 +98,8 @@ static void device_manager_destroy( struct object *obj );
static const struct sync_ops device_manager_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ device_manager_signaled, /* signaled */ @@ -773,7 +776,7 @@ static struct sync *device_manager_get_sync( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; assert( obj->ops == &device_manager_ops ); - return &manager->obj.sync; + return manager->sync; }
static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -817,6 +820,8 @@ static void device_manager_destroy( struct object *obj ) assert( !irp->file && !irp->async ); release_object( irp ); } + + release_sync( manager->sync ); }
static struct device_manager *create_device_manager(void) @@ -825,7 +830,7 @@ static struct device_manager *create_device_manager(void)
if ((manager = alloc_object( &device_manager_ops ))) { - manager->obj.sync.ops = &device_manager_sync_ops; + manager->sync = alloc_sync( &device_manager_sync_ops ); manager->current_call = NULL; list_init( &manager->devices ); list_init( &manager->requests ); diff --git a/server/event.c b/server/event.c index eeba7fcaf58..85c9686f2c9 100644 --- a/server/event.c +++ b/server/event.c @@ -53,6 +53,7 @@ struct type_descr event_type = 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 */ @@ -60,6 +61,7 @@ struct event
static void event_dump( struct object *obj, int verbose ); static struct sync *event_get_sync( struct object *obj ); +static void event_destroy( struct object *obj ); 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); @@ -67,6 +69,8 @@ static struct list *event_get_kernel_obj_list( struct object *obj );
static const struct sync_ops event_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ event_signaled, /* signaled */ @@ -91,7 +95,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 */ };
@@ -112,14 +116,18 @@ struct type_descr keyed_event_type = struct keyed_event { struct object obj; /* object header */ + struct sync *sync; /* object sync */ };
static void keyed_event_dump( struct object *obj, int verbose ); static struct sync *keyed_event_get_sync( struct object *obj ); +static void keyed_event_destroy( struct object *obj ); static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry );
static const struct sync_ops keyed_event_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ keyed_event_signaled, /* signaled */ @@ -144,7 +152,7 @@ static const struct object_ops keyed_event_ops = no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + keyed_event_destroy, /* destroy */ };
@@ -159,7 +167,7 @@ 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->obj.sync.ops = &event_sync_ops; + event->sync = alloc_sync( &event_sync_ops ); list_init( &event->kernel_object ); event->manual_reset = manual_reset; event->signaled = initial_state; @@ -205,7 +213,14 @@ static struct sync *event_get_sync( struct object *obj ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops ); - return &event->obj.sync; + return event->sync; +} + +static void event_destroy( struct object *obj ) +{ + struct event *event = (struct event *)obj; + assert( obj->ops == &event_ops ); + release_sync( event->sync ); }
static int event_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -253,7 +268,7 @@ struct keyed_event *create_keyed_event( struct object *root, const struct unicod if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - event->obj.sync.ops = &keyed_event_sync_ops; + event->sync = alloc_sync( &keyed_event_sync_ops ); } } return event; @@ -273,7 +288,14 @@ static struct sync *keyed_event_get_sync( struct object *obj ) { struct keyed_event *event = (struct keyed_event *)obj; assert( obj->ops == &keyed_event_ops ); - return &event->obj.sync; + return event->sync; +} + +static void keyed_event_destroy( struct object *obj ) +{ + struct event *event = (struct event *)obj; + assert( obj->ops == &keyed_event_ops ); + release_sync( event->sync ); }
static enum select_opcode matching_op( enum select_opcode op ) @@ -283,6 +305,8 @@ static enum select_opcode matching_op( enum select_opcode op )
static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry ) { + struct keyed_event *event = (struct keyed_event *)obj; + struct sync *sync = event->sync; struct wait_queue_entry *ptr; struct process *process; enum select_opcode select_op; @@ -293,7 +317,7 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en select_op = get_wait_queue_select_op( entry ); if (select_op != SELECT_KEYED_EVENT_WAIT && select_op != SELECT_KEYED_EVENT_RELEASE) return 1;
- LIST_FOR_EACH_ENTRY( ptr, &obj->wait_queue, struct wait_queue_entry, entry ) + LIST_FOR_EACH_ENTRY( ptr, &sync->wait_queue, struct wait_queue_entry, entry ) { if (ptr == entry) continue; if (get_wait_queue_thread( ptr )->process != process) continue; diff --git a/server/fd.c b/server/fd.c index 497056d9fa4..aa16f097f40 100644 --- a/server/fd.c +++ b/server/fd.c @@ -128,6 +128,7 @@ struct closed_fd struct fd { struct object obj; /* object header */ + struct sync *sync; /* object sync */ 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 */ @@ -163,6 +164,8 @@ static void fd_destroy( struct object *obj );
const struct sync_ops fd_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ fd_signaled, /* signaled */ @@ -268,6 +271,7 @@ static const struct object_ops inode_ops = struct file_lock { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct fd *fd; /* fd owning this lock */ struct list fd_entry; /* entry in list of locks on a given fd */ struct list inode_entry; /* entry in inode list of locks */ @@ -280,10 +284,13 @@ struct file_lock
static void file_lock_dump( struct object *obj, int verbose ); static struct sync *file_lock_get_sync( struct object *obj ); +static void file_lock_destroy( struct object *obj ); static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry );
static const struct sync_ops file_lock_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ file_lock_signaled, /* signaled */ @@ -308,7 +315,7 @@ static const struct object_ops file_lock_ops = no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + file_lock_destroy, /* destroy */ };
@@ -1245,7 +1252,14 @@ static struct sync *file_lock_get_sync( struct object *obj ) { struct file_lock *lock = (struct file_lock *)obj; assert( obj->ops == &file_lock_ops ); - return &lock->obj.sync; + return lock->sync; +} + +static void file_lock_destroy( struct object *obj ) +{ + struct file_lock *lock = (struct file_lock *)obj; + assert( obj->ops == &file_lock_ops ); + release_sync( lock->sync ); }
static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -1434,7 +1448,7 @@ static struct file_lock *add_lock( struct fd *fd, int shared, file_pos_t start, struct file_lock *lock;
if (!(lock = alloc_object( &file_lock_ops ))) return NULL; - lock->obj.sync.ops = &file_lock_sync_ops; + lock->sync = alloc_sync( &file_lock_sync_ops ); lock->shared = shared; lock->start = start; lock->end = end; @@ -1576,7 +1590,7 @@ static void fd_dump( struct object *obj, int verbose ) static struct sync *fd_get_sync( struct object *obj ) { struct fd *fd = (struct fd *)obj; - return &fd->obj.sync; + return fd->sync; }
static void fd_destroy( struct object *obj ) @@ -1603,6 +1617,7 @@ static void fd_destroy( struct object *obj ) if (fd->unix_fd != -1) close( fd->unix_fd ); free( fd->unix_name ); } + release_sync( fd->sync ); }
/* check if the desired access is possible without violating */ @@ -1701,7 +1716,7 @@ static struct fd *alloc_fd_object(void) struct fd *fd;
if (!(fd = alloc_object( &fd_ops ))) return NULL; - fd->obj.sync.ops = &fd_sync_ops; + fd->sync = alloc_sync( &fd_sync_ops ); fd->fd_ops = NULL; fd->user = NULL; fd->inode = NULL; @@ -1741,7 +1756,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use struct fd *fd;
if (!(fd = alloc_object( &fd_ops ))) return NULL; - fd->obj.sync.ops = &fd_sync_ops; + fd->sync = alloc_sync( &fd_sync_ops ); fd->fd_ops = fd_user_ops; fd->user = user; fd->inode = NULL; @@ -2200,7 +2215,7 @@ static int fd_signaled( struct object *obj, struct wait_queue_entry *entry ) struct sync *default_fd_get_sync( struct object *obj ) { struct fd *fd = get_obj_fd( obj ); - struct sync *sync = &fd->obj.sync; + struct sync *sync = fd->sync; release_object( fd ); return sync; } diff --git a/server/file.h b/server/file.h index 06622c40783..0b8c87757b7 100644 --- a/server/file.h +++ b/server/file.h @@ -24,7 +24,6 @@ #include <sys/types.h>
#include "object.h" -#include "thread.h"
struct fd; struct mapping; @@ -120,6 +119,7 @@ extern void no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ); extern void no_fd_write( struct fd *fd, struct async *async, file_pos_t pos ); extern void no_fd_flush( struct fd *fd, struct async *async ); extern void no_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class ); +extern struct sync *default_fd_get_sync( struct object *obj ); extern void default_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class ); extern void no_fd_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class ); extern void no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); diff --git a/server/mutex.c b/server/mutex.c index f2ddbe9cc1e..493f7f60ad7 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -53,6 +53,7 @@ struct type_descr mutex_type = struct mutex { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct thread *owner; /* mutex owner */ unsigned int count; /* recursion count */ int abandoned; /* has it been abandoned? */ @@ -68,6 +69,8 @@ static int mutex_signal( struct object *obj, unsigned int access );
static const struct sync_ops mutex_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ mutex_signaled, /* signaled */ @@ -129,7 +132,7 @@ static struct mutex *create_mutex( struct object *root, const struct unicode_str if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - mutex->obj.sync.ops = &mutex_sync_ops; + mutex->sync = alloc_sync( &mutex_sync_ops ); mutex->count = 0; mutex->owner = NULL; mutex->abandoned = 0; @@ -164,7 +167,7 @@ static struct sync *mutex_get_sync( struct object *obj ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops ); - return &mutex->obj.sync; + return mutex->sync; }
static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -208,9 +211,13 @@ static void mutex_destroy( struct object *obj ) struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops );
- if (!mutex->count) return; - mutex->count = 0; - do_release( mutex ); + if (mutex->count) + { + mutex->count = 0; + do_release( mutex ); + } + + release_sync( mutex->sync ); }
/* create a mutex */ diff --git a/server/object.c b/server/object.c index 302bbb53523..eead499e2c4 100644 --- a/server/object.c +++ b/server/object.c @@ -287,8 +287,15 @@ WCHAR *default_get_full_name( struct object *obj, data_size_t *ret_len ) return (WCHAR *)ret; }
+static void no_sync_destroy( struct sync *sync ) +{ + assert( 0 ); +} + static const struct sync_ops no_sync_ops = { + 0, /* size */ + no_sync_destroy, /* destroy */ no_add_queue, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ @@ -298,6 +305,7 @@ static const struct sync_ops no_sync_ops =
static struct sync no_sync = { + 1, &no_sync_ops, };
@@ -311,10 +319,8 @@ void *alloc_object( const struct object_ops *ops ) obj->handle_count = 0; obj->is_permanent = 0; obj->ops = ops; - obj->sync.ops = &no_sync_ops; obj->name = NULL; obj->sd = NULL; - list_init( &obj->wait_queue ); #ifdef DEBUG_OBJECTS list_add_head( &object_list, &obj->obj_list ); #endif @@ -325,6 +331,16 @@ void *alloc_object( const struct object_ops *ops ) return NULL; }
+struct sync *alloc_sync( const struct sync_ops *ops ) +{ + struct sync *sync = mem_alloc( ops->size ); + assert( sync ); + sync->refcount = 1; + sync->ops = ops; + list_init( &sync->wait_queue ); + return sync; +} + /* free an object once it has been destroyed */ static void free_object( struct object *obj ) { @@ -553,8 +569,6 @@ void release_object( void *ptr ) if (!--obj->refcount) { assert( !obj->handle_count ); - /* if the refcount is 0, nobody can be in the wait queue */ - assert( list_empty( &obj->wait_queue )); free_kernel_objects( obj ); unlink_named_object( obj ); obj->ops->destroy( obj ); @@ -562,6 +576,27 @@ void release_object( void *ptr ) } }
+/* grab a sync (i.e. increment its refcount) and return the sync */ +struct sync *grab_sync( void *ptr ) +{ + struct sync *sync = (struct sync *)ptr; + assert( sync->refcount < INT_MAX ); + sync->refcount++; + return sync; +} + +/* release a sync (i.e. decrement its refcount) */ +void release_sync( void *ptr ) +{ + struct sync *sync = (struct sync *)ptr; + assert( sync->refcount ); + if (!--sync->refcount) + { + sync->ops->destroy( sync ); + free( sync ); + } +} + /* find an object by its name; the refcount is incremented */ struct object *find_object( const struct namespace *namespace, const struct unicode_str *name, unsigned int attributes ) @@ -640,6 +675,13 @@ int no_signal( struct object *obj, unsigned int access ) return 0; }
+void sync_destroy( struct sync *obj ) +{ + struct sync *sync = (struct sync *)obj; + /* if the refcount is 0, nobody can be in the wait queue */ + assert( list_empty( &sync->wait_queue ) ); +} + struct fd *no_get_fd( struct object *obj ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); @@ -651,6 +693,24 @@ struct sync *no_get_sync( struct object *obj ) return &no_sync; }
+/* attempt to wake threads sleeping on the object wait queue */ +void sync_wake_up( struct sync *sync, int max ) +{ + struct list *ptr; + int ret; + + if (sync == &no_sync) return; + + LIST_FOR_EACH( ptr, &sync->wait_queue ) + { + struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry ); + if (!(ret = wake_thread( get_wait_queue_thread( entry )))) continue; + if (ret > 0 && max && !--max) break; + /* restart at the head of the list since a wake up can change the object wait queue */ + ptr = &sync->wait_queue; + } +} + 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 3db4f3d56cb..08ee577a91a 100644 --- a/server/object.h +++ b/server/object.h @@ -42,6 +42,7 @@ struct async; struct async_queue; struct winstation; struct object_type; +struct sync;
struct unicode_str @@ -66,6 +67,10 @@ struct type_descr /* operations valid on waitable objects */ struct sync_ops { + /* size of this sync type */ + size_t size; + /* destroy a sync object */ + void (*destroy)(struct sync *); /* add a thread to the object wait queue */ int (*add_queue)(struct object *,struct wait_queue_entry *); /* remove a thread from the object wait queue */ @@ -80,7 +85,9 @@ struct sync_ops
struct sync { + unsigned int refcount; const struct sync_ops *ops; + struct list wait_queue; };
/* operations valid on all objects */ @@ -126,8 +133,6 @@ struct object unsigned int refcount; /* reference count */ unsigned int handle_count;/* handle count */ const struct object_ops *ops; - struct sync sync; - struct list wait_queue; struct object_name *name; struct security_descriptor *sd; unsigned int is_permanent:1; @@ -157,6 +162,7 @@ extern void mark_block_uninitialized( void *ptr, size_t size ); extern void *mem_alloc( size_t size ) __WINE_ALLOC_SIZE(1) __WINE_DEALLOC(free) __WINE_MALLOC; extern void *memdup( const void *data, size_t len ) __WINE_ALLOC_SIZE(2) __WINE_DEALLOC(free); extern void *alloc_object( const struct object_ops *ops ); +extern struct sync *alloc_sync( const struct sync_ops *ops ); extern void namespace_add( struct namespace *namespace, struct object_name *ptr ); extern const WCHAR *get_object_name( struct object *obj, data_size_t *len ); extern WCHAR *default_get_full_name( struct object *obj, data_size_t *ret_len ) __WINE_DEALLOC(free) __WINE_MALLOC; @@ -176,14 +182,18 @@ extern void free_kernel_objects( struct object *obj ); /* that the thing pointed to starts with a struct object... */ extern struct object *grab_object( void *obj ); extern void release_object( void *obj ); +extern struct sync *grab_sync( void *obj ); +extern void release_sync( void *obj ); extern struct object *find_object( const struct namespace *namespace, const struct unicode_str *name, unsigned int attributes ); 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 void sync_destroy( struct sync *obj ); extern struct fd *no_get_fd( struct object *obj ); extern struct sync *no_get_sync( struct object *obj ); +extern void sync_wake_up( struct sync *sync, int max ); 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 eac2df227c9..0201f92c44a 100644 --- a/server/process.c +++ b/server/process.c @@ -100,6 +100,8 @@ static void terminate_process( struct process *process, struct thread *skip, int
static const struct sync_ops process_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ process_signaled, /* signaled */ @@ -144,6 +146,7 @@ static const struct fd_ops process_fd_ops = struct startup_info { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct process *process; /* created process */ data_size_t info_size; /* size of startup info */ data_size_t data_size; /* size of whole startup data */ @@ -157,6 +160,8 @@ static void startup_info_destroy( struct object *obj );
static const struct sync_ops startup_info_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ startup_info_signaled, /* signaled */ @@ -209,6 +214,7 @@ static void job_destroy( struct object *obj ); struct job { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list process_list; /* list of processes */ int num_processes; /* count of running processes */ int total_processes; /* count of processes which have been assigned */ @@ -224,6 +230,8 @@ struct job
static const struct sync_ops job_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ job_signaled, /* signaled */ @@ -261,7 +269,7 @@ static struct job *create_job_object( struct object *root, const struct unicode_ if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - job->obj.sync.ops = &job_sync_ops; + job->sync = alloc_sync( &job_sync_ops ); list_init( &job->process_list ); list_init( &job->child_job_list ); job->num_processes = 0; @@ -458,6 +466,8 @@ static void job_destroy( struct object *obj ) list_remove( &job->parent_job_entry ); release_object( job->parent ); } + + release_sync( job->sync ); }
static void job_dump( struct object *obj, int verbose ) @@ -472,7 +482,7 @@ static struct sync *job_get_sync( struct object *obj ) { struct job *job = (struct job *)obj; assert( obj->ops == &job_ops ); - return &job->obj.sync; + return job->sync; }
static int job_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -676,7 +686,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla close( fd ); goto error; } - process->obj.sync.ops = &process_sync_ops; + process->sync = alloc_sync( &process_sync_ops ); process->parent_id = 0; process->debug_obj = NULL; process->debug_event = NULL; @@ -811,6 +821,7 @@ static void process_destroy( struct object *obj ) free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); + release_sync( process->sync ); }
/* dump a process on stdout for debugging purposes */ @@ -826,7 +837,7 @@ static struct sync *process_get_sync( struct object *obj ) { struct process *process = (struct process *)obj; assert( obj->ops == &process_ops ); - return &process->obj.sync; + return process->sync; }
static int process_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -905,6 +916,7 @@ static void startup_info_destroy( struct object *obj ) assert( obj->ops == &startup_info_ops ); free( info->data ); if (info->process) release_object( info->process ); + release_sync( info->sync ); }
static void startup_info_dump( struct object *obj, int verbose ) @@ -923,7 +935,7 @@ static struct sync *startup_info_get_sync( struct object *obj ) { struct startup_info *info = (struct startup_info *)obj; assert( obj->ops == &startup_info_ops ); - return &info->obj.sync; + return info->sync; }
static int startup_info_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -1240,7 +1252,7 @@ DECL_HANDLER(new_process) release_object( parent ); return; } - info->obj.sync.ops = &startup_info_sync_ops; + info->sync = alloc_sync( &startup_info_sync_ops ); info->process = NULL; info->data = NULL;
diff --git a/server/process.h b/server/process.h index e49529b06fa..09de931cf61 100644 --- a/server/process.h +++ b/server/process.h @@ -36,6 +36,7 @@ enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED }; struct process { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list entry; /* entry in system-wide process list */ process_id_t parent_id; /* parent process id (at the time of creation) */ struct list thread_list; /* thread list */ diff --git a/server/queue.c b/server/queue.c index f607fafa882..d833fac033a 100644 --- a/server/queue.c +++ b/server/queue.c @@ -115,6 +115,7 @@ struct thread_input struct msg_queue { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct fd *fd; /* optional file descriptor to poll */ int paint_count; /* pending paint messages count */ int hotkey_count; /* pending hotkey messages count */ @@ -160,6 +161,8 @@ static void timer_callback( void *private );
static const struct sync_ops msg_queue_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ msg_queue_add_queue, /* add_queue */ msg_queue_remove_queue, /* remove_queue */ msg_queue_signaled, /* signaled */ @@ -303,7 +306,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
if ((queue = alloc_object( &msg_queue_ops ))) { - queue->obj.sync.ops = &msg_queue_sync_ops; + queue->sync = alloc_sync( &msg_queue_sync_ops ); queue->fd = NULL; queue->paint_count = 0; queue->hotkey_count = 0; @@ -1261,12 +1264,13 @@ static void cleanup_results( struct msg_queue *queue ) /* check if the thread owning the queue is hung (not checking for messages) */ static int is_queue_hung( struct msg_queue *queue ) { + struct sync *sync = queue->sync; struct wait_queue_entry *entry;
if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC) return 0; /* less than 5 seconds since last get message -> not hung */
- LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry ) + LIST_FOR_EACH_ENTRY( entry, &sync->wait_queue, struct wait_queue_entry, entry ) { if (get_wait_queue_thread(entry)->queue == queue) return 0; /* thread is waiting on queue -> not hung */ @@ -1277,6 +1281,7 @@ static int is_queue_hung( struct msg_queue *queue ) static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ) { struct msg_queue *queue = (struct msg_queue *)obj; + struct sync *sync = queue->sync;
/* a thread can only wait on its own queue */ if (get_wait_queue_thread(entry)->queue != queue) @@ -1285,18 +1290,19 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent return 0; }
- if (queue->fd && list_empty( &obj->wait_queue )) /* first on the queue */ + if (queue->fd && list_empty( &sync->wait_queue )) /* first on the queue */ set_fd_events( queue->fd, POLLIN ); add_queue( obj, entry ); return 1; }
-static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry ) +static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ) { struct msg_queue *queue = (struct msg_queue *)obj; + struct sync *sync = queue->sync;
remove_queue( obj, entry ); - if (queue->fd && list_empty( &obj->wait_queue )) /* last on the queue is gone */ + if (queue->fd && list_empty( &sync->wait_queue )) /* last on the queue is gone */ set_fd_events( queue->fd, 0 ); }
@@ -1312,12 +1318,13 @@ static struct sync *msg_queue_get_sync( struct object *obj ) { struct msg_queue *queue = (struct msg_queue *)obj; assert( obj->ops == &msg_queue_ops ); - return &queue->obj.sync; + return queue->sync; }
static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ) { struct msg_queue *queue = (struct msg_queue *)obj; + struct sync *sync = queue->sync; int ret = 0;
if (queue->fd) @@ -1325,7 +1332,7 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr if ((ret = check_fd_events( queue->fd, POLLIN ))) /* stop waiting on select() if we are signaled */ set_fd_events( queue->fd, 0 ); - else if (!list_empty( &obj->wait_queue )) + else if (!list_empty( &sync->wait_queue )) /* restart waiting on poll() if we are no longer signaled */ set_fd_events( queue->fd, POLLIN ); } @@ -1388,6 +1395,7 @@ static void msg_queue_destroy( struct object *obj ) if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); + release_sync( queue->sync ); }
static void msg_queue_poll_event( struct fd *fd, int event ) diff --git a/server/semaphore.c b/server/semaphore.c index 3ac9ff23a2d..716baf87369 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -53,18 +53,22 @@ struct type_descr semaphore_type = struct semaphore { struct object obj; /* object header */ + struct sync *sync; /* object sync */ unsigned int count; /* current count */ unsigned int max; /* maximum possible count */ };
static void semaphore_dump( struct object *obj, int verbose ); static struct sync *semaphore_get_sync( struct object *obj ); +static void semaphore_destroy( struct object *obj ); 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 const struct sync_ops semaphore_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ semaphore_signaled, /* signaled */ @@ -89,7 +93,7 @@ static const struct object_ops semaphore_ops = no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + semaphore_destroy, /* destroy */ };
@@ -109,7 +113,7 @@ static struct semaphore *create_semaphore( struct object *root, const struct uni if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - sem->obj.sync.ops = &semaphore_sync_ops; + sem->sync = alloc_sync( &semaphore_sync_ops ); sem->count = initial; sem->max = max; } @@ -150,7 +154,14 @@ static struct sync *semaphore_get_sync( struct object *obj ) { struct semaphore *semaphore = (struct semaphore *)obj; assert( obj->ops == &semaphore_ops ); - return &semaphore->obj.sync; + return semaphore->sync; +} + +static void semaphore_destroy( struct object *obj ) +{ + struct semaphore *semaphore = (struct semaphore *)obj; + assert( obj->ops == &semaphore_ops ); + release_sync( semaphore->sync ); }
static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry ) diff --git a/server/thread.c b/server/thread.c index 770c50784f7..43e09728f01 100644 --- a/server/thread.c +++ b/server/thread.c @@ -85,6 +85,7 @@ struct thread_wait struct thread_apc { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list entry; /* queue linked list */ struct thread *caller; /* thread that queued this apc */ struct object *owner; /* object that queued this apc */ @@ -101,6 +102,8 @@ static void clear_apc_queue( struct list *queue );
static const struct sync_ops thread_apc_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ thread_apc_signaled, /* signaled */ @@ -134,6 +137,7 @@ static const struct object_ops thread_apc_ops = struct context { struct object obj; /* object header */ + struct sync *sync; /* object sync */ unsigned int status; /* status of the context */ struct context_data regs[2];/* context data */ }; @@ -145,10 +149,13 @@ static const unsigned int system_flags = SERVER_CTX_DEBUG_REGISTERS;
static void dump_context( struct object *obj, int verbose ); static struct sync *context_get_sync( struct object *obj ); +static void context_destroy( struct object *obj ); static int context_signaled( struct object *obj, struct wait_queue_entry *entry );
static const struct sync_ops context_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ context_signaled, /* signaled */ @@ -173,7 +180,7 @@ static const struct object_ops context_ops = no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - no_destroy /* destroy */ + context_destroy, /* destroy */ };
@@ -204,6 +211,8 @@ static void destroy_thread( struct object *obj );
static const struct sync_ops thread_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ thread_signaled, /* signaled */ @@ -405,7 +414,7 @@ static inline void init_thread_structure( struct thread *thread ) { int i;
- thread->obj.sync.ops = &thread_sync_ops; + thread->sync = alloc_sync( &thread_sync_ops ); thread->unix_pid = -1; /* not known yet */ thread->unix_tid = -1; /* not known yet */ thread->context = NULL; @@ -467,9 +476,15 @@ static struct sync *context_get_sync( struct object *obj ) { struct context *context = (struct context *)obj; assert( obj->ops == &context_ops ); - return &context->obj.sync; + return context->sync; }
+static void context_destroy( struct object *obj ) +{ + struct context *context = (struct context *)obj; + assert( obj->ops == &context_ops ); + release_sync( context->sync ); +}
static int context_signaled( struct object *obj, struct wait_queue_entry *entry ) { @@ -482,7 +497,7 @@ static struct context *create_thread_context( struct thread *thread ) { struct context *context; if (!(context = alloc_object( &context_ops ))) return NULL; - context->obj.sync.ops = &context_sync_ops; + context->sync = alloc_sync( &context_sync_ops ); context->status = STATUS_PENDING; memset( &context->regs, 0, sizeof(context->regs) ); context->regs[CTX_NATIVE].machine = native_machine; @@ -646,6 +661,7 @@ static void destroy_thread( struct object *obj ) release_object( thread->process ); if (thread->id) free_ptid( thread->id ); if (thread->token) release_object( thread->token ); + release_sync( thread->sync ); }
/* dump a thread on stdout for debugging purposes */ @@ -662,7 +678,7 @@ static struct sync *thread_get_sync( struct object *obj ) { struct thread *thread = (struct thread *)obj; assert( obj->ops == &thread_ops ); - return &thread->obj.sync; + return thread->sync; }
static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -691,7 +707,7 @@ static struct sync *thread_apc_get_sync( struct object *obj ) { struct thread_apc *apc = (struct thread_apc *)obj; assert( obj->ops == &thread_apc_ops ); - return &apc->obj.sync; + return apc->sync; }
static int thread_apc_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -713,6 +729,7 @@ static void thread_apc_destroy( struct object *obj ) async_set_result( apc->owner, apc->call.async_io.status, 0 ); release_object( apc->owner ); } + release_sync( apc->sync ); }
/* queue an async procedure call */ @@ -722,7 +739,7 @@ static struct thread_apc *create_apc( struct object *owner, const union apc_call
if ((apc = alloc_object( &thread_apc_ops ))) { - apc->obj.sync.ops = &thread_apc_sync_ops; + apc->sync = alloc_sync( &thread_apc_sync_ops ); if (call_data) apc->call = *call_data; else apc->call.type = APC_NONE; apc->caller = NULL; @@ -962,9 +979,10 @@ 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 ) { + struct sync *sync = obj->ops->get_sync( obj ); grab_object( obj ); entry->obj = obj; - list_add_tail( &obj->wait_queue, &entry->entry ); + list_add_tail( &sync->wait_queue, &entry->entry ); return 1; }
@@ -1337,17 +1355,8 @@ static int select_on( const union select_op *select_op, data_size_t op_size, cli /* attempt to wake threads sleeping on the object wait queue */ void wake_up( struct object *obj, int max ) { - struct list *ptr; - int ret; - - LIST_FOR_EACH( ptr, &obj->wait_queue ) - { - struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry ); - if (!(ret = wake_thread( get_wait_queue_thread( entry )))) continue; - if (ret > 0 && max && !--max) break; - /* restart at the head of the list since a wake up can change the object wait queue */ - ptr = &obj->wait_queue; - } + struct sync *sync = obj->ops->get_sync( obj ); + sync_wake_up( sync, max ); }
/* return the apc queue to use for a given apc type */ diff --git a/server/thread.h b/server/thread.h index 7fdae3a629f..270bc7ed096 100644 --- a/server/thread.h +++ b/server/thread.h @@ -50,6 +50,7 @@ struct inflight_fd struct thread { struct object obj; /* object header */ + struct sync *sync; /* object sync */ struct list entry; /* entry in system-wide thread list */ struct list proc_entry; /* entry in per-process thread list */ struct list desktop_entry; /* entry in per-desktop thread list */ diff --git a/server/timer.c b/server/timer.c index 50cb7a618e5..8dec11e77c7 100644 --- a/server/timer.c +++ b/server/timer.c @@ -53,6 +53,7 @@ struct type_descr timer_type = struct timer { struct object obj; /* object header */ + struct sync *sync; /* object sync */ int manual; /* manual reset */ int signaled; /* current signaled state */ unsigned int period; /* timer period in ms */ @@ -71,6 +72,8 @@ static void timer_destroy( struct object *obj );
static const struct sync_ops timer_sync_ops = { + sizeof(struct sync), /* size */ + sync_destroy, /* destroy */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ timer_signaled, /* signaled */ @@ -110,7 +113,7 @@ static struct timer *create_timer( struct object *root, const struct unicode_str if (get_error() != STATUS_OBJECT_NAME_EXISTS) { /* initialize it if it didn't already exist */ - timer->obj.sync.ops = &timer_sync_ops; + timer->sync = alloc_sync( &timer_sync_ops ); timer->manual = manual; timer->signaled = 0; timer->when = 0; @@ -212,7 +215,7 @@ static struct sync *timer_get_sync( struct object *obj ) { struct timer *timer = (struct timer *)obj; assert( obj->ops == &timer_ops ); - return &timer->obj.sync; + return timer->sync; }
static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) @@ -236,6 +239,7 @@ static void timer_destroy( struct object *obj )
if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); + release_sync( timer->sync ); }
/* create a timer */