2008/12/23

C言語: ファイルサイズの取得

C言語の標準関数では直接ファイルサイズを取得する関数が無い.
そこで,fseekとfgetposを使ってファイルポインタの位置を調べることで
間接的にファイルサイズを取得するそうな.
fpos_t fpos;
FILE *fp = fopen(fname, "rb");

fseek(fp, 0, SEEK_END);
fgetpos(fp, &fpos);
fclose(fp);

fpos.__pos; // これがファイルサイズ


// Reference
ファイルサイズの取得方法
半年くらい前にはまったこと
標準C言語関数

2008/12/20

Linux Command: eog

eogはGnome標準の画像ビューア.
コマンドラインから画像を確認したい際に使う.

# eog *.png


[Reference]
Desktop Linux Memo - ビューア(画像・動画・文書等)

2008/12/15

likely / unlikely

likely / unlikelyマクロはコンパイラに分岐予測のヒントを与える.
分岐予測ミスによる投機実行ペナルティを減らすために使う.

プログラムのアルゴリズムには影響を与えないため,ソースを読む際には無視して良い.



// Example
int i = 0;
while (1) {
 i++;
 if (unlikely(i > 100))
  break;
}
上記の例では,ループを抜ける条件式の
if ( unlikely(i > 100) )
が成り立つのは,101回の比較の中で1回のみである. よって,この場合はunlikelyがあった方がコンパイラは 最適化されたコードを生成する.はず.


// Reference
likely()-linux2.6 - LinuxKernelHackJapan

2008/12/14

Intel CPU: Fixed Performance Counter (FPC)

Fixed Performance Counter(FPC) // 勝手な命名
は固定のパフォーマンスイベントをカウントするMSR.
最大で3つで,CPUがいくつサポートしているかは,以前のエントリ
パフォーマンスカウンタの情報を表示
の "Number of fixed-function PCs" で得られる.

以下FPCの詳細.

[IA32_FIXED_CTR0(MSR_PERF_FIXED_CTR0)]
Register Address: 0x309
Performance Event: Inst_Retired.Any
実行した命令数をカウントする.

[IA32_FIXED_CTR1(MSR_PERF_FIXED_CTR1)]
Register Address: 0x30A
Performance Event: CPU_CLK_Unhalted.Core
CPUがHalt状態でない時のCPUサイクル数をカウントする.

[IA32_FIXED_CTR2(MSR_PERF_FIXED_CTR2)]
Register Address: 0x30B
Performance Event: CPU_CLK_Unhalted.Ref
CPUがHalt状態でない時のバスクロック数をカウントする.


【使用時の注意】
FPCはデフォルトではdisableになっている.
enableにするには,FPCの動作をコントロールするMSRである
IA32_FIXED_CTR_CTL(MSR_PERF_FIXED_CTR_CTL)
Register Address: 0x3BD
の値を変更する必要がある.
IA32_FIXED_CTR_CTLは,3つのFPCのenable/disableの設定を行う.


[bit fields]
0-4: IA32_FIXED_CTR0の設定
0: EN0_OS(CPL=0の時にenable)
1: EN0_Usr(CPL>0の時にenable)
2: Reserved
3: EN0_PMI(カウンタがオーバーフローした時にPMIを発生)
4-7: IA32_FIXED_CTR1の設定,0-3と同様
8-11: IA32_FIXED_CTR2の設定,0-3と同様


[Reference]
IntelR 64 and IA-32 Architectures Software Developer’s Manual Volume 3B: APPENDIX B
MODEL-SPECIFIC REGISTERS (MSRS)

__attribute__

gccの拡張機能.
関数,変数,型に属性を付加する.

[section]
__attribute__((section("name")))
関数または変数が格納されるセクションを明示的に指定するために使用する.


【参考】
yunoの雑記帳 - gcc-attribute
__attribute__で設定できる属性一覧

Linux カーネルで使われている gcc の拡張機能

Xenソースコード英単語

Linuxカーネルソースコードが元になっているが,細部が結構異なっている.
コメントとかで使われている単語の意味をメモ・

