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











