4 * Copyright 1998 Alexandre Julliard
18 THREAD_QUEUE wait_queue
;
26 static BOOL32
MUTEX_Signaled( K32OBJ
*obj
, DWORD thread_id
);
27 static BOOL32
MUTEX_Satisfied( K32OBJ
*obj
, DWORD thread_id
);
28 static void MUTEX_AddWait( K32OBJ
*obj
, DWORD thread_id
);
29 static void MUTEX_RemoveWait( K32OBJ
*obj
, DWORD thread_id
);
30 static void MUTEX_Destroy( K32OBJ
*obj
);
32 const K32OBJ_OPS MUTEX_Ops
=
34 MUTEX_Signaled
, /* signaled */
35 MUTEX_Satisfied
, /* satisfied */
36 MUTEX_AddWait
, /* add_wait */
37 MUTEX_RemoveWait
, /* remove_wait */
40 MUTEX_Destroy
/* destroy */
44 /***********************************************************************
47 * Release a mutex once the count is 0.
48 * Helper function for MUTEX_Abandon and ReleaseMutex.
50 static void MUTEX_Release( MUTEX
*mutex
)
52 /* Remove the mutex from the thread list of owned mutexes */
53 if (mutex
->next
) mutex
->next
->prev
= mutex
->prev
;
54 if (mutex
->prev
) mutex
->prev
->next
= mutex
->next
;
55 else THREAD_Current()->mutex_list
= &mutex
->next
->header
;
56 mutex
->next
= mutex
->prev
= NULL
;
58 SYNC_WakeUp( &mutex
->wait_queue
, INFINITE32
);
62 /***********************************************************************
67 void MUTEX_Abandon( K32OBJ
*obj
)
69 MUTEX
*mutex
= (MUTEX
*)obj
;
70 assert( obj
->type
== K32OBJ_MUTEX
);
71 assert( mutex
->count
&& (mutex
->owner
== GetCurrentThreadId()) );
73 mutex
->abandoned
= TRUE
;
74 MUTEX_Release( mutex
);
78 /***********************************************************************
79 * CreateMutex32A (KERNEL32.166)
81 HANDLE32 WINAPI
CreateMutex32A( SECURITY_ATTRIBUTES
*sa
, BOOL32 owner
,
88 mutex
= (MUTEX
*)K32OBJ_Create( K32OBJ_MUTEX
, sizeof(*mutex
),
89 name
, MUTEX_ALL_ACCESS
, sa
, &handle
);
92 /* Finish initializing it */
93 mutex
->wait_queue
= NULL
;
94 mutex
->abandoned
= FALSE
;
99 mutex
->owner
= GetCurrentThreadId();
101 /* Add the mutex in the thread list of owned mutexes */
102 list
= &THREAD_Current()->mutex_list
;
103 if ((mutex
->next
= (MUTEX
*)*list
)) mutex
->next
->prev
= mutex
;
104 *list
= &mutex
->header
;
112 K32OBJ_DecCount( &mutex
->header
);
114 SetLastError(0); /* FIXME */
120 /***********************************************************************
121 * CreateMutex32W (KERNEL32.167)
123 HANDLE32 WINAPI
CreateMutex32W( SECURITY_ATTRIBUTES
*sa
, BOOL32 owner
,
126 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
127 HANDLE32 ret
= CreateMutex32A( sa
, owner
, nameA
);
128 if (nameA
) HeapFree( GetProcessHeap(), 0, nameA
);
133 /***********************************************************************
134 * OpenMutex32A (KERNEL32.541)
136 HANDLE32 WINAPI
OpenMutex32A( DWORD access
, BOOL32 inherit
, LPCSTR name
)
141 if ((obj
= K32OBJ_FindNameType( name
, K32OBJ_MUTEX
)) != NULL
)
143 handle
= HANDLE_Alloc( PROCESS_Current(), obj
, access
, inherit
);
144 K32OBJ_DecCount( obj
);
151 /***********************************************************************
152 * OpenMutex32W (KERNEL32.542)
154 HANDLE32 WINAPI
OpenMutex32W( DWORD access
, BOOL32 inherit
, LPCWSTR name
)
156 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
157 HANDLE32 ret
= OpenMutex32A( access
, inherit
, nameA
);
158 if (nameA
) HeapFree( GetProcessHeap(), 0, nameA
);
163 /***********************************************************************
164 * ReleaseMutex (KERNEL32.582)
166 BOOL32 WINAPI
ReleaseMutex( HANDLE32 handle
)
170 if (!(mutex
= (MUTEX
*)HANDLE_GetObjPtr(PROCESS_Current(), handle
,
171 K32OBJ_MUTEX
, MUTEX_MODIFY_STATE
)))
176 if (!mutex
->count
|| (mutex
->owner
!= GetCurrentThreadId()))
179 SetLastError( ERROR_NOT_OWNER
);
182 if (!--mutex
->count
) MUTEX_Release( mutex
);
183 K32OBJ_DecCount( &mutex
->header
);
189 /***********************************************************************
192 static BOOL32
MUTEX_Signaled( K32OBJ
*obj
, DWORD thread_id
)
194 MUTEX
*mutex
= (MUTEX
*)obj
;
195 assert( obj
->type
== K32OBJ_MUTEX
);
196 return (!mutex
->count
|| (mutex
->owner
== thread_id
));
200 /***********************************************************************
203 * Wait on this object has been satisfied.
205 static BOOL32
MUTEX_Satisfied( K32OBJ
*obj
, DWORD thread_id
)
208 MUTEX
*mutex
= (MUTEX
*)obj
;
209 assert( obj
->type
== K32OBJ_MUTEX
);
210 assert( !mutex
->count
|| (mutex
->owner
== thread_id
) );
211 mutex
->owner
= thread_id
;
214 /* Add the mutex in the thread list of owned mutexes */
215 K32OBJ
**list
= &THREAD_ID_TO_THDB( thread_id
)->mutex_list
;
216 assert( !mutex
->next
);
217 if ((mutex
->next
= (MUTEX
*)*list
)) mutex
->next
->prev
= mutex
;
218 *list
= &mutex
->header
;
221 ret
= mutex
->abandoned
;
222 mutex
->abandoned
= FALSE
;
227 /***********************************************************************
230 * Add a thread to the object wait queue.
232 static void MUTEX_AddWait( K32OBJ
*obj
, DWORD thread_id
)
234 MUTEX
*mutex
= (MUTEX
*)obj
;
235 assert( obj
->type
== K32OBJ_MUTEX
);
236 THREAD_AddQueue( &mutex
->wait_queue
, THREAD_ID_TO_THDB(thread_id
) );
240 /***********************************************************************
243 * Remove a thread from the object wait queue.
245 static void MUTEX_RemoveWait( K32OBJ
*obj
, DWORD thread_id
)
247 MUTEX
*mutex
= (MUTEX
*)obj
;
248 assert( obj
->type
== K32OBJ_MUTEX
);
249 THREAD_RemoveQueue( &mutex
->wait_queue
, THREAD_ID_TO_THDB(thread_id
) );
253 /***********************************************************************
256 static void MUTEX_Destroy( K32OBJ
*obj
)
258 MUTEX
*mutex
= (MUTEX
*)obj
;
259 assert( obj
->type
== K32OBJ_MUTEX
);
260 /* There cannot be any thread on the list since the ref count is 0 */
261 assert( mutex
->wait_queue
== NULL
);
262 obj
->type
= K32OBJ_UNKNOWN
;
263 HeapFree( SystemHeap
, 0, mutex
);