4 * Copyright 1998 Alexandre Julliard
14 #include "server/request.h"
20 THREAD_QUEUE wait_queue
;
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 */
42 MUTEX_Destroy
/* destroy */
46 /***********************************************************************
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
;
60 SYNC_WakeUp( &mutex
->wait_queue
, INFINITE32
);
64 /***********************************************************************
69 void MUTEX_Abandon( K32OBJ
*obj
)
71 MUTEX
*mutex
= (MUTEX
*)obj
;
72 assert( obj
->type
== K32OBJ_MUTEX
);
73 assert( mutex
->count
&& (mutex
->owner
== GetCurrentThreadId()) );
75 mutex
->abandoned
= TRUE
;
76 MUTEX_Release( mutex
);
80 /***********************************************************************
81 * CreateMutex32A (KERNEL32.166)
83 HANDLE32 WINAPI
CreateMutex32A( SECURITY_ATTRIBUTES
*sa
, BOOL32 owner
,
86 struct create_mutex_request req
;
87 struct create_mutex_reply reply
;
88 int len
= name
? strlen(name
) + 1 : 0;
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
;
101 mutex
= (MUTEX
*)K32OBJ_Create( K32OBJ_MUTEX
, sizeof(*mutex
),
102 name
, reply
.handle
, MUTEX_ALL_ACCESS
,
106 /* Finish initializing it */
107 mutex
->wait_queue
= NULL
;
108 mutex
->abandoned
= FALSE
;
113 mutex
->owner
= GetCurrentThreadId();
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
;
126 K32OBJ_DecCount( &mutex
->header
);
128 SetLastError(0); /* FIXME */
134 /***********************************************************************
135 * CreateMutex32W (KERNEL32.167)
137 HANDLE32 WINAPI
CreateMutex32W( SECURITY_ATTRIBUTES
*sa
, BOOL32 owner
,
140 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
141 HANDLE32 ret
= CreateMutex32A( sa
, owner
, nameA
);
142 if (nameA
) HeapFree( GetProcessHeap(), 0, nameA
);
147 /***********************************************************************
148 * OpenMutex32A (KERNEL32.541)
150 HANDLE32 WINAPI
OpenMutex32A( DWORD access
, BOOL32 inherit
, LPCSTR name
)
155 if ((obj
= K32OBJ_FindNameType( name
, K32OBJ_MUTEX
)) != NULL
)
157 handle
= HANDLE_Alloc( PROCESS_Current(), obj
, access
, inherit
, -1 );
158 K32OBJ_DecCount( obj
);
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
);
177 /***********************************************************************
178 * ReleaseMutex (KERNEL32.582)
180 BOOL32 WINAPI
ReleaseMutex( HANDLE32 handle
)
182 struct release_mutex_request req
;
185 if (!(mutex
= (MUTEX
*)HANDLE_GetObjPtr(PROCESS_Current(), handle
,
186 K32OBJ_MUTEX
, MUTEX_MODIFY_STATE
,
192 if (req
.handle
!= -1)
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()))
201 SetLastError( ERROR_NOT_OWNER
);
204 if (!--mutex
->count
) MUTEX_Release( mutex
);
205 K32OBJ_DecCount( &mutex
->header
);
211 /***********************************************************************
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 /***********************************************************************
225 * Wait on this object has been satisfied.
227 static BOOL32
MUTEX_Satisfied( K32OBJ
*obj
, DWORD thread_id
)
230 MUTEX
*mutex
= (MUTEX
*)obj
;
231 assert( obj
->type
== K32OBJ_MUTEX
);
232 assert( !mutex
->count
|| (mutex
->owner
== thread_id
) );
233 mutex
->owner
= thread_id
;
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
;
243 ret
= mutex
->abandoned
;
244 mutex
->abandoned
= FALSE
;
249 /***********************************************************************
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 /***********************************************************************
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 /***********************************************************************
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
);