> 7R系はは試していないので、ちょっと恐いのですが、6.4Rなら対応可能なので、
> 2つ先の週末までにでもやってみたいと思います。
 先の mail に書きましたが、
手元にある G33-DS3R, G33m-DS2R の 7.1-RELEASE でもおかしい感じです。

> さて、昨日(1/6)から実行していたsleep 10;date +%sの繰り返しですが、date
> の間隔について
>   10秒 … 7387回
>   11秒 …  962回
>   12秒 …    1回 15:43:21まで
>   16秒 …    1回 15:44:30まで
>   388秒 …   1回 15:56:45まで
> という結果になりました。この12秒以上のところはmksnap_ffsが裏で走ってい
> る時間なので、明らかに理由がわかります。ということで、残念ながら10秒で
> は発現しませんでした。
 10 秒だと短すぎましたね。
こちらで出ているのと同じ現象だとすると、100 秒 から 1000 秒くらいで
見てみてください。

> > patch は 7.1-RELEASE 用なので、6.3R にはそのまま適用できないと思います…。
> > 大した量ではないので、手で該当する部分を edit してみてください。
> 
> 了解です。
 setitimer を使って sleep を書き直して試してみましたが、特に
改善しなかったので、これも有効ではないですね。先の patch は捨ててください。

> > この機能が働いている場合、BIOS上でOFFにすると改善するかもしれません。
> 
> ちょっと再起動できるタイミングを逃してしまったので、わかりませんが、可
> 能になり次第試したいと思います。
 BIOS は最新の beta にしてみましたが、それらしい設定を見つけることが
できませんでした。

ということで、sleep を改造して、半分の時間 sleep してから gettimeofday
してみて、残りの半分の時間は補正した時間 sleep する sleep を作って
みました。手元では 1000 秒で動作確認済みです。
# またつまらないものを…。

以下、7.1-RELEASE の sleep.c との diff 。
=========================================================================
--- sleep.c.org 2009-01-07 19:02:24.000000000 +0900
+++ sssleep.c   2009-01-08 18:59:03.000000000 +0900
@@ -47,13 +47,17 @@
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <sys/time.h>
 
 void usage(void);
+int nanosleep_correct(const struct timeval *, struct timeval *);
+double timerdiv(struct timeval *, struct timeval *);
+void timermul(struct timeval *, double, struct timeval *);
 
 int
 main(int argc, char *argv[])
 {
-       struct timespec time_to_sleep;
+       struct timeval time_to_sleep;
        long l;
        int neg;
        char *p;
@@ -97,21 +101,21 @@
        time_to_sleep.tv_sec = (time_t)l;
 
        /* Calculate nanoseconds. */
-       time_to_sleep.tv_nsec = 0;
+       time_to_sleep.tv_usec = 0;
 
        if (*p == '.') {                /* Decimal point. */
-               l = 100000000L;
+               l = 100000L;
                do {
                        if (isdigit((unsigned char)*++p))
-                               time_to_sleep.tv_nsec += (*p - '0') * l;
+                               time_to_sleep.tv_usec += (*p - '0') * l;
                        else
                                break;
                        l /= 10;
                } while (l);
        }
 
-       if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
-               (void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
+       if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_usec > 0))
+               (void)nanosleep_correct(&time_to_sleep, (struct timeval *)NULL);
 
        return(0);
 }
@@ -123,3 +127,50 @@
 
        write(STDERR_FILENO, msg, sizeof(msg) - 1);
 }
+
+int nanosleep_correct(const struct timeval *rqtp, struct timeval *rmtp)
+{
+  struct timespec ts;
+  struct timeval starttv, endtv, halftv, realhalftv;
+  struct timezone tz;
+  struct timeval curtv, remaintv , deltatv, realremaintv;
+  double correct;
+  long rqusec;
+
+  gettimeofday(&starttv, &tz);
+
+  rqusec = rqtp->tv_sec * 1000000 + rqtp->tv_usec;
+  rqusec /= 2;
+  halftv.tv_sec = rqusec / 1000000 ;
+  halftv.tv_usec = rqusec % 1000000; 
+  ts.tv_sec = halftv.tv_sec;
+  ts.tv_nsec = halftv.tv_usec * 1000;
+  nanosleep(&ts, (struct timespec *)NULL);
+
+  gettimeofday(&curtv, &tz);
+  timersub(&curtv, &starttv, &realhalftv);
+
+  timersub(&realhalftv, &halftv, &deltatv);
+  timersub(&halftv, &deltatv, &remaintv);
+  correct = timerdiv(&halftv, &realhalftv);
+  timermul(&remaintv, correct, &realremaintv);
+  ts.tv_sec = realremaintv.tv_sec;
+  ts.tv_nsec = realremaintv.tv_usec * 1000;
+  nanosleep(&ts, (struct timespec *)NULL);
+
+}
+
+void timermul(struct timeval *a, double mul, struct timeval *res)
+{
+  double usec;
+
+  usec =(double)(a->tv_sec * 1000000 + a->tv_usec) * mul;
+
+  res->tv_sec = (long)(usec / 1000000);
+  res->tv_usec = (long)((long)usec % 1000000);
+}
+
+double timerdiv(struct timeval *a, struct timeval *b)
+{
+  return (double)((a->tv_sec) * 1000000 + (a->tv_usec))/(double)((b->tv_sec) * 
1000000 + (b->tv_usec));
+}
=========================================================================


吉田 充@横浜チーム.情報基盤センター.理化学研究所 (mits...@zebu.riken.go.jp)

メールによる返信