/** * \file * Portability wrappers around POSIX Mutexes * * Authors: Jeffrey Stedfast * * Copyright 2002 Ximian, Inc. (www.ximian.com) * * Licensed under the MIT license. See LICENSE file in the project root for full license information. * */ #include #if !defined(HOST_WIN32) #if defined(TARGET_OSX) /* So we can use the declaration of pthread_cond_timedwait_relative_np () */ #undef _XOPEN_SOURCE #endif #include #include "mono-os-mutex.h" int mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms) { 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 */ /* This function only seems to be available on 64bit osx */ #if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) && defined(TARGET_OSX) memset (&ts, 0, sizeof (struct timespec)); ts.tv_sec = timeout_ms / 1000; ts.tv_nsec = (timeout_ms % 1000) * 1000 * 1000; res = pthread_cond_timedwait_relative_np (cond, mutex, &ts); if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) { g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex); 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); } return res != 0 ? -1 : 0; #else #ifdef BROKEN_CLOCK_SOURCE struct timeval tv; /* 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); ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; #else /* cond is using CLOCK_MONOTONIC as time source */ 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); #endif ts.tv_sec += timeout_ms / 1000; ts.tv_nsec += (timeout_ms % 1000) * 1000 * 1000; if (ts.tv_nsec >= 1000 * 1000 * 1000) { ts.tv_nsec -= 1000 * 1000 * 1000; ts.tv_sec ++; } res = pthread_cond_timedwait (cond, mutex, &ts); if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) { g_print ("cond: %p mutex: %p\n", *(gpointer*)cond, *(gpointer*)mutex); 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); } return res != 0 ? -1 : 0; #endif /* !HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */ } #endif /* HOST_WIN32 */