7 #include <mono/io-layer/wapi.h>
8 #include <mono/io-layer/wapi-private.h>
9 #include <mono/io-layer/wait-private.h>
10 #include <mono/io-layer/misc-private.h>
11 #include <mono/io-layer/handles-private.h>
12 #include <mono/io-layer/mono-mutex.h>
13 #include <mono/io-layer/mutex-private.h>
17 static void mutex_close(gpointer handle);
18 static void mutex_signal(gpointer handle);
19 static void mutex_own (gpointer handle);
20 static gboolean mutex_is_owned (gpointer handle);
22 static struct _WapiHandleOps mutex_ops = {
23 mutex_close, /* close */
24 NULL, /* getfiletype */
29 NULL, /* setendoffile */
30 NULL, /* getfilesize */
31 NULL, /* getfiletime */
32 NULL, /* setfiletime */
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_ops (WAPI_HANDLE_MUTEX, &mutex_ops);
43 _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX,
44 WAPI_HANDLE_CAP_WAIT |
45 WAPI_HANDLE_CAP_SIGNAL |
49 static void mutex_close(gpointer handle)
51 struct _WapiHandle_mutex *mutex_handle;
54 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
55 (gpointer *)&mutex_handle, NULL);
57 g_warning (G_GNUC_PRETTY_FUNCTION
58 ": error looking up mutex handle %p", handle);
63 g_message(G_GNUC_PRETTY_FUNCTION ": closing mutex handle %p", handle);
66 if(mutex_handle->name!=0) {
67 _wapi_handle_scratch_delete (mutex_handle->name);
72 static void mutex_signal(gpointer handle)
77 static void mutex_own (gpointer handle)
79 struct _WapiHandle_mutex *mutex_handle;
82 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
83 (gpointer *)&mutex_handle, NULL);
85 g_warning (G_GNUC_PRETTY_FUNCTION
86 ": error looking up mutex handle %p", handle);
91 g_message(G_GNUC_PRETTY_FUNCTION ": owning mutex handle %p", handle);
94 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
96 mutex_handle->pid=getpid ();
97 mutex_handle->tid=pthread_self ();
98 mutex_handle->recursion++;
101 g_message (G_GNUC_PRETTY_FUNCTION
102 ": mutex handle %p locked %d times by %d:%ld", handle,
103 mutex_handle->recursion, mutex_handle->pid,
108 static gboolean mutex_is_owned (gpointer handle)
110 struct _WapiHandle_mutex *mutex_handle;
113 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
114 (gpointer *)&mutex_handle, NULL);
116 g_warning (G_GNUC_PRETTY_FUNCTION
117 ": error looking up mutex handle %p", handle);
122 g_message(G_GNUC_PRETTY_FUNCTION
123 ": testing ownership mutex handle %p", handle);
126 if(mutex_handle->recursion>0 &&
127 mutex_handle->pid==getpid () &&
128 mutex_handle->tid==pthread_self ()) {
130 g_message (G_GNUC_PRETTY_FUNCTION
131 ": mutex handle %p owned by %d:%ld", handle,
132 getpid (), pthread_self ());
138 g_message (G_GNUC_PRETTY_FUNCTION
139 ": mutex handle %p not owned by %d:%ld", handle,
140 getpid (), pthread_self ());
149 * @security: Ignored for now.
150 * @owned: If %TRUE, the mutex is created with the calling thread
151 * already owning the mutex.
152 * @name:Pointer to a string specifying the name of this mutex, or
155 * Creates a new mutex handle. A mutex is signalled when no thread
156 * owns it. A thread acquires ownership of the mutex by waiting for
157 * it with WaitForSingleObject() or WaitForMultipleObjects(). A
158 * thread relinquishes ownership with ReleaseMutex().
160 * A thread that owns a mutex can specify the same mutex in repeated
161 * wait function calls without blocking. The thread must call
162 * ReleaseMutex() an equal number of times to release the mutex.
164 * Return value: A new handle, or %NULL on error.
166 gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
169 struct _WapiHandle_mutex *mutex_handle;
173 pthread_once (&mutex_ops_once, mutex_ops_init);
175 handle=_wapi_handle_new (WAPI_HANDLE_MUTEX);
176 if(handle==_WAPI_HANDLE_INVALID) {
177 g_warning (G_GNUC_PRETTY_FUNCTION
178 ": error creating mutex handle");
182 _wapi_handle_lock_handle (handle);
184 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
185 (gpointer *)&mutex_handle, NULL);
187 g_warning (G_GNUC_PRETTY_FUNCTION
188 ": error looking up mutex handle %p", handle);
189 _wapi_handle_unlock_handle (handle);
194 mutex_handle->name=_wapi_handle_scratch_store (name,
201 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
205 g_message (G_GNUC_PRETTY_FUNCTION ": returning mutex handle %p",
209 _wapi_handle_unlock_handle (handle);
216 * @handle: The mutex handle.
218 * Releases ownership if the mutex handle @handle.
220 * Return value: %TRUE on success, %FALSE otherwise. This function
221 * fails if the calling thread does not own the mutex @handle.
223 gboolean ReleaseMutex(gpointer handle)
225 struct _WapiHandle_mutex *mutex_handle;
227 pthread_t tid=pthread_self();
230 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
231 (gpointer *)&mutex_handle, NULL);
233 g_warning (G_GNUC_PRETTY_FUNCTION
234 ": error looking up mutex handle %p", handle);
238 _wapi_handle_lock_handle (handle);
241 g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex handle %p",
245 if(mutex_handle->tid!=tid || mutex_handle->pid!=pid) {
247 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);
250 _wapi_handle_unlock_handle (handle);
254 /* OK, we own this mutex */
255 mutex_handle->recursion--;
257 if(mutex_handle->recursion==0) {
259 g_message(G_GNUC_PRETTY_FUNCTION ": Unlocking mutex handle %p",
265 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
268 _wapi_handle_unlock_handle (handle);