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)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.