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.

116 lines
3.5 KiB
C

/* See the end of this file for copyright, license, and warranty information. */
#pragma once
#include <ardix/kent.h>
#include <ardix/list.h>
#include <ardix/types.h>
#include <config.h>
#if CONFIG_SCHED_MAXTASK > 64
#warning "CONFIG_SCHED_MAXTASK is > 64, this could have a significant performance impact"
#endif
enum task_state {
/** Task is dead / doesn't exist */
TASK_DEAD,
/** Task is ready for execution or currently running. */
TASK_READY,
/** Task is waiting for its next time share. */
TASK_QUEUE,
/** Task is sleeping, `task::sleep` specifies for how many ticks. */
TASK_SLEEP,
/** Task is waiting for I/O to flush buffers. */
TASK_IOWAIT,
};
/** @brief Core structure holding information about a task. */
struct task {
struct kent kent;
/** current stack pointer (only gets updated for task switching) */
void *sp;
/** first address of the stack (highest if the stack grows downwards) */
void *stack_bottom;
/** @brief If state is `TASK_SLEEP`, the total amount of ticks to sleep */
unsigned long int sleep;
/** @brief Last execution in ticks */
unsigned long int last_tick;
enum task_state state;
pid_t pid;
};
/** @brief Current task (access from syscall context only) */
extern struct task *current;
/** @brief Global system tick counter (may overflow) */
extern volatile unsigned long int tick;
/**
* @brief If nonzero, the scheduler is invoked after the current syscall.
* This is checked and then cleared after every syscall. If it has a nonzero
* value, `sched_switch()` is called after `arch_enter()`.
*/
extern int need_resched;
/**
* @brief Initialize the scheduler subsystem.
* This sets up a hardware interrupt timer (SysTick for Cortex-M3).
*/
int sched_init(void);
/**
* @brief Switch to the next task (scheduler context only).
* Must be called directly from within an interrupt routine.
* This selects a new task to be run and updates the old and new task's `state`
* field to the appropriate value. Called from the scheduler exception handler.
*
* @param curr_sp Stack pointer of the current task
* @returns Stack pointer of the new task
*/
void *sched_switch(void *curr_sp);
/**
* @brief Create a copy of the `current` task and return it.
* The new task becomes a child of the `current` task and is inserted into the
* process table so that it can be executed by the scheduler after its state
* is set to `TASK_QUEUE`. When the task is returned, its initial state is
* `TASK_UNKNOWN` so that the caller has time to do any additional required
* setup work.
*
* @param task Task to make a copy of
* @returns The new (child) task copy, or `NULL` on failure
*/
struct task *task_clone(struct task *task);
/**
* @brief Sleep for an approximate amount of milliseconds.
* Must not be invoked from atomic or irq context.
*
* @param ms Amount of milliseconds
*/
void msleep(unsigned long int ms);
/**
* @brief Suspend the `current` task and invoke the scheduler early.
* May only be called from syscall context.
*
* @param state State the task should enter.
* Allowed values are `TASK_SLEEP` and `TASK_IOWAIT`.
*/
void yield(enum task_state state);
/*
* This file is part of Ardix.
* Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>.
*
* Ardix is non-violent software: you may only use, redistribute,
* and/or modify it under the terms of the CNPLv6+ as found in
* the LICENSE file in the source code root directory or at
* <https://git.pixie.town/thufie/CNPL>.
*
* Ardix comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPLv6+ for details.
*/