【Xen単語】
crank: クランクを回す,不安定な
expiry: 満期,終了
idler: 怠け者
tickle: 満足させる

C言語: マクロ展開マクロ

Xenのコードを眺めていたらマクロを展開するためのマクロを見つけたのでメモメモ.
下記のようなマクロが定義されているものとする.

#define EXPAND_MACRO(_MACRO) \
 _MACRO(a) \
 _MACRO(b) \

#define DEFINE(_X) int _X;
#define FUNC(_X) do { func(_X); } while (0);

このとき,
EXPAND_MACRO(DEFINE);
は下記のように展開される.
int a;
int b;

同様に
EXPAND_MACRO(FUNC);
は下記のように展開される.
func(a);
func(b);

便利そうな気もするけど多用すると混乱しそう.

local_irq_save / local_irq_restore

[local_irq_save]
この関数を呼び出したCPUの割り込み禁止/許可状態(EFLAGSレジスタ)を引数で与えた値に保存する.

[local_irq_restore]
この関数を呼び出したCPUの割り込み禁止/許可状態(EFLAGSレジスタ)を引数で与えた値に設定する.

// Reference
local_irq_save()-linux2.6 - LinuxKernelHackJapan
local_irq_restore()-linux2.6 - LinuxKernelHackJapan
spin_lock_irqsave()-linux2.6 - LinuxKernelHackJapan
_spin_lock_irqsave()-linux2.6 - LinuxKernelHackJapan
EFLAGS - 通信用語の基礎知識

BUG

[BUG]
(i386の場合)ud2命令を実行し,未定義命令例外を発生させる.

[BUG_ON]
真ならBUGを呼ぶ(パニックで落ちる).

【参考】
Omicron Linux-カーネルハッキング入門
アジアのペンギン アセンブラの勉強方法 3

__alignof__

__alignof__はgccのCコンパイラの拡張機能.
あるオブジェクトがどのようにアライメントされるか,
または,ある型が通常必要とする最小アライメント値を調べることができる.

[Example]
__alignof__(int) == 4
__alignof__(double) == 8

struct test { int x; char y; }  t;
__alignof__(t) == 4;

[Reference]
Using and Porting GNU CC - C 言語ファミリに対する拡張

2008/12/11

Intel CPU: パフォーマンスイベントUmask

モニタリングするパフォーマンスイベントのUmaskでTable 18-11, 18-13, 18-14を見るべし.
という指示がちょくちょくあったのでメモ.
intel manual Vol. 3 capter 18 p59-60 より,


[Table 18-11. Core Specificity Encoding]
Bit 15:14
11B All cores
10B Reserved
01B This core
00B Reserved

Some microarchitectural conditions allow detection specificity only at the boundary of physical processors. Some bus events belong to this category, providing specificity between the originating physical processor (a bus agent) versus other agents on the bus. Sub-field encoding for agent specificity is shown in Table 18-12.


[Table 18-12. Agent Specificity Encoding]
Bit 13
0 This agent
1 Include all agents

Some microarchitectural conditions are detectable only from the originating core. In such cases, unit mask does not support core-specificity or agent-specificity encodings. These are referred to as core-only conditions. Some microarchitectural conditions allow detection specificity that includes or excludes the action of hardware prefetches. A two-bit encoding may be supported to qualify hardware prefetch actions. Typically, this applies only to some L2 or bus events. The sub-field encoding for hardware prefetch qualification is shown in Table 18-13.

[Table 18-13. HW Prefetch Qualification Encoding]
Bit 13:12
11B All inclusive
10B Reserved
01B Hardware prefetch only
00B Exclude hardware prefetch

[Table 18-14. MESI Qualification Definitions]
Bit Position 11:8
Bit 11 Counts modified state
Bit 10 Counts exclusive state
Bit 9 Counts shared state
Bit 8 Counts Invalid state

// よく使いそうな16進マスク
//--------------------------------------------------
[Table 18-11. Core Specificity Encoding]
0xc000: All cores
0x4000: This core

