s-matyukevich/raspberry-pi-os

[Lession4] schedule function explanation seems incorrect

drymon opened this issue · 3 comments

Someone can you please help me to understand this explaination of the _schedule?

The algorithm works like the following:

The first inner for loop iterates over all tasks and tries to find a task in TASK_RUNNING state with the maximum counter. If such task is found and its counter is greater then 0, we immediately break from the outer while loop and switch to this task. If no such task is found this means that no tasks in TASK_RUNNING state currently exist or all such tasks have 0 counters. In a real OS, the first case might happen, for example, when all tasks are waiting for an interrupt. In this case, the second nested for loop is executed. For each task (no matter what state it is in) this loop increases its counter. The counter increase is done in a very smart way:

The more iterations of the second for loop a task passes, the more its counter will be increased.
A task counter can never get larger than 2 * priority.

My understanding is if all task are waiting for an interrupt, after the first for loop, 'c'=-1 and the if(c){break} will break the while loop and the second for loop will not be executed.
If my understanding is correct, the above explanation should be corrected.

I pasted the function here for convenient:

void _schedule(void)
{
    preempt_disable();
    int next,c;
    struct task_struct * p;
    while (1) {
        c = -1;
        next = 0;
        for (int i = 0; i < NR_TASKS; i++){
            p = task[i];
            if (p && p->state == TASK_RUNNING && p->counter > c) {
                c = p->counter;
                next = i;
            }
        }
        if (c) {
            break;
        }
        for (int i = 0; i < NR_TASKS; i++) {
            p = task[i];
            if (p) {
                p->counter = (p->counter >> 1) + p->priority;
            }
        }
    }
    switch_to(task[next]);
    preempt_enable();
}
X-141 commented

Fairly old post, but the explanation is correct. Since c = -1, the if statement containing the break will not execute and it will fall through to the second for loop.

Normal case is that some process will have a counter value of 1 or more and will have the running state (as of this lesson). In this case, this will be the chosen task, and we will switch to it. In the case that all processes are waiting for an interrupt, the statement: "if (p && p->state == TASK_RUNNING && p->counter > c)" will never be true . Therefore, c will remain -1 and "if (c)" will be false and we will fall through to the second for loop.

There is also the case where all tasks have counter of 0, and as the paragraph mentions, the second for loop will increase their counter within their priority range. We will stay in the while loop until at least on task has a state RUNNING.

I know this is an old response now, but I am responding because I have the same question as the op.
In C, if c=-1, then C interprets this as a truth value, so the if (c) will be true, and we will break the while loop and the second for loop will not be executed as the op said.

X-141 commented

You're correct. After quickly testing it myself I believe there is an error in the description as @drymon mentioned.