/* Copyright (C) 2021,2022 fef . All rights reserved. */ #pragma once #include #include #include #include #include enum task_state { TASK_READY, TASK_BLOCKED, TASK_DEAD, }; struct task { /** * @brief List node for enqueuing this task in the scheduler's pipeline. * When the task is currently running, this is invalid because the task * is not in any queue. */ struct clist run_queue; tcb_t tcb; struct task *parent; pid_t pid; /** * @brief 0 = interruptable, > 0 = uninterruptible, < 0 = we messed up. * Increment/decrement using `critical_enter()`/`critical_leave()`. */ volatile int critnest; enum task_state state; }; /** * @brief The task that is currently running on this particular cpu core. * May not be accessed from irq context. * * This will become a macro which calls some function once we have SMP support, * so if you need to access it multiple times from the same place you should * copy it into a local variable first to avoid extra overhead. * * For the same reason, don't assign values to this directly, and use * `set_current()` instead. */ extern struct task *current_array[CFG_MAX_CPU]; #define current (current_array[smp_cpuid()]) /** * @brief Update the `current` task. * You will almost never need this because `switch_to()` does it automatically. */ static inline void set_current(struct task *task) { current_array[smp_cpuid()] = task; } extern struct task kernel_task; /** * @brief Initialize the scheduler. * * @return 0 on success, or a negative error number on failure */ int sched_init(void); /** * @brief Main scheduler routine. * Calling this function will result in the current task being suspended and put * back to the queue, and a new one is selected to be run next. The scheduler * is free to choose the current task again, in which case this call does not * sleep. The function returns when the scheduler has been invoked again and * decided to give this task its next turn. */ void schedule(void); /** * @brief Perform an in-kernel task switch. * `new` must not be equal to `old` or the whole thing probably blows up. * * The Linux kernel has a similar function with the same name, except that the * arguments are in reverse order because i find it funny to cause unnecessary * confusion which will undoubtedly result in a lot of bugs further down the * road that are going to take weeks to find. * * @param new New task to switch to * @param old Current task */ void switch_to(struct task *new, struct task *old);