[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[debian-users:23287] Re: hwclock can't terminate some PC(was Re: Re: unable to complete shutdown, problem of hwclock?)
佐野@浜松です。
In <20000722150659F.matsuda@xxxxxxxxxxxx>,
on "Sat, 22 Jul 2000 15:07:07 +0900',
with "Re: hwclock can't terminate some PC(was Re: Re: unable to complete shutdown, problem of hwclock?)",
MATSUDA Yoh-ichi / 松田陽一 <yoh@xxxxxxxxxxxx> さん wrote:
> で、UTC に設定し直してみました。
> /etc/default/rcSにて、
> UTC=yes
> を設定しました。
>
> …UTC への設定ってこれだけでいいんですよね?^^;
デフォルトから何もいじってなければ、この変更の後で shutdown した
時にシステムタイムが UTC として CMOS clock にコピーされ、それ以降
再起動時には UTC として CMOS clock の時刻を読むので、いいはずです。
cat /etc/adjtime すると 3 行目が "UTC" になってるでしょう ?
> 今の所、症状は再発しておりません。
> UTC 設定は有効だったようです。
と、いうことは、CMOS clock を LOCALTIME にしていると問題が
おきるような bug が SMP 関連にありそう、ということですね。
カーネルの問題かなぁ、という気がするのですが、とりあえず
util-linux と kernel の BTS をチェックして、まだ報告されて
いないようだったら wishlist として症状の説明と一緒に report
しておいたほうがいいかもしれません。まあ最初は hwclock に
関する現象、ということで util-linux に投げておくのがいいのかな ?
説明の中に "(maybe kernel-related problem ?)" とか入れておけば
util-linux のメンテナーが kernel に振ってくれるか、あるいは
「いったんクローズするから kernel 向けに再登録してくれ」と返事
してくるか、何か反応があるでしょう。
ちょうど手元に 2.4.0-test1 なカーネルソースツリーが展開して
あるので、 arch/i386/kernel/time.c と kernel/time.c を比較して
みました。
kernel/time.c のほうだと
--- potato/2.2.15-vga16fb/kernel-source-2.2.15-vga16fb/kernel/time.c Wed Oct
20 09:14:02 1999
+++ check/linux/kernel/time.c Sat May 13 03:21:20 2000
@@ -22,8 +22,6 @@
* "A Kernel Model for Precision Timekeeping" by Dave Mills
* Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
* (Even though the technical memorandum forbids it)
- * 1999-09-17 Andrea Arcangeli <andrea@xxxxxxx>
- * Fixed adjtimex/settimeofday/stime SMP races.
*/
#include <linux/mm.h>
@@ -57,21 +55,20 @@
}
/* The xtime_lock is not only serializing the xtime read/writes but it's also
- serializing all accesses to the global NTP variables.
- NOTE NOTE: We really need a spinlock here as the global irq locking
- only protect us against the timer irq and not against other time-related
- syscall running under us. */
+ serializing all accesses to the global NTP variables now. */
extern rwlock_t xtime_lock;
なんてのがありますね。
中身のほうだと
@@ -205,20 +202,20 @@
return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
}
-long pps_offset = 0; /* pps time offset (us) */
+long pps_offset; /* pps time offset (us) */
long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
-long pps_freq = 0; /* frequency offset (scaled ppm) */
+long pps_freq; /* frequency offset (scaled ppm) */
long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
long pps_valid = PPS_VALID; /* pps signal watchdog counter */
int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
-long pps_jitcnt = 0; /* jitter limit exceeded */
-long pps_calcnt = 0; /* calibration intervals */
-long pps_errcnt = 0; /* calibration errors */
-long pps_stbcnt = 0; /* stability limit exceeded */
+long pps_jitcnt; /* jitter limit exceeded */
+long pps_calcnt; /* calibration intervals */
+long pps_errcnt; /* calibration errors */
+long pps_stbcnt; /* stability limit exceeded */
/* hook for a loadable hardpps kernel module */
void (*hardpps_ptr)(struct timeval *) = (void (*)(struct timeval *))0;
このあたりの初期化してるかどうかという点が違うみたいですが。
(あと、関数が int から long になったりしてるという点もある)
arch/i386/kernel/time.c のほうを見ると、いろいろ違いはあるけど
@@ -77,11 +79,13 @@
unsigned long fast_gettimeoffset_quotient=0;
extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
+
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static inline unsigned long do_fast_gettimeoffset(void)
{
- register unsigned long eax asm("ax");
- register unsigned long edx asm("dx");
+ register unsigned long eax, edx;
/* Read the Time Stamp Counter */
@@ -112,6 +116,8 @@
#ifndef CONFIG_X86_TSC
+spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
+
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
このへんとか
@@ -156,6 +162,8 @@
*/
unsigned long jiffies_t;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
@@ -214,6 +222,7 @@
}
} else
jiffies_p = jiffies_t;
+ spin_unlock(&i8253_lock);
count_p = count;
@@ -237,7 +246,6 @@
*/
void do_gettimeofday(struct timeval *tv)
{
- extern volatile unsigned long lost_ticks;
unsigned long flags;
unsigned long usec, sec;
@@ -271,6 +279,7 @@
* would have done, and then undo it!
*/
tv->tv_usec -= do_gettimeoffset();
+ tv->tv_usec -= lost_ticks * (1000000 / HZ);
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
@@ -301,6 +310,8 @@
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
@@ -346,6 +357,7 @@
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
return retval;
}
@@ -369,7 +381,7 @@
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
-#ifndef __SMP__
+#ifndef CONFIG_X86_LOCAL_APIC
if (!user_mode(regs))
x86_do_profile(regs->eip);
#else
@@ -447,10 +459,19 @@
rdtscl(last_tsc_low);
+#if 0 /*
+ * SUBTLE: this is not necessary from here because it's implicit in the
+ * write xtime_lock.
+ */
+ spin_lock(&i8253_lock);
+#endif
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
+#if 0
+ spin_unlock(&i8253_lock);
+#endif
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
このへんが怪しそうな気はする。(ただのヤマ勘だけど)
--
# (わたしのおうちは浜松市、「夜のお菓子」で有名さ。)
<kgh12351@xxxxxxxxxxx> : Taketoshi Sano (佐野 武俊)