Jelajahi Sumber

增加锁的持有计数

fslongjin 3 tahun lalu
induk
melakukan
7295565e5e
4 mengubah file dengan 100 tambahan dan 38 penghapusan
  1. 23 0
      kernel/process/preempt.h
  2. 28 6
      kernel/process/process.c
  3. 16 21
      kernel/process/process.h
  4. 33 11
      kernel/process/spinlock.h

+ 23 - 0
kernel/process/preempt.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include <process/process.h>
+
+/**
+ * @brief 增加自旋锁计数变量
+ * 
+ */
+#define preempt_disable()   \
+do  \
+{   \
+    --(current_pcb->preempt_count);\
+} while (0)
+
+/**
+ * @brief 减少自旋锁计数变量
+ * 
+ */
+#define preempt_enable()   \
+do  \
+{   \
+    ++(current_pcb->preempt_count);\
+}while(0)

+ 28 - 6
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(&current_pcb->list), struct process_control_block, list);
+    //struct process_control_block *p = container_of(list_next(&current_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;

+ 16 - 21
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);
+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];

+ 33 - 11
kernel/process/spinlock.h

@@ -9,7 +9,8 @@
  *
  */
 #pragma once
-#include "../common/glib.h"
+#include <common/glib.h>
+#include <process/preempt.h>
 
 /**
  * @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;
 }