Fix g_get_monotonic_time on non-Intel processors https://bugzilla.gnome.org/show_bug.cgi?id=728123 https://bug728123.bugzilla-attachments.gnome.org/attachment.cgi?id=275596 --- glib/gmain.c.orig 2017-05-08 09:59:29.000000000 -0500 +++ glib/gmain.c 2017-06-19 13:39:05.000000000 -0500 @@ -2811,46 +2811,34 @@ g_get_monotonic_time (void) { static mach_timebase_info_data_t timebase_info; + static double absolute_to_micro; if (timebase_info.denom == 0) { - /* This is a fraction that we must use to scale - * mach_absolute_time() by in order to reach nanoseconds. - * - * We've only ever observed this to be 1/1, but maybe it could be - * 1000/1 if mach time is microseconds already, or 1/1000 if - * picoseconds. Try to deal nicely with that. + /* mach_absolute_time() returns "absolute time units", rather than + seconds; the mach_timebase_info_data_t struct provides a + fraction that can be used to convert these units into seconds. */ mach_timebase_info (&timebase_info); - - /* We actually want microseconds... */ - if (timebase_info.numer % 1000 == 0) - timebase_info.numer /= 1000; - else - timebase_info.denom *= 1000; - - /* We want to make the numer 1 to avoid having to multiply... */ - if (timebase_info.denom % timebase_info.numer == 0) - { - timebase_info.denom /= timebase_info.numer; - timebase_info.numer = 1; - } - else - { - /* We could just multiply by timebase_info.numer below, but why - * bother for a case that may never actually exist... - * - * Plus -- performing the multiplication would risk integer - * overflow. If we ever actually end up in this situation, we - * should more carefully evaluate the correct course of action. - */ - mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */ - g_error ("Got weird mach timebase info of %d/%d. Please file a bug against GLib.", - timebase_info.numer, timebase_info.denom); - } + absolute_to_micro = 1e-3 * timebase_info.numer / timebase_info.denom; } - return mach_absolute_time () / timebase_info.denom; + if (timebase_info.denom == 1 && timebase_info.numer == 1) + { + /* On Intel, the fraction has been 1/1 to date, so we can shortcut + the conversion into microseconds. + */ + return mach_absolute_time () / 1000; + } + else + { + /* On ARM and PowerPC, the value is unpredictable and is hardware + dependent, so we can't guess. Both the units and numer/denom + are extremely large, so the conversion number is stored as a + double in order to avoid integer overflow. + */ + return mach_absolute_time () * absolute_to_micro; + } } #else gint64