From: Rémi Bernon rbernon@codeweavers.com
--- server/mutex.c | 168 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 119 insertions(+), 49 deletions(-)
diff --git a/server/mutex.c b/server/mutex.c index 7ba79181dde..f56cc6fab75 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -50,31 +50,30 @@ struct type_descr mutex_type = }, };
-struct mutex +struct mutex_sync { - struct object obj; /* object header */ - struct thread *owner; /* mutex owner */ - unsigned int count; /* recursion count */ - int abandoned; /* has it been abandoned? */ - struct list entry; /* entry in owner thread mutex list */ + struct object obj; /* object header */ + struct thread *owner; /* mutex owner */ + unsigned int count; /* recursion count */ + int abandoned; /* has it been abandoned? */ + struct list entry; /* entry in owner thread mutex list */ };
-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 void mutex_sync_dump( struct object *obj, int verbose ); +static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry ); +static void mutex_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ); +static void mutex_sync_destroy( struct object *obj );
-static const struct object_ops mutex_ops = +static const struct object_ops mutex_sync_ops = { - sizeof(struct mutex), /* size */ - &mutex_type, /* type */ - mutex_dump, /* dump */ + sizeof(struct mutex_sync), /* size */ + &no_type, /* type */ + mutex_sync_dump, /* dump */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ - mutex_signaled, /* signaled */ - mutex_satisfied, /* satisfied */ - mutex_signal, /* signal */ + mutex_sync_signaled, /* signaled */ + mutex_sync_satisfied, /* satisfied */ + no_signal, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -87,12 +86,11 @@ static const struct object_ops mutex_ops = no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ no_close_handle, /* close_handle */ - mutex_destroy /* destroy */ + mutex_sync_destroy, /* destroy */ };
- /* grab a mutex for a given thread */ -static void do_grab( struct mutex *mutex, struct thread *thread ) +static void do_grab( struct mutex_sync *mutex, struct thread *thread ) { assert( !mutex->count || (mutex->owner == thread) );
@@ -105,7 +103,7 @@ static void do_grab( struct mutex *mutex, struct thread *thread ) }
/* release a mutex once the recursion count is 0 */ -static int do_release( struct mutex *mutex, int count ) +static int do_release( struct mutex_sync *mutex, int count ) { if (!mutex->count || (mutex->owner != current)) { @@ -123,6 +121,87 @@ static int do_release( struct mutex *mutex, int count ) return 1; }
+static void mutex_sync_dump( struct object *obj, int verbose ) +{ + struct mutex_sync *mutex = (struct mutex_sync *)obj; + assert( obj->ops == &mutex_sync_ops ); + fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner ); +} + +static void mutex_sync_destroy( struct object *obj ) +{ + struct mutex_sync *mutex = (struct mutex_sync *)obj; + assert( obj->ops == &mutex_sync_ops ); + + if (mutex->count) do_release( mutex, mutex->count ); +} + +static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry ) +{ + struct mutex_sync *mutex = (struct mutex_sync *)obj; + assert( obj->ops == &mutex_sync_ops ); + return (!mutex->count || (mutex->owner == get_wait_queue_thread( entry ))); +} + +static void mutex_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ) +{ + struct mutex_sync *mutex = (struct mutex_sync *)obj; + assert( obj->ops == &mutex_sync_ops ); + + do_grab( mutex, get_wait_queue_thread( entry )); + if (mutex->abandoned) make_wait_abandoned( entry ); + mutex->abandoned = 0; +} + +static struct mutex_sync *create_mutex_sync( int owned ) +{ + struct mutex_sync *mutex; + + if (!(mutex = alloc_object( &mutex_sync_ops ))) return NULL; + mutex->count = 0; + mutex->owner = NULL; + mutex->abandoned = 0; + if (owned) do_grab( mutex, current ); + + return mutex; +} + +struct mutex +{ + struct object obj; /* object header */ + struct mutex_sync *sync; /* mutex sync object */ +}; + +static void mutex_dump( struct object *obj, int verbose ); +static struct object *mutex_get_sync( struct object *obj ); +static int mutex_signal( struct object *obj, unsigned int access ); +static void mutex_destroy( struct object *obj ); + +static const struct object_ops mutex_ops = +{ + sizeof(struct mutex), /* size */ + &mutex_type, /* type */ + mutex_dump, /* dump */ + NULL, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + mutex_signal, /* signal */ + no_get_fd, /* get_fd */ + mutex_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 */ + mutex_destroy, /* destroy */ +}; + static struct mutex *create_mutex( struct object *root, const struct unicode_str *name, unsigned int attr, int owned, const struct security_descriptor *sd ) { @@ -133,10 +212,13 @@ 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->count = 0; - mutex->owner = NULL; - mutex->abandoned = 0; - if (owned) do_grab( mutex, current ); + mutex->sync = NULL; + + if (!(mutex->sync = create_mutex_sync( owned ))) + { + release_object( mutex ); + return NULL; + } } } return mutex; @@ -148,7 +230,7 @@ void abandon_mutexes( struct thread *thread )
while ((ptr = list_head( &thread->mutex_list )) != NULL) { - struct mutex *mutex = LIST_ENTRY( ptr, struct mutex, entry ); + struct mutex_sync *mutex = LIST_ENTRY( ptr, struct mutex_sync, entry ); assert( mutex->owner == thread ); mutex->abandoned = 1; do_release( mutex, mutex->count ); @@ -159,24 +241,14 @@ static void mutex_dump( struct object *obj, int verbose ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops ); - fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner ); + mutex->sync->obj.ops->dump( &mutex->sync->obj, verbose ); }
-static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry ) +static struct object *mutex_get_sync( struct object *obj ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops ); - return (!mutex->count || (mutex->owner == get_wait_queue_thread( entry ))); -} - -static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry ) -{ - struct mutex *mutex = (struct mutex *)obj; - assert( obj->ops == &mutex_ops ); - - do_grab( mutex, get_wait_queue_thread( entry )); - if (mutex->abandoned) make_wait_abandoned( entry ); - mutex->abandoned = 0; + return grab_object( mutex->sync ); }
static int mutex_signal( struct object *obj, unsigned int access ) @@ -189,16 +261,14 @@ static int mutex_signal( struct object *obj, unsigned int access ) set_error( STATUS_ACCESS_DENIED ); return 0; } - return do_release( mutex, 1 ); + return do_release( mutex->sync, 1 ); }
static void mutex_destroy( struct object *obj ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops ); - - if (!mutex->count) return; - do_release( mutex, mutex->count ); + if (mutex->sync) release_object( mutex->sync ); }
/* create a mutex */ @@ -242,8 +312,8 @@ DECL_HANDLER(release_mutex) if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle, 0, &mutex_ops ))) { - reply->prev_count = mutex->count; - do_release( mutex, 1 ); + reply->prev_count = mutex->sync->count; + do_release( mutex->sync, 1 ); release_object( mutex ); } } @@ -256,9 +326,9 @@ DECL_HANDLER(query_mutex) if ((mutex = (struct mutex *)get_handle_obj( current->process, req->handle, MUTANT_QUERY_STATE, &mutex_ops ))) { - reply->count = mutex->count; - reply->owned = (mutex->owner == current); - reply->abandoned = mutex->abandoned; + reply->count = mutex->sync->count; + reply->owned = (mutex->sync->owner == current); + reply->abandoned = mutex->sync->abandoned;
release_object( mutex ); }