http://mput.dip.jp/mput/?date=20040314#p01
「タイムスタンプカウンタは Pentium と Alpha と PowerPC にある」 なんて言われてしまうと Alpha でも誰かがやらなければなるまい。 "Alpha Architecture Reference Manual" を見てみると なんとなくそれっぽい PCC (Process Cycle Counter) register というのを発見した。
下位 32 ビット (PCC_CNT) は CPU サイクル N ごとにインクリメントされるらしい。 N は 1 から 16 までの実装依存……てなんだよそりゃ。 PowerPC みたいにバスクロックでカウントされるのかなあ。
一方、上位 32 ビット (PCC_OFF) は OS 依存らしい。OS? でも「OFF」はたぶん「offset」の略だろうな。 普通に実装してあれば 64 ビット整数として読めるってことか。
あっ、それも書いてあった。 OpenVMS と Tru64UNIX はプロセスごとのタイムスライスを持つようだ。 マシン全体ではないのね。
PCC レジスタは RPCC (Read PCC) 命令で読めるらしい。 ふーむ。こんな感じでいいのかなあ。
#include <stdio.h>
static unsigned long
rpcc(void)
{
__asm__ volatile (
"rpcc $0\n"
);
return;
}
#define PCC_CNT(pcc) ((pcc) & 0xffffffffL)
#define PCC_OFF(pcc) ((pcc) >> 32)
static void
print_rpcc()
{
unsigned long pcc = rpcc();
printf("PCC = %016lx\n", pcc);
printf("PCC_CNT = %08lx\n", PCC_CNT(pcc));
printf("PCC_OFF = %08lx\n", PCC_OFF(pcc));
}
これだと rpcc() の返り値が正しくないように見えるが、 Alpha では返り値を整数レジスタ 0 ($0) で返すので アセンブラレベルではうまくいく。と思う。 unsigned long を返す関数を定義してコンパイルしてみたら ほぼ同じコードになったのでたぶん大丈夫だろう。
この関数を使い 1 秒 sleep しつつ PCC を表示してみる。 できれば Tru64 でやりたかったんだけど、 まだ gcc を入れてないのでとりあえず NetBSD/Alpha だ。
aamine@asv800 % ./rpcc PCC = 3a7950a5579ad207 PCC_CNT = 579ad207 PCC_OFF = 3a7950a5 PCC = 309d4e756ba2cda0 PCC_CNT = 6ba2cda0 PCC_OFF = 309d4e75 PCC = 26a43e187fa3ce87 PCC_CNT = 7fa3ce87 PCC_OFF = 26a43e18 PCC = 1c8d622f93a4cb79 PCC_CNT = 93a4cb79 PCC_OFF = 1c8d622f PCC = 1258c7a0a7a5cd87 PCC_CNT = a7a5cd87 PCC_OFF = 1258c7a0
えっと、なんか PCC_OFF が変化しすぎ? なんだろうなこの値は。これは NetBSD カーネルも読まないとだめか。
つづく。
(18:01)
NetBSD のヘッダファイル alpha/alpha_cpu.h で、 alpha_rpcc() という直球な関数を発見した。
static __inline unsigned long
alpha_rpcc(void)
{
unsigned long v0;
__asm __volatile("rpcc %0" : "=r" (v0));
return (v0);
}
こう書けばよかったのか。
(18:09)
一方 Tru64UNIX では、alpha/kintrinsics.h という 怪しげなヘッダファイルに rpcc() という関数の宣言を発見した。 しかし「k」intrinsics だけあってカーネルの内部関数だったらしい。
しかたがないので、まずダミー関数を書いておいて cc -S rpcc.c でアセンブリソースを生成し、return 77 に相当する部分を rpcc $0 に置き換えた。うまくいくかな。
~/c/test/rpcc % for i (a b c d e) { ./rpcc; sleep 1 }
5a0f27cda62505f6
410e81e0bf212645
286c7741d7c2c8d4
0fc9d1aff0642e68
f72717a20907be70
取れた。値の遷移には NetBSD と同じ傾向が見られる。 ますます謎だ。
(19:03)
今日 3/15 (月) の 19:30 ごろ、 i.loveruby.net が原因不明の過負荷状態に陥ったため一時マシンを停止しました。 いちおう直ったみたいですが、まだ妙に重いですね。やばいかなこれは。
(19:46)