このページを編集する際は、編集に関する方針に従ってください。

概要

  • kernel/sched.cにて定義
  • 負荷を分散する目的でタスクの移動を行う
    • 優先度の高いカーネルスレッドである
    • このタスクを停止するように設定(kthread_stop_info.kに現在実行中のmigration_threadを設定)されない限り、繰り返しタスクの移動を行う。

引数

  • data--CPU識別子

実装

/*

* migration_thread - this is a highprio system thread that performs
* thread migration by bumping thread off CPU then 'pushing' onto
* another runqueue.
*/

static int migration_thread(void * data) {

	runqueue_t *rq;
	int cpu = (long)data;
	rq = cpu_rq(cpu);
	BUG_ON(rq->migration_thread != current);
  • カレントタスクがmigration_threadで無い場合はバグ
	set_current_state(TASK_INTERRUPTIBLE);
  • カレントタスク(つまりmigration_thread)を待機状態にする
  • カレントタスクのstateをTASK_INTERRUPTIBLEに設定する
	while (!kthread_should_stop()) {
  • カレントタスク(migration_thread)がストップしていない場合、ストップ状態になるまで繰り返す:
		struct list_head *head;
		migration_req_t *req;
  • タスクのドメイン内での移動やドメインの切り替えに関するリクエストを扱う構造体
		if (current->flags & PF_FREEZE)
			refrigerator(PF_FREEZE);
  • カレントタスクのフラグが凍結状態PF_FREEZEを指しているなら、カレントタスクを凍結する
  • カレントタスクを凍結する
    • 他の要因によって凍結が解除されるまでスケジューラを呼び出し、実行権を放棄する
    • サスペンドなどで使われる
    • 詳細はrefrigerator()/linux2.6を参照
		spin_lock_irq(&rq->lock);
		if (cpu_is_offline(cpu)) {
  • cpuがオフラインである場合、ロックrq->lockを解除し、wait_to_dieへジャンプ:
  • cpuがオフライン状態であるか調べる
    • オフライン状態であれば1を返す
    • CPUホットプラグ(CONFIG_HOTPLUG_CPU)を想定した関数である
    • 詳細はcpu_is_offline()/linux2.6を参照
			spin_unlock_irq(&rq->lock);
  • スピンロックrq->lockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
			goto wait_to_die;
		}
		if (rq->active_balance) {
  • ランキューrqがロードバランス(負荷分散)を必要としている場合:
			active_load_balance(rq, cpu);
  • cpuのタスクを他のCPUへ移動させ、負荷の分散を試みる
    • SMTに対する考慮がなされており、同じCPU上にて論理CPUから論理CPUへの負荷分散は行わない。物理CPUから物理CPUへの負荷分散のみ行われる
    • 詳細はactive_load_balance()/linux2.6を参照
			rq->active_balance = 0;
  • 再びrqの負荷が偏るまで、ロードバランス(負荷分散)の必要がないことを意味する
		}
		head = &rq->migration_queue;
  • 移動対象のタスクをheadへ設定
		if (list_empty(head)) {
  • headが空であるか調べる
			spin_unlock_irq(&rq->lock);
  • スピンロックrq->lockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
			schedule();
			set_current_state(TASK_INTERRUPTIBLE);
			continue;
  • 次のwhileループに移る(現在のループを終了して、新たなループのwhile条件チェックを行う)
    • continue文は、その文を含む最も内側の繰り返し文のループ本体の終わりに制御を移す
		}
  • headが空ではない場合:
		req = list_entry(head->next, migration_req_t, list);
  • head->nextが組み込まれている(migration_req_t型の)オブジェクトのポインタを割り出す
		list_del_init(head->next);
  • リストのエントリhead->nextを、所属するリストlistから削除し、req->headを初期化する
		if (req->type == REQ_MOVE_TASK) {
  • reqのリクエストタイプがREQ_MOVE_TASK(タスクの移動)である場合:
			spin_unlock(&rq->lock);
  • スピンロックrq->lockの開放を行う。プリエンプション機能を有効にし、可能であれば自ら積極的にプリエンプション(実行権の移譲を行うこと)する
			__migrate_task(req->task, smp_processor_id(),
					req->dest_cpu);
  • 現在このタスクが使用しているCPUの識別子を取得する
  • タスクreq->taskを現在使用しているCPUからreq->dest_cpu移動させ、必要であればreq->dest_cpuへプロセッサ間通信(IPI)を行い、dest_cpuの再スケジューリングを要求する
			local_irq_enable();
		} else if (req->type == REQ_SET_DOMAIN) {
  • reqのリクエストタイプがREQ_SET_DOMAIN(ドメインの切り替え)である場合:
			rq->sd = req->sd;
			spin_unlock_irq(&rq->lock);
  • スピンロックrq->lockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
		} else {
  • reqのリクエストタイプが不明である場合:
			spin_unlock_irq(&rq->lock);
  • スピンロックrq->lockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
			WARN_ON(1);
		}
		complete(&req->done);
  • reqから1つだけ待ち合わせ中のタスクを起床する
	}
	__set_current_state(TASK_RUNNING);
	return 0;

wait_to_die:

	/* Wait for kthread_stop */
	set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		schedule();
		set_current_state(TASK_INTERRUPTIBLE);
	}
	__set_current_state(TASK_RUNNING);
	return 0;

}

呼出元

  • load_balance()/linux2.6 -- 2005-06-09 (木) 10:47:44
  • 1 -- 2014-08-24 (日) 16:04:48
  • 1 -- 2014-08-24 (日) 16:04:58
  • 1 -- 2014-08-24 (日) 16:05:01
    • 1' -- 2014-08-24 (日) 16:05:04
  • 1 -- 2014-08-24 (日) 16:05:05

  • 1 -- 2014-08-24 (日) 16:05:00

履歴

  • 作者:ひら
  • 日付:2005/6/9
  • 対象:2.6.10
    更新日更新者更新内容

コメント

  • 1 -- 1? 2014-08-24 (日) 16:05:08
  • 1 -- 1? 2014-08-24 (日) 16:05:34
  • 1 -- 1? 2014-08-24 (日) 16:05:37
  • 1 -- -1'? 2014-08-24 (日) 16:05:38
    • 1' -- 1? 2014-08-24 (日) 16:05:40
  • 1 -- 1? 2014-08-24 (日) 16:05:42

  • 1 -- 1? 2014-08-24 (日) 16:05:35

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-08-24 (日) 16:05:42 (1395d)