Scheduler

Scheduler’s job is to maintain the list of tasks and decide which one should be running next.

Description

Task states can be running, ready to run or sleeping.

When task is running, CPU is executing in that task’s context. The program counter (PC) is pointing to instructions task wants to execute and stack pointer (SP) is pointing to task’s stack.

Task which is ready to run wants to get on the CPU to do its work.

Task which is sleeping has no more work to do. It’s waiting for someone else to wake it up.

Scheduler algorithm is simple: from among the tasks which are ready to run, pick the the one with highest priority (lowest numeric value in task’s t_prio field), and make its state running.

Tasks which are either running or ready to run are kept in linked list g_os_run_list. This list is ordered by priority.

Tasks which are sleeping are kept in linked list g_os_sleep_list.

Scheduler has a CPU architecture specific component; this code is responsible for swapping in the task which should be running. This process is called context switch. During context switching the state of the CPU (e.g. registers) for the currently running task is stored and the new task is swapped in.

API

struct os_task *os_sched_get_current_task(void)

Returns the currently running task.

Note that this task may or may not be the highest priority task ready to run.

Return

The currently running task.

void os_sched_set_current_task(struct os_task *t)

Sets the currently running task to ‘t’.

Note that this function simply sets the global variable holding the currently running task. It does not perform a context switch or change the os run or sleep list.

Parameters
  • t: Pointer to currently running task.

struct os_task *os_sched_next_task(void)

Returns the task that we should be running.

This is the task at the head of the run list.

Note

If you want to guarantee that the os run list does not change after calling this function, you have to call it with interrupts disabled.

Return

The task at the head of the list

void os_sched_suspend(void)

Suspend task scheduling.

Function suspends the scheduler. Suspending the scheduler prevents a context switch but leaves interrupts enabled. Call to os_sched_resume() enables task scheduling again. Calls to os_sched_suspend() can be nested. The same number of calls must be made to os_sched_resume() as have previously been made to os_sched_suspend() before task scheduling work again.

int os_sched_resume(void)

Resume task scheduling.

Resumes the scheduler after it was suspended with os_sched_suspend().

Return

0 when scheduling resumed; non-0 when scheduling is still locked and more calls to os_sched_resume() are needed

void os_sched(struct os_task *next_t)

Performs context switch if needed.

If next_t is set, that task will be made running. If next_t is NULL, highest priority ready to run is swapped in. This function can be called when new tasks were made ready to run or if the current task is moved to sleeping state.

This function will call the architecture specific routine to swap in the new task.

// example
os_error_t
os_mutex_release(struct os_mutex *mu)
{
    ...
    OS_EXIT_CRITICAL(sr);

    // Re-schedule if needed
    if (resched) {
        os_sched(rdy);
    }

    return OS_OK;

}
Note

Interrupts must be disabled when calling this.

Parameters
  • next_t: Pointer to task which must run next (optional)