[Table 18-12. Agent Specificity Encoding]
0x0000 This agent
0x2000 Include all agents

[Table 18-13. HW Prefetch Qualification Encoding]
0x3000: All inclusive
0x1000: Hardware prefetch only

[Table 18-14. MESI Qualification Definitions]
0x0f00: 全部


// Reference
Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3B: APPENDIX A
PERFORMANCE-MONITORING EVENTS

RDMSR / WRMSR

// RDMSR
ECXで指定したアドレスのMSRを読み込む.
読み込んだデータはEDX:EAXに格納される.
特権レベル0でのみ実行可能.
(ex)
unsigned low, high;
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr_addr));

// WRMSR
ECXで指定したアドレスのMSRにEDX:EAXを書き込む.
特権レベル0でのみ実行可能.
(ex)
asm volatile("wrmsr" : : "c"(msr_addr), "=a"(low), "=d"(high) : "memory");

// Reference
wrmsr()/linux2.6 - LinuxKernelHackJapan
rdmsr()/linux2.6 - LinuxKernelHackJapan

Linuxカーネルプログラミングメモ

・浮動小数点は使えない
・使えないC言語標準関数が結構ある(文字列関係とか)
・普通のプログラムなら警告で済むものもコンパイルエラーになる(未使用な変数がある,等)
・関数宣言でint test(void)のように省略しないで宣言する必要がある
・int test()はコンパイルエラーになる.

2008/12/10

C言語: ハードウェアパフォーマンスカウンタの情報を表示

CPUIDでハードウェアパフォーマンスカウンタの情報を表示するプログラム.
#include 
#include 

#define BIT(x, bit) (((x) >> (bit)) & 0x00000001)

int main()
{
  unsigned int a, b, c, d;
  unsigned char eax_07_00, eax_15_08, eax_23_16, eax_31_24;
  unsigned char edx_04_00, edx_12_05;

  asm volatile ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x0a));

  printf("CPUID(EAX=0AH): Architectural Performance Monitoring\n");

  eax_07_00 = (unsigned char)(a & 0xff);
  eax_15_08 = (unsigned char)((a >> 8) & 0xff);
  eax_23_16 = (unsigned char)((a >> 16) & 0xff);
  eax_31_24 = (unsigned char)((a >> 24) & 0xff);
  printf(" Version ID of architectural PM: %d\n", eax_07_00);
  printf(" Number of general-purpose PMC per logical processor: %d\n", eax_15_08);
  printf(" Bit width of general-purpose PMC: %d\n", eax_23_16);
  printf(" Length of EBX bit vector: %d\n", eax_31_24);
  printf("\n");
 
  printf(" Core cycle event not available: %d\n", BIT(b, 0));
  printf(" Instruction retired event not available: %d\n", BIT(b, 1));
  printf(" Reference cycles event not available: %d\n", BIT(b, 2));
  printf(" Last-level cache reference event not available: %d\n", BIT(b, 3));
  printf(" Last-level cache misses event not available: %d\n", BIT(b, 4));
  printf(" Branch instrunction retired event not available: %d\n", BIT(b, 5));
  printf(" Branch mispredict retired event not available: %d\n", BIT(b, 6));
  printf("\n");

  if (eax_07_00 > 1) {
    edx_04_00 = (unsigned char)(d & 0x1f);
    edx_12_05 = (unsigned char)((d >> 5) & 0xff);
    printf(" Number of fixed-function PCs: %d\n", edx_04_00);
    printf(" Bit width of fixed-function PCs: %d\n", edx_12_05);
  }

  return 0;
}

2008/12/09

Linux2.6スケジューラの特徴

・SMPシステムに対応
・O(1)のスケジューラ
 ・(タスクの数が増えても,スケジューリングのオーバーヘッドは不変)
・マルチコアの場合でも,CPU毎にタスクのrunqueueを持つことで,タスクを特定のCPUに関連付けできる
・カーネルモードではプリエンプトされない(カーネル内部の処理を単純化するため)

