MIRACLE
メールサービス申込 ユーザー登録 パートナー情報
お問い合わせ FAQ サイトマップ
MIRACLE LINUXの特長 製品紹介 サービス案内 購入 サポート 技術フォーラム

プロフィール

コアテクノロジー部

ミラクル・リナックスのOS開発やサポートを担う、技術部の精鋭陣が交代で担当します。

ミラクル関連リンク

採用情報

サイト検索

2008年5月

        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

« | メイン | Linux と CMMI »

スピンロックその1

今回は趣向を変えて、少しだけカーネル内部に触れてみたいと思います。

みなさん「スピンロック」という言葉に馴染みがあるでしょうか。そのメカニズムを詳しく知ってる方も多いかもしれませんし、例えばどこかで「スピンロック待ちの『ビジーウェイト』でCPUにロスが発生した」のような会話を小耳に挟む機会などもあるかもしれません。しかし、Linux カーネルにおけるスピンロックの実装部分を読んだことのある方は、もしかして意外に多くないかもしれません。ということで、今回はそのあたり(ただし i386 アーキテクチャのみ)を追ってみたいと思います。スピンロックの概念についての説明は省きます。

いきなりソースコードに飛び込んでみましょう(これがミラクル流です)。C言語に馴染みのない方はごめんなさい。弊社MIRACLE LINUXでもいいのですが、ここでは本家の http://www.kernel.org/pub/linux/kernel/v2.6/ に置いてある一番新しそうな linux-2.6.16.20.tar.bz2 を拾ってきて解凍しました。Linux カーネルは更新が速く、コードがどんどん変わっています。異なるバージョンでは以下の文章とは違う実装になっていると思いますので、そのへんは注意して下さい。

スピンロックはカーネル内の色々なところで使われています。どこでもよいのですが、ここではプロセス・スケジューラ kernel/sched.c でも覗いてみましょうか。。。

void __init sched_init(void)
{
        runqueue_t *rq;
        int i, j, k;

        for_each_cpu(i) {
                prio_array_t *array;

                rq = cpu_rq(i);
                spin_lock_init(&rq->lock);
                rq->nr_running = 0;

スケジューラを初期化する関数 sched_init() の中で、ランキューのスピンロック情報を保持する lock メンバを spin_lock_init() で初期化している処理が見つかりました。この lock メンバは spinlock_t 型で、これは include/linux/spinlock_types.h で次のように定義されています。

typedef struct {
        raw_spinlock_t raw_lock;
#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
        unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
        unsigned int magic, owner_cpu;
        void *owner;
#endif
} spinlock_t;

メインは raw_spinlock_t 型の raw_lock メンバのようです。この型は i386 では include/asm-i386/spinlock_types.h で次のように定義されています。

typedef struct {
        volatile unsigned int slock;
} raw_spinlock_t;

この slock 変数の値がロックの状態を保持するんですね。

データ構造が分かったところで、スピンロックの初期化処理に戻りましょう。 spinlock_t 型の &rq->lock メンバを初期化する spin_lock_init() は実は関数ではなくマクロで、 include/linux/spinlock.h で定義されていました。

#define spin_lock_init(lock)    do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0)

この SPIN_LOCK_UNLOCKED は、普通のカーネル (CONFIG_DEBUG_SPINLOCK が未定義のカーネル) では、次のように定義されています。

include/linux/spinlock_types.h

# define SPIN_LOCK_UNLOCKED \
        (spinlock_t)    {       .raw_lock = __RAW_SPIN_LOCK_UNLOCKED }

include/asm-i386/spinlock_types.h

#define __RAW_SPIN_LOCK_UNLOCKED        { 1 }

ということで、slock に 1 が代入された状態が初期状態、すなわち UNLOCKED 状態であることがわかりました。

区切りが良いので、今回はここまでです。ロックが取得されることで、この slock の値が 1 からどのように変化するのか、あるいはどんなコードで実装されているのか、それらは次回、またコードを追ってみることにします。

トラックバック

このページのトラックバックURL:
http://www.typepad.jp/t/trackback/4447/4090071

このページへのトラックバック一覧 スピンロックその1:

» スピンロックその2 トラックバック コアテクの路地
もうすっかり忘れられているかもしれませんが、スピンロックその1の続編です。 今回 [続きを読む]

» スピンロックその3 トラックバック コアテクの路地
前回に続き、スピンロック取得処理の定義を追います。今回は(b)のケースです。(a [続きを読む]

コメント

コメントを投稿

会社情報 採用情報 個人情報保護方針 商標等取り扱い事項 English
Copyright(c)2000-2006 MIRACLE LINUX CORPORATION. All Rights Reserved.