無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

CPU変数


CPU変数は、DEFINE_PER_CPUマクロで、通常静的変数のセクションと異なる.data..percpuセクションに設定されます。__per_cpu_offset[]にCPU変数セクションの.data..percpuからのCPUに掛かる参照オフセットが設定され、CPU毎の変数は、CPU変数アドレス+__per_cpu_offset[CPU ID]のアドレスをCPUの変数となります。

サンプルは、カレントCPUのbabakaka1をインクリメントし、CPU IDの0/1でのCPU変数を検証するもので、カーネルマクロによるものと、そのマクロに元ずく実装によるものです。
#include <linux/kmod.h>

static DEFINE_PER_CPU(int, babakaka1) = 1;
static DEFINE_PER_CPU(int, babakaka2) = 1;

static int babakaka_init (void)
{
       int     *addr1, *addr2;

       printk("add 1 babakaka1 on cpu%d\n", get_cpu());
       percpu_add(babakaka1, 1);

       printk("cpu0 babakaka1:%d babakaka2:%d\n", per_cpu(babakaka1, 0), per_cpu(babakaka2, 0));
       printk("cpu1 babakaka1:%d babakaka2:%d\n", per_cpu(babakaka1, 1), per_cpu(babakaka2, 1));

       printk("-------\n");

       printk("cpu0 off:%lx cpu1 off:%lx\n", __per_cpu_offset[0], __per_cpu_offset[1]);
       addr1 = (int *)((unsigned long)&babakaka1 + (unsigned long)__per_cpu_offset[0]);
       addr2 = (int *)((unsigned long)&babakaka2 + (unsigned long)__per_cpu_offset[0]);
       printk("cpu0 babakaka1:%d babakaka2:%d\n", *addr1, *addr2);

       addr1 = (int *)((unsigned long)&babakaka1 + (unsigned long)__per_cpu_offset[1]);
       addr2 = (int *)((unsigned long)&babakaka2 + (unsigned long)__per_cpu_offset[1]);
       printk("cpu1 babakaka1:%d babakaka2:%d\n", *addr1, *addr2);

      return -1;
}
module_init(babakaka_init);
カレントCPU IDは1で、従ってCPU ID=1のbabakaka1=2となりますが、CPU ID=0のbabakaka1=1です。
[root@localhost lkm]# insmod cpuval.ko
[root@localhost lkm]# dmesg -c
  :
[ 1654.995045] add 1 babakaka1 on cpu1
[ 1654.995056] cpu0 babakaka1:1 babakaka2:1
[ 1654.995063] cpu1 babakaka1:2 babakaka2:1
[ 1654.995069] -------
[ 1654.995075] cpu0 off:1f397000 cpu1 off:1f3a4000
[ 1654.995081] cpu0 babakaka1:1 babakaka2:1
[ 1654.995087] cpu1 babakaka1:2 babakaka2:1

補足

実装可能なCPU数は、セクションサイズとCPU毎の必要とする変数サイズに依存し、また実装は、CPUに依存し、ここではX32での検証です。

DEFINE_PER_CPU(type, name)マクロは__attribute__((section(.data..percp))) のtype型のname変数で宣言されます。
#ifndef PER_CPU_DEF_ATTRIBUTES
#define PER_CPU_DEF_ATTRIBUTES
#endif

#define DEFINE_PER_CPU(type, name)                                      \
       DEFINE_PER_CPU_SECTION(type, name, "")

#define DEFINE_PER_CPU_SECTION(type, name, sec)                         \
       __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES                        \
       __typeof__(type) name

#define __PCPU_ATTRS(sec)                                               \
       __percpu __attribute__((section(PER_CPU_BASE_SECTION sec)))     

#define PER_CPU_BASE_SECTION ".data..percpu"

最終更新 2016/08/27 22:02:46 - north
(2012/03/23 16:19:37 作成)