プロフィール

kosaki

Author:kosaki
連絡先はコチラ

ブログ検索
最近の記事
最近のコメント
最近のトラックバック
リンク
カテゴリー
月別アーカイブ
RSSフィード
FC2ブログランキング

スポンサーサイト このエントリーをはてなブックマークに追加

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


スポンサー広告 | 【--------(--) --:--:--】 | Trackback(-) | Comments(-)

weak functionをインライン展開してしまうgccたん このエントリーをはてなブックマークに追加

子ネタ

「[BUG] next-20081216 - WARNING: at kernel/smp.c:333 smp_call_function_mask」というスレッドでKamalesh Babulal が sparse irq のせいでパニックしたぞ。ゴルァーと報告

で、色々と試行錯誤のすえgccが悪い。という結論に。
Kamalesh Babulal はRHELを使っているらしいのだが、RHEL5.1のgccは腐っていて、weak global functionが空関数だと、global functionなのにインライン展開してしまう。
・・・こら。

Linuxにおいては、アーキスペシフィックな関数を呼ぶのに、共通部にweakな空関数を入れておいて、アーキ依存部でそれを上書きするという事をよくやる。
そうすると、特に処理が必要ないアーキは、なにもしなければ共通部の空関数を呼んでくれて便利だから。
これだけ対応アーキが増えてくると全アーキを一気に直すとかありえんし。

で、要するにせっかくx86専用初期化関数をつくったのに、呼ばれていなかったという。
さらに悪い事に、 __attribute__((noinline)) も無視してインライン化する最強伝説モードらしい。

しかたがないので、weak関数に片っ端からbarrier()マクロを挿入する祭り発生中。
ちなみに、barrier()は以下のようなコンパイラバリアだ

#define barrier() __asm__ __volatile__("": : :"memory")


以下脱線。
sparse irqってのは、x86だと、割り込みが昔16個しかなくて死ぬほど苦しんだ反省からか、 Intelがトチ狂って IO_APIC毎に割り込みをつけちゃったので、IRQ数が死ぬほどでかい。ちなみに現時点でのマクロは

# if NR_CPUS < MAX_IO_APICS
# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
# else
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
# endif

NR_CPUSはコンパイル時に決める最大値なので、4096とかなので、結局


NR_IRQS = (NR_VECTORS + (32 * MAX_IO_APICS))
= 256 + (32 * 128)
= 4352


となる。
で、従来のコードでは struct irq_desc irq_desc[NR_IRQS] とかふつーにグローバル変数の配列にしちゃってたので、数メガの連続領域をとられちゃってた。
もちろん、全IO_APICの全割り込みを使うなんてあるわけないから、壮大な無駄だ。そういうわけで
struct irq_desc *irq_desc_ptr[NR_IRQS] みたいなポインタの配列にして、実際のirq_descriptorは初めて使った時に動的に確保するようにしてメモリを節約するぜ。って機能

ぶっちゃけオレの敵。コードが汚くて見るに耐えないし、そもそも割り込みの延長でメモリ確保呼んで失敗したら割り込み捨てるとかって頭おかしい。

ちなみに、たぶん 2.6.29でマージされるので、みんなで悲鳴をあげやがれ。

追記: barrier()入れてもやっぱりダメな事がわかって、Andrew Mortonからそんなコンパイラ捨ててしまおうぜ。とか提案されてる。
うーむ、LKML的には非常に魅力的なので反対者が出る気がしないのだが、企業の中の人はRHEL5.1切り捨てはちょっと厳しいような気もする



関連記事


linux | 【2008-12-27(Sat) 15:12:00】 | Trackback:(0) | Comments:(0)
  1. 無料アクセス解析
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。