В чем разница между ”текущим“ и “предыдущим” в функции “__schedule”, почему бы не использовать current напрямую?

#c #linux-kernel #scheduled-tasks #scheduler

#c #linux-ядро #запланированные задачи #планировщик

Вопрос:

Из исходного кода ядра:

 static void __sched notrace __schedule(bool preempt)
{
        struct task_struct *prev, *next;
        unsigned long *switch_count;
        struct rq_flags rf;
        struct rq *rq;
        int cpu;

        cpu = smp_processor_id();
        rq = cpu_rq(cpu);
        prev = rq->curr;  // <=================(1)
        .....
 

В чем разница между current и prev в строке (1) выше?

Добавление a printk() после этой строки:

 static void __sched notrace __schedule(bool preempt)
{
        struct task_struct *prev, *next;
        unsigned long *switch_count;
        struct rq_flags rf;
        struct rq *rq;
        int cpu;

        cpu = smp_processor_id();
        rq = cpu_rq(cpu);
        prev = rq->curr;
        //if(prev->pid != current->pid)
        printk("the prev->pid =%d, The current = %d n", prev->pid, current->pid); // <===========(2)

        schedule_debug(prev);

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

Результирующие журналы из (2):

 [ 4184.164038] the prev->pid =0, The current = 0 
[ 4184.165365] the prev->pid =12, The current = 12 
[ 4186.008068] the prev->pid =0, The current = 0 
[ 4186.009396] the prev->pid =30, The current = 30 
[ 4188.008046] the prev->pid =0, The current = 0 
[ 4188.009334] the prev->pid =30, The current = 30 
[ 4188.164041] the prev->pid =0, The current = 0 
[ 4188.165315] the prev->pid =12, The current = 12 
[ 4190.008047] the prev->pid =0, The current = 0 
[ 4190.009431] the prev->pid =30, The current = 30 
 

На дисплеях показано, что результат тот же.

  • почему бы не использовать current вместо
     cpu = smp_processor_id(); 
    rq = cpu_rq(cpu); 
    prev = rq->curr; 
 

Комментарии:

1. Способ его выполнения отключает упреждение. Использование current может иметь условия гонки.

Ответ №1:

prev это переменная, используемая для временного запоминания текущей задачи при замене ее новой в очереди выполнения. Конечно, если вы посмотрите на prev это точно сразу после того, как сделаете prev = rq->curr , у вас будет prev == rq->curr == current , так как это было только что назначено.

Если вы хотите проверить, какая задача выбирается для следующего запуска, вам придется позаботиться об этом, когда __schedule() это произойдет:

 next = pick_next_task(rq, prev, amp;rf);
 

Теперь next будет отличаться от prev .

Комментарии:

1. Член структуры curr , а не current

2. @MarcoBonelli Спасибо за ваш ответ, мне интересно, почему бы не использовать current вместо « cpu = smp_processor_id(); rq = cpu_rq (cpu); prev = rq-> curr; «

3. @Joeys посмотрите на это так: алгоритм планировщика имеет дело с очередями выполнения, и он должен работать независимо от того, существует глобальная current переменная или нет. Таким образом, структуры и код, реализующий алгоритм, не зависят от внешних факторов. Планировщику все равно, что current существует, это просто глобальная переменная (фактически макрос), которая существует для удобства, когда в ней нуждаются другие части кода ядра.