Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / utils / mono-os-mutex.c
1 /**
2  * \file
3  * Portability wrappers around POSIX Mutexes
4  *
5  * Authors: Jeffrey Stedfast <fejj@ximian.com>
6  *
7  * Copyright 2002 Ximian, Inc. (www.ximian.com)
8  *
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  *
11  */
12
13 #include <config.h>
14
15 #if !defined(HOST_WIN32)
16
17 #if defined(TARGET_OSX)
18 /* So we can use the declaration of pthread_cond_timedwait_relative_np () */
19 #undef _XOPEN_SOURCE
20 #endif
21 #include <pthread.h>
22
23 #include "mono-os-mutex.h"
24
25 int
26 mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
27 {
28         struct timespec ts;
29         int res;
30
31         if (timeout_ms == MONO_INFINITE_WAIT) {
32                 mono_os_cond_wait (cond, mutex);
33                 return 0;
34         }
35
36         /* ms = 10^-3, us = 10^-6, ns = 10^-9 */
37
38         /* This function only seems to be available on 64bit osx */
39 #if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) && defined(TARGET_OSX)
40         memset (&ts, 0, sizeof (struct timespec));
41         ts.tv_sec = timeout_ms / 1000;
42         ts.tv_nsec = (timeout_ms % 1000) * 1000 * 1000;
43
44         res = pthread_cond_timedwait_relative_np (cond, mutex, &ts);
45         if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) {
46                 g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex);
47                 g_error ("%s: pthread_cond_timedwait_relative_np failed with \"%s\" (%d) %ld %ld %d", __func__, g_strerror (res), res, ts.tv_sec, ts.tv_nsec, timeout_ms);
48         }
49         return res != 0 ? -1 : 0;
50 #else
51 #ifdef BROKEN_CLOCK_SOURCE
52         struct timeval tv;
53
54         /* clock_gettime is not supported in MAC OS x */
55         res = gettimeofday (&tv, NULL);
56         if (G_UNLIKELY (res != 0))
57                 g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
58
59         ts.tv_sec = tv.tv_sec;
60         ts.tv_nsec = tv.tv_usec * 1000;
61 #else
62         /* cond is using CLOCK_MONOTONIC as time source */
63         res = clock_gettime (CLOCK_MONOTONIC, &ts);
64         if (G_UNLIKELY (res != 0))
65                 g_error ("%s: clock_gettime failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
66 #endif
67
68         ts.tv_sec += timeout_ms / 1000;
69         ts.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;
70         if (ts.tv_nsec >= 1000 * 1000 * 1000) {
71                 ts.tv_nsec -= 1000 * 1000 * 1000;
72                 ts.tv_sec ++;
73         }
74
75         res = pthread_cond_timedwait (cond, mutex, &ts);
76         if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) {
77                 g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex);
78                 g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d) %ld %ld %d", __func__, g_strerror (res), res, ts.tv_sec, ts.tv_nsec, timeout_ms);
79         }
80         return res != 0 ? -1 : 0;
81 #endif /* !HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */
82 }
83
84 #endif /* HOST_WIN32 */