ToDo:
SADの Cパートを ISO C99規格で厳格にチェックし始めると、 エラーが大量に出て凹む。 EPICS Channel Access周り以外は、ほぼ修正完了
ただし、各OS毎の include headerサポート状況が異なり config/*.specの修正が泥沼... Orz
FreeBSDは、何もしないと POSIX, X/OPEN等の最新規格 + BSD拡張な include headerが提供される。で、_POSIX_C_SOURCEや _XOPEN_SOURCE マクロがあると、定義された分だけ提供する。 つまり、_POSIX_C_SOURCEや _XOPEN_SOURCEを下手に定義すると 一部の関数や typedefが提供されなくなります。
対して、Linuxは _POSIX_C_SOURCE, _XOPEN_SOURCEを明示的に 定義しないと 新しい規格に対する include headerの機能が 活性化しない...
CVS MAIN trunkへまめにバックポートが行われてますが、 ほとんどは ISO C99対応、POSIX等の C libraryの呼び出し仕様を 満足するための修正です。なんか、Tru64の C compilerは ISO C99対応みたいですが、POSIX等の仕様が古いままで printfがらみの新しいフォーマット文字列が未サポートのようですが 主にデバック出力関連な上、消え行くプラットフォームなので 気にしないように...
ただ、EPICS library linkageの更新では、build framework側の デフォルトをEPICS base-3.14.9に切替えているので、 USE_KEKB_EPICS=YESを使っている場合は、sad.confの 最後を新しいsad.conf.sampleの物と入れ換えないと 上手く動作しません。
あと、一部の64bit環境でプラットフォーム依存の拡張機能を 使って SADを動かすためのhackを入れてありますが、 使用を推奨するものではないのでデフォルトはOFFに してあります。必要なかたは、src/sim/unix_memory_.cを 熟読の上で自己責任で御利用下さい。
NotePCを FreeBSD/i386 6.3-PRERELEASEから 7.0-BETA4へアップデートして ports類を再コンパイルしてから表題のとおり、「かんな」が 動かなくなりました。(cannastatとかはできるけど、まともにクライアントが 接続するとcannaserverが core dumpする Orz)
で、ホテルでごそごそ調査をしてましたが、結論からいうと物凄く単純なバグ で、いままで運良く動いていただけのようです。修正は、わずか 2文字追加で完了
--- lib/RK/ncache.c~ 2003-09-17 10:50:30.000000000 +0200 +++ lib/RK/ncache.c 2007-12-21 02:05:00.000000000 +0100 @@ -26,7 +26,7 @@ #include "RKintern.h" -#define NCHASH 101 +#define NCHASH 101UL #define hash(x) ((int)((x)%NCHASH)) static struct ncache Nchash[NCHASH];
え?なんで直るかが判らないって? hash(x)は、整数型変数 xを 0〜(NCHASH-1)の整数にハッシュするための 関数で、それをインデックスにして Nchash[]配列をアクセスするコードが lib/RK/ncache.cにあります。で、修正前だと hash(x)が負になったりする ので、当然 signal 11で core dumpするわけです。
NCHASHでとる剰余だから、0〜(NCHASH-1)が返るのは当り前だと思う人は、 もう一度 Cの仕様書を読みましょう
ISO C99以前と以降で違いがあるのですが、 少なくとも整数演算における剰余の振舞は次の恒等式を満たします
a = (a / b) * b + (a % b)
さて、問題は整数値(a/b)がどうなるかです
少なくとも a, bともに正の場合は切り下げと定義されています。 が、その他の組合せの場合はどうでしょう。 驚くなかれ、ISO C99以前は未定義なため実装依存です。 ISO C99では、常に 0へ向かって丸めることになりました。 つまり、剰余 a % bの値域は -abs(b) + 1〜 abs(b) - 1なのです
で、問題のかんなの件ですが、実は hash()への入力は long型の アドレス情報で、FreeBSD 6.3-PRERELEASE -> 7.0-BETA4での VM空間の割り当て変更によって 2GB境界を跨いだために負に なっていました。
では、なぜこの修正で直るのでしょう? xが long型だとして、NCHASHを ULで修飾した unsigned long定数とすると 整数演算 x % NCHASHでは型の不一致を long型の xを unsigned longへ 昇格することで解決します。unsigned long型同士の剰余は 必ず unsigned longです。したがって、hash(x)が負になる問題は解決です。
ここでの剰余は、ハッシュとして使うのが目的なのでこれで解決ですが、 剰余 a % b を0若しくは正の値に正規化する必要があるときは、 剰余が負の場合に 商 a / bから abs(b)/bを引いて、 剰余に abs(b)を加える操作が必要になります。
カテゴリー: Admin | Emacs | EPICS | Fortran | FreeBSD | GCC | hgsubversion | IPv6 | KEKB | LHC | Lisp | LLVM | MADX | Ryzen | SAD | samba | tDiary | unix | WWW | YaSAI | お仕事 | イベント | 出張 | 宴会 | 数学 | 艦これ | 買いもの | 追記 | 雑記
_ 大西幸喜 [森田様、ベンチマークの参考になればと思います。最近、iMac(24インチ)を買いました。静かで、スタイリッシュで、と..]
_ 影山達也 [アレス空洞に光子魚雷直撃:富士テストビームラインのタングステンターゲットを素通り出来た高エネルギー光子が最初のBマグ..]