2 * mutexes.c: Mutex handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
16 #include <mono/io-layer/wapi.h>
17 #include <mono/io-layer/wapi-private.h>
18 #include <mono/io-layer/misc-private.h>
19 #include <mono/io-layer/handles-private.h>
20 #include <mono/io-layer/mono-mutex.h>
21 #include <mono/io-layer/mutex-private.h>
25 static void mutex_close_shared (gpointer handle);
26 static void mutex_signal(gpointer handle);
27 static void mutex_own (gpointer handle);
28 static gboolean mutex_is_owned (gpointer handle);
30 struct _WapiHandleOps _wapi_mutex_ops = {
31 mutex_close_shared, /* close_shared */
32 NULL, /* close_private */
33 mutex_signal, /* signal */
35 mutex_is_owned, /* is_owned */
38 static pthread_once_t mutex_ops_once=PTHREAD_ONCE_INIT;
40 static void mutex_ops_init (void)
42 _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX,
43 WAPI_HANDLE_CAP_WAIT |
44 WAPI_HANDLE_CAP_SIGNAL |
48 static void mutex_close_shared (gpointer handle)
50 struct _WapiHandle_mutex *mutex_handle;
53 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
54 (gpointer *)&mutex_handle, NULL);
56 g_warning (G_GNUC_PRETTY_FUNCTION
57 ": error looking up mutex handle %p", handle);
62 g_message(G_GNUC_PRETTY_FUNCTION ": closing mutex handle %p", handle);
65 if(mutex_handle->name!=0) {
66 _wapi_handle_scratch_delete (mutex_handle->name);
71 static void mutex_signal(gpointer handle)
76 static void mutex_own (gpointer handle)
78 struct _WapiHandle_mutex *mutex_handle;
81 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
82 (gpointer *)&mutex_handle, NULL);
84 g_warning (G_GNUC_PRETTY_FUNCTION
85 ": error looking up mutex handle %p", handle);
90 g_message(G_GNUC_PRETTY_FUNCTION ": owning mutex handle %p", handle);
93 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
95 mutex_handle->pid=getpid ();
96 mutex_handle->tid=pthread_self ();
97 mutex_handle->recursion++;
100 g_message (G_GNUC_PRETTY_FUNCTION
101 ": mutex handle %p locked %d times by %d:%ld", handle,
102 mutex_handle->recursion, mutex_handle->pid,
107 static gboolean mutex_is_owned (gpointer handle)
109 struct _WapiHandle_mutex *mutex_handle;
112 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
113 (gpointer *)&mutex_handle, NULL);
115 g_warning (G_GNUC_PRETTY_FUNCTION
116 ": error looking up mutex handle %p", handle);
121 g_message(G_GNUC_PRETTY_FUNCTION
122 ": testing ownership mutex handle %p", handle);
125 if(mutex_handle->recursion>0 &&
126 mutex_handle->pid==getpid () &&
127 mutex_handle->tid==pthread_self ()) {
129 g_message (G_GNUC_PRETTY_FUNCTION
130 ": mutex handle %p owned by %d:%ld", handle,
131 getpid (), pthread_self ());
137 g_message (G_GNUC_PRETTY_FUNCTION
138 ": mutex handle %p not owned by %d:%ld", handle,
139 getpid (), pthread_self ());
148 * @security: Ignored for now.
149 * @owned: If %TRUE, the mutex is created with the calling thread
150 * already owning the mutex.
151 * @name:Pointer to a string specifying the name of this mutex, or
154 * Creates a new mutex handle. A mutex is signalled when no thread
155 * owns it. A thread acquires ownership of the mutex by waiting for
156 * it with WaitForSingleObject() or WaitForMultipleObjects(). A
157 * thread relinquishes ownership with ReleaseMutex().
159 * A thread that owns a mutex can specify the same mutex in repeated
160 * wait function calls without blocking. The thread must call
161 * ReleaseMutex() an equal number of times to release the mutex.
163 * Return value: A new handle, or %NULL on error.
165 gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
168 struct _WapiHandle_mutex *mutex_handle;
172 pthread_once (&mutex_ops_once, mutex_ops_init);
174 handle=_wapi_handle_new (WAPI_HANDLE_MUTEX);
175 if(handle==_WAPI_HANDLE_INVALID) {
176 g_warning (G_GNUC_PRETTY_FUNCTION
177 ": error creating mutex handle");
181 _wapi_handle_lock_handle (handle);
183 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
184 (gpointer *)&mutex_handle, NULL);
186 g_warning (G_GNUC_PRETTY_FUNCTION
187 ": error looking up mutex handle %p", handle);
188 _wapi_handle_unlock_handle (handle);
193 mutex_handle->name=_wapi_handle_scratch_store (name,
200 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
204 g_message (G_GNUC_PRETTY_FUNCTION ": returning mutex handle %p",
208 _wapi_handle_unlock_handle (handle);
215 * @handle: The mutex handle.
217 * Releases ownership if the mutex handle @handle.
219 * Return value: %TRUE on success, %FALSE otherwise. This function
220 * fails if the calling thread does not own the mutex @handle.
222 gboolean ReleaseMutex(gpointer handle)
224 struct _WapiHandle_mutex *mutex_handle;
226 pthread_t tid=pthread_self();
229 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
230 (gpointer *)&mutex_handle, NULL);
232 g_warning (G_GNUC_PRETTY_FUNCTION
233 ": error looking up mutex handle %p", handle);
237 _wapi_handle_lock_handle (handle);
240 g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex handle %p",
244 if(mutex_handle->tid!=tid || mutex_handle->pid!=pid) {
246 g_message(G_GNUC_PRETTY_FUNCTION ": We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
249 _wapi_handle_unlock_handle (handle);
253 /* OK, we own this mutex */
254 mutex_handle->recursion--;
256 if(mutex_handle->recursion==0) {
258 g_message(G_GNUC_PRETTY_FUNCTION ": Unlocking mutex handle %p",
264 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
267 _wapi_handle_unlock_handle (handle);