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 int pthread_mutex_timedlock (pthread_mutex_t
*mutex
,
26 const struct timespec
*timeout
);
29 pthread_mutex_timedlock (pthread_mutex_t
*mutex
, const struct timespec
*timeout
)
31 struct timeval timenow
;
32 struct timespec sleepytime
;
35 /* This is just to avoid a completely busy wait */
36 sleepytime
.tv_sec
= 0;
37 sleepytime
.tv_nsec
= 10000000; /* 10ms */
39 while ((retcode
= pthread_mutex_trylock (mutex
)) == EBUSY
) {
40 gettimeofday (&timenow
, NULL
);
42 if (timenow
.tv_sec
>= timeout
->tv_sec
&&
43 (timenow
.tv_usec
* 1000) >= timeout
->tv_nsec
) {
47 nanosleep (&sleepytime
, NULL
);
52 #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
56 mono_once (mono_once_t
*once
, void (*once_init
) (void))
60 if (!once
->complete
) {
61 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock
,
62 (void *)&once
->mutex
);
63 thr_ret
= pthread_mutex_lock (&once
->mutex
);
64 g_assert (thr_ret
== 0);
66 if (!once
->complete
) {
68 once
->complete
= TRUE
;
70 thr_ret
= pthread_mutex_unlock (&once
->mutex
);
71 g_assert (thr_ret
== 0);
73 pthread_cleanup_pop (0);
83 mono_mutexattr_init (mono_mutexattr_t
*attr
)
85 memset (attr
, 0, sizeof (mono_mutexattr_t
));
90 mono_mutexattr_settype (mono_mutexattr_t
*attr
, int type
)
97 mono_mutexattr_gettype (mono_mutexattr_t
*attr
, int *type
)
104 mono_mutexattr_setpshared (mono_mutexattr_t
*attr
, int pshared
)
106 attr
->shared
= pshared
;
111 mono_mutexattr_getpshared (mono_mutexattr_t
*attr
, int *pshared
)
113 *pshared
= attr
->shared
;
118 mono_mutexattr_setprotocol (mono_mutexattr_t
*attr
, int protocol
)
120 attr
->protocol
= protocol
;
125 mono_mutexattr_getprotocol (mono_mutexattr_t
*attr
, int *protocol
)
127 *protocol
= attr
->protocol
;
132 mono_mutexattr_setprioceiling (mono_mutexattr_t
*attr
, int prioceiling
)
134 attr
->priority
= prioceiling
;
139 mono_mutexattr_getprioceiling (mono_mutexattr_t
*attr
, int *prioceiling
)
141 *prioceiling
= attr
->priority
;
146 mono_mutexattr_destroy (mono_mutexattr_t
*attr
)
153 mono_mutex_init (mono_mutex_t
*mutex
, const mono_mutexattr_t
*attr
)
160 mutex
->owner
= MONO_THREAD_NONE
;
162 if (!attr
|| attr
->type
== MONO_MUTEX_NORMAL
) {
163 mutex
->type
= MONO_MUTEX_NORMAL
;
164 ret
= pthread_mutex_init (&mutex
->mutex
, NULL
);
166 mutex
->type
= MONO_MUTEX_RECURSIVE
;
167 ret
= pthread_mutex_init (&mutex
->mutex
, NULL
);
168 thr_ret
= pthread_cond_init (&mutex
->cond
, NULL
);
169 g_assert (thr_ret
== 0);
176 mono_mutex_lock (mono_mutex_t
*mutex
)
180 switch (mutex
->type
) {
181 case MONO_MUTEX_NORMAL
:
182 return pthread_mutex_lock (&mutex
->mutex
);
183 case MONO_MUTEX_RECURSIVE
:
184 id
= pthread_self ();
185 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
189 if (pthread_equal (mutex
->owner
, MONO_THREAD_NONE
)) {
193 } else if (pthread_equal (mutex
->owner
, id
)) {
198 if (pthread_cond_wait (&mutex
->cond
, &mutex
->mutex
) != 0)
204 return pthread_mutex_unlock (&mutex
->mutex
);
211 mono_mutex_trylock (mono_mutex_t
*mutex
)
215 switch (mutex
->type
) {
216 case MONO_MUTEX_NORMAL
:
217 return pthread_mutex_trylock (&mutex
->mutex
);
218 case MONO_MUTEX_RECURSIVE
:
219 id
= pthread_self ();
221 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
224 if (!pthread_equal (mutex
->owner
, MONO_THREAD_NONE
) &&
225 !pthread_equal (mutex
->owner
, id
)) {
226 pthread_mutex_unlock (&mutex
->mutex
);
231 if (pthread_equal (mutex
->owner
, MONO_THREAD_NONE
)) {
241 return pthread_mutex_unlock (&mutex
->mutex
);
248 mono_mutex_timedlock (mono_mutex_t
*mutex
, const struct timespec
*timeout
)
252 switch (mutex
->type
) {
253 case MONO_MUTEX_NORMAL
:
254 return pthread_mutex_timedlock (&mutex
->mutex
, timeout
);
255 case MONO_MUTEX_RECURSIVE
:
256 id
= pthread_self ();
258 if (pthread_mutex_timedlock (&mutex
->mutex
, timeout
) != 0)
262 if (pthread_equal (mutex
->owner
, MONO_THREAD_NONE
)) {
266 } else if (pthread_equal (mutex
->owner
, id
)) {
271 if (pthread_cond_timedwait (&mutex
->cond
, &mutex
->mutex
, timeout
) != 0)
277 return pthread_mutex_unlock (&mutex
->mutex
);
284 mono_mutex_unlock (mono_mutex_t
*mutex
)
288 switch (mutex
->type
) {
289 case MONO_MUTEX_NORMAL
:
290 return pthread_mutex_unlock (&mutex
->mutex
);
291 case MONO_MUTEX_RECURSIVE
:
292 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
295 if (pthread_equal (mutex
->owner
, pthread_self())) {
296 /* Not owned by this thread */
297 pthread_mutex_unlock (&mutex
->mutex
);
302 if (mutex
->depth
== 0) {
303 mutex
->owner
= MONO_THREAD_NONE
;
304 if (mutex
->waiters
> 0) {
305 thr_ret
= pthread_cond_signal (&mutex
->cond
);
306 g_assert (thr_ret
== 0);
310 return pthread_mutex_unlock (&mutex
->mutex
);
317 mono_mutex_destroy (mono_mutex_t
*mutex
)
322 switch (mutex
->type
) {
323 case MONO_MUTEX_NORMAL
:
324 ret
= pthread_mutex_destroy (&mutex
->mutex
);
326 case MONO_MUTEX_RECURSIVE
:
327 if ((ret
= pthread_mutex_destroy (&mutex
->mutex
)) == 0) {
328 thr_ret
= pthread_cond_destroy (&mutex
->cond
);
329 g_assert (thr_ret
== 0);
338 mono_cond_wait (pthread_cond_t
*cond
, mono_mutex_t
*mutex
)
340 return pthread_cond_wait (cond
, &mutex
->mutex
);
344 mono_cond_timedwait (pthread_cond_t
*cond
, mono_mutex_t
*mutex
, const struct timespec
*timeout
)
346 return pthread_cond_timedwait (cond
, &mutex
->mutex
, timeout
);
349 #endif /* USE_MONO_MUTEX */