蝉は、やがて死ぬる午後に気づいた。ああ、私たち、もっと仕合せになってよかったのだ。:2010年04月分

2010/04/01(Thu)

今日

we can be hero, just for one day

といえばDavid Bowieの Herosですが、今日一日だけなら私でもUnicode信者になれるそんな日。

2010/04/02(Fri)

[C1X] dead store elimination

secure_bzero()ネタ、C1X の方で提案されている memset_s()[pdf] だったらどうだったんでしょうかねぇ。

2010/04/11(Sun)

訃報

先日何の気なしにいまさら Sun blade100なんぞを衝動買いしてしまったのですが
その荷物が届いた4/7、あのCSIの権化こと 樋浦さんお亡くなりになられていたそうで…言葉も出ない。

ジャストを退社された後もIMEngine SPIに関わっておられたようで これ[pdf]がパブリックな最後のプレゼンですかね。

Xutf8騒動、XomCTLのXFree86へのcontribにOKを出さないTOGのlawer、 IIIMFのアレなど
相手がたとえ すっとこどっこいだろうと、いつも穏やかな口調で戦われてた姿はもう見れないのですね…悲しい。

The Unicode hardwired program unveils the programmers' understanding
level of Unicode architecture. Such hardwired programs no longer work
correctly once the scripts/languages/cultural-behavior to be processed
go beyond the programers' understanding level of Unicode.

これはCSIにしてもそうですな、常によそ様の文化に対する畏れなくしてi18n語る無かれ。

2010/04/14(Wed)

[NetBSD] Only one ABI change in libc, in more than 15 years!

NetBSDでは後方互換が壊れるような変更をlibcに加える場合、__RENAME()マクロというトリックを使い
ABIを保ち、libcのsonameを変更をしないですむ(OpenBSDのような賽の河原とか嫌だし)ように工夫してるのは
以前もこのチラシの裏に 書いた通りです。

やっぱりこれもっと宣伝すべきよね

Only one ABI change in libc, in more than 15 years!

ちなみにこの一回ってのもa.out → ELFのことだからGNU toolchainのせいだしね:D

#っても今や他のOSはもっとナウい(死語)方法(ELF symbol versioning *1)で実現してるので、ちょっと恥ずかしいかもしれない。

ところがですね、来るreleng-6ではtime_tの64bit化による2038年問題解決がスケジュールされとりまして
time_tのsizeofがかわるってーのはlibcの__RENAMEだけでABIを保証するのは 厳しいものがありまして
2回目のABI変更、すなわちlibcのsoname変更 や ら な い か、という決定が下されまして、その為のもろもろの準備が
src/libc/compat以下で進められとりやす。

他のOSなんかだとglibcだとlibc5とglibc2(libc6)なんてのは別リポジトリで進化してますので
メンテナンスはそれぞれ個別ですし、FreeBSDなんかだとメジャーリリース(例えば2.2から→3.0みたいな)毎に
libcのmajorはcrunkしますので、その枝のstableをメンテしているわけです(ports/misc/compat*参照)。 *2

NetBSDもFreeBSDのようにstable branchで後方互換の為の古いlibc(libc12)をメンテしていく方が楽なのですが
残念ながらstable branchを保守していくにはその枝の寿命の問題があります。

最近のFreeBSDのEOLポリシーはよう知らんですが、NetBSDの場合は6.0がリリースされるとその2つ前、つまり4.x系が
EOLになりますので、ここ最近は2年に一度程度のメジャーリリースですから *3libc12をリンクしたアプリの寿命は
あと4年程度ということになってしまいます、せっかく12年間守り続けた後方互換ですのでこれはなんとも勿体無い話なわけです 。

一方、XFree86/xorgでも3系から因縁の4系に移行する際(だったっけ?)にXaw(X Atena Widget)のmajorが変更になりました。
ですが3系をとっとと捨てたかったのか:D 4系のコードベースからlibXaw6(旧)とlibXaw7(新)という異なるABIのライブラリを
どちらもビルドできるよう上手いことやっとります、このためlibXaw6にはいまのところ寿命設定なしで保守され続けてるわけです。

