diff --git a/mono/utils/mono-os-mutex.h b/mono/utils/mono-os-mutex.h index cd33375894c1d..728b421a2ad04 100644 --- a/mono/utils/mono-os-mutex.h +++ b/mono/utils/mono-os-mutex.h @@ -122,10 +122,28 @@ static inline void mono_os_cond_init (mono_cond_t *cond) { int res; - + /* POSIX standard does not compel to have CLOCK_MONOTONIC */ +#if !defined(PLATFORM_MACOSX) && defined(CLOCK_MONOTONIC) + pthread_condattr_t attr; + + res = pthread_condattr_init (&attr); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_condattr_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + res = pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_condattr_setclock failed with \"%s\" (%d)", __func__, g_strerror (res), res); + /* Attach an attribute having CLOCK_MONOTONIC to condition */ + res = pthread_cond_init (cond, &attr); +#else res = pthread_cond_init (cond, NULL); +#endif if (G_UNLIKELY (res != 0)) g_error ("%s: pthread_cond_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + res = pthread_condattr_destroy (&attr); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_condattr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res); } static inline void @@ -151,22 +169,35 @@ mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex) static inline int mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms) { + +#if defined(PLATFORM_MACOSX) struct timeval tv; - struct timespec ts; gint64 usecs; +#endif + struct timespec ts; int res; - if (timeout_ms == MONO_INFINITE_WAIT) { mono_os_cond_wait (cond, mutex); return 0; } /* ms = 10^-3, us = 10^-6, ns = 10^-9 */ - +#if !defined(PLATFORM_MACOSX) && defined(CLOCK_MONOTONIC) + /* cond is using CLOCK_MONOTONIC as time source, & give up rather than screwing if clock_gettime fails */ + res = clock_gettime (CLOCK_MONOTONIC, &ts); + if (G_UNLIKELY (res != 0)) + g_error ("%s: clock_gettime failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); + ts.tv_sec += timeout_ms / 1000; + ts.tv_nsec = ((timeout_ms % 1000) * 1000) * 1000; + if (ts.tv_nsec >= 1000000000){ + ts.tv_nsec -= 1000000000; + ts.tv_sec ++; + } +#else + /* clock_gettime is not supported in MAC OS x */ res = gettimeofday (&tv, NULL); if (G_UNLIKELY (res != 0)) g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); - tv.tv_sec += timeout_ms / 1000; usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000); if (usecs >= 1000000) { @@ -175,7 +206,7 @@ mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ } ts.tv_sec = tv.tv_sec; ts.tv_nsec = usecs * 1000; - +#endif res = pthread_cond_timedwait (cond, mutex, &ts); if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d)", __func__, g_strerror (res), res);