読者です 読者をやめる 読者になる 読者になる

NetBSDのスケジューラを読んでみるめも5

netbsd kernel

〆(.. )カリカリッ!! sched_proc_fork()sched_proc_exit()

sched_proc_fork()は特にこれといった処理はないですね。

    405  * sched_proc_fork:
    406  *
    407  *	Inherit the parent's scheduler history.
    408  */
    409 void
    410 sched_proc_fork(struct proc *parent, struct proc *child)
    411 {
    412 	lwp_t *pl;
    413 
    414 	KASSERT(mutex_owned(parent->p_lock));
    415 
    416 	pl = LIST_FIRST(&parent->p_lwps);
    417 	child->p_estcpu_inherited = pl->l_estcpu;
    418 	child->p_forktime = sched_pstats_ticks;
    419 }

処理としては親プロセスのlwpリストから最初の要素を取得して、そのlwpのcpu利用率をp_estcpu_inheritedにセット。
p_forktimeにsched_pstats_ticksの値をセット。sched_pstats_ticksはkern_sync.cに実体があるグローバル変数で同じくkern_sync.c内のsched_pstats()の実行時にインクリメントされます。

   1110 /*
   1111  * sched_pstats:
   1112  *
   1113  * => Update process statistics and check CPU resource allocation.
   1114  * => Call scheduler-specific hook to eventually adjust LWP priorities.
   1115  * => Compute load average of a quantity on 1, 5 and 15 minute intervals.
   1116  */

sched_pstats()の役割はコメントに書かれている通りで、プロセスの統計、cpuリソースの使用状況をチェックして、この結果がロードアベレージとして使われるようですね。
このsched_proc_fork()が使われるのはkern_fork.cのfork1()sys/kern/kern_exec.cのdo_posix_spawn()の2ヶ所です。
fork1()はsys_fork()、sys_vfork()、sys___vfork14()、sys_clone()から呼ばれるfork全般の関数ですね。do_posix_spawnはsys_posix_spawn()から呼ばれます。このシステムコールは初めて知ったのですがこれも新しいプロセスを作るためのAPIなんですね。posix_spawn(3)

さて、sched_proc_exit()はというと。

    421 /*
    422  * sched_proc_exit:
    423  *
    424  *	Chargeback parents for the sins of their children.
    425  */
    426 void
    427 sched_proc_exit(struct proc *parent, struct proc *child)
    428 {
    429 	fixpt_t loadfac = loadfactor(averunnable.ldavg[0]);
    430 	fixpt_t estcpu;
    431 	lwp_t *pl, *cl;
    432 
    433 	/* XXX Only if parent != init?? */
    434 
    435 	mutex_enter(parent->p_lock);
    436 	pl = LIST_FIRST(&parent->p_lwps);
    437 	cl = LIST_FIRST(&child->p_lwps);

最初に親プロセス、子プロセスのlwpリストから最初の要素を取り出す。

    438 	estcpu = decay_cpu_batch(loadfac, child->p_estcpu_inherited,
    439 	    sched_pstats_ticks - child->p_forktime);

次に子プロセスのcpu利用度の計算をdecay_cpu_batch()で実施。

    440 	if (cl->l_estcpu > estcpu) {
    441 		lwp_lock(pl);
    442 		pl->l_estcpu = ESTCPULIM(pl->l_estcpu + cl->l_estcpu - estcpu);
    443 		lwp_unlock(pl);
    444 	}
    445 	mutex_exit(parent->p_lock);
    446 }

子プロセスのcpu利用度が先ほど計算したものより大きかったら親プロセスのcpu利用度を再設定。
この関数で行いたいのはプロセス終了時に子プロセスのcpu利用度に応じて親プロセスのほうのl_estcpuを再設定すると。