> 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)