[glib] win32: Make g_get_monotonic_clock lockless
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] win32: Make g_get_monotonic_clock lockless
- Date: Wed, 16 Nov 2011 08:44:16 +0000 (UTC)
commit 3a7960f75730fdde77652b97ad6492004c5b1ec1
Author: Alexander Larsson <alexl redhat com>
Date: Fri Nov 4 16:45:41 2011 +0100
win32: Make g_get_monotonic_clock lockless
glib/gmain.c | 32 ++++++++++++++++++++------------
1 files changed, 20 insertions(+), 12 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 6a3aaf4..a4f33e5 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -1974,10 +1974,9 @@ g_get_real_time (void)
}
#ifdef G_OS_WIN32
-G_LOCK_DEFINE_STATIC (g_win32_clock);
static ULONGLONG (*g_GetTickCount64) (void) = NULL;
-static guint32 g_win32_last_ticks32 = 0;
static guint32 g_win32_tick_epoch = 0;
+
G_GNUC_INTERNAL void
g_clock_win32_init (void)
{
@@ -1987,7 +1986,7 @@ g_clock_win32_init (void)
kernel32 = GetModuleHandle ("KERNEL32.DLL");
if (kernel32 != NULL)
g_GetTickCount64 = (void *) GetProcAddress (kernel32, "GetTickCount64");
- g_win32_last_ticks32 = GetTickCount();
+ g_win32_tick_epoch = ((guint32)GetTickCount()) >> 31;
}
#endif
@@ -2126,26 +2125,35 @@ g_get_monotonic_time (void)
}
else
{
- G_LOCK (g_win32_clock);
+ guint32 epoch;
+
+ epoch = g_atomic_int_get (&g_win32_tick_epoch);
+ /* Must read ticks after the epoch, then we're guaranteed
+ that the ticks value we read is higher or equal to any
+ previous ones that lead to the writing of the epoch. */
ticks32 = timeGetTime();
- /* We have wrapped the 32bit counter, increase the epoch.
+ /* We store the msb of the current time as the lsb
+ * of the epoch. Comparing these bits lets us detect when
+ * the 32bit counter has wrapped so we can increase the
+ * epoch.
* This will work as long as this function is called at
- * least once every ~50 days, which is the wrap time of
- * a 32bit msec counter. I think this is pretty likely.
+ * least once every ~24 days, which is half the wrap time
+ * of a 32bit msec counter. I think this is pretty likely.
*
* Note that g_win32_tick_epoch is a process local state,
* so the monotonic clock will not be the same between
* processes.
*/
- if (ticks32 < g_win32_last_ticks32)
- g_win32_tick_epoch++;
+ if ((ticks32 >> 31) != (epoch & 1))
+ {
+ epoch++;
+ g_atomic_int_set (&g_win32_tick_epoch, epoch);
+ }
- ticks = (guint64)ticks32 | ((guint64)g_win32_tick_epoch) << 32;
- g_win32_last_ticks32 = ticks32;
- G_UNLOCK (g_win32_clock);
+ ticks = (guint64)ticks32 | ((guint64)epoch) << 31;
}
return ticks * 1000;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]