Port-xen archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Strange numbers from gettimeofday(2)



> Sometimes, gettimeofday(2) will return large negative numbers for the
> tv_usec field; this has been happening spontaneously, but I've been
> able to reproduce it by either pausing or ddb-breaking a domU for a
> few seconds (the exact interval varies on different hardware).

cc_microtime assumes that both of timer and tsc is somewhat stable.
however, both of them can be unstable on xen.

i think that the attached patch eases the problem.
but i agree that cc_microtime is not suitable for xen anyway.

YAMAMOTO Takashi
Index: kern_microtime.c
===================================================================
--- kern_microtime.c    (revision 1464)
+++ kern_microtime.c    (working copy)
@@ -144,9 +144,11 @@ cc_microtime(struct timeval *tvp)
                usec += 1000000;
                sec--;
        }
+       KASSERT(usec >= 0);
+       KASSERT(usec < 1000000);
        if (sec == 0 && usec > 0)  {
                t.tv_usec += usec + 1;
-               if (t.tv_usec >= 1000000) {
+               while (t.tv_usec >= 1000000) {
                        t.tv_usec -= 1000000;
                        t.tv_sec++;
                }
@@ -199,7 +201,28 @@ cc_microset(struct cpu_info *ci)
            (t.tv_usec - ci->ci_cc_time.tv_usec);
 
        ci->ci_cc_time = t;
+
        /*
+        * check if our cpu frequency is sane.
+        */
+
+       if (delta != 0) {
+               uint64_t freq = cpu_frequency(ci);
+               uint64_t ourfreq;
+
+               ourfreq = denom * 1000000 / delta;
+               if (__predict_false(ourfreq > freq * 2 || ourfreq * 2 < freq)) {
+#if 0
+                       printf("%s[%d]: ourfreq=%" PRIu64 ", freq=%"
+                           PRIu64 ", delta=%" PRId64 ", denom=%" PRId64 "\n",
+                           __func__, (int)ci->ci_cpuid,
+                           ourfreq, freq, delta, denom);
+#endif
+                       goto insane;
+               }
+       }
+
+       /*
         * Make sure it's within .5 to 1.5 seconds -- otherwise,
         * the time is probably be frobbed with by the timekeeper
         * or the human.
@@ -212,6 +235,7 @@ cc_microset(struct cpu_info *ci)
                    ", denom %" PRId64 "\n", ci->ci_cpuid, delta, denom);
 #endif
        } else {
+insane:
 #if 0
                printf("cc_microset[%lu]: delta %" PRId64 ", resetting state\n",
                       (u_long)ci->ci_cpuid, delta);


Home | Main Index | Thread Index | Old Index