diff --git a/.vscode/settings.json b/.vscode/settings.json index 160dbc83..f20a1c31 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -150,11 +150,11 @@ "cfs.h": "c", "err.h": "c", "rtc.h": "c", - "wait_queue_head.h": "c", "list.h": "c", "compiler.h": "c", "completion.h": "c", - "fat32.h": "c" + "fat32.h": "c", + "irqflags.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "", diff --git a/docs/kernel/sched/waiting.md b/docs/kernel/sched/waiting.md index 2bff0240..bc4f84a5 100644 --- a/docs/kernel/sched/waiting.md +++ b/docs/kernel/sched/waiting.md @@ -9,13 +9,7 @@   当您需要等待一个事件完成时,使用wait_queue机制能减少进程同步的开销。相比于滥用自旋锁以及信号量,或者是循环使用usleep(1000)这样的函数来完成同步,wait_queue是一个高效的解决方案。 :::{warning} -`wait_queue.h`中的等待队列的实现并没有把队列头独立出来,同时没有考虑为等待队列加锁。所以在后来的开发中加入了`wait_queue_head.h`的队列头实现,实质上就是链表+自旋锁。它与`wait_queue.h`中的队列是兼容的,当你使用`struct wait_queue_head`作为队列头时,你同样可以使用等待队列添加节点的函数。 - -但是在之后的版本中可能会把两者合并,目前仍然没有进行,且存在头文件相互引用的问题: - - "spin_lock.h" 引用了 "wait_queue.h" - - "wait_queue_head.h" 引用了 "spin_lock.h"; - -所以在合并之前必须解决这个问题。 +`wait_queue.h`中的等待队列的实现并没有把队列头独立出来,同时没有考虑为等待队列加锁。所以在后来的开发中加入了`wait_queue_head_t`的队列头实现,实质上就是链表+自旋锁。它与`wait_queue.h`中的队列`wait_queue_node_t`是兼容的,当你使用`struct wait_queue_head`作为队列头时,你同样可以使用等待队列添加节点的函数。 ::: ### 简单用法 @@ -89,7 +83,7 @@ typedef struct    等待队列头的使用逻辑与等待队列实际是一样的,因为他同样也是等待队列的节点(仅仅多了一把锁)。且wait_queue_head的函数基本上与wait_queue一致,只不过多了\*\*\*\_with\_node\_\*\*\*的字符串。 -   同时,wait_queue_head.h文件中提供了很多的宏,可以方便您的工作。 +   同时,wait_queue.h文件中提供了很多的宏,可以方便您的工作。 ### 提供的宏 | 宏 | 解释 | diff --git a/kernel/build.rs b/kernel/build.rs index c2c90f90..fe0890b1 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -20,6 +20,8 @@ fn main() { { let bindings = bindgen::Builder::default() .clang_arg("-I./src") + .clang_arg("-I./src/include") + .clang_arg("-I./src/arch/x86_64/include") // todo: 当引入多种架构之后,需要修改这里,对于不同的架构编译时,include不同的路径 // The input header we would like to generate // bindings for. .header("src/include/bindings/wrapper.h") diff --git a/kernel/src/Makefile b/kernel/src/Makefile index e94bd5e3..0fa4c6bb 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -10,7 +10,7 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_ PIC := _INTR_APIC_ -CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd) +CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include export ASFLAGS := --64 diff --git a/kernel/src/arch/x86_64/Makefile b/kernel/src/arch/x86_64/Makefile index 097231ed..60215816 100644 --- a/kernel/src/arch/x86_64/Makefile +++ b/kernel/src/arch/x86_64/Makefile @@ -1,10 +1,22 @@ + CFLAGS += -I . -all: x86_64_ipi.o ia64_msi.o +kernel_arch_x86_64_subdirs:= asm -x86_64_ipi.o: x86_64_ipi.c - $(CC) $(CFLAGS) -c x86_64_ipi.c -o x86_64_ipi.o +kernel_arch_x86_64_objs:= $(shell find ./*.c) -ia64_msi.o: ia64_msi.c - $(CC) $(CFLAGS) -c ia64_msi.c -o ia64_msi.o +ECHO: + @echo "$@" + +$(kernel_arch_x86_64_objs): ECHO + $(CC) $(CFLAGS) -c $@ -o $@.o + +$(kernel_arch_x86_64_subdirs): ECHO + $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)" + +all: $(kernel_arch_x86_64_objs) $(kernel_arch_x86_64_subdirs) + + +clean: + echo "Done." \ No newline at end of file diff --git a/kernel/src/arch/x86_64/asm/Makefile b/kernel/src/arch/x86_64/asm/Makefile new file mode 100644 index 00000000..38af6da5 --- /dev/null +++ b/kernel/src/arch/x86_64/asm/Makefile @@ -0,0 +1,22 @@ + +CFLAGS += -I . + +# kernel_arch_x86_64_asm_subdirs:= + +kernel_arch_x86_64_asm_objs:= $(shell find ./*.c) + +ECHO: + @echo "$@" + + +$(kernel_arch_x86_64_asm_objs): ECHO + $(CC) $(CFLAGS) -c $@ -o $@.o + +# $(kernel_arch_x86_64_asm_subdirs): ECHO +# $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)" + +all: $(kernel_arch_x86_64_asm_objs) + + +clean: + echo "Done." \ No newline at end of file diff --git a/kernel/src/arch/x86_64/asm/spinlock.c b/kernel/src/arch/x86_64/asm/spinlock.c new file mode 100644 index 00000000..7b4cb73d --- /dev/null +++ b/kernel/src/arch/x86_64/asm/spinlock.c @@ -0,0 +1,56 @@ +#include +#include + +void __arch_spin_lock(spinlock_t *lock) +{ + __asm__ __volatile__("1: \n\t" + "lock decb %0 \n\t" // 尝试-1 + "jns 3f \n\t" // 加锁成功,跳转到步骤3 + "2: \n\t" // 加锁失败,稍后再试 + "pause \n\t" + "cmpb $0, %0 \n\t" + "jle 2b \n\t" // 若锁被占用,则继续重试 + "jmp 1b \n\t" // 尝试加锁 + "3:" + : "=m"(lock->lock)::"memory"); + preempt_disable(); +} + +void __arch_spin_unlock(spinlock_t *lock) +{ + preempt_enable(); + __asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory"); +} + +void __arch_spin_lock_no_preempt(spinlock_t *lock) +{ + __asm__ __volatile__("1: \n\t" + "lock decb %0 \n\t" // 尝试-1 + "jns 3f \n\t" // 加锁成功,跳转到步骤3 + "2: \n\t" // 加锁失败,稍后再试 + "pause \n\t" + "cmpb $0, %0 \n\t" + "jle 2b \n\t" // 若锁被占用,则继续重试 + "jmp 1b \n\t" // 尝试加锁 + "3:" + : "=m"(lock->lock)::"memory"); +} + +void __arch_spin_unlock_no_preempt(spinlock_t *lock) +{ + __asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory"); +} + +long __arch_spin_trylock(spinlock_t *lock) +{ + uint64_t tmp_val = 0; + preempt_disable(); + // 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功 + asm volatile("lock xchg %%bx, %1 \n\t" // 确保只有1个进程能得到锁 + : "=q"(tmp_val), "=m"(lock->lock) + : "b"(0) + : "memory"); + if (!tmp_val) + preempt_enable(); + return tmp_val; +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/current.h b/kernel/src/arch/x86_64/include/asm/current.h similarity index 100% rename from kernel/src/arch/x86_64/current.h rename to kernel/src/arch/x86_64/include/asm/current.h diff --git a/kernel/src/arch/x86_64/include/asm/irqflags.h b/kernel/src/arch/x86_64/include/asm/irqflags.h new file mode 100644 index 00000000..6d84c171 --- /dev/null +++ b/kernel/src/arch/x86_64/include/asm/irqflags.h @@ -0,0 +1,10 @@ +#pragma once + +// 保存当前rflags的值到变量x内并关闭中断 +#define local_irq_save(x) __asm__ __volatile__("pushfq ; popq %0 ; cli" \ + : "=g"(x)::"memory") +// 恢复先前保存的rflags的值x +#define local_irq_restore(x) __asm__ __volatile__("pushq %0 ; popfq" ::"g"(x) \ + : "memory") +#define local_irq_disable() cli(); +#define local_irq_enable() sti(); diff --git a/kernel/src/common/completion.h b/kernel/src/common/completion.h index db66e966..dfc2937f 100644 --- a/kernel/src/common/completion.h +++ b/kernel/src/common/completion.h @@ -1,5 +1,5 @@ #include -#include +#include #include #include