summaryrefslogtreecommitdiff
path: root/na/kernel/sched_internal.h
blob: 514b6135af2f572ba6c1a459e76763497835d5bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright (C) 2026 Richard Qin */

#pragma once

#include <lume/types.h>
#include <lume/list.h>
#include <lume/sched.h>
#include <lume/config.h>
#include <lume/bitops.h>
#include <lume/task.h>
#include <kernel/sync/spinlock.h>

class O1RunQueue {
public:
    void init() {
        bitmap_ = 0;
        nr_running_ = 0;
        for (int p = 0; p < kNumPriorities; p++) {
            queues_[p].init();
        }
    }

    void enqueue(TaskControlBlock* task) {
        int prio = task->priority;

        list_node* head = &queues_[prio];
        task->run_link.prev = head->prev;
        task->run_link.next = head;
        head->prev->next = &task->run_link;
        head->prev = &task->run_link;

        bitmap_ |= (1U << prio);
        nr_running_++;

        task->state = TaskState::Runnable;
    }

    void dequeue(TaskControlBlock* task) {
        int prio = task->priority;

        task->run_link.prev->next = task->run_link.next;
        task->run_link.next->prev = task->run_link.prev;
        task->run_link.init();

        if (queues_[prio].is_empty()) {
            bitmap_ &= ~(1U << prio);
        }

        if (nr_running_ > 0) {
            nr_running_--;
        }
    }

    TaskControlBlock* pick_next() const {
        if (bitmap_ == 0) {
            return nullptr;
        }

        int prio = lume::ctz32(bitmap_);
        list_node* node = queues_[prio].next;
        return list_entry<TaskControlBlock, &TaskControlBlock::run_link>(node);
    }

    uint32 nr_running() const { return nr_running_; }

private:
    uint32 bitmap_ = 0;
    list_node queues_[kNumPriorities];
    uint32 nr_running_ = 0;
};

class RunQueue {
public:
    void init(uint32 cpu_id) {
        lock_.init("RunQueue");
        cpu_id_ = cpu_id;
        nr_running_ = 0;
        need_resched_ = false;
        current_ = nullptr;
        idle_ = nullptr;
    }

    Spinlock& lock() { return lock_; }

    uint32 cpu_id() const { return cpu_id_; }

    uint32 nr_running() const { return nr_running_; }
    void inc_running() { nr_running_++; }
    void dec_running() { if (nr_running_ > 0) nr_running_--; }

    bool need_resched() const { return need_resched_; }
    void set_need_resched(bool v) { need_resched_ = v; }
    void clear_need_resched() { need_resched_ = false; }

    TaskControlBlock* current() const { return current_; }
    void set_current(TaskControlBlock* task) { current_ = task; }

    TaskControlBlock* idle() const { return idle_; }
    void set_idle(TaskControlBlock* task) { idle_ = task; }

    O1RunQueue& o1() { return o1_; }
    const O1RunQueue& o1() const { return o1_; }

private:
    Spinlock lock_;
    uint32 cpu_id_ = 0;
    uint32 nr_running_ = 0;
    bool need_resched_ = false;

    TaskControlBlock* current_ = nullptr;
    TaskControlBlock* idle_ = nullptr;

    O1RunQueue o1_;
};