んでNetBSDもそれにインスパイヤされたのかどうかは知らんですが、cvsのHEADでlibc12とlibc13両方をビルドできるようにして
今後もlibc12の保守をしていくことになったようです *4

んでもですね、このlibc/compat以下のカラクリってのがどこにもドキュメントが無いまま作業が進められてて
(the typical NetBSD style we did not document/advertise it. といういつもの悪癖です、はい)手が出しづらい状況なんすよね。
なもんで、今後どういう風にlibc12からlibc13への以降をやろうとしてるのかたぶんこんな感じじゃね?と
風の息づかいを感じたので、次回に記事を書いてみる予定。

たぶんdeveloperなら このサンプルこのサンプルの差分をみただけで理解できると思われ。

というかこれまで理解してなかったのは俺だけかもしれない、くっ。

*1:GSoCで何かやりたい学生さん、どうっすかね?
*2:ちなみにOpenBSDの場合「バイナリ互換なんぞ知るかボケ、半年に一度リリースソング聴きながら再インストールしやがれ」でんな。
*3:6はそろそろ枝切りの予定、5.1が出ないことについては深く追求しないで下さい:-P
*4:かつてmatt@氏がlibc13はlibc12のwrapperとして提供しようぜ と 提案してたのですが
これバイナリレベルでのwrapperだと 問題あるので、ソースレベルでやろうぜってことだったのだと思われまする。

2010/04/15(Thu)

[NetBSD] Only one ABI change in libc, in more than 15 years!(その2)

昨日の都築。

libfoo12.tar.gzの状態ですと Makefile は

1 LIB=            foo
2 CPPFLAGS+=      -I${.CURDIR}
3 COMPATDIR=      ${.CURDIR}/compat
4 
5 .include "${.CURDIR}/foo/Makefile.inc"
6 .include "${COMPATDIR}/Makefile.inc"
7 
8 .include <bsd.lib.mk>

5~6行目で libfoo12/foo/Makefile.inc と libfoo12/compat/Makefile.inc をインクルードしていますので
libfoo12/foo/foo.c と libfoo12/compat/foo/compat_foo.c がコンパイルされ
共有ライブラリの libfoo.so が作られることになります。

$ cd libfoo12
$ make obj
$ make depend all
$ ls obj*/*.pico
obj.i386/compat_foo.pico  obj.i386/foo.pico

あ、HEADではつい先日-fPICあり(position independent code)でコンパイルされたオブジェクトファイルの
拡張子が *.so から *.pico に変更になってますので、5 系使いの方は注意。

libfoo12/foo/foo.cは↓のようなコードになってます。

 1 #include <sys/cdefs.h>
 2 #include <foo.h>
 3 #include <stdio.h>
 4 
 5 void
 6 foo()
 7 {
 8 #if defined(__LIBFOO12_SOURCE__)
 9         puts("hello, libfoo12.");
10 #else
11         puts("hello, libfoo13.");
12 #endif
13 }

__LIBFOO12_SOURCE__が定義されているか否かで
挨拶文が変わる=挙動が変わりますが、これがABI変更(のつもり)です。
このファイルはそのままコンパイルされますので出力する挨拶文は "hello, libfoo13." です。

またこのファイルは libfoo12/foo/Makefile.inc で

1 .PATH: ${.CURDIR}/foo
2 
3 SRCS+=                  foo.c
4 CPPFLAGS.foo.c+=        -I${.CURDIR}/include

のように、libfoo12/include に対してパスが設定されていますので
include/foo.h つまりは↓な内容をインクルードしとります。

 1 #ifndef _FOO_H_
 2 #define _FOO_H_
 3 
 4 #include <sys/cdefs.h>
 5 
 6 __BEGIN_DECLS
 7 void foo(void)  __RENAME(__foo60);
 8 __END_DECLS
 9 
10 #endif /*_FOO_H_*/

ですので foo シンボルは __RENAME マクロによって __foo60 に置換されとるわけです。

vmware$ nm obj*/foo.pico | grep foo
00000000 T __foo60

