Add support for selection of console mode drivers to use using the
[wine/multimedia.git] / scheduler / mutex.c
blob4a32e15065bcdf46075052e7f560cdc30655dcea
1 /*
2 * Win32 mutexes
4 * Copyright 1998 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include "windows.h"
9 #include "winerror.h"
10 #include "k32obj.h"
11 #include "process.h"
12 #include "thread.h"
13 #include "heap.h"
14 #include "server/request.h"
15 #include "server.h"
17 typedef struct _MUTEX
19 K32OBJ header;
20 THREAD_QUEUE wait_queue;
21 DWORD owner;
22 DWORD count;
23 BOOL32 abandoned;
24 struct _MUTEX *next;
25 struct _MUTEX *prev;
26 } MUTEX;
28 static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id );
29 static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id );
30 static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id );
31 static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id );
32 static void MUTEX_Destroy( K32OBJ *obj );
34 const K32OBJ_OPS MUTEX_Ops =
36 MUTEX_Signaled, /* signaled */
37 MUTEX_Satisfied, /* satisfied */
38 MUTEX_AddWait, /* add_wait */
39 MUTEX_RemoveWait, /* remove_wait */
40 NULL, /* read */
41 NULL, /* write */
42 MUTEX_Destroy /* destroy */
46 /***********************************************************************
47 * MUTEX_Release
49 * Release a mutex once the count is 0.
50 * Helper function for MUTEX_Abandon and ReleaseMutex.
52 static void MUTEX_Release( MUTEX *mutex )
54 /* Remove the mutex from the thread list of owned mutexes */
55 if (mutex->next) mutex->next->prev = mutex->prev;
56 if (mutex->prev) mutex->prev->next = mutex->next;
57 else THREAD_Current()->mutex_list = &mutex->next->header;
58 mutex->next = mutex->prev = NULL;
59 mutex->owner = 0;
60 SYNC_WakeUp( &mutex->wait_queue, INFINITE32 );
64 /***********************************************************************
65 * MUTEX_Abandon
67 * Abandon a mutex.
69 void MUTEX_Abandon( K32OBJ *obj )
71 MUTEX *mutex = (MUTEX *)obj;
72 assert( obj->type == K32OBJ_MUTEX );
73 assert( mutex->count && (mutex->owner == GetCurrentThreadId()) );
74 mutex->count = 0;
75 mutex->abandoned = TRUE;
76 MUTEX_Release( mutex );
80 /***********************************************************************
81 * CreateMutex32A (KERNEL32.166)
83 HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
84 LPCSTR name )
86 struct create_mutex_request req;
87 struct create_mutex_reply reply;
88 int len = name ? strlen(name) + 1 : 0;
89 HANDLE32 handle;
90 MUTEX *mutex;
92 req.owned = owner;
93 req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
95 CLIENT_SendRequest( REQ_CREATE_MUTEX, -1, 2, &req, sizeof(req), name, len );
96 CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
97 CHECK_LEN( len, sizeof(reply) );
98 if (reply.handle == -1) return NULL;
100 SYSTEM_LOCK();
101 mutex = (MUTEX *)K32OBJ_Create( K32OBJ_MUTEX, sizeof(*mutex),
102 name, reply.handle, MUTEX_ALL_ACCESS,
103 sa, &handle );
104 if (mutex)
106 /* Finish initializing it */
107 mutex->wait_queue = NULL;
108 mutex->abandoned = FALSE;
109 mutex->prev = NULL;
110 if (owner)
112 K32OBJ **list;
113 mutex->owner = GetCurrentThreadId();
114 mutex->count = 1;
115 /* Add the mutex in the thread list of owned mutexes */
116 list = &THREAD_Current()->mutex_list;
117 if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
118 *list = &mutex->header;
120 else
122 mutex->owner = 0;
123 mutex->count = 0;
124 mutex->next = NULL;
126 K32OBJ_DecCount( &mutex->header );
128 SetLastError(0); /* FIXME */
129 SYSTEM_UNLOCK();
130 return handle;
134 /***********************************************************************
135 * CreateMutex32W (KERNEL32.167)
137 HANDLE32 WINAPI CreateMutex32W( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
138 LPCWSTR name )
140 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
141 HANDLE32 ret = CreateMutex32A( sa, owner, nameA );
142 if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
143 return ret;
147 /***********************************************************************
148 * OpenMutex32A (KERNEL32.541)
150 HANDLE32 WINAPI OpenMutex32A( DWORD access, BOOL32 inherit, LPCSTR name )
152 HANDLE32 handle = 0;
153 K32OBJ *obj;
154 SYSTEM_LOCK();
155 if ((obj = K32OBJ_FindNameType( name, K32OBJ_MUTEX )) != NULL)
157 handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, -1 );
158 K32OBJ_DecCount( obj );
160 SYSTEM_UNLOCK();
161 return handle;
165 /***********************************************************************
166 * OpenMutex32W (KERNEL32.542)
168 HANDLE32 WINAPI OpenMutex32W( DWORD access, BOOL32 inherit, LPCWSTR name )
170 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
171 HANDLE32 ret = OpenMutex32A( access, inherit, nameA );
172 if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
173 return ret;
177 /***********************************************************************
178 * ReleaseMutex (KERNEL32.582)
180 BOOL32 WINAPI ReleaseMutex( HANDLE32 handle )
182 struct release_mutex_request req;
183 MUTEX *mutex;
184 SYSTEM_LOCK();
185 if (!(mutex = (MUTEX *)HANDLE_GetObjPtr(PROCESS_Current(), handle,
186 K32OBJ_MUTEX, MUTEX_MODIFY_STATE,
187 &req.handle )))
189 SYSTEM_UNLOCK();
190 return FALSE;
192 if (req.handle != -1)
194 SYSTEM_UNLOCK();
195 CLIENT_SendRequest( REQ_RELEASE_MUTEX, -1, 1, &req, sizeof(req) );
196 return !CLIENT_WaitReply( NULL, NULL, 0 );
198 if (!mutex->count || (mutex->owner != GetCurrentThreadId()))
200 SYSTEM_UNLOCK();
201 SetLastError( ERROR_NOT_OWNER );
202 return FALSE;
204 if (!--mutex->count) MUTEX_Release( mutex );
205 K32OBJ_DecCount( &mutex->header );
206 SYSTEM_UNLOCK();
207 return TRUE;
211 /***********************************************************************
212 * MUTEX_Signaled
214 static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id )
216 MUTEX *mutex = (MUTEX *)obj;
217 assert( obj->type == K32OBJ_MUTEX );
218 return (!mutex->count || (mutex->owner == thread_id));
222 /***********************************************************************
223 * MUTEX_Satisfied
225 * Wait on this object has been satisfied.
227 static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id )
229 BOOL32 ret;
230 MUTEX *mutex = (MUTEX *)obj;
231 assert( obj->type == K32OBJ_MUTEX );
232 assert( !mutex->count || (mutex->owner == thread_id) );
233 mutex->owner = thread_id;
234 if (!mutex->count++)
236 /* Add the mutex in the thread list of owned mutexes */
237 K32OBJ **list = &THREAD_ID_TO_THDB( thread_id )->mutex_list;
238 assert( !mutex->next );
239 if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
240 *list = &mutex->header;
241 mutex->prev = NULL;
243 ret = mutex->abandoned;
244 mutex->abandoned = FALSE;
245 return ret;
249 /***********************************************************************
250 * MUTEX_AddWait
252 * Add a thread to the object wait queue.
254 static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id )
256 MUTEX *mutex = (MUTEX *)obj;
257 assert( obj->type == K32OBJ_MUTEX );
258 THREAD_AddQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
262 /***********************************************************************
263 * MUTEX_RemoveWait
265 * Remove a thread from the object wait queue.
267 static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id )
269 MUTEX *mutex = (MUTEX *)obj;
270 assert( obj->type == K32OBJ_MUTEX );
271 THREAD_RemoveQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
275 /***********************************************************************
276 * MUTEX_Destroy
278 static void MUTEX_Destroy( K32OBJ *obj )
280 MUTEX *mutex = (MUTEX *)obj;
281 assert( obj->type == K32OBJ_MUTEX );
282 /* There cannot be any thread on the list since the ref count is 0 */
283 assert( mutex->wait_queue == NULL );
284 obj->type = K32OBJ_UNKNOWN;
285 HeapFree( SystemHeap, 0, mutex );