Core dumps...

Matthew Dillon dillon at apollo.backplane.com
Thu Nov 11 12:03:58 PST 2004


:> :[ adamk at sorrow - ~ ]: gnome-terminal 
:> :Fatal error 'gc cannot wait for a signal' at line ? in file /usr/src/lib/libc_r/uthread/uthread_gc.c (errno = ?)
:> :Abort trap (core dumped)
:> :
:> :Same for mozilla, thunderbird, firefox, etc..
:> :
:> :I left my machine, brushed my teeth, came back, and suddenly it's working again.  Any ideas what happened? 
:> :
:> :Adam
:> 
:>...
:
:I'm seeing this too when my laptop resumed from suspended state, and my
:workaround is to adjust your system clock (with ntpdate for instance)
:a few times. You'll get "Invalid argument" error from ntpdate, but just ignore
:it and try a few times.

    Well, they say a fresh look always helps, and it looks like that
    is true.  In about 5 seconds I found an overflow in the
    'cputimer_freq64_nsec * delta' calculations in kern_clock.c.

    It turns out that cputimer_freq_nsec is such a large number that
    it doesn't take a delta much larger then cputimer_freq to overflow
    it, and the delta calculation can certainly exceed cputimer_freq
    due to all sorts of reasons... interrupt latency, blockages, and other
    things.  laptop resumption only being one of them.

    So I would like both of you to please try this patch and tell me what
    happens.

					-Matt
					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

Index: kern_clock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clock.c,v
retrieving revision 1.24
diff -u -r1.24 kern_clock.c
--- kern_clock.c	17 Sep 2004 00:18:09 -0000	1.24
+++ kern_clock.c	11 Nov 2004 19:53:13 -0000
@@ -279,10 +279,14 @@
 	 * stay in synch.
 	 *
 	 * Note that we never allow info->time (aka gd->gd_hardclock.time)
-	 * to reverse index gd_cpuclock_base.
+	 * to reverse index gd_cpuclock_base, but that it is possible for
+	 * it to temporarily get behind in the seconds if something in the
+	 * system locks interrupts for a long period of time.  Since periodic
+	 * timers count events, though everything should resynch again
+	 * immediately.
 	 */
 	cputicks = info->time - gd->gd_cpuclock_base;
-	if (cputicks > cputimer_freq) {
+	if (cputicks >= cputimer_freq) {
 		++gd->gd_time_seconds;
 		gd->gd_cpuclock_base += cputimer_freq;
 	}
@@ -676,6 +680,12 @@
  * Each cpu independantly maintains the current time of day, so all
  * we need to do to protect ourselves from changes is to do a loop
  * check on the seconds field changing out from under us.
+ *
+ * The system timer maintains a 32 bit count and due to various issues
+ * it is possible for the calculated delta to occassionally exceed
+ * cputimer_freq.  If this occurs the cputimer_freq64_nsec multiplication
+ * can easily overflow, so we deal with the case.  For uniformity we deal
+ * with the case in the usec case too.
  */
 void
 getmicrouptime(struct timeval *tvp)
@@ -687,6 +697,11 @@
 		tvp->tv_sec = gd->gd_time_seconds;
 		delta = gd->gd_hardclock.time - gd->gd_cpuclock_base;
 	} while (tvp->tv_sec != gd->gd_time_seconds);
+
+	if (delta >= cputimer_freq) {
+		tvp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
+	}
 	tvp->tv_usec = (cputimer_freq64_usec * delta) >> 32;
 	if (tvp->tv_usec >= 1000000) {
 		tvp->tv_usec -= 1000000;
@@ -704,11 +719,12 @@
 		tsp->tv_sec = gd->gd_time_seconds;
 		delta = gd->gd_hardclock.time - gd->gd_cpuclock_base;
 	} while (tsp->tv_sec != gd->gd_time_seconds);
-	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
-	if (tsp->tv_nsec >= 1000000000) {
-		tsp->tv_nsec -= 1000000000;
-		++tsp->tv_sec;
+
+	if (delta >= cputimer_freq) {
+		tsp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
 	}
+	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
 }
 
 void
