]> git.sur5r.net Git - openldap/commitdiff
ITS#5668 avoid overflows in Windows microsecond computation
authorHoward Chu <hyc@openldap.org>
Thu, 11 Sep 2008 01:51:02 +0000 (01:51 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 11 Sep 2008 01:51:02 +0000 (01:51 +0000)
libraries/liblutil/utils.c

index 63b0f3802a2b58db4c0be5e1450eb7fe61f34c9a..8a199f85dd41d78c889149094384b554b176ce3f 100644 (file)
@@ -303,41 +303,52 @@ lutil_gettime( struct lutil_tm *tm )
        GetSystemTime( &st );
        QueryPerformanceCounter( &count );
 
+       /* It shouldn't ever go backwards, but multiple CPUs might
+        * be able to hit in the same tick.
+        */
+       if ( count.QuadPart <= prevCount.QuadPart ) {
+               subs++;
+       } else {
+               subs = 0;
+               prevCount = count;
+       }
+
        /* We assume Windows has at least a vague idea of
         * when a second begins. So we align our microsecond count
         * with the Windows millisecond count using this offset.
         * We retain the submillisecond portion of our own count.
+        *
+        * Note - this also assumes that the relationship between
+        * the PerformanceCouunter and SystemTime stays constant;
+        * that assumption breaks if the SystemTime is adjusted by
+        * an external action.
         */
        if ( !cFreq.QuadPart ) {
                long long t;
                int usec;
                QueryPerformanceFrequency( &cFreq );
 
-               t = count.QuadPart * 1000000;
-               t /= cFreq.QuadPart;
-               usec = t % 10000000;
-               usec /= 1000;
-               offset = ( usec - st.wMilliseconds ) * 1000;
-       }
+               /* just get sub-second portion of counter */
+               t = count.QuadPart % cFreq.QuadPart;
 
-       /* It shouldn't ever go backwards, but multiple CPUs might
-        * be able to hit in the same tick.
-        */
-       if ( count.QuadPart <= prevCount.QuadPart ) {
-               subs++;
-       } else {
-               subs = 0;
-               prevCount = count;
+               /* convert to microseconds */
+               t *= 1000000;
+               usec = t / cFreq.QuadPart;
+
+               offset = usec - st.wMilliseconds * 1000;
        }
 
        tm->tm_usub = subs;
 
        /* convert to microseconds */
+       count.QuadPart %= cFreq.QuadPart;
        count.QuadPart *= 1000000;
        count.QuadPart /= cFreq.QuadPart;
        count.QuadPart -= offset;
 
        tm->tm_usec = count.QuadPart % 1000000;
+       if ( tm->tm_usec < 0 )
+               tm->tm_usec += 1000000;
 
        /* any difference larger than microseconds is
         * already reflected in st