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.
32 #include "mono-mutex.h"
35 #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
37 pthread_mutex_timedlock (pthread_mutex_t *mutex, const 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 = 10000; /* 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 */
67 mono_mutexattr_init (mono_mutexattr_t *attr)
69 memset (attr, 0, sizeof (mono_mutexattr_t));
74 mono_mutexattr_settype (mono_mutexattr_t *attr, int type)
81 mono_mutexattr_gettype (mono_mutexattr_t *attr, int *type)
88 mono_mutexattr_setpshared (mono_mutexattr_t *attr, int pshared)
90 attr->shared = pshared;
95 mono_mutexattr_getpshared (mono_mutexattr_t *attr, int *pshared)
97 *pshared = attr->shared;
102 mono_mutexattr_setprotocol (mono_mutexattr_t *attr, int protocol)
104 attr->protocol = protocol;
109 mono_mutexattr_getprotocol (mono_mutexattr_t *attr, int *protocol)
111 *protocol = attr->protocol;
116 mono_mutexattr_setprioceiling (mono_mutexattr_t *attr, int prioceiling)
118 attr->priority = prioceiling;
123 mono_mutexattr_getprioceiling (mono_mutexattr_t *attr, int *prioceiling)
125 *prioceiling = attr->priority;
130 mono_mutexattr_destroy (mono_mutexattr_t *attr)
137 mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr)
141 mutex->owner = MONO_THREAD_NONE;
143 if (!attr || attr->type == MONO_MUTEX_NORMAL) {
144 mutex->type = MONO_MUTEX_NORMAL;
145 pthread_mutex_init (&mutex->mutex, NULL);
147 mutex->type = MONO_MUTEX_RECURSIVE;
148 pthread_mutex_init (&mutex->mutex, NULL);
149 pthread_cond_init (&mutex->cond, NULL);
156 mono_mutex_lock (mono_mutex_t *mutex)
160 switch (mutex->type) {
161 case MONO_MUTEX_NORMAL:
162 return pthread_mutex_lock (&mutex->mutex);
163 case MONO_MUTEX_RECURSIVE:
164 id = pthread_self ();
165 if (pthread_mutex_lock (&mutex->mutex) != 0)
169 if (mutex->owner == MONO_THREAD_NONE) {
173 } else if (mutex->owner == id) {
178 if (pthread_cond_wait (&mutex->cond, &mutex->mutex) == -1)
184 return pthread_mutex_unlock (&mutex->mutex);
191 mono_mutex_trylock (mono_mutex_t *mutex)
195 switch (mutex->type) {
196 case MONO_MUTEX_NORMAL:
197 return pthread_mutex_trylock (&mutex->mutex);
198 case MONO_MUTEX_RECURSIVE:
199 id = pthread_self ();
201 if (pthread_mutex_lock (&mutex->mutex) != 0)
204 if (mutex->owner != MONO_THREAD_NONE && mutex->owner != id) {
205 pthread_mutex_unlock (&mutex->mutex);
210 if (mutex->owner == MONO_THREAD_NONE) {
220 return pthread_mutex_unlock (&mutex->mutex);
227 mono_mutex_timedlock (mono_mutex_t *mutex, const struct timespec *timeout)
231 switch (mutex->type) {
232 case MONO_MUTEX_NORMAL:
233 return pthread_mutex_timedlock (&mutex->mutex, timeout);
234 case MONO_MUTEX_RECURSIVE:
235 id = pthread_self ();
237 if (pthread_mutex_timedlock (&mutex->mutex, timeout) != 0)
241 if (mutex->owner == MONO_THREAD_NONE) {
245 } else if (mutex->owner == id) {
250 if (pthread_cond_timedwait (&mutex->cond, &mutex->mutex, timeout) != 0)
256 return pthread_mutex_unlock (&mutex->mutex);
263 mono_mutex_unlock (mono_mutex_t *mutex)
265 switch (mutex->type) {
266 case MONO_MUTEX_NORMAL:
267 return pthread_mutex_unlock (&mutex->mutex);
268 case MONO_MUTEX_RECURSIVE:
269 if (pthread_mutex_lock (&mutex->mutex) != 0)
272 g_assert (mutex->owner == pthread_self ());
275 if (mutex->depth == 0) {
276 mutex->owner = MONO_THREAD_NONE;
277 if (mutex->waiters > 0)
278 pthread_cond_signal (&mutex->cond);
281 return pthread_mutex_unlock (&mutex->mutex);
288 mono_mutex_destroy (mono_mutex_t *mutex)
292 switch (mutex->type) {
293 case MONO_MUTEX_NORMAL:
294 ret = pthread_mutex_destroy (&mutex->mutex);
296 case MONO_MUTEX_RECURSIVE:
297 if ((ret = pthread_mutex_destroy (&mutex->mutex)) == 0) {
298 pthread_cond_destroy (&mutex->cond);
307 mono_cond_wait (pthread_cond_t *cond, mono_mutex_t *mutex)
309 return pthread_cond_wait (cond, &mutex->mutex);
313 mono_cond_timedwait (pthread_cond_t *cond, mono_mutex_t *mutex, const struct timespec *timeout)
315 return pthread_cond_wait (cond, &mutex->mutex, timeout);
318 #endif /* USE_MONO_MUTEX */