From: Rémi Bernon rbernon@codeweavers.com
--- server/fd.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/server/fd.c b/server/fd.c index 7054dc17d30..6c71336247f 100644 --- a/server/fd.c +++ b/server/fd.c @@ -273,6 +273,7 @@ static const struct object_ops inode_ops = struct file_lock { struct object obj; /* object header */ + struct event_sync *sync; /* sync object for wait/signal */ 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 */ @@ -284,20 +285,21 @@ struct file_lock };
static void file_lock_dump( struct object *obj, int verbose ); -static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *file_lock_get_sync( struct object *obj ); +static void file_lock_destroy( struct object *obj );
static const struct object_ops file_lock_ops = { sizeof(struct file_lock), /* size */ &no_type, /* type */ file_lock_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - file_lock_signaled, /* signaled */ - no_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + file_lock_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -308,7 +310,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 */ };
@@ -1241,11 +1243,18 @@ static void file_lock_dump( struct object *obj, int verbose ) fprintf( stderr, "\n" ); }
-static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *file_lock_get_sync( struct object *obj ) { struct file_lock *lock = (struct file_lock *)obj; - /* lock is signaled if it has lost its owner */ - return !lock->process; + assert( obj->ops == &file_lock_ops ); + return grab_object( lock->sync ); +} + +static void file_lock_destroy( struct object *obj ) +{ + struct file_lock *lock = (struct file_lock *)obj; + assert( obj->ops == &file_lock_ops ); + if (lock->sync) release_object( lock->sync ); }
/* set (or remove) a Unix lock if possible for the given range */ @@ -1427,22 +1436,24 @@ 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->sync = NULL; lock->shared = shared; lock->start = start; lock->end = end; lock->fd = fd; lock->process = current->process;
+ if (!(lock->sync = create_event_sync( 1, 0 ))) goto error; /* now try to set a Unix lock */ - if (!set_unix_lock( lock->fd, lock->start, lock->end, lock->shared ? F_RDLCK : F_WRLCK )) - { - release_object( lock ); - return NULL; - } + if (!set_unix_lock( lock->fd, lock->start, lock->end, lock->shared ? F_RDLCK : F_WRLCK )) goto error; list_add_tail( &fd->locks, &lock->fd_entry ); list_add_tail( &fd->inode->locks, &lock->inode_entry ); list_add_tail( &lock->process->locks, &lock->proc_entry ); return lock; + +error: + release_object( lock ); + return NULL; }
/* remove an existing lock */ @@ -1456,7 +1467,7 @@ static void remove_lock( struct file_lock *lock, int remove_unix ) if (remove_unix) remove_unix_locks( lock->fd, lock->start, lock->end ); if (list_empty( &inode->locks )) inode_close_pending( inode, 1 ); lock->process = NULL; - wake_up( &lock->obj, 0 ); + signal_sync( lock->sync ); release_object( lock ); }
From: Rémi Bernon rbernon@codeweavers.com
--- server/debugger.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/server/debugger.c b/server/debugger.c index 43d01fbf246..5f8b0ffc8fe 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 event_sync *sync; /* sync object for wait/signal */ 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 */ @@ -75,7 +76,7 @@ struct debug_obj
static void debug_event_dump( struct object *obj, int verbose ); -static int debug_event_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *debug_event_get_sync( struct object *obj ); static void debug_event_destroy( struct object *obj );
static const struct object_ops debug_event_ops = @@ -83,13 +84,13 @@ static const struct object_ops debug_event_ops = sizeof(struct debug_event), /* size */ &no_type, /* type */ debug_event_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_event_signaled, /* signaled */ - no_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + debug_event_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -263,6 +264,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) static void resume_event( struct debug_obj *debug_obj, struct debug_event *event ) { event->state = EVENT_QUEUED; + reset_sync( event->sync ); if (!event->sender->process->debug_event) { grab_object( debug_obj ); @@ -275,6 +277,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event static void delay_event( struct debug_obj *debug_obj, struct debug_event *event ) { event->state = EVENT_DELAYED; + reset_sync( event->sync ); if (event->sender->process->debug_event == event) event->sender->process->debug_event = NULL; }
@@ -301,11 +304,11 @@ static void debug_event_dump( struct object *obj, int verbose ) debug_event->sender, debug_event->data.code, debug_event->state ); }
-static int debug_event_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *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->state == EVENT_CONTINUED; + return grab_object( debug_event->sync ); }
static void debug_event_destroy( struct object *obj ) @@ -313,6 +316,7 @@ static void debug_event_destroy( struct object *obj ) struct debug_event *event = (struct debug_event *)obj; assert( obj->ops == &debug_event_ops );
+ if (event->sync) release_object( event->sync ); if (event->file) release_object( event->file ); release_object( event->sender ); } @@ -408,7 +412,7 @@ static int continue_debug_event( struct debug_obj *debug_obj, struct process *pr assert( event->sender->process->debug_event == event ); event->status = status; event->state = EVENT_CONTINUED; - wake_up( &event->obj, 0 ); + signal_sync( event->sync ); unlink_event( debug_obj, event ); resume_process( process ); return 1; @@ -429,12 +433,20 @@ 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->sync = NULL; event->state = EVENT_QUEUED; event->sender = (struct thread *)grab_object( thread ); event->file = NULL; memset( &event->data, 0, sizeof(event->data) ); fill_debug_event[code - DbgCreateThreadStateChange]( event, arg ); event->data.code = code; + + if (!(event->sync = create_event_sync( 1, 0 ))) + { + release_object( event ); + return NULL; + } + return event; }
@@ -520,7 +532,7 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj ) assert( event->state != EVENT_CONTINUED ); event->status = DBG_CONTINUE; event->state = EVENT_CONTINUED; - wake_up( &event->obj, 0 ); + signal_sync( event->sync ); unlink_event( debug_obj, event ); /* from queued debug event */ resume_process( process ); @@ -566,6 +578,7 @@ DECL_HANDLER(wait_debug_event) if ((event = find_event_to_send( debug_obj ))) { event->state = EVENT_SENT; + reset_sync( event->sync ); event->sender->process->debug_event = event; reply->pid = get_process_id( event->sender->process ); reply->tid = get_thread_id( event->sender );
From: Elizabeth Figura zfigura@codeweavers.com
--- server/debugger.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/server/debugger.c b/server/debugger.c index 5f8b0ffc8fe..2956ee17b8e 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -70,6 +70,7 @@ struct type_descr debug_obj_type = struct debug_obj { struct object obj; /* object header */ + struct event_sync *sync; /* sync object for wait/signal */ struct list event_queue; /* pending events queue */ unsigned int flags; /* debug flags */ }; @@ -105,7 +106,7 @@ static const struct object_ops debug_event_ops = };
static void debug_obj_dump( struct object *obj, int verbose ); -static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *debug_obj_get_sync( struct object *obj ); static void debug_obj_destroy( struct object *obj );
static const struct object_ops debug_obj_ops = @@ -113,13 +114,13 @@ static const struct object_ops debug_obj_ops = sizeof(struct debug_obj), /* size */ &debug_obj_type, /* type */ debug_obj_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - debug_obj_signaled, /* signaled */ - no_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + debug_obj_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -255,7 +256,7 @@ static void link_event( struct debug_obj *debug_obj, struct debug_event *event ) { /* grab reference since debugger could be killed while trying to wake up */ grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); + signal_sync( debug_obj->sync ); release_object( debug_obj ); } } @@ -268,7 +269,7 @@ static void resume_event( struct debug_obj *debug_obj, struct debug_event *event if (!event->sender->process->debug_event) { grab_object( debug_obj ); - wake_up( &debug_obj->obj, 0 ); + signal_sync( debug_obj->sync ); release_object( debug_obj ); } } @@ -329,11 +330,11 @@ static void debug_obj_dump( struct object *obj, int verbose ) debug_obj->event_queue.next, debug_obj->event_queue.prev ); }
-static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *debug_obj_get_sync( struct object *obj ) { struct debug_obj *debug_obj = (struct debug_obj *)obj; assert( obj->ops == &debug_obj_ops ); - return find_event_to_send( debug_obj ) != NULL; + return grab_object( debug_obj->sync ); }
static void debug_obj_destroy( struct object *obj ) @@ -348,6 +349,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 )); + + if (debug_obj->sync) release_object( debug_obj->sync ); }
struct debug_obj *get_debug_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -365,8 +368,15 @@ static struct debug_obj *create_debug_obj( struct object *root, const struct uni { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { + debug_obj->sync = NULL; debug_obj->flags = flags; list_init( &debug_obj->event_queue ); + + if (!(debug_obj->sync = create_event_sync( 1, 0 ))) + { + release_object( debug_obj ); + return NULL; + } } } return debug_obj; @@ -584,6 +594,7 @@ DECL_HANDLER(wait_debug_event) reply->tid = get_thread_id( event->sender ); alloc_event_handles( event, current->process ); set_reply_data( &event->data, min( get_reply_max_size(), sizeof(event->data) )); + if (!find_event_to_send( debug_obj )) reset_sync( debug_obj->sync ); } else {
From: Elizabeth Figura zfigura@codeweavers.com
--- server/device.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/server/device.c b/server/device.c index 892ec98c44f..f4b3f19028b 100644 --- a/server/device.c +++ b/server/device.c @@ -89,6 +89,7 @@ static const struct object_ops irp_call_ops = struct device_manager { struct object obj; /* object header */ + struct event_sync *sync; /* sync object for wait/signal */ 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 */ @@ -96,7 +97,7 @@ struct device_manager };
static void device_manager_dump( struct object *obj, int verbose ); -static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *device_manager_get_sync( struct object *obj ); static void device_manager_destroy( struct object *obj );
static const struct object_ops device_manager_ops = @@ -104,13 +105,13 @@ static const struct object_ops device_manager_ops = sizeof(struct device_manager), /* size */ &no_type, /* type */ device_manager_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - device_manager_signaled, /* signaled */ - no_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + device_manager_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -422,7 +423,7 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i irp->thread = thread ? (struct thread *)grab_object( thread ) : NULL; if (irp->file) list_add_tail( &irp->file->requests, &irp->dev_entry ); list_add_tail( &manager->requests, &irp->mgr_entry ); - if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ + if (list_head( &manager->requests ) == &irp->mgr_entry) signal_sync( manager->sync ); }
static struct object *device_open_file( struct object *obj, unsigned int access, @@ -752,6 +753,7 @@ struct object *create_unix_device( struct object *root, const struct unicode_str /* terminate requests when the underlying device is deleted */ static void delete_file( struct device_file *file ) { + struct device_manager *manager = file->device->manager; struct irp_call *irp, *next;
/* the pending requests may be the only thing holding a reference to the file */ @@ -764,6 +766,7 @@ static void delete_file( struct device_file *file ) set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); }
+ if (list_empty( &manager->requests )) reset_sync( manager->sync ); release_object( file ); }
@@ -788,11 +791,11 @@ static void device_manager_dump( struct object *obj, int verbose ) fprintf( stderr, "Device manager\n" ); }
-static int device_manager_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *device_manager_get_sync( struct object *obj ) { struct device_manager *manager = (struct device_manager *)obj; - - return !list_empty( &manager->requests ); + assert( obj->ops == &device_manager_ops ); + return grab_object( manager->sync ); }
static void device_manager_destroy( struct object *obj ) @@ -829,6 +832,8 @@ static void device_manager_destroy( struct object *obj ) assert( !irp->file && !irp->async ); release_object( irp ); } + + if (manager->sync) release_object( manager->sync ); }
static struct device_manager *create_device_manager(void) @@ -837,10 +842,17 @@ static struct device_manager *create_device_manager(void)
if ((manager = alloc_object( &device_manager_ops ))) { + manager->sync = NULL; manager->current_call = NULL; list_init( &manager->devices ); list_init( &manager->requests ); wine_rb_init( &manager->kernel_objects, compare_kernel_object ); + + if (!(manager->sync = create_event_sync( 1, 0 ))) + { + release_object( manager ); + return NULL; + } } return manager; } @@ -1027,6 +1039,8 @@ DECL_HANDLER(get_next_device_request) } list_remove( &irp->mgr_entry ); list_init( &irp->mgr_entry ); + if (list_empty( &manager->requests )) reset_sync( manager->sync ); + /* we already own the object if it's only on manager queue */ if (irp->file) grab_object( irp ); manager->current_call = irp;
From: Elizabeth Figura zfigura@codeweavers.com
--- server/completion.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/server/completion.c b/server/completion.c index fd623b36d5a..a2028a89823 100644 --- a/server/completion.c +++ b/server/completion.c @@ -72,11 +72,11 @@ struct completion_wait
struct completion { - struct object obj; - struct list queue; - struct list wait_queue; - unsigned int depth; - int closed; + struct object obj; + struct event_sync *sync; + struct list queue; + struct list wait_queue; + unsigned int depth; };
static void completion_wait_dump( struct object*, int ); @@ -155,7 +155,7 @@ static void completion_wait_satisfied( struct object *obj, struct wait_queue_ent }
static void completion_dump( struct object*, int ); -static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); +static struct object *completion_get_sync( struct object * ); static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void completion_destroy( struct object * );
@@ -164,13 +164,13 @@ static const struct object_ops completion_ops = sizeof(struct completion), /* size */ &completion_type, /* type */ completion_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - completion_signaled, /* signaled */ - no_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + completion_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -193,6 +193,8 @@ static void completion_destroy( struct object *obj) { free( tmp ); } + + if (completion->sync) release_object( completion->sync ); }
static void completion_dump( struct object *obj, int verbose ) @@ -203,11 +205,11 @@ static void completion_dump( struct object *obj, int verbose ) fprintf( stderr, "Completion depth=%u\n", completion->depth ); }
-static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *completion_get_sync( struct object *obj ) { struct completion *completion = (struct completion *)obj; - - return !list_empty( &completion->queue ) || completion->closed; + assert( obj->ops == &completion_ops ); + return grab_object( completion->sync ); }
static int completion_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) @@ -228,8 +230,7 @@ static int completion_close_handle( struct object *obj, struct process *process, cleanup_thread_completion( wait->thread ); } } - completion->closed = 1; - wake_up( obj, 0 ); + signal_sync( completion->sync ); return 1; }
@@ -273,10 +274,16 @@ static struct completion *create_completion( struct object *root, const struct u { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { + completion->sync = NULL; list_init( &completion->queue ); list_init( &completion->wait_queue ); completion->depth = 0; - completion->closed = 0; + + if (!(completion->sync = create_event_sync( 1, 0 ))) + { + release_object( completion ); + return NULL; + } } }
@@ -309,7 +316,7 @@ void add_completion( struct completion *completion, apc_param_t ckey, apc_param_ wake_up( &wait->obj, 1 ); if (list_empty( &completion->queue )) return; } - if (!list_empty( &completion->queue )) wake_up( &completion->obj, 0 ); + if (!list_empty( &completion->queue )) signal_sync( completion->sync ); }
/* create a completion */ @@ -410,6 +417,7 @@ DECL_HANDLER(remove_completion) reply->information = msg->information; free( msg ); reply->wait_handle = 0; + if (list_empty( &completion->queue )) reset_sync( completion->sync ); }
release_object( completion );
From: Elizabeth Figura zfigura@codeweavers.com
--- server/timer.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/server/timer.c b/server/timer.c index 4ad4ca19072..6357569ccba 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 event_sync *sync; /* sync object for wait/signal */ int manual; /* manual reset */ int signaled; /* current signaled state */ unsigned int period; /* timer period in ms */ @@ -64,8 +65,7 @@ struct timer };
static void timer_dump( struct object *obj, int verbose ); -static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ); -static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ); +static struct object *timer_get_sync( struct object *obj ); static void timer_destroy( struct object *obj );
static const struct object_ops timer_ops = @@ -73,13 +73,13 @@ static const struct object_ops timer_ops = sizeof(struct timer), /* size */ &timer_type, /* type */ timer_dump, /* dump */ - add_queue, /* add_queue */ - remove_queue, /* remove_queue */ - timer_signaled, /* signaled */ - timer_satisfied, /* satisfied */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ - default_get_sync, /* get_sync */ + timer_get_sync, /* get_sync */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ @@ -105,12 +105,19 @@ 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->sync = NULL; timer->manual = manual; timer->signaled = 0; timer->when = 0; timer->period = 0; timer->timeout = NULL; timer->thread = NULL; + + if (!(timer->sync = create_event_sync( manual, 0 ))) + { + release_object( timer ); + return NULL; + } } } return timer; @@ -149,9 +156,8 @@ static void timer_callback( void *private ) } else timer->timeout = NULL;
- /* wake up waiters */ timer->signaled = 1; - wake_up( &timer->obj, 0 ); + signal_sync( timer->sync ); }
/* cancel a running timer */ @@ -182,6 +188,7 @@ static int set_timer( struct timer *timer, timeout_t expire, unsigned int period { period = 0; /* period doesn't make any sense for a manual timer */ timer->signaled = 0; + reset_sync( timer->sync ); } timer->when = (expire <= 0) ? expire - monotonic_time : max( expire, current_time ); timer->period = period; @@ -202,18 +209,11 @@ static void timer_dump( struct object *obj, int verbose ) timer->manual, get_timeout_str(timeout), timer->period ); }
-static int timer_signaled( struct object *obj, struct wait_queue_entry *entry ) -{ - struct timer *timer = (struct timer *)obj; - assert( obj->ops == &timer_ops ); - return timer->signaled; -} - -static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry ) +static struct object *timer_get_sync( struct object *obj ) { struct timer *timer = (struct timer *)obj; assert( obj->ops == &timer_ops ); - if (!timer->manual) timer->signaled = 0; + return grab_object( timer->sync ); }
static void timer_destroy( struct object *obj ) @@ -223,6 +223,7 @@ static void timer_destroy( struct object *obj )
if (timer->timeout) remove_timeout_user( timer->timeout ); if (timer->thread) release_object( timer->thread ); + if (timer->sync) release_object( timer->sync ); }
/* create a timer */
This merge request was approved by Rémi Bernon.