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 だけの実装なのでそれが問題になるのか。などなど
[ツッコミを入れる]






