From 7295565e5e7ea88f57c8f932f603e73d81202830 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Wed, 13 Apr 2022 11:14:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=94=81=E7=9A=84=E6=8C=81?= =?UTF-8?q?=E6=9C=89=E8=AE=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/process/preempt.h | 23 ++++++++++++++++++++ kernel/process/process.c | 34 ++++++++++++++++++++++++------ kernel/process/process.h | 37 ++++++++++++++------------------ kernel/process/spinlock.h | 44 +++++++++++++++++++++++++++++---------- 4 files changed, 100 insertions(+), 38 deletions(-) create mode 100644 kernel/process/preempt.h diff --git a/kernel/process/preempt.h b/kernel/process/preempt.h new file mode 100644 index 00000000..49cfce0d --- /dev/null +++ b/kernel/process/preempt.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +/** + * @brief 增加自旋锁计数变量 + * + */ +#define preempt_disable() \ +do \ +{ \ + --(current_pcb->preempt_count);\ +} while (0) + +/** + * @brief 减少自旋锁计数变量 + * + */ +#define preempt_enable() \ +do \ +{ \ + ++(current_pcb->preempt_count);\ +}while(0) diff --git a/kernel/process/process.c b/kernel/process/process.c index 58fc9e6f..10168235 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -10,6 +10,25 @@ extern void system_call(void); +struct mm_struct initial_mm = {0}; +struct thread_struct initial_thread = + { + .rbp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), + .rsp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), + .fs = KERNEL_DS, + .gs = KERNEL_DS, + .cr2 = 0, + .trap_num = 0, + .err_code = 0}; + +// 初始化 初始进程的union ,并将其链接到.data.init_proc段内 +union proc_union initial_proc_union __attribute__((__section__(".data.init_proc_union"))) = {INITIAL_PROC(initial_proc_union.pcb)}; + +struct process_control_block *initial_proc[MAX_CPU_NUM] = {&initial_proc_union.pcb, 0}; + +// 为每个核心初始化初始进程的tss +struct tss_struct initial_tss[MAX_CPU_NUM] = {[0 ... MAX_CPU_NUM - 1] = INITIAL_TSS}; + /** * @brief 切换进程 * @@ -56,7 +75,7 @@ void user_level_function() long ret = 0; // color_printk(RED,BLACK,"user_level_function task is running\n"); - char string[] = "Hello World!\n"; + char string[] = "User level process.\n"; /* __asm__ __volatile__("leaq sysexit_return_address(%%rip), %%rdx \n\t" "movq %%rsp, %%rcx \n\t" @@ -274,6 +293,7 @@ void process_init() initial_mm.stack_start = *(ul *)phys_2_virt(&_stack_start); + /* // 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址 wrmsr(0x174, KERNEL_CS); // 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp(在syscall入口中会将rsp减去相应的数值) @@ -281,6 +301,7 @@ void process_init() // 向MSR寄存器组中的 IA32_SYSENTER_EIP寄存器写入系统调用入口的地址。 wrmsr(0x176, (ul)system_call); + */ // 初始化进程和tss set_tss64((uint *)phys_2_virt(TSS64_Table), initial_thread.rbp, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7); @@ -294,11 +315,11 @@ void process_init() list_init(&initial_proc_union.pcb.list); kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); // 初始化内核进程 initial_proc_union.pcb.state = PROC_RUNNING; - + initial_proc_union.pcb.preempt_count = 0; // 获取新的进程的pcb - struct process_control_block *p = container_of(list_next(¤t_pcb->list), struct process_control_block, list); + //struct process_control_block *p = container_of(list_next(¤t_pcb->list), struct process_control_block, list); - kdebug("Ready to switch..."); + //kdebug("Ready to switch..."); // 切换到新的内核线程 // switch_proc(current_pcb, p); } @@ -327,13 +348,14 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned // 将当前进程的pcb复制到新的pcb内 *tsk = *current_pcb; - kdebug("current_pcb->flags=%#010lx", current_pcb->flags); + //kdebug("current_pcb->flags=%#010lx", current_pcb->flags); // 将进程加入循环链表 list_init(&tsk->list); // list_add(&initial_proc_union.pcb.list, &tsk->list); tsk->priority = 2; + tsk->preempt_count = 0; ++(tsk->pid); tsk->state = PROC_UNINTERRUPTIBLE; list_init(&tsk->list); @@ -353,7 +375,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned thd->fs = KERNEL_DS; thd->gs = KERNEL_DS; - kdebug("do_fork() thd->rsp=%#018lx", thd->rsp); + //kdebug("do_fork() thd->rsp=%#018lx", thd->rsp); // 若进程不是内核层的进程,则跳转到ret from system call if (!(tsk->flags & PF_KTHREAD)) thd->rip = regs->rip = (ul)ret_from_system_call; diff --git a/kernel/process/process.h b/kernel/process/process.h index 28ecddc4..f314baa4 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -16,8 +16,7 @@ #include "../syscall/syscall.h" #include "ptrace.h" -extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S) -extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) + // 进程的内核栈大小 32K #define STACK_SIZE 32768 @@ -99,6 +98,7 @@ struct process_control_block volatile long state; // 进程标志:进程、线程、内核线程 unsigned long flags; + int64_t preempt_count; // 持有的自旋锁的数量 long signal; // 内存空间分布结构体, 记录内存页表和程序段信息 struct mm_struct *mm; @@ -126,8 +126,6 @@ union proc_union ul stack[STACK_SIZE / sizeof(ul)]; } __attribute__((aligned(8))); -struct mm_struct initial_mm; -struct thread_struct initial_thread; // 设置初始进程的PCB #define INITIAL_PROC(proc) \ @@ -140,24 +138,13 @@ struct thread_struct initial_thread; .pid = 0, \ .virtual_runtime = 0, \ .signal = 0, \ - .priority = 2 \ + .priority = 2, \ + .preempt_count = 0, \ } -// 初始化 初始进程的union ,并将其链接到.data.init_proc段内 -union proc_union initial_proc_union __attribute__((__section__(".data.init_proc_union"))) = {INITIAL_PROC(initial_proc_union.pcb)}; -struct process_control_block *initial_proc[MAX_CPU_NUM] = {&initial_proc_union.pcb, 0}; -struct mm_struct initial_mm = {0}; -struct thread_struct initial_thread = - { - .rbp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), - .rsp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), - .fs = KERNEL_DS, - .gs = KERNEL_DS, - .cr2 = 0, - .trap_num = 0, - .err_code = 0}; + /** * @brief 任务状态段结构体 @@ -202,8 +189,7 @@ struct tss_struct .reserved3 = 0, \ .io_map_base_addr = 0 \ } -// 为每个核心初始化初始进程的tss -struct tss_struct initial_tss[MAX_CPU_NUM] = {[0 ... MAX_CPU_NUM - 1] = INITIAL_TSS}; + // 获取当前的pcb struct process_control_block *get_current_pcb() @@ -262,4 +248,13 @@ void process_init(); * @param stack_size 堆栈大小 * @return unsigned long */ -unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size); \ No newline at end of file +unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size); + +extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S) +extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) + +extern struct tss_struct initial_tss[MAX_CPU_NUM]; +extern struct mm_struct initial_mm; +extern struct thread_struct initial_thread; +extern union proc_union initial_proc_union; +extern struct process_control_block *initial_proc[MAX_CPU_NUM]; \ No newline at end of file diff --git a/kernel/process/spinlock.h b/kernel/process/spinlock.h index 68d044a5..fe441adf 100644 --- a/kernel/process/spinlock.h +++ b/kernel/process/spinlock.h @@ -9,7 +9,8 @@ * */ #pragma once -#include "../common/glib.h" +#include +#include /** * @brief 定义自旋锁结构体 @@ -22,8 +23,8 @@ typedef struct /** * @brief 初始化自旋锁 - * - * @param lock + * + * @param lock */ void spin_init(spinlock_t *lock) { @@ -37,21 +38,42 @@ void spin_init(spinlock_t *lock) */ void spin_lock(spinlock_t *lock) { + preempt_disable(); __asm__ __volatile__("1: \n\t" - "lock decq %0 \n\t" // 尝试-1 - "jns 3f \n\t" // 加锁成功,跳转到步骤3 - "2: \n\t" // 加锁失败,稍后再试 + "lock decq %0 \n\t" // 尝试-1 + "jns 3f \n\t" // 加锁成功,跳转到步骤3 + "2: \n\t" // 加锁失败,稍后再试 "pause \n\t" "cmpq $0, %0 \n\t" - "jle 2b \n\t" // 若锁被占用,则继续重试 - "jmp 1b \n\t" // 尝试加锁 + "jle 2b \n\t" // 若锁被占用,则继续重试 + "jmp 1b \n\t" // 尝试加锁 "3:" : "=m"(lock->lock)::"memory"); } - -void spin_unlock(spinlock_t * lock) +void spin_unlock(spinlock_t *lock) { __asm__ __volatile__("movq $1, %0 \n\t" - :"=m"(lock->lock)::"memory"); + : "=m"(lock->lock)::"memory"); + preempt_enable(); +} + +/** + * @brief 尝试加锁 + * + * @param lock + * @return long 锁变量的值(1为成功加锁,0为加锁失败) + */ +long spin_trylock(spinlock_t *lock) +{ + uint64_t tmp_val = 0; + preempt_disable(); + // 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功 + asm volatile("lock xchgq %0, %1 \n\t" // 确保只有1个进程能得到锁 + : "=q"(tmp_val), "=m"(lock->lock) + : "0"(0) + : "memory"); + if (!tmp_val) + preempt_enable(); + return tmp_val; } \ No newline at end of file