コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2008年3月10日 >>> 2008年3月10日
link もっと後

2008年3月10日

かーねる

以前、hdk神からLinuxカーネルは最適化を有効にしないとコンパイルできないという話を聞いたのですが、詳解Linuxカーネルをパラパラと読んでいたら理由が書いてありました。

この不思議な現象を生み出す原因はfix_to_virt関数にあります。どのアーキテクチャにもあると思います。ざっと確認した限りではmips, sh, x86_64, sparc, i386, umに同様の関数が定義されていました(ファイル名はasm/fixmap.h)。
例えばmipsのコードを見ると、以下のようになっています。

fix_to_virt関数(linux kernel 2.6.23.8)

static inline unsigned long fix_to_virt(const unsigned int idx)
{
        /*
         * this branch gets completely eliminated after inlining,
         * except when someone tries to use fixaddr indices in an
         * illegal way. (such as mixing up address types or using
         * out-of-range indices).
         *
         * If it doesn't get removed, the linker will complain
         * loudly with a reasonably clear error message..
         */
        if (idx >= __end_of_fixed_addresses)
                __this_fixmap_does_not_exist();

        return __fix_to_virt(idx);
}

引数idxには必ず __end_of_fixed_addresses未満の定数を渡します。するとこのコードが最適化される際にifの条件が評価され、if文が常に成立しないことがわかります。コンパイラはifブロックを全て消しさってから、呼び出し元の関数に埋め込み(インライン展開)ます。

__end_of_fixed_addressesってのは、各アーキテクチャの固定メモリマップのアドレスを定義するfixed_addresses列挙型の最後に置かれる定数です。値そのものより「どの固定メモリマップアドレスよりも大きい」ことが重要です。この値を越えたアドレスへのアクセスは不正なアクセスなのです。
mipsでは以下のような列挙型で定義されています。

idxに渡すfixed_addresses列挙型

enum fixed_addresses {
#define FIX_N_COLOURS 8
        FIX_CMAP_BEGIN,
#ifdef CONFIG_MIPS_MT_SMTC
        FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS),
#else
        FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS,
#endif
#ifdef CONFIG_HIGHMEM
        /* reserved pte's for temporary kernel mappings */
        FIX_KMAP_BEGIN = FIX_CMAP_END + 1,
        FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
        __end_of_fixed_addresses
};

正しくない引数(変数や __end_of_fixed_addresses以上の定数)を渡す呼び出しがあると、if文が消去できず __this_fixmap_does_not_exist関数の呼び出しが残ります。しかしこの関数はどこにも定義されていないため、リンク時にエラーになるのです。

つまりこのif文は、最適化によって消去されることを前提に作ってあります。逆に言うと、最適化しなければ正しい呼び出しでも __this_fixmap_does_not_exist関数の呼び出しが残ってしまってコンパイルが通らないことを意味しています。

こうすることで実行時のチェックを省略できて速くなるのでしょうけど、gccの挙動にべったり依存しています。この技を使わずとも実現できる何か良い方法は無かったのかなあ…。

編集者:すずき(2008/03/11 21:18)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2008年3月10日 >>> 2008年3月10日
link もっと後

管理用メニュー

link 記事を新規作成

<2008>
<<<03>>>
------1
2345678
9101112131415
16171819202122
23242526272829
3031-----

最近のコメント5件

  • link 20年8月16日
    すずきさん (07/01 01:11)
    「そうですね。残念ながら私には向いてなかっ...」
  • link 20年8月16日
    ざんねんさん (06/29 17:12)
    「ゲーム内容を理解していない人の残念な雑記」
  • link 24年6月17日
    すずきさん (06/05 23:32)
    「Thnaks for your info...」
  • link 24年6月17日
    Bobさん (06/04 09:25)
    「BindIPv6Only=no does...」
  • link 18年8月12日
    すずきさん (05/29 16:57)
    「コメントありがとうございます。\n\nこ...」

最近の記事3件

  • link 23年5月15日
    すずき (07/01 02:15)
    「[車 - まとめリンク] 目次: 車三菱FTOの話。群馬県へのドライブ1群馬県へのドライブ2将来車を買い替えるとしたら?FTO...」
  • link 13年3月25日
    すずき (07/01 02:15)
    「[免許の更新と車のレッカー] 目次: 車前回の免許更新は免許センターまで行ったのですが、遠いわ、混んでいるわ、で辟易したので、...」
  • link 13年3月27日
    すずき (07/01 02:14)
    「[車の修理が終わった] 目次: 車先日レガシィを運び込んだ(2013年3月25日の日記参照)ディーラーから電話があり「バッテリ...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 2025年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 07/01 02:15