2 * Server-side mutex management
4 * Copyright (C) 1998 Alexandre Julliard
13 #include "server/thread.h"
17 struct object obj; /* object header */
18 struct thread *owner; /* mutex owner */
19 unsigned int count; /* recursion count */
20 int abandoned; /* has it been abandoned? */
25 static void mutex_dump( struct object *obj, int verbose );
26 static int mutex_signaled( struct object *obj, struct thread *thread );
27 static int mutex_satisfied( struct object *obj, struct thread *thread );
28 static void mutex_destroy( struct object *obj );
30 static const struct object_ops mutex_ops =
44 struct object *create_mutex( const char *name, int owned )
48 if (!(mutex = (struct mutex *)create_named_object( name, &mutex_ops, sizeof(*mutex) )))
50 if (GET_ERROR() != ERROR_ALREADY_EXISTS)
52 /* initialize it if it didn't already exist */
56 mutex->next = mutex->prev = NULL;
57 if (owned) mutex_satisfied( &mutex->obj, current );
62 int open_mutex( unsigned int access, int inherit, const char *name )
64 return open_object( name, &mutex_ops, access, inherit );
67 /* release a mutex once the recursion count is 0 */
68 static void do_release( struct mutex *mutex, struct thread *thread )
70 assert( !mutex->count );
71 /* remove the mutex from the thread list of owned mutexes */
72 if (mutex->next) mutex->next->prev = mutex->prev;
73 if (mutex->prev) mutex->prev->next = mutex->next;
74 else thread->mutex = mutex->next;
76 mutex->next = mutex->prev = NULL;
77 wake_up( &mutex->obj, 0 );
80 int release_mutex( int handle )
84 if (!(mutex = (struct mutex *)get_handle_obj( current->process, handle,
85 MUTEX_MODIFY_STATE, &mutex_ops )))
87 if (!mutex->count || (mutex->owner != current))
89 SET_ERROR( ERROR_NOT_OWNER );
92 if (!--mutex->count) do_release( mutex, current );
93 release_object( mutex );
97 void abandon_mutexes( struct thread *thread )
101 struct mutex *mutex = thread->mutex;
102 assert( mutex->owner == thread );
104 mutex->abandoned = 1;
105 do_release( mutex, thread );
109 static void mutex_dump( struct object *obj, int verbose )
111 struct mutex *mutex = (struct mutex *)obj;
112 assert( obj->ops == &mutex_ops );
113 printf( "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
116 static int mutex_signaled( struct object *obj, struct thread *thread )
118 struct mutex *mutex = (struct mutex *)obj;
119 assert( obj->ops == &mutex_ops );
120 return (!mutex->count || (mutex->owner == thread));
123 static int mutex_satisfied( struct object *obj, struct thread *thread )
125 struct mutex *mutex = (struct mutex *)obj;
126 assert( obj->ops == &mutex_ops );
127 assert( !mutex->count || (mutex->owner == thread) );
129 if (!mutex->count++) /* FIXME: avoid wrap-around */
131 assert( !mutex->owner );
132 mutex->owner = thread;
134 if ((mutex->next = thread->mutex)) mutex->next->prev = mutex;
135 thread->mutex = mutex;
137 if (!mutex->abandoned) return 0;
138 mutex->abandoned = 0;
142 static void mutex_destroy( struct object *obj )
144 struct mutex *mutex = (struct mutex *)obj;
145 assert( obj->ops == &mutex_ops );