diff --git a/.vscode/settings.json b/.vscode/settings.json index f840a4b2..96619eba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -146,7 +146,8 @@ "lockref.h": "c", "compiler_attributes.h": "c", "timer.h": "c", - "hid.h": "c" + "hid.h": "c", + "cfs.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/common/kfifo.h b/kernel/common/kfifo.h index 1c9c7778..f0490eb5 100644 --- a/kernel/common/kfifo.h +++ b/kernel/common/kfifo.h @@ -127,10 +127,10 @@ uint32_t kfifo_out_peek(struct kfifo_t *fifo, void *to, uint32_t size); * @param lock 自旋锁 * @return uint32_t 推入的数据大小 */ -uint32_t __always_inline kfifo_in_lockd(struct kfifo_t *fifo, const void *from, uint32_t size, spinlock_t *lock) +uint32_t __always_inline kfifo_in_locked(struct kfifo_t *fifo, const void *from, uint32_t size, spinlock_t *lock) { spin_lock(lock); - uint32_t retval = kfifo_in(&fifo, &from, size); + uint32_t retval = kfifo_in(fifo, from, size); spin_unlock(lock); return retval; } @@ -144,10 +144,10 @@ uint32_t __always_inline kfifo_in_lockd(struct kfifo_t *fifo, const void *from, * @param lock 自旋锁 * @return uint32_t 取出的数据大小 */ -uint32_t __always_inline kfifo_out_lockd(struct kfifo_t *fifo, void *to, uint32_t size, spinlock_t *lock) +uint32_t __always_inline kfifo_out_locked(struct kfifo_t *fifo, void *to, uint32_t size, spinlock_t *lock) { spin_lock(lock); - uint32_t retval = kfifo_out(&fifo, &to, size); + uint32_t retval = kfifo_out(fifo, to, size); spin_unlock(lock); return retval; } diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index c22a6e24..7a90f4c9 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -2,7 +2,12 @@ CFLAGS += -I . -all: sched.o +all: sched.o cfs.o + +cfs.o: cfs.c + $(CC) $(CFLAGS) -c cfs.c -o cfs.o sched.o: sched.c $(CC) $(CFLAGS) -c sched.c -o sched.o +clean: + echo "Done." \ No newline at end of file diff --git a/kernel/sched/cfs.c b/kernel/sched/cfs.c new file mode 100644 index 00000000..9319891f --- /dev/null +++ b/kernel/sched/cfs.c @@ -0,0 +1,154 @@ +#include "cfs.h" +#include +#include +#include + +struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 + +/** + * @brief 从就绪队列中取出PCB + * + * @return struct process_control_block* + */ +struct process_control_block *sched_cfs_dequeue() +{ + if (list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) + { + // kdebug("list empty, count=%d", sched_cfs_ready_queue[proc_current_cpu_id].count); + return &initial_proc_union.pcb; + } + + 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); + + list_del(&proc->list); + --sched_cfs_ready_queue[proc_current_cpu_id].count; + return proc; +} + +/** + * @brief 将PCB加入就绪队列 + * + * @param pcb + */ +void sched_cfs_enqueue(struct process_control_block *pcb) +{ + if (pcb == initial_proc[proc_current_cpu_id]) + return; + 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); + if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0) + { + while (proc->virtual_runtime < pcb->virtual_runtime) + { + proc = container_of(list_next(&proc->list), struct process_control_block, list); + } + } + list_append(&proc->list, &pcb->list); + ++sched_cfs_ready_queue[proc_current_cpu_id].count; +} + +/** + * @brief 调度函数 + * + */ +void sched_cfs() +{ + + cli(); + + current_pcb->flags &= ~PF_NEED_SCHED; + // kdebug("current_pcb pid= %d", current_pcb->pid); + struct process_control_block *proc = sched_cfs_dequeue(); + // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d", sched_cfs_ready_queue[proc_current_cpu_id].count); + if (current_pcb->virtual_runtime >= proc->virtual_runtime || !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换 + { + + // kdebug("current_pcb->virtual_runtime = %d,proc->vt= %d", current_pcb->virtual_runtime, proc->virtual_runtime); + if (current_pcb->state & PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 + sched_cfs_enqueue(current_pcb); + // kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count); + if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) + { + switch (proc->priority) + { + case 0: + case 1: + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; + break; + case 2: + default: + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; + break; + } + } + + + process_switch_mm(proc); + + switch_proc(current_pcb, proc); + } + else // 不进行切换 + { + // kdebug("not switch."); + sched_cfs_enqueue(proc); + + if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) + { + switch (proc->priority) + { + case 0: + case 1: + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; + break; + case 2: + default: + + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; + break; + } + } + } + + sti(); +} + +/** + * @brief 当时钟中断到达时,更新时间片 + * + */ +void sched_update_jiffies() +{ + + switch (current_pcb->priority) + { + case 0: + case 1: + --sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies; + ++current_pcb->virtual_runtime; + break; + case 2: + default: + sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies -= 2; + current_pcb->virtual_runtime += 2; + break; + } + // 时间片耗尽,标记可调度 + if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) + current_pcb->flags |= PF_NEED_SCHED; +} + +/** + * @brief 初始化CFS调度器 + * + */ +void sched_cfs_init() +{ + memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t) * MAX_CPU_NUM); + for (int i = 0; i < MAX_CPU_NUM; ++i) + { + + list_init(&sched_cfs_ready_queue[i].proc_queue.list); + sched_cfs_ready_queue[i].count = 1; // 因为存在IDLE进程,因此为1 + sched_cfs_ready_queue[i].cpu_exec_proc_jiffies = 5; + sched_cfs_ready_queue[i].proc_queue.virtual_runtime = 0x7fffffffffffffff; + } +} \ No newline at end of file diff --git a/kernel/sched/cfs.h b/kernel/sched/cfs.h new file mode 100644 index 00000000..734783d4 --- /dev/null +++ b/kernel/sched/cfs.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +// @todo: 用红黑树重写cfs的队列 +struct sched_queue_t +{ + long count; // 当前队列中的数量 + long cpu_exec_proc_jiffies; // 进程可执行的时间片数量 + struct process_control_block proc_queue; +}; + +extern struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 + +/** + * @brief 调度函数 + * + */ +void sched_cfs(); + +/** + * @brief 将PCB加入就绪队列 + * + * @param pcb + */ +void sched_cfs_enqueue(struct process_control_block *pcb); + +/** + * @brief 从就绪队列中取出PCB + * + * @return struct process_control_block* + */ +struct process_control_block *sched_cfs_dequeue(); +/** + * @brief 初始化CFS进程调度器 + * + */ +void sched_cfs_init(); + +/** + * @brief 当时钟中断到达时,更新时间片 + * + */ +void sched_update_jiffies(); diff --git a/kernel/sched/sched.c b/kernel/sched/sched.c index c142c32e..8f3d7b36 100644 --- a/kernel/sched/sched.c +++ b/kernel/sched/sched.c @@ -2,54 +2,11 @@ #include #include #include - - -struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 - -/** - * @brief 从就绪队列中取出PCB - * - * @return struct process_control_block* - */ -struct process_control_block *sched_cfs_dequeue() -{ - if (list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) - { - // kdebug("list empty, count=%d", sched_cfs_ready_queue[proc_current_cpu_id].count); - return &initial_proc_union.pcb; - } - - 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); - - list_del(&proc->list); - --sched_cfs_ready_queue[proc_current_cpu_id].count; - return proc; -} - -/** - * @brief 将PCB加入就绪队列 - * - * @param pcb - */ -void sched_cfs_enqueue(struct process_control_block *pcb) -{ - if (pcb == initial_proc[proc_current_cpu_id]) - return; - 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); - if ((list_empty(&sched_cfs_ready_queue[proc_current_cpu_id].proc_queue.list)) == 0) - { - while (proc->virtual_runtime < pcb->virtual_runtime) - { - proc = container_of(list_next(&proc->list), struct process_control_block, list); - } - } - list_append(&proc->list, &pcb->list); - ++sched_cfs_ready_queue[proc_current_cpu_id].count; -} +#include /** * @brief 包裹shced_cfs_enqueue(),将PCB加入就绪队列 - * + * * @param pcb */ void sched_enqueue(struct process_control_block *pcb) @@ -57,124 +14,16 @@ void sched_enqueue(struct process_control_block *pcb) sched_cfs_enqueue(pcb); } -/** - * @brief 调度函数 - * - */ -void sched_cfs() -{ - - cli(); - - current_pcb->flags &= ~PF_NEED_SCHED; - struct process_control_block *proc = sched_cfs_dequeue(); - // kdebug("sched_cfs_ready_queue[proc_current_cpu_id].count = %d", sched_cfs_ready_queue[proc_current_cpu_id].count); - if (current_pcb->virtual_runtime >= proc->virtual_runtime || !(current_pcb->state & PROC_RUNNING)) // 当前进程运行时间大于了下一进程的运行时间,进行切换 - { - - if (current_pcb->state & PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 - sched_cfs_enqueue(current_pcb); - // kdebug("proc->pid=%d, count=%d", proc->pid, sched_cfs_ready_queue[proc_current_cpu_id].count); - if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) - { - switch (proc->priority) - { - case 0: - case 1: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; - break; - case 2: - default: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; - break; - } - } - - // if (proc->pid == 0) - // { - // kdebug("switch to pid0, current pid%ld, vrt=%ld pid0 vrt=%ld", current_pcb->pid, current_pcb->virtual_runtime, proc->virtual_runtime); - // if(current_pcb->state != PROC_RUNNING) - // kdebug("current_pcb->state!=PROC_RUNNING"); - // } - - process_switch_mm(proc); - - switch_proc(current_pcb, proc); - } - else // 不进行切换 - { - // kdebug("not switch."); - sched_cfs_enqueue(proc); - - if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) - { - switch (proc->priority) - { - case 0: - case 1: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue[proc_current_cpu_id].count; - // sched_cfs_ready_queue.cpu_exec_proc_jiffies = 5; - break; - case 2: - default: - // sched_cfs_ready_queue.cpu_exec_proc_jiffies = 5; - - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue[proc_current_cpu_id].count) << 2; - break; - } - } - } - - sti(); -} - /** * @brief 包裹sched_cfs(),调度函数 - * + * */ void sched() { sched_cfs(); } -/** - * @brief 当时钟中断到达时,更新时间片 - * - */ -void sched_update_jiffies() -{ - - switch (current_pcb->priority) - { - case 0: - case 1: - --sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies; - ++current_pcb->virtual_runtime; - break; - case 2: - default: - sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies -= 2; - current_pcb->virtual_runtime += 2; - break; - } - // 时间片耗尽,标记可调度 - if (sched_cfs_ready_queue[proc_current_cpu_id].cpu_exec_proc_jiffies <= 0) - current_pcb->flags |= PF_NEED_SCHED; -} - -/** - * @brief 初始化进程调度器 - * - */ void sched_init() { - memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t) * MAX_CPU_NUM); - for (int i = 0; i < MAX_CPU_NUM; ++i) - { - - list_init(&sched_cfs_ready_queue[i].proc_queue.list); - sched_cfs_ready_queue[i].count = 1; // 因为存在IDLE进程,因此为1 - sched_cfs_ready_queue[i].cpu_exec_proc_jiffies = 5; - sched_cfs_ready_queue[i].proc_queue.virtual_runtime = 0x7fffffffffffffff; - } + sched_cfs_init(); } \ No newline at end of file diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 8159ae72..8f088354 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2,60 +2,17 @@ #include #include - -// @todo: 用红黑树重写cfs的队列 -struct sched_queue_t -{ - long count; // 当前队列中的数量 - long cpu_exec_proc_jiffies; // 进程可执行的时间片数量 - struct process_control_block proc_queue; -}; - - -extern struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列 - -/** - * @brief 调度函数 - * - */ -void sched_cfs(); - -/** - * @brief 包裹sched_cfs(),调度函数 - * - */ -void sched(); - -/** - * @brief 将PCB加入就绪队列 - * - * @param pcb - */ -void sched_cfs_enqueue(struct process_control_block *pcb); - /** * @brief 包裹sched_enqueue(),将PCB加入就绪队列 - * + * * @param pcb */ void sched_enqueue(struct process_control_block *pcb); - /** - * @brief 从就绪队列中取出PCB + * @brief 包裹sched_cfs(),调度函数 * - * @return struct process_control_block* */ -struct process_control_block *sched_cfs_dequeue(); +void sched(); -/** - * @brief 初始化进程调度器 - * - */ -void sched_init(); - -/** - * @brief 当时钟中断到达时,更新时间片 - * - */ -void sched_update_jiffies(); +void sched_init(); \ No newline at end of file