Help us understand the problem. What is going on with this article?

タスクスケジューラのカウンタ

More than 3 years have passed since last update.

Linuxにはよく分からない単語を短縮した変数があるので、たまに困ります。

昔、タスクスケジューラの関数 schedule() (最近の処理のメインは __schedule() になってます) で使われていた struct task_struct のメンバ変数 nivcswnvcsw の意味が全然分からず悩んだ時があったんですが、なんてことはない「nivcsw = involuntary context switch の数」、「nvcsw = voluntary context switch の数」でした。
一応ソースにもコメントはついてるんですが、それぞれ何を意味してるのかが掴めなかったんですよね。

linux-3.10.0-123.el7/kernel/sched/sched.h
struct task_struct {
    volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
    void *stack;
・・・(省略)・・・
    unsigned long nvcsw, nivcsw; /* context switch counts */
    struct timespec start_time;         /* monotonic time */
    struct timespec real_start_time;    /* boot based time */

分かってからメンバ変数の使用している箇所をみれば一目瞭然なんですが、初見でピーンとくるほど勘は良くなかったです・・・。タスクが自分でスリープするとき (prev->state がTASK_RUNNINGじゃなくなった時) は nvcsw を、まだ実行可能状態だけど他の優先度の高いタスクに切り替わるときは nivcsw をインクリメントするという仕組み。コンテキストスイッチ context_switch() する直前でインクリメント ++*switch_count してますね。

linux-3.10.0-123.el7/kernel/sched/core.c
static void __sched __schedule(void)
{
    struct task_struct *prev, *next;
    unsigned long *switch_count;
    struct rq *rq;
    int cpu;

need_resched:
    preempt_disable();
    cpu = smp_processor_id();
    rq = cpu_rq(cpu);
    rcu_note_context_switch(cpu);
    prev = rq->curr;

    schedule_debug(prev);

    if (sched_feat(HRTICK))
        hrtick_clear(rq);

    /*
     * Make sure that signal_pending_state()->signal_pending() below
     * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
     * done by the caller to avoid the race with signal_wake_up().
     */
    smp_mb__before_spinlock();
    raw_spin_lock_irq(&rq->lock);

    switch_count = &prev->nivcsw;
    if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
        if (unlikely(signal_pending_state(prev->state, prev))) {
            prev->state = TASK_RUNNING;
        } else {
            deactivate_task(rq, prev, DEQUEUE_SLEEP);
            prev->on_rq = 0;

            /*
             * If a worker went to sleep, notify and ask workqueue
             * whether it wants to wake up a task to maintain
             * concurrency.
             */
            if (prev->flags & PF_WQ_WORKER) {
                struct task_struct *to_wakeup;

                to_wakeup = wq_worker_sleeping(prev, cpu);
                if (to_wakeup)
                    try_to_wake_up_local(to_wakeup);
            }
        }
        switch_count = &prev->nvcsw;
    }

    pre_schedule(rq, prev);

    if (unlikely(!rq->nr_running))
        idle_balance(cpu, rq);

    put_prev_task(rq, prev);
    next = pick_next_task(rq);
    clear_tsk_need_resched(prev);
    rq->skip_clock_update = 0;

    if (likely(prev != next)) {
        rq->nr_switches++;
        rq->curr = next;
        ++*switch_count;

        context_switch(rq, prev, next); /* unlocks the rq */
        /*
         * The context switch have flipped the stack from under us
         * and restored the local variables which were saved when
         * this task called schedule() in the past. prev == current
         * is still correct, but it can be moved to another cpu/rq.
         */
        cpu = smp_processor_id();
        rq = cpu_rq(cpu);
    } else
        raw_spin_unlock_irq(&rq->lock);

    post_schedule(rq);

    sched_preempt_enable_no_resched();
    if (need_resched())
        goto need_resched;
}

これらのカウンタ値は /proc/PID/state で確認することができます。しかも、オンラインマニュアルにはちゃんと以下の説明がついてるんですよね〜。知ってればすぐに気づいたんでしょうけど。ユーザがこのカウンタ値を気にするとしたらどういう場面かな。

voluntary_ctxt_switches, nonvoluntary_ctxt_switches: 自発的/非自発的なコンテキストスイッチの回数 (Linux 2.6.23 以降)。

それにしても schedule() 読みやすくなったなぁ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away