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

概要

引数

  • p--タスク
  • clone_flags--クローンフラグ
    フラグ名説明
    CSIGNAL0x000000ffsignal mask to be sent at exit
    CLONE_VM0x00000100メモリ空間(mm_struct/linux2.6)を共有する
    CLONE_FS0x00000200ファイルシステム情報(fs_struct/linux2.6)を共有する
    CLONE_FILES0x00000400ファイルディスクリプタテーブル(files_struct/linux2.6)を共有する
    CLONE_SIGHAND0x00000800シグナルハンドラ(signal_struct/linux2.6sighand_struct/linux2.6)を共有する
    CLONE_PTRACE0x00002000ptrace状態をコピーする(clone元のプロセスはclone先の親プロセスにならない)
    CLONE_VFORK0x00004000vfork。子プロセスがメモリ空間(mm_struct/linux2.6)を解放する(mm_release()/linux2.6)まで親プロセスを動作させない
    CLONE_PARENT0x00008000親プロセスをコピーする(clone元のプロセスはclone先の親プロセスにならない)
    CLONE_THREAD0x00010000子プロセスが親プロセスと同じスレッドグループに属させる
    CLONE_NEWNS0x00020000名前空間(namespace/linux2.6)を共有
    CLONE_SYSVSEM0x00040000system V セマフォのundo list(sem_undo/linux2.6)を共有
    CLONE_SETTLS0x00080000TLS(Thread Local Storage)を設定。i386ではGDTを設定
    CLONE_PARENT_SETTID0x00100000set the TID in the parent
    CLONE_CHILD_CLEARTID0x00200000clear the TID in the child
    CLONE_DETACHED0x00400000使用されていない
    CLONE_UNTRACED0x00800000親プロセスがptraceされているのを強制的に解除する。カーネルスレッドを生成する場合などに使用。例えば、gdbやstraceがデバッグ対象と認識していないプロセスから、意図しないイベントを受けないようにするため
    CLONE_CHILD_SETTID0x01000000set the TID in the child
    CLONE_STOPPED0x02000000子プロセスが生成したSIGSTOPを送信して、プロセスの状態をTASK_STOPPEDにする

実装

/*

* wake_up_new_task - wake up a newly created task for the first time.
*
* This function will do some initial scheduler statistics housekeeping
* that must be done for every newly created context, then puts the task
* on the runqueue and wakes it.
*/

void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags) {

	unsigned long flags;
	int this_cpu, cpu;
	runqueue_t *rq, *this_rq;
	rq = task_rq_lock(p, &flags);
  • タスクpにマッピングされたCPUのランキューのロックを取得する
	cpu = task_cpu(p);
  • タスクpがマッピングされているCPU識別子を返す
	this_cpu = smp_processor_id();
	BUG_ON(p->state != TASK_RUNNING);
  • 条件(p->state != TASK_RUNNING)が真である場合はバグである
	schedstat_inc(rq, wunt_cnt);
	/*
	 * We decrease the sleep average of forking parents
	 * and children as well, to keep max-interactive tasks
	 * from forking tasks that are max-interactive. The parent
	 * (current) is done further down, under its lock.
	 */
	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
	p->interactive_credit = 0;
	p->prio = effective_prio(p);
	if (likely(cpu == this_cpu)) {
  • 値(cpu == this_cpu)が1の場合である可能性が高い
    • (1である可能性が高いとの)分岐を予測し、キャッシュミスを減らす。
    • 詳細はlikely()/linux2.6を参照
		if (!(clone_flags & CLONE_VM)) {
			/*
			 * The VM isn't cloned, so we're in a good position to
			 * do child-runs-first in anticipation of an exec. This
			 * usually avoids a lot of COW overhead.
			 */
			if (unlikely(!current->array))
				__activate_task(p, rq);
  • 値(!current->array)が0の場合である可能性が高い
    • (0である可能性が高いとの)分岐を予測し、キャッシュミスを減らす。
    • 詳細はunlikely()/linux2.6を参照
  • ランキューrqにタスクpを移動する
			else {
				p->prio = current->prio;
				list_add_tail(&p->run_list, &current->run_list);
				p->array = current->array;
				p->array->nr_active++;
				rq->nr_running++;
			}
			set_need_resched();
		} else
			/* Run child last */
			__activate_task(p, rq);
		/*
		 * We skip the following code due to cpu == this_cpu
	 	 *
		 *   task_rq_unlock(rq, &flags);
		 *   this_rq = task_rq_lock(current, &flags);
		 */
		this_rq = rq;
	} else {
		this_rq = cpu_rq(this_cpu);
		/*
		 * Not the local CPU - must adjust timestamp. This should
		 * get optimised away in the !CONFIG_SMP case.
		 */
		p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
					+ rq->timestamp_last_tick;
		__activate_task(p, rq);
		if (TASK_PREEMPTS_CURR(p, rq))
			resched_task(rq->curr);
  • タスクpの優先度が、ランキューrqのカレントタスクの優先度より高い場合、1を返す。低い場合は0を返す。
  • ローカルAPICのフラグを調査&設定し、必要であればタスクrq->currのCPUに対してプロセッサ間通信(IPI)を行い再スケジュールを要求する
		schedstat_inc(rq, wunt_moved);
		/*
		 * Parent and child are on different CPUs, now get the
		 * parent runqueue to update the parent's ->sleep_avg:
		 */
		task_rq_unlock(rq, &flags);
  • ランキューrqのロックをアンロックし、可能であればプリエンプションする
		this_rq = task_rq_lock(current, &flags);
  • カレントタスクにマッピングされたCPUのランキューのロックを取得する
	}
	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
	task_rq_unlock(this_rq, &flags);
  • ランキューrqのロックをアンロックし、可能であればプリエンプションする

}

呼出元


履歴

  • 作者:ひら
  • 日付:2007/3/29
  • 対象:2.6.10
    更新日更新者更新内容

コメント/タグ?



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-11-24 (火) 07:20:26 (3129d)