看板 DFBSD_bugs 關於我們 聯絡資訊
:> :[ adamk@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@backplane.com> 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