1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * mono-mutex.h: Portability wrappers around POSIX Mutexes
5 * Authors: Jeffrey Stedfast <fejj@ximian.com>
7 * Copyright 2002 Ximian, Inc. (www.ximian.com)
21 #include "mono-mutex.h"
24 #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
25 /* Android does not implement pthread_mutex_timedlock(), but does provide an
26 * unusual declaration: http://code.google.com/p/android/issues/detail?id=7807
28 #ifdef PLATFORM_ANDROID
31 #define CONST_NEEDED const
34 int pthread_mutex_timedlock (pthread_mutex_t *mutex,
35 CONST_NEEDED struct timespec *timeout);
37 pthread_mutex_timedlock (pthread_mutex_t *mutex, CONST_NEEDED struct timespec *timeout)
39 struct timeval timenow;
40 struct timespec sleepytime;
43 /* This is just to avoid a completely busy wait */
44 sleepytime.tv_sec = 0;
45 sleepytime.tv_nsec = 10000000; /* 10ms */
47 while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY) {
48 gettimeofday (&timenow, NULL);
50 if (timenow.tv_sec >= timeout->tv_sec &&
51 (timenow.tv_usec * 1000) >= timeout->tv_nsec) {
55 nanosleep (&sleepytime, NULL);
60 #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
64 mono_once (mono_once_t *once, void (*once_init) (void))
68 if (!once->complete) {
69 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
70 (void *)&once->mutex);
71 thr_ret = pthread_mutex_lock (&once->mutex);
72 g_assert (thr_ret == 0);
74 if (!once->complete) {
76 once->complete = TRUE;
78 thr_ret = pthread_mutex_unlock (&once->mutex);
79 g_assert (thr_ret == 0);
81 pthread_cleanup_pop (0);
91 mono_mutexattr_init (mono_mutexattr_t *attr)
93 memset (attr, 0, sizeof (mono_mutexattr_t));
98 mono_mutexattr_settype (mono_mutexattr_t *attr, int type)
105 mono_mutexattr_gettype (mono_mutexattr_t *attr, int *type)
112 mono_mutexattr_setpshared (mono_mutexattr_t *attr, int pshared)
114 attr->shared = pshared;
119 mono_mutexattr_getpshared (mono_mutexattr_t *attr, int *pshared)
121 *pshared = attr->shared;
126 mono_mutexattr_setprotocol (mono_mutexattr_t *attr, int protocol)
128 attr->protocol = protocol;
133 mono_mutexattr_getprotocol (mono_mutexattr_t *attr, int *protocol)
135 *protocol = attr->protocol;
140 mono_mutexattr_setprioceiling (mono_mutexattr_t *attr, int prioceiling)
142 attr->priority = prioceiling;
147 mono_mutexattr_getprioceiling (mono_mutexattr_t *attr, int *prioceiling)
149 *prioceiling = attr->priority;
154 mono_mutexattr_destroy (mono_mutexattr_t *attr)
161 mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr)
168 mutex->owner = MONO_THREAD_NONE;
170 if (!attr || attr->type == MONO_MUTEX_NORMAL) {
171 mutex->type = MONO_MUTEX_NORMAL;
172 ret = pthread_mutex_init (&mutex->mutex, NULL);
174 mutex->type = MONO_MUTEX_RECURSIVE;
175 ret = pthread_mutex_init (&mutex->mutex, NULL);
176 thr_ret = pthread_cond_init (&mutex->cond, NULL);
177 g_assert (thr_ret == 0);
184 mono_mutex_lock (mono_mutex_t *mutex)
188 switch (mutex->type) {
189 case MONO_MUTEX_NORMAL:
190 return pthread_mutex_lock (&mutex->mutex);
191 case MONO_MUTEX_RECURSIVE:
192 id = pthread_self ();
193 if (pthread_mutex_lock (&mutex->mutex) != 0)
197 if (pthread_equal (mutex->owner, MONO_THREAD_NONE)) {
201 } else if (pthread_equal (mutex->owner, id)) {
206 if (pthread_cond_wait (&mutex->cond, &mutex->mutex) != 0)
212 return pthread_mutex_unlock (&mutex->mutex);
219 mono_mutex_trylock (mono_mutex_t *mutex)
223 switch (mutex->type) {
224 case MONO_MUTEX_NORMAL:
225 return pthread_mutex_trylock (&mutex->mutex);
226 case MONO_MUTEX_RECURSIVE:
227 id = pthread_self ();
229 if (pthread_mutex_lock (&mutex->mutex) != 0)
232 if (!pthread_equal (mutex->owner, MONO_THREAD_NONE) &&
233 !pthread_equal (mutex->owner, id)) {
234 pthread_mutex_unlock (&mutex->mutex);
239 if (pthread_equal (mutex->owner, MONO_THREAD_NONE)) {
249 return pthread_mutex_unlock (&mutex->mutex);
256 mono_mutex_timedlock (mono_mutex_t *mutex, const struct timespec *timeout)
260 switch (mutex->type) {
261 case MONO_MUTEX_NORMAL:
262 return pthread_mutex_timedlock (&mutex->mutex, timeout);
263 case MONO_MUTEX_RECURSIVE:
264 id = pthread_self ();
266 if (pthread_mutex_timedlock (&mutex->mutex, timeout) != 0)
270 if (pthread_equal (mutex->owner, MONO_THREAD_NONE)) {
274 } else if (pthread_equal (mutex->owner, id)) {
279 if (pthread_cond_timedwait (&mutex->cond, &mutex->mutex, timeout) != 0)
285 return pthread_mutex_unlock (&mutex->mutex);
292 mono_mutex_unlock (mono_mutex_t *mutex)
296 switch (mutex->type) {
297 case MONO_MUTEX_NORMAL:
298 return pthread_mutex_unlock (&mutex->mutex);
299 case MONO_MUTEX_RECURSIVE:
300 if (pthread_mutex_lock (&mutex->mutex) != 0)
303 if (pthread_equal (mutex->owner, pthread_self())) {
304 /* Not owned by this thread */
305 pthread_mutex_unlock (&mutex->mutex);
310 if (mutex->depth == 0) {
311 mutex->owner = MONO_THREAD_NONE;
312 if (mutex->waiters > 0) {
313 thr_ret = pthread_cond_signal (&mutex->cond);
314 g_assert (thr_ret == 0);
318 return pthread_mutex_unlock (&mutex->mutex);
325 mono_mutex_destroy (mono_mutex_t *mutex)
330 switch (mutex->type) {
331 case MONO_MUTEX_NORMAL:
332 ret = pthread_mutex_destroy (&mutex->mutex);
334 case MONO_MUTEX_RECURSIVE:
335 if ((ret = pthread_mutex_destroy (&mutex->mutex)) == 0) {
336 thr_ret = pthread_cond_destroy (&mutex->cond);
337 g_assert (thr_ret == 0);
346 mono_cond_wait (pthread_cond_t *cond, mono_mutex_t *mutex)
348 return pthread_cond_wait (cond, &mutex->mutex);
352 mono_cond_timedwait (pthread_cond_t *cond, mono_mutex_t *mutex, const struct timespec *timeout)
354 return pthread_cond_timedwait (cond, &mutex->mutex, timeout);
357 #endif /* USE_MONO_MUTEX */