スケジューラのソースは
/usr/src/linux/kernel/sched.c

[Reference]
Linux スケジューラーの内側
ITmedia エンタープライズ:プロセススケジューラの実装――プロセススケジューリング(その4)
Linuxカーネルの基本機能 第3回 プロセス・スケジューリング
Linuxのプロセス管理

gccインラインアセンブラ

gccのasm命令を使うことで,Cの中でインラインアセンブラを使える.

【構文】
asm volatile ("アセンブラテンプレート"
: "出力オペランド"
: "入力オペランド"
: "アセンブラの実行で変更されてしまうもの");

[アセンブラテンプレート]
ニーモニックを指定する.
"cpuid"とか"mov"とか.
複数指定することもできる.

[出力オペランド]
下記のように指定する
"=a" (出力先変数), "=b" (出力先変数)
ex)
"=a (buf)" はeaxレジスタの内容を変数bufに出力することを示す.

[入力オペランド]
"a" (入力)のように指定する
"0"(入力)と指定すると,1番目に指定した出力オペランドの制約条件を流用する.
ex)
"a" (0) はEAXレジスタに入力として0を与えることを示す.

【オペランドの制約条件】
"=" asmが終わった後に変更された結果が指定された変数に代入される
"a" eax
"b" ebx
"c" ecx
"d" edx
"A" edx:eax(上位bitにedx,下位bitにeax)
"g" gccが適当なレジスタに割り当てる

【例】
unsigned int a, b, c, d;
asm volatile ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0));
// 変数a,b,c,dにcpuidで取得した情報が格納される


【参考】
GCC-インラインアセンブリ-HOWTO (日本語訳)
gccのx86インラインアセンブリに関して

Binary Hacks ―ハッカー秘伝のテクニック100選

2008/12/01

Intel CPU: Hardware Performance Counter(HPC)

intel CPUのハードウェアパフォーマンスカウンタ(HPC)は
自分で監視するイベントを指定できる汎用的なカウンタと
固定のイベントを監視する固定カウンタの二種類がある.

Core 2では汎用カウンタは2個,固定カウンタは3個ある.
固定カウンタで監視するイベントは
Inst_Retired.Any: 完了した命令の数
CPU_CLK_Unhalted.Core: HLT状態でないCPUのクロックサイクル数
CPU_CLK_Unhalted.Ref: 上記のreference cycle版

【用語】
CCCR: Counter Configuration ContRol
ESCRで選択されたイベントをフィルタリングしてカウントする場合に使用する.
CPL: Current Privilege Level
ESCR: Event Selection ContRol
LLC: Last Level Cache
MSR: Model Specific Register
PEBS: Precise Event-Based Sampling
PMC: PerforMance Counter
PMI: Performance Monitoring Interrupt

【命令】
(RD/WR)MSR: MSRをRead/Writeする命令
RDPMC: PMCをReadする命令

【制限】
MSRをRead/Writeする命令を実行できるのは特権モード(ring 0)のみ.
アプリケーション(ring 3)からはPMCのReadのみ可能.

【イベント】
[リタイアイベント]
リタイアしたイベントとは,マシンステートを確定した命令によるイベントのみを含む.

[非リタイアイベント]
非リタイアイベントは,マイクロアーキテクチャーにおける
アウトオブオーダーの推測による流れで発生する.

[L2キャッシュイベント]
・MEM_LOAD_RETIRED.L2_LINE_MISS
L2キャッシュのミスで発生したロード数

・MEM_LOAD_RETIRED.L2_MISS


【参考資料】
インテルCoreマイクロアーキテクチャー・プロセッサーのパフォーマンス・カウンター
MEM_LOAD_RETIRED.L2_LINE_MISS
MEM_LOAD_RETIRED.L2_MISS

rdmsr - 通信用語の基礎知識
CPU-CPUID-MSR - SyncHack
CPU-MSR - SyncHack
linux2.6-include-asm-i386-msr.h - LinuxKernelHackJapan

Intel® 64 and IA-32 Architectures Software Developer's Manuals