一方 libc12/compat/foo/compat_foo.c は以下のようになっています。

1 #define __LIBFOO12_SOURCE__
2 
3 #include <sys/cdefs.h>
4 
5 __warn_references(foo,
6     "warning: reference to compatibility foo();"
7     " include <foo.h> for correct reference")
8 
9 #include "foo/foo.c"

このファイルで注意すべき点は第一に、1行目で__LIBFOO12_SOURCE__が定義されていますので
9行目でインクルードした foo/foo.c は "hello, libfoo12." と表示することになるのと
以前説明した__warn_references()マクロによってリンク時に警告を出しているということです。

このままコンパイルしてしまいますと libc12/foo/foo.c と同じように
__RENAME マクロの魔力で foo が __foo60 に 置換されてしまい

libfoo_pic.a(foo.pico): In function `__foo60':
foo.c:(.text+0x0): multiple definition of `__foo60'
libfoo_pic.a(compat_foo.pico):compat_foo.c:(.text+0x0): first defined here
*** Error code 1

Stop.

と重複シンボルによるエラーが起きてしまうのですが、ここでちょっとしたトリックで
libfoo12/compat/foo/Makefile.inc において

1 .PATH: ${COMPATDIR}/foo
2 SRCS+=                  compat_foo.c
3 CPPFLAGS.compat_foo.c+= -I${COMPATDIR}/include

として libfoo12/include ではなく libfoo12/compat/include にパスが通してあり、こっちでは

1 #ifndef _COMPAT_FOO_H_
2 #define _COMPAT_FOO_H_
3 
4 __BEGIN_DECLS
5 void foo(void);
6 __END_DECLS
7 
8 #endif /*_FOO_H_*/

と シンボル置換が行われず、foo のままになるということです。

$ nm obj*/compat_foo.pico | grep foo
00000000 T foo

簡単にまとめると

ということです、なんかディレクトリが増えたり同じヘッダを2バージョン用意せなあかんかったりで
余計ややこしくなっただけに思えますが、これが実際にこの libfoo の major を crunk する時に
なるほどーという効果を生むようになるのです、以下次回に続く。

2010/04/16(Fri)

[NetBSD] Only one ABI change in libc, in more than 15 years!(その3)

さて誰得な気もするけど、昨日のチラシの裏のつづきにして最後。

(これまでのうらすじ)

昔々 libfoo.so.12 のところに foo というシンボルがありました。
このシンボルを call すると、"hello, libfoo12."というどうでもいい文字列を表示します。

ある日のことどっかのloopyな王様が仕様変更を唱えまして、"hello, libcfoo13."と表示しなければならなくなりま。
困ったことにこの変更でバイナリ後方互換が壊れてしまった(ということにしといてくらはい)ので
*BSD 村一番の後方互換パラノイア、NetBSD は、奥義 __RENAME マクロを使って対処しました。

