2014-06-25 :-(
_ 午後
1300 射撃しつつ前転
_ [コードリーディング][NetBSD][/bin/sleep]NetBSD /bin/sleep を読む
ソース src\bin\sleep
マニュアル sleep - NetBSD Manual Pages
Note: The NetBSD sleep command will accept and honor a non-integer number of specified seconds. This is a non-portable extension, and its use will nearly guarantee that a shell script will not execute properly on another system.
NetBSD では小数点にも対応してるけど互換性が無いので非推奨。
コード読む
処理は main() のみ。
冒頭のコメントも含めて
昔の sleep との互換性のために小数点をチェックしてる。 最近はでかい数値であっても問題ないはずだけどねー 1000000000.9 とかいう数値を渡してきても知らんよ :-) atof は locale の影響を受けるので isdigit してます。 /* * Okay, why not just use atof for everything? Why bother * checking if there is a fraction in use? Because the old * sleep handled the full range of integers, that's why, and a * double can't handle a large long. This is fairly useless * given how large a number a double can hold on most * machines, but now we won't ever have trouble. If you want * 1000000000.9 seconds of sleep, well, that's your * problem. Why use an isdigit() check instead of checking for * a period? Because doing it this way means locales will be * handled transparently by the atof code. */ fracflag = 0; arg = *argv; for (temp = arg; *temp != '\0'; temp++) if (!isdigit((unsigned char)*temp)) fracflag++; if (fracflag) { val = atof(arg); if (val <= 0) usage(); ival = floor(val); fval = (1000000000 * (val-ival)); ntime.tv_sec = ival; ntime.tv_nsec = fval; } else { ntime.tv_sec = atol(arg); if (ntime.tv_sec <= 0) return EXIT_SUCCESS; ntime.tv_nsec = 0; }
国ごとに小数点が異なるので( 小数点 - Wikipedia ) atof は locale に影響されるという。
あとは nanosleep で寝るだけ nanosleep(2) - NetBSD Manual Pages
original = ntime.tv_sec; signal(SIGINFO, report_request); while ((rv = nanosleep(&ntime, &ntime)) != 0) {
tv_nsec について
timespec 構造体の tv_nsec はナノ秒である timespec(3) - NetBSD Manual Pages
ナノ秒は 1/100万秒( 0.000000001秒 )である。
コメントに書かれている 1000000000.9 を指定するとようするに tv_nsec はオーバーフローする。
おためしコード。
char *arg = "1000000000.9"; val = atof(arg); ival = floor(val); fval = (1000000000 * (val-ival));
値は以下のとおり
val=1000000000.900000 ival=1000000000.000000 fval=899999976.158142
10.9 を指定すると
char *arg = "10.9";
こうなる
val=10.900000 ival=10.000000 fval=900000000.000000
とはいえ tv_nsec (ナノ秒) がオーバーフローしたところで、ナノ秒のスケールでの誤差が果てして問題になるのか、OS の tick がナノ秒に対応しているのか( 対応してないだろ )、そもそもナノ秒の sleep が NetBSD だけの実装なのでそれが問題になるのか。などなど
[ツッコミを入れる]