1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright 2002 Ximain, Inc. (www.ximian.com)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
34 #include "mono-mutex.h"
37 #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
38 int pthread_mutex_timedlock (pthread_mutex_t
*mutex
,
39 const struct timespec
*timeout
);
42 pthread_mutex_timedlock (pthread_mutex_t
*mutex
, const struct timespec
*timeout
)
44 struct timeval timenow
;
45 struct timespec sleepytime
;
48 /* This is just to avoid a completely busy wait */
49 sleepytime
.tv_sec
= 0;
50 sleepytime
.tv_nsec
= 10000000; /* 10ms */
52 while ((retcode
= pthread_mutex_trylock (mutex
)) == EBUSY
) {
53 gettimeofday (&timenow
, NULL
);
55 if (timenow
.tv_sec
>= timeout
->tv_sec
&&
56 (timenow
.tv_usec
* 1000) >= timeout
->tv_nsec
) {
60 nanosleep (&sleepytime
, NULL
);
65 #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */
69 mono_once (mono_once_t
*once
, void (*once_init
) (void))
73 if (!once
->complete
) {
74 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock
,
75 (void *)&once
->mutex
);
76 thr_ret
= pthread_mutex_lock (&once
->mutex
);
77 g_assert (thr_ret
== 0);
79 if (!once
->complete
) {
81 once
->complete
= TRUE
;
83 thr_ret
= pthread_mutex_unlock (&once
->mutex
);
84 g_assert (thr_ret
== 0);
86 pthread_cleanup_pop (0);
96 mono_mutexattr_init (mono_mutexattr_t
*attr
)
98 memset (attr
, 0, sizeof (mono_mutexattr_t
));
103 mono_mutexattr_settype (mono_mutexattr_t
*attr
, int type
)
110 mono_mutexattr_gettype (mono_mutexattr_t
*attr
, int *type
)
117 mono_mutexattr_setpshared (mono_mutexattr_t
*attr
, int pshared
)
119 attr
->shared
= pshared
;
124 mono_mutexattr_getpshared (mono_mutexattr_t
*attr
, int *pshared
)
126 *pshared
= attr
->shared
;
131 mono_mutexattr_setprotocol (mono_mutexattr_t
*attr
, int protocol
)
133 attr
->protocol
= protocol
;
138 mono_mutexattr_getprotocol (mono_mutexattr_t
*attr
, int *protocol
)
140 *protocol
= attr
->protocol
;
145 mono_mutexattr_setprioceiling (mono_mutexattr_t
*attr
, int prioceiling
)
147 attr
->priority
= prioceiling
;
152 mono_mutexattr_getprioceiling (mono_mutexattr_t
*attr
, int *prioceiling
)
154 *prioceiling
= attr
->priority
;
159 mono_mutexattr_destroy (mono_mutexattr_t
*attr
)
166 mono_mutex_init (mono_mutex_t
*mutex
, const mono_mutexattr_t
*attr
)
173 mutex
->owner
= MONO_THREAD_NONE
;
175 if (!attr
|| attr
->type
== MONO_MUTEX_NORMAL
) {
176 mutex
->type
= MONO_MUTEX_NORMAL
;
177 ret
= pthread_mutex_init (&mutex
->mutex
, NULL
);
179 mutex
->type
= MONO_MUTEX_RECURSIVE
;
180 ret
= pthread_mutex_init (&mutex
->mutex
, NULL
);
181 thr_ret
= pthread_cond_init (&mutex
->cond
, NULL
);
182 g_assert (thr_ret
== 0);
189 mono_mutex_lock (mono_mutex_t
*mutex
)
193 switch (mutex
->type
) {
194 case MONO_MUTEX_NORMAL
:
195 return pthread_mutex_lock (&mutex
->mutex
);
196 case MONO_MUTEX_RECURSIVE
:
197 id
= pthread_self ();
198 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
202 if (mutex
->owner
== MONO_THREAD_NONE
) {
206 } else if (mutex
->owner
== id
) {
211 if (pthread_cond_wait (&mutex
->cond
, &mutex
->mutex
) != 0)
217 return pthread_mutex_unlock (&mutex
->mutex
);
224 mono_mutex_trylock (mono_mutex_t
*mutex
)
228 switch (mutex
->type
) {
229 case MONO_MUTEX_NORMAL
:
230 return pthread_mutex_trylock (&mutex
->mutex
);
231 case MONO_MUTEX_RECURSIVE
:
232 id
= pthread_self ();
234 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
237 if (mutex
->owner
!= MONO_THREAD_NONE
&& mutex
->owner
!= id
) {
238 pthread_mutex_unlock (&mutex
->mutex
);
243 if (mutex
->owner
== MONO_THREAD_NONE
) {
253 return pthread_mutex_unlock (&mutex
->mutex
);
260 mono_mutex_timedlock (mono_mutex_t
*mutex
, const struct timespec
*timeout
)
264 switch (mutex
->type
) {
265 case MONO_MUTEX_NORMAL
:
266 return pthread_mutex_timedlock (&mutex
->mutex
, timeout
);
267 case MONO_MUTEX_RECURSIVE
:
268 id
= pthread_self ();
270 if (pthread_mutex_timedlock (&mutex
->mutex
, timeout
) != 0)
274 if (mutex
->owner
== MONO_THREAD_NONE
) {
278 } else if (mutex
->owner
== id
) {
283 if (pthread_cond_timedwait (&mutex
->cond
, &mutex
->mutex
, timeout
) != 0)
289 return pthread_mutex_unlock (&mutex
->mutex
);
296 mono_mutex_unlock (mono_mutex_t
*mutex
)
300 switch (mutex
->type
) {
301 case MONO_MUTEX_NORMAL
:
302 return pthread_mutex_unlock (&mutex
->mutex
);
303 case MONO_MUTEX_RECURSIVE
:
304 if (pthread_mutex_lock (&mutex
->mutex
) != 0)
307 if (mutex
->owner
!= pthread_self()) {
308 /* Not owned by this thread */
309 pthread_mutex_unlock (&mutex
->mutex
);
314 if (mutex
->depth
== 0) {
315 mutex
->owner
= MONO_THREAD_NONE
;
316 if (mutex
->waiters
> 0) {
317 thr_ret
= pthread_cond_signal (&mutex
->cond
);
318 g_assert (thr_ret
== 0);
322 return pthread_mutex_unlock (&mutex
->mutex
);
329 mono_mutex_destroy (mono_mutex_t
*mutex
)
334 switch (mutex
->type
) {
335 case MONO_MUTEX_NORMAL
:
336 ret
= pthread_mutex_destroy (&mutex
->mutex
);
338 case MONO_MUTEX_RECURSIVE
:
339 if ((ret
= pthread_mutex_destroy (&mutex
->mutex
)) == 0) {
340 thr_ret
= pthread_cond_destroy (&mutex
->cond
);
341 g_assert (thr_ret
== 0);
350 mono_cond_wait (pthread_cond_t
*cond
, mono_mutex_t
*mutex
)
352 return pthread_cond_wait (cond
, &mutex
->mutex
);
356 mono_cond_timedwait (pthread_cond_t
*cond
, mono_mutex_t
*mutex
, const struct timespec
*timeout
)
358 return pthread_cond_timedwait (cond
, &mutex
->mutex
, timeout
);
361 #endif /* USE_MONO_MUTEX */