You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.6 KiB
C

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#pragma once
#include <arch/sched.h>
#include <arch/smp.h>
#include <gay/cdefs.h>
#include <gay/clist.h>
#include <gay/types.h>
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);