Skip to content

Scheduler

include/sch/sched.h View source View on GitHub
struct idle_thread_data {
    _Atomic uint64_t  last_entry_ms;
    uint64_t          last_exit_ms;
};
struct scheduler {
    atomic_bool                 tick_enabled;
    time_t                      tick_duration_ms;
    struct list_head            urgent_threads;
    struct rbt                  thread_rbt;
    struct rbt                  completed_rbt;
    struct list_head            rt_threads;
    struct list_head            bg_threads;
    struct rbt                  climb_threads;
    _Atomic uint8_t             queue_bitmap;
    struct thread               *current;
    struct thread               *drop_last_ref;
    size_t                      thread_count[THREAD_PRIO_CLASS_COUNT];
    size_t                      total_thread_count;
    size_t                      total_weight;
    bool                        period_enabled;
    uint64_t                    current_period;
    time_t                      period_ms;
    time_t                      period_start_ms;
    uint64_t                    core_id;
    atomic_bool                 being_robbed;
    atomic_bool                 stealing_work;
    struct spinlock             lock;
    struct thread               *idle_thread;
    struct idle_thread_data     idle_thread_data;
    struct scheduler            *other_locked;
    struct rt_scheduler_percpu  *rt;
};
struct scheduler_data {
    uint32_t          max_concurrent_stealers;
    _Atomic uint32_t  active_stealers;
    _Atomic uint32_t  total_threads;
    _Atomic int64_t   steal_min_diff;
};
void scheduler_init();
struct scheduler * scheduler_select_best_for_thread(struct thread *t);
void scheduler_add_thread(struct scheduler *sched, struct thread *thread, bool lock_held);
void scheduler_remove_thread(struct scheduler *sched, struct thread *t, bool lock_held);
void schedule(void);
void k_sch_main(void * *);
void scheduler_idle_main(void * *);
void scheduler_yield();
void scheduler_period_start(struct scheduler *s, uint64_t now_ms);
void switch_context(struct cpu_context *old, struct cpu_context *new);
void load_context(struct cpu_context *new);
void save_context(struct cpu_context *new);
bool scheduler_can_steal_work(struct scheduler *sched);
bool scheduler_can_take_thread(size_t core, struct thread *target);
uint64_t scheduler_compute_steal_threshold();
struct thread * scheduler_try_do_steal(struct scheduler *sched);
struct scheduler * scheduler_pick_victim(struct scheduler *self);
struct thread * scheduler_steal_work(struct scheduler *new, struct scheduler *victim);
size_t scheduler_try_push_to_idle_core(struct scheduler *sched);
void scheduler_tick_enable();
void scheduler_tick_disable();
enum irq_result scheduler_timer_isr(void *ctx, uint8_t vector, struct irq_context *rsp);
bool scheduler_self_in_resched();
bool scheduler_mark_self_in_resched(bool new);
bool scheduler_mark_core_needs_resched(struct core *c, bool new);
bool scheduler_mark_self_needs_resched(bool new);
bool scheduler_self_needs_resched(void);
void scheduler_mark_self_idle(bool new);
void scheduler_resched_if_needed(void);
bool scheduler_core_idle(struct core *c);
void scheduler_force_resched(struct scheduler *sched);
bool scheduler_preemption_disabled(void);
extern struct scheduler_data scheduler_data;
#define WORK_STEAL_THRESHOLD \
    75ULL /* How little work the core needs to be \
           * doing to try to steal work from another \
           * core. This means "% of the average" \
           */
#define SCHEDULER_DEFAULT_WORK_STEAL_MIN_DIFF 130
#define TICKS_FOR_PRIO(level) (level == THREAD_PRIO_LOW ? 64 : 1ULL << level)