2011年08月23日

/proc/cpuinfoの疑問点をソースコードで確認する

いくつかのAndroid端末の/proc/cpuinfoを見比べてみると疑問なところがあります。

  • ブート時のBogoMIPSと値と/proc/cpuinfoでの値が異なるものがある。
  • デュアルコアの端末でブート時のログでは2つCPUを起動しているのに、/proc/cpuinfoではひとつしか表示されない。

これらをソースコードで調べてみました。



ブート時のBogoMIPSと値と/proc/cpuinfoでの値が異なるものがある。

KZM-A9-Dualボードなどの評価ボードでは起動時のBogoMIPSと/proc/cpuinfoでの値は一致しています。しかし、市販の携帯電話では両者は異なっていて、/proc/cpuinfoでの方が非常に小さな値になります。

Nexus Oneの例では、ブート時のBogoMIPS

<6>[ 0.000000] NR_IRQS:316
<6>[ 0.000000] Calibrating delay loop... 509.54 BogoMIPS (lpj=2547712)
<6>[ 0.229461] pid_max: default: 32768 minimum: 301
<4>[ 0.229705] Mount-cache hash table entries: 512

右側のタイムスタンプからBogoMIPSの計測に約200msecかけて実測したと思われます。

一方、/proc/cpuinfoでの値はその約1/3です。

Processor : ARMv7 Processor rev 2 (v7l)
BogoMIPS : 162.54
Features : swp half thumb fastmult vfp edsp thumbee neon

デュアルコアの端末でブート時のログでは2つCPUを起動しているのに、/proc/cpuinfoではひとつしか表示されない。

KZM-A9-Dualボードはデュアルコアです。SMP対応のカーネルを使えば2つのCPUを起動します。/proc/cpuinfoではCPUの情報が2つ表示されます。

GALAXY S IIもデュアルコアです。ブートログでは以下のように2つCPUを起動しています。

<6>[ 0.000176] Calibrating delay loop (skipped) preset value.. 1592.52 BogoMIPS (lpj=3981312)
<6>[ 0.000203] pid_max: default: 32768 minimum: 301
<4>[ 0.000331] Mount-cache hash table entries: 512
 ...

<4>[ 0.025099] CPU1: Booted secondary processor
<6>[ 0.025175] Brought up 2 CPUs
<6>[ 0.025188] SMP: Total of 2 processors activated (3185.04 BogoMIPS).

しかし、/proc/cpuinfoではひとつのCPUしか表示されません。

Processor : ARMv7 Processor rev 1 (v7l)
processor : 0
BogoMIPS : 1592.52

Features : swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 1

Hardware : SMDKC210
Revision : 000c
Serial : xxxxxxxxxxxxxxxx

/proc/cpuinfoを表示する部分のkernelのソースコードを調べる

fs/proc/cpuinfo.c からたどっていくと

arch/arm/kernel/setup.c

static int c_show(struct seq_file *m, void *v)
{
	int i;

	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
		   cpu_name, read_cpuid_id() & 15, elf_platform);

#if defined(CONFIG_SMP)
	for_each_online_cpu(i) {
		/*
		 * glibc reads /proc/cpuinfo to determine the number of
		 * online processors, looking for lines beginning with
		 * "processor".  Give glibc what it expects.
		 */
		seq_printf(m, "processor\t: %d\n", i);
		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
			   per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
			   (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
	}
#else /* CONFIG_SMP */
	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
		   loops_per_jiffy / (500000/HZ),
		   (loops_per_jiffy / (5000/HZ)) % 100);
#endif

	/* dump out the processor features */
	seq_puts(m, "Features\t: ");

	for (i = 0; hwcap_str[i]; i++)
            ...

	return 0;
}

BogoMIPSはloops_per_jiffyという変数から算出されていることがわかりました。この値は短い時間をタイトループで待つときのカウンタで、省電力モードでCPUのクロックを下げるときには連動してこの値を変えていました。

つまり、Nexus Oneで通常状態でのBogoMIPSの値が小さかったのは、省電力のためにCPUのクロックを落としていたからでした。

また、SMPのときは、for_each_online_cpu(i)というマクロでループを回しています。このマクロは include/linux/cpumask.h で定義されています。

for_each_online_cpu(i)ではそのときに稼働しているCPUだけになります。ブート時に認識した全てのCPUで回すのは for_each_possible_cpu(i)です。

つまり、GALAXY S IIは通常時は2つのCPUのうちのひとつしか動かしていないということがわかりました。おそらく省電力のために止めているのでしょう。



トラックバックURL

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード