g_get_monotonic_time: fix race condition

Since there was nothing guaranteeing synchronization of the
assignments to checked and clockid, it would be possible for one
thread to set clockid = CLOCK_MONOTONIC, and for another thread to see
checked = TRUE but still clockid = CLOCK_REALTIME.

https://bugzilla.gnome.org/show_bug.cgi?id=655129
This commit is contained in:
Dan Winship 2011-08-16 19:12:59 -04:00
parent c0eb77bfc8
commit 2955981569

View File

@ -2042,25 +2042,24 @@ g_get_monotonic_time (void)
#ifdef HAVE_CLOCK_GETTIME #ifdef HAVE_CLOCK_GETTIME
/* librt clock_gettime() is our first choice */ /* librt clock_gettime() is our first choice */
{ {
static int clockid = CLOCK_REALTIME; #ifdef HAVE_MONOTONIC_CLOCK
static volatile gsize clockid = 0;
#else
static clockid_t clockid = CLOCK_REALTIME;
#endif
struct timespec ts; struct timespec ts;
#ifdef HAVE_MONOTONIC_CLOCK #ifdef HAVE_MONOTONIC_CLOCK
/* We have to check if we actually have monotonic clock support. if (g_once_init_enter (&clockid))
* {
* There is no thread safety issue here since there is no harm if we clockid_t best_clockid;
* check twice.
*/
{
static gboolean checked;
if G_UNLIKELY (!checked) if (sysconf (_SC_MONOTONIC_CLOCK) >= 0)
{ best_clockid = CLOCK_MONOTONIC;
if (sysconf (_SC_MONOTONIC_CLOCK) >= 0) else
clockid = CLOCK_MONOTONIC; best_clockid = CLOCK_REALTIME;
checked = TRUE; g_once_init_leave (&clockid, (gsize)best_clockid);
} }
}
#endif #endif
clock_gettime (clockid, &ts); clock_gettime (clockid, &ts);