1 #include "cfs.h"
2 #include <common/kprint.h>
3 #include <driver/video/video.h>
4 #include <common/spinlock.h>
5
6 struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列
7
8 /**
9 * @brief 从就绪队列中取出PCB
10 *
11 * @return struct process_control_block*
12 */
sched_cfs_dequeue()13 struct process_control_block *sched_cfs_dequeue()
14 {
15 if (list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list))
16 {
17 // kdebug("list empty, count=%d", sched_cfs_ready_queue[proc_current_cpu_id].count);
18 return &initial_proc_union.pcb;
19 }
20
21 struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list);
22
23 list_del(&proc->list);
24 --sched_cfs_ready_queue[proc_current_cpu_id].count;
25 return proc;
26 }
27
28 /**
29 * @brief 将PCB加入就绪队列
30 *
31 * @param pcb
32 */
sched_cfs_enqueue(struct process_control_block * pcb)33 void sched_cfs_enqueue(struct process_control_block *pcb)
34 {
35 if (pcb == initial_proc[proc_current_cpu_id])
36 return;
37 struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list), struct process_control_block, list);
38 if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0)
39 {
40 while (proc->virtual_runtime < pcb->virtual_runtime)
41 {
42 proc = container_of(list_next(&proc->list), struct process_control_block, list);
43 }
44 }
45 list_append(&proc->list, &pcb->list);
46 ++sched_cfs_ready_queue[proc_current_cpu_id].count;
47 }
48
49 /**
50 * @brief 调度函数
51 *
52 */
sched_cfs()53 void sched_cfs()
54 {
55
56 cli();
57
58 current_pcb->flags &= ~PF_NEED_SCHED;
59 // kdebug("current_pcb pid= %d", current_pcb->pid);
60 struct process_control_block *proc = sched_cfs_dequeue();
61 // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d", sched_cfs_ready_queue[proc_current_cpu_id].count);
62 if (current_pcb->virtual_runtime >= proc->virtual_runtime || !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换
63 {
64
65 // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime, proc->virtual_runtime);
66 if (current_pcb->state & PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
67 sched_cfs_enqueue(current_pcb);
68 // kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count);
69 if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
70 {
71 switch (proc->priority)
72 {
73 case 0:
74 case 1:
75 sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count;
76 break;
77 case 2:
78 default:
79 sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2;
80 break;
81 }
82 }
83
84 process_switch_mm(proc);
85
86 switch_proc(current_pcb, proc);
87 }
88 else // 不进行切换
89 {
90 // kdebug("not switch.");
91 sched_cfs_enqueue(proc);
92
93 if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
94 {
95 switch (proc->priority)
96 {
97 case 0:
98 case 1:
99 sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count;
100 break;
101 case 2:
102 default:
103
104 sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2;
105 break;
106 }
107 }
108 }
109
110 sti();
111 }
112
113 /**
114 * @brief 当时钟中断到达时,更新时间片
115 *
116 */
sched_update_jiffies()117 void sched_update_jiffies()
118 {
119
120 switch (current_pcb->priority)
121 {
122 case 0:
123 case 1:
124 --sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies;
125 ++current_pcb->virtual_runtime;
126 break;
127 case 2:
128 default:
129 sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies -= 2;
130 current_pcb->virtual_runtime += 2;
131 break;
132 }
133 // 时间片耗尽,标记可调度
134 if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0)
135 current_pcb->flags |= PF_NEED_SCHED;
136 }
137
138 /**
139 * @brief 初始化CFS调度器
140 *
141 */
sched_cfs_init()142 void sched_cfs_init()
143 {
144 memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t) * MAX_CPU_NUM);
145 for (int i = 0; i < MAX_CPU_NUM; ++i)
146 {
147
148 list_init(&sched_cfs_ready_queue[i].proc_queue.list);
149 sched_cfs_ready_queue[i].count = 1; // 因为存在IDLE进程,因此为1
150 sched_cfs_ready_queue[i].cpu_exec_proc_jiffies = 5;
151 sched_cfs_ready_queue[i].proc_queue.virtual_runtime = 0x7fffffffffffffff;
152 }
153 }