ですので古いバイナリは foo を呼びますが、新しいバイナリは ヘッダ中ですりかえられた
__foo60 を呼んでます、ですのでバイナリ後方互換は守られみな幸せに暮らしましたとさ(おわr

このすりかえは ヘッダをインクルードせずに extern foo した場合には just won't work on youですが
まぁその場合は __warn_references マクロでリンク時警告出してますんで自己責任ということで。

そもそも __RENAME マクロは共有ライブラリのの soname を変更したくない為の怪しげな voodoo です。
ですので major を crunk するといちど決めてしまえば "hello, libfoo12." を表示する foo の方はもはや不要です。
そして "hello, libfoo13."を表示する __foo60 は元の正しい名前、foo としてコンパイルして欲しいわけです。

ですので libfoo12.tar.gzから libfoo13.tar.gzで以下の書き換えを行いました。

とまぁこんな感じでヘッダとMakefile関係をちょびっと書き直すだけで major crunk 前後にうまく対応してるわけです。

はい、ややこし過ぎてとても正気の沙汰とは思えませんです :D うまくない!

しかも弱点がこれあって、foo.c が1関数で完結してないと駄目だよねという、それともstatic な関数
とかはまだしも、libc内部でだけ使われるシンボルも全部 __RENAME しちゃうんですかね。
とーっても無駄すぎると思うのですが。

あと compat だと 1回の soname 変更にしか対応できないよね、次に libfoo14 とかが必要になる事態まで考えてないよね。
libfoo13/compat じゃなくて libfoo13/compat12 としといた方がいいんじゃないの、とかかなぁ。

とまぁこんな感じです。トリックが無駄にややこしいので私の貧弱な文章力では何人理解できるか大変不安、ごめんちゃい。

2010/04/20(Tue)

今日

ねこ三回忌、いまだに思い出すと悲しい。

[NetBSD] TODOs 消化中

例の libc/compat + __LIBC12_SOURCE__ にあわせて insufficient _ctype_ bits の件に対する patch 作成中。
libc/locale/setlocale_local.h と libc/locale/runetype_local.h に ifdef が生じるので本当はこれを
インクルードするファイルは全て compat 送りにしないとならないのだけども、さすがにそれはやっとれんので
_locale_impl_t の構造を若干変更して影響の出るファイルを最小限にとどめ、あとは回避できないコードだけ
compat 送りの刑に処することで回避、とっても危険だけどね。

いちおこれで tech-userlevel に投げるか、反応次第で __LIBC12_SOURCE__ は evil だと暴れることにする(ぉ

あとそれとちょっと前に libstdc++ がらみの問題があるから極力ソース互換を保とうかと 考えてた( その1その2)
のですが、よく考えると今のコードって isprint(3)が

#define isprint(c)      ((int)((_ctype_ + 1)[(c)] & (_P|_U|_L|_N|_B)))

になっとるので、皆さん大好きないわゆる半角カナ(笑)は ja_JP.SJIS の場合だと0xa6~0xdfと
1バイト文字に割り当てられとるわけですが、こいつらについて Ancient BSD由来の ctype は
現在の NetBSD の ctype.hでも

#define _P      0x10	/* Punct 記号 */
#define _U      0x01	/* Uppercase 大文字 */
#define _L      0x02	/* Lowercase 小文字 */
#define _N      0x04	/* Numner(Digit) 数字 */
#define _S      0x08	/* Space スペース */
#define _C      0x20	/* Control コントロール */
#define _X      0x40	/* Xdigit HEX */
#define _B      0x80	/* Blank ブランク */

のいずれにも分類することができない(Runeでは_RUNETYPE_QつまりPhonogram表音文字)ので
isprint(半角カナ)が偽を返すちゅーバグがあるのですよな、この話についてはもう何年も前から
201.5号室長が気づいておられたはずなので、適当に"NetBSD isprint phonogram"でググってちょ。

ということでソース互換放棄、libstdc++についてはupstreamにもpatch投げんとならんめんどい。

2010/04/23(Fri)

散財

SONY SAL2875が某所で新品が定価の半額しかも金利0%だったので衝動買い。
淀とかビックだとナナキュッパのポイント10%なので高いわーとスルーしてたのですけどね。

こいつは TAMRON A9 の OEM で、コニミノ時代にあった AF28-75mm F2.8(D) の後継なんだけど
A9の実売(3万ちょい)と比べて、プラス2万弱で売ってるなら、円形絞りとかレンズ内モーター化など改良されてるし
それを考えると大変お買い得、デザインもましになってるしね。ただピントリングが他製品の逆なのは健在。

以前コニミノ時代のやつ持ってたんだけど、故障した時に修理出したらパーツ払底でアウトだったのね
(保証期間内だったので返金してもらえたから助かりましたが)。未だにオクで3~4万で落札されてるようだけど
古いボディでレンズ内モータじゃAF効かない機種使ってるとかでない限りはそんなリスクは以下略

あとは TAMRON A05 の OEM だった AF17-35mm F2.8-4(D)の後継がいつ出るかっすね。

それと SONY の ミラーレス、これ APS-C だからマイクロフォーサーズでマウントアダプタ遊びするより楽しそうっすね。
EVFは嫌いなんですが、純正でミノルタSR/MC/MDアダプタ出してくれたりすると買っちゃいそう。