tianole/kernel/sched/sched.h

133 lines
3.1 KiB
C

#ifndef KERNEL_SCHED_SCHED_H
#define KERNEL_SCHED_SCHED_H
#include <stdint.h>
#include <tianole/early_log.h>
#include <tianole/sched.h>
#include <tianole/spinlock.h>
extern struct thread *run_queue_head;
extern struct thread *run_queue_tail;
extern struct thread *current_thread;
extern uintptr_t boot_stack_pointer;
extern uint64_t next_thread_id;
extern int scheduler_ready;
extern int schedule_locked;
extern int need_resched;
extern struct thread *idle_thread;
extern struct spinlock scheduler_lock;
static inline int thread_is_ready(const struct thread *thread)
{
return thread != 0 && thread->state == THREAD_READY;
}
static inline int thread_is_running(const struct thread *thread)
{
return thread != 0 && thread->state == THREAD_RUNNING;
}
static inline int thread_is_sleeping(const struct thread *thread)
{
return thread != 0 && thread->state == THREAD_SLEEPING;
}
static inline int thread_is_waiting(const struct thread *thread)
{
return thread != 0 && thread->state == THREAD_WAITING;
}
static inline int thread_is_dead(const struct thread *thread)
{
return thread != 0 && thread->state == THREAD_DEAD;
}
static inline int thread_state_transition_is_valid(
enum thread_state from, enum thread_state to)
{
if (from == to) {
return 1;
}
switch (from) {
case THREAD_READY:
return to == THREAD_RUNNING;
case THREAD_RUNNING:
return to == THREAD_READY || to == THREAD_SLEEPING ||
to == THREAD_WAITING || to == THREAD_DEAD;
case THREAD_SLEEPING:
case THREAD_WAITING:
return to == THREAD_READY || to == THREAD_DEAD;
case THREAD_DEAD:
return 0;
default:
return 0;
}
}
static inline void thread_validate_state_transition(
struct thread *thread, enum thread_state state)
{
if (thread == 0) {
panic("null thread state transition");
}
if (!thread_state_transition_is_valid(thread->state, state)) {
panic("invalid thread state transition");
}
}
static inline void thread_set_state(
struct thread *thread, enum thread_state state)
{
thread_validate_state_transition(thread, state);
thread->state = state;
}
static inline void thread_init_ready(struct thread *thread)
{
thread->wake_tick = 0;
thread->state = THREAD_READY;
}
static inline void thread_set_ready(struct thread *thread)
{
thread_set_state(thread, THREAD_READY);
thread->wake_tick = 0;
}
static inline void thread_set_running(struct thread *thread)
{
thread_set_state(thread, THREAD_RUNNING);
}
static inline void thread_set_sleeping(
struct thread *thread, uint64_t wake_tick)
{
thread_validate_state_transition(thread, THREAD_SLEEPING);
thread->wake_tick = wake_tick;
thread->state = THREAD_SLEEPING;
}
static inline void thread_set_waiting(struct thread *thread)
{
thread_set_state(thread, THREAD_WAITING);
thread->wake_tick = 0;
}
static inline void thread_set_dead(struct thread *thread)
{
thread_set_state(thread, THREAD_DEAD);
thread->wake_tick = 0;
}
void enqueue_thread(struct thread *thread);
void sched_reap_dead_threads(void);
void sched_thread_exit(void) __attribute__((noreturn));
void sched_selftest(void);
int sched_idle_create(void);
void sched_demo_start(void) __attribute__((noreturn));
#endif