@@ -721,11 +737,12 @@
 		tvp->tv_sec = gd->gd_time_seconds;
 		delta = cputimer_count() - gd->gd_cpuclock_base;
 	} while (tvp->tv_sec != gd->gd_time_seconds);
-	tvp->tv_usec = (cputimer_freq64_usec * delta) >> 32;
-	if (tvp->tv_usec >= 1000000) {
-		tvp->tv_usec -= 1000000;
-		++tvp->tv_sec;
+
+	if (delta >= cputimer_freq) {
+		tvp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
 	}
+	tvp->tv_usec = (cputimer_freq64_usec * delta) >> 32;
 }
 
 void
@@ -738,11 +755,12 @@
 		tsp->tv_sec = gd->gd_time_seconds;
 		delta = cputimer_count() - gd->gd_cpuclock_base;
 	} while (tsp->tv_sec != gd->gd_time_seconds);
-	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
-	if (tsp->tv_nsec >= 1000000000) {
-		tsp->tv_nsec -= 1000000000;
-		++tsp->tv_sec;
+
+	if (delta >= cputimer_freq) {
+		tsp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
 	}
+	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
 }
 
 /*
@@ -759,6 +777,11 @@
 		tvp->tv_sec = gd->gd_time_seconds;
 		delta = gd->gd_hardclock.time - gd->gd_cpuclock_base;
 	} while (tvp->tv_sec != gd->gd_time_seconds);
+
+	if (delta >= cputimer_freq) {
+		tvp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
+	}
 	tvp->tv_usec = (cputimer_freq64_usec * delta) >> 32;
 
 	tvp->tv_sec += basetime.tv_sec;
@@ -779,6 +802,11 @@
 		tsp->tv_sec = gd->gd_time_seconds;
 		delta = gd->gd_hardclock.time - gd->gd_cpuclock_base;
 	} while (tsp->tv_sec != gd->gd_time_seconds);
+
+	if (delta >= cputimer_freq) {
+		tsp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
+	}
 	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
 
 	tsp->tv_sec += basetime.tv_sec;
@@ -799,6 +827,11 @@
 		tvp->tv_sec = gd->gd_time_seconds;
 		delta = cputimer_count() - gd->gd_cpuclock_base;
 	} while (tvp->tv_sec != gd->gd_time_seconds);
+
+	if (delta >= cputimer_freq) {
+		tvp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
+	}
 	tvp->tv_usec = (cputimer_freq64_usec * delta) >> 32;
 
 	tvp->tv_sec += basetime.tv_sec;
@@ -819,6 +852,11 @@
 		tsp->tv_sec = gd->gd_time_seconds;
 		delta = cputimer_count() - gd->gd_cpuclock_base;
 	} while (tsp->tv_sec != gd->gd_time_seconds);
+
+	if (delta >= cputimer_freq) {
+		tsp->tv_sec += delta / cputimer_freq;
+		delta %= cputimer_freq;
+	}
 	tsp->tv_nsec = (cputimer_freq64_nsec * delta) >> 32;
 
 	tsp->tv_sec += basetime.tv_sec;
@@ -941,7 +979,8 @@
 		ts.tv_sec = gd->gd_time_seconds;
 		delta = count - gd->gd_cpuclock_base;
 	} while (ts.tv_sec != gd->gd_time_seconds);
-	if (delta > cputimer_freq) {
+
+	if (delta >= cputimer_freq) {
 		ts.tv_sec += delta / cputimer_freq;
 		delta %= cputimer_freq;
 	}
@@ -968,7 +1007,13 @@
 		/* magic, at its best... */
 		tcount = count - pps->ppscount[2];
 		pps->ppscount[2] = count;
-		delta = (cputimer_freq64_nsec * tcount) >> 32;
+		if (tcount >= cputimer_freq) {
+			delta = 1000000000 * (tcount / cputimer_freq) +
+				(cputimer_freq64_nsec * 
+				 (tcount % cputimer_freq)) >> 32;
+		} else {
+			delta = (cputimer_freq64_nsec * tcount) >> 32;
+		}
 		hardpps(tsp, delta);
 	}
 #endif





More information about the Bugs mailing list