[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 (佐野 武俊)