mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
signal相关数据结构&代码结构优化 (#84)
* 解决由于spinlock.h中包含preempt_enable()带来的循环include问题 * new: 初步实现signal的数据结构
This commit is contained in:
parent
fb6c29d01d
commit
cffd7144fb
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -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": "",
|
||||
|
@ -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文件中提供了很多的宏,可以方便您的工作。
|
||||
|
||||
### 提供的宏
|
||||
| 宏 | 解释 |
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
||||
|
@ -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."
|
22
kernel/src/arch/x86_64/asm/Makefile
Normal file
22
kernel/src/arch/x86_64/asm/Makefile
Normal file
@ -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."
|
56
kernel/src/arch/x86_64/asm/spinlock.c
Normal file
56
kernel/src/arch/x86_64/asm/spinlock.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <process/preempt.h>
|
||||
|
||||
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;
|
||||
}
|
10
kernel/src/arch/x86_64/include/asm/irqflags.h
Normal file
10
kernel/src/arch/x86_64/include/asm/irqflags.h
Normal file
@ -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();
|
@ -1,5 +1,5 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <common/wait_queue_head.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <process/process.h>
|
||||
#include <time/sleep.h>
|
||||
#include <time/timer.h>
|
||||
|
@ -9,8 +9,8 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <asm/irqflags.h>
|
||||
#include <common/glib.h>
|
||||
#include <process/preempt.h>
|
||||
#include <debug/bug.h>
|
||||
|
||||
/**
|
||||
@ -22,6 +22,14 @@ typedef struct
|
||||
int8_t lock; // 1:unlocked 0:locked
|
||||
} spinlock_t;
|
||||
|
||||
extern void __arch_spin_lock(spinlock_t *lock);
|
||||
extern void __arch_spin_unlock(spinlock_t *lock);
|
||||
|
||||
extern void __arch_spin_lock_no_preempt(spinlock_t *lock);
|
||||
extern void __arch_spin_unlock_no_preempt(spinlock_t *lock);
|
||||
|
||||
extern long __arch_spin_trylock(spinlock_t *lock);
|
||||
|
||||
/**
|
||||
* @brief 自旋锁加锁
|
||||
*
|
||||
@ -29,17 +37,7 @@ typedef struct
|
||||
*/
|
||||
void 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();
|
||||
__arch_spin_lock(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,9 +47,7 @@ void spin_lock(spinlock_t *lock)
|
||||
*/
|
||||
void spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
preempt_enable();
|
||||
__asm__ __volatile__("movb $1, %0 \n\t"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
__arch_spin_unlock(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,17 +69,9 @@ void spin_init(spinlock_t *lock)
|
||||
*/
|
||||
void 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");
|
||||
__arch_spin_lock_no_preempt(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 自旋锁解锁(不改变自旋锁持有计数)
|
||||
*
|
||||
@ -91,8 +79,7 @@ void spin_lock_no_preempt(spinlock_t *lock)
|
||||
*/
|
||||
void spin_unlock_no_preempt(spinlock_t *lock)
|
||||
{
|
||||
__asm__ __volatile__("movb $1, %0 \n\t"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
__arch_spin_unlock_no_preempt(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,74 +90,56 @@ void spin_unlock_no_preempt(spinlock_t *lock)
|
||||
*/
|
||||
long 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;
|
||||
return __arch_spin_trylock(lock);
|
||||
}
|
||||
|
||||
// 保存当前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();
|
||||
|
||||
/**
|
||||
* @brief 保存中断状态,关闭中断,并自旋锁加锁
|
||||
*
|
||||
*/
|
||||
#define spin_lock_irqsave(lock, flags) \
|
||||
do \
|
||||
{ \
|
||||
local_irq_save(flags); \
|
||||
spin_lock(lock); \
|
||||
#define spin_lock_irqsave(lock, flags) \
|
||||
do \
|
||||
{ \
|
||||
local_irq_save(flags); \
|
||||
spin_lock(lock); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 恢复rflags以及中断状态并解锁自旋锁
|
||||
*
|
||||
*/
|
||||
#define spin_unlock_irqrestore(lock, flags) \
|
||||
do \
|
||||
{ \
|
||||
spin_unlock(lock); \
|
||||
local_irq_restore(flags); \
|
||||
#define spin_unlock_irqrestore(lock, flags) \
|
||||
do \
|
||||
{ \
|
||||
spin_unlock(lock); \
|
||||
local_irq_restore(flags); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 关闭中断并加锁
|
||||
*
|
||||
*/
|
||||
#define spin_lock_irq(lock) \
|
||||
do \
|
||||
{ \
|
||||
local_irq_disable(); \
|
||||
spin_lock(lock); \
|
||||
#define spin_lock_irq(lock) \
|
||||
do \
|
||||
{ \
|
||||
local_irq_disable(); \
|
||||
spin_lock(lock); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 解锁并开启中断
|
||||
*
|
||||
*/
|
||||
#define spin_unlock_irq(lock) \
|
||||
do \
|
||||
{ \
|
||||
spin_unlock(lock); \
|
||||
local_irq_enable(); \
|
||||
#define spin_unlock_irq(lock) \
|
||||
do \
|
||||
{ \
|
||||
spin_unlock(lock); \
|
||||
local_irq_enable(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 判断自旋锁是否已经加锁
|
||||
*
|
||||
*
|
||||
* @param lock 待判断的自旋锁
|
||||
* @return true 已经加锁
|
||||
* @return false 尚未加锁
|
||||
|
@ -13,7 +13,7 @@ typedef uint32_t gid_t;
|
||||
typedef long long ssize_t;
|
||||
|
||||
typedef int __pid_t;
|
||||
#define pid_t uint64_t
|
||||
#define pid_t int64_t
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
typedef char *caddr_t;
|
||||
|
@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
#include <common/spinlock.h>
|
||||
struct process_control_block;
|
||||
|
||||
// todo: 按照linux里面的样子,修正等待队列。也就是修正好wait_queue_node和wait_queue_head的意思。
|
||||
|
||||
/**
|
||||
* @brief 信号量的等待队列
|
||||
@ -31,8 +35,7 @@ void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head);
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head,
|
||||
void *lock);
|
||||
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head, void *lock);
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断)
|
||||
*
|
||||
@ -46,4 +49,70 @@ void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head);
|
||||
* @param wait_queue_head 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
|
||||
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct List wait_list;
|
||||
spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
|
||||
} wait_queue_head_t;
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK(name, pcb) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK_SELF(name) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC(name, pcb) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC_SELF(name) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
||||
struct wait_queue_head_t name = {0}; \
|
||||
wait_queue_head_init(&name);
|
||||
|
||||
/**
|
||||
* @brief 初始化wait_queue队列头
|
||||
*
|
||||
* @param wait_queue
|
||||
*/
|
||||
void wait_queue_head_init(wait_queue_head_t *wait_queue);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
* @param lock
|
||||
*/
|
||||
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
|
||||
*
|
||||
* @param wait_queue_head_t q: 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);
|
@ -1,68 +0,0 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct List wait_list;
|
||||
spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
|
||||
} wait_queue_head_t;
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK(name, pcb) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ON_STACK_SELF(name) \
|
||||
wait_queue_node_t name = {0}; \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC(name, pcb) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), pcb);
|
||||
|
||||
#define DECLARE_WAIT_ALLOC_SELF(name) \
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
|
||||
wait_queue_init(&(name), current_pcb);
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
||||
struct wait_queue_head_t name = {0}; \
|
||||
wait_queue_head_init(&name);
|
||||
|
||||
/**
|
||||
* @brief 初始化wait_queue队列头
|
||||
*
|
||||
* @param wait_queue
|
||||
*/
|
||||
void wait_queue_head_init(wait_queue_head_t *wait_queue);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param q 队列头指针
|
||||
* @param wait wait节点
|
||||
* @param lock
|
||||
*/
|
||||
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
* @param wait wait节点
|
||||
*/
|
||||
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
|
||||
*
|
||||
* @param wait_queue_head_t q: 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);
|
3
kernel/src/include/DragonOS/mod.rs
Normal file
3
kernel/src/include/DragonOS/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod gfp;
|
||||
pub mod printk;
|
||||
pub mod signal;
|
6
kernel/src/include/DragonOS/refcount.h
Normal file
6
kernel/src/include/DragonOS/refcount.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <common/atomic.h>
|
||||
|
||||
typedef struct refcount_struct {
|
||||
atomic_t refs;
|
||||
} refcount_t;
|
88
kernel/src/include/DragonOS/signal.h
Normal file
88
kernel/src/include/DragonOS/signal.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include <DragonOS/refcount.h>
|
||||
#include <common/atomic.h>
|
||||
#include <common/list.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <common/sys/types.h>
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
// 系统最大支持的信号数量
|
||||
#define MAX_SIG_NUM 64
|
||||
|
||||
typedef void __signalfn_t(int);
|
||||
typedef __signalfn_t *__sighandler_t;
|
||||
|
||||
typedef uint64_t sigset_t;
|
||||
|
||||
union __sifields {
|
||||
/* kill() */
|
||||
struct
|
||||
{
|
||||
pid_t _pid; /* 信号发送者的pid */
|
||||
} _kill;
|
||||
};
|
||||
|
||||
// 注意,该结构体最大大小为32字节
|
||||
#define __SIGINFO \
|
||||
struct \
|
||||
{ \
|
||||
int32_t si_signo; /* signal number */ \
|
||||
int32_t code; \
|
||||
int32_t si_errno; \
|
||||
union __sifields _sifields; \
|
||||
}
|
||||
|
||||
struct siginfo
|
||||
{
|
||||
union {
|
||||
__SIGINFO;
|
||||
uint64_t padding[4]; // 让siginfo占用32字节大小
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体
|
||||
*
|
||||
*/
|
||||
struct sigaction
|
||||
{
|
||||
// 信号处理函数的指针
|
||||
union {
|
||||
__sighandler_t _sa_handler;
|
||||
void (*_sa_sigaction)(int sig, struct siginfo *sinfo, void *);
|
||||
} _u;
|
||||
uint64_t sa_flags;
|
||||
sigset_t sa_mask;
|
||||
void (*sa_restorer)(void); // 暂时未实现
|
||||
};
|
||||
|
||||
/**
|
||||
* 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁,
|
||||
* 因此signal_struct不用加锁
|
||||
*/
|
||||
struct signal_struct
|
||||
{
|
||||
atomic_t sig_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体,位于pcb之中。
|
||||
*
|
||||
*/
|
||||
struct sighand_struct
|
||||
{
|
||||
spinlock_t siglock;
|
||||
refcount_t count;
|
||||
wait_queue_head_t signal_fd_wqh;
|
||||
// 为每个信号注册的处理函数的结构体
|
||||
struct sigaction action[MAX_SIG_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 正在等待的信号的标志位
|
||||
*
|
||||
*/
|
||||
struct sigpending
|
||||
{
|
||||
sigset_t signal;
|
||||
};
|
113
kernel/src/include/DragonOS/signal.rs
Normal file
113
kernel/src/include/DragonOS/signal.rs
Normal file
@ -0,0 +1,113 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
// 这是signal暴露给其他模块的公有的接口文件
|
||||
|
||||
// todo: 将这里更换为手动编写的ffi绑定
|
||||
use crate::include::bindings::bindings::atomic_t;
|
||||
use crate::include::bindings::bindings::refcount_t;
|
||||
use crate::include::bindings::bindings::spinlock_t;
|
||||
use crate::include::bindings::bindings::wait_queue_head_t;
|
||||
|
||||
pub type sigset_t = u64;
|
||||
pub type __signalfn_t = ::core::option::Option<unsafe extern "C" fn(arg1: ::core::ffi::c_int)>;
|
||||
pub type __sighandler_t = __signalfn_t;
|
||||
|
||||
/// 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁
|
||||
/// 因此signal_struct不用加锁
|
||||
/// **请将该结构体与`include/DragonOS/signal.h`中的保持同步**
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct signal_struct {
|
||||
pub sig_cnt: atomic_t,
|
||||
}
|
||||
|
||||
/**
|
||||
* sigaction中的信号处理函数结构体
|
||||
* 分为两种处理函数
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union sigaction__union_u {
|
||||
pub _sa_handler: __sighandler_t, // 传统处理函数
|
||||
pub _sa_sigaction: ::core::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
sig: ::core::ffi::c_int,
|
||||
sinfo: *mut siginfo,
|
||||
arg1: *mut ::core::ffi::c_void,
|
||||
),
|
||||
>,
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sigaction {
|
||||
pub _u: sigaction__union_u,
|
||||
pub sa_flags: u64,
|
||||
pub sa_mask: sigset_t,
|
||||
pub sa_restorer: ::core::option::Option<unsafe extern "C" fn()>, // 暂时未实现该函数
|
||||
}
|
||||
|
||||
/**
|
||||
* 信号消息的结构体,作为参数传入sigaction结构体中指向的处理函数
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct siginfo {
|
||||
pub _sinfo: __siginfo_union,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union __siginfo_union {
|
||||
pub data: __siginfo_union_data,
|
||||
pub padding: [u64; 4usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct __siginfo_union_data {
|
||||
pub si_signo: i32,
|
||||
pub code: i32,
|
||||
pub si_errno: i32,
|
||||
pub _sifields: __sifields,
|
||||
}
|
||||
|
||||
/**
|
||||
* siginfo中,根据signal的来源不同,该union中对应了不同的数据
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union __sifields {
|
||||
pub _kill: __sifields__kill,
|
||||
}
|
||||
|
||||
/**
|
||||
* 来自kill命令的signal
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct __sifields__kill {
|
||||
pub _pid: i64, /* 发起kill的进程的pid */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 信号处理结构体,位于pcb之中
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sighand_struct {
|
||||
pub siglock: spinlock_t,
|
||||
pub count: refcount_t,
|
||||
pub signal_fd_wqh: wait_queue_head_t,
|
||||
pub action: [sigaction; 64usize],
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 正在等待的信号的标志位
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct sigpending {
|
||||
pub signal: sigset_t,
|
||||
}
|
@ -23,6 +23,8 @@
|
||||
#include <common/spinlock.h>
|
||||
#include <common/unistd.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <include/DragonOS/refcount.h>
|
||||
#include <include/DragonOS/signal.h>
|
||||
#include <mm/mm.h>
|
||||
#include <mm/slab.h>
|
||||
#include <sched/cfs.h>
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![allow(non_snake_case)]
|
||||
pub mod bindings;
|
||||
pub mod gfp;
|
||||
pub mod printk;
|
||||
|
||||
pub mod DragonOS;
|
1
kernel/src/ipc/mod.rs
Normal file
1
kernel/src/ipc/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod signal;
|
0
kernel/src/ipc/signal.rs
Normal file
0
kernel/src/ipc/signal.rs
Normal file
@ -15,6 +15,7 @@ use core::panic::PanicInfo;
|
||||
mod mm;
|
||||
mod include;
|
||||
mod libs;
|
||||
mod ipc;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <common/wait_queue_head.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE};
|
||||
use crate::include::gfp::__GFP_ZERO;
|
||||
use crate::include::DragonOS::gfp::__GFP_ZERO;
|
||||
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/glib.h>
|
||||
#include <asm/current.h>
|
||||
#include <common/gfp.h>
|
||||
#include <common/glib.h>
|
||||
#include <mm/mm-types.h>
|
||||
#include <process/process.h>
|
||||
|
||||
@ -48,7 +49,7 @@
|
||||
#define IO_APIC_MAPPING_OFFSET 0xfec00000UL
|
||||
#define LOCAL_APIC_MAPPING_OFFSET 0xfee00000UL
|
||||
#define AHCI_MAPPING_OFFSET 0xff200000UL // AHCI 映射偏移量,之后使用了4M的地址
|
||||
#define XHCI_MAPPING_OFFSET 0x100000000 // XHCI控制器映射偏移量(后方请预留1GB的虚拟空间来映射不同的controller)
|
||||
#define XHCI_MAPPING_OFFSET 0x100000000 // XHCI控制器映射偏移量(后方请预留1GB的虚拟空间来映射不同的controller)
|
||||
|
||||
// ===== 内存区域属性 =====
|
||||
// DMA区域
|
||||
@ -145,16 +146,15 @@
|
||||
* @brief 刷新TLB的宏定义
|
||||
* 由于任何写入cr3的操作都会刷新TLB,因此这个宏定义可以刷新TLB
|
||||
*/
|
||||
#define flush_tlb() \
|
||||
do \
|
||||
{ \
|
||||
ul tmp; \
|
||||
io_mfence(); \
|
||||
__asm__ __volatile__( \
|
||||
"movq %%cr3, %0\n\t" \
|
||||
"movq %0, %%cr3\n\t" \
|
||||
: "=r"(tmp)::"memory"); \
|
||||
\
|
||||
#define flush_tlb() \
|
||||
do \
|
||||
{ \
|
||||
ul tmp; \
|
||||
io_mfence(); \
|
||||
__asm__ __volatile__("movq %%cr3, %0\n\t" \
|
||||
"movq %0, %%cr3\n\t" \
|
||||
: "=r"(tmp)::"memory"); \
|
||||
\
|
||||
} while (0);
|
||||
|
||||
/**
|
||||
@ -231,9 +231,7 @@ unsigned long page_init(struct Page *page, ul flags);
|
||||
unsigned long *get_CR3()
|
||||
{
|
||||
ul *tmp;
|
||||
__asm__ __volatile__(
|
||||
"movq %%cr3, %0\n\t"
|
||||
: "=r"(tmp)::"memory");
|
||||
__asm__ __volatile__("movq %%cr3, %0\n\t" : "=r"(tmp)::"memory");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@ -420,7 +418,8 @@ int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags
|
||||
* @param flush 是否刷新tlb
|
||||
* @param use4k 是否使用4k页
|
||||
*/
|
||||
int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k);
|
||||
int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length,
|
||||
ul flags, bool user, bool flush, bool use4k);
|
||||
|
||||
int mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags);
|
||||
|
||||
@ -440,9 +439,7 @@ void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_sta
|
||||
* @param virt_addr 虚拟地址
|
||||
* @param length 地址长度
|
||||
*/
|
||||
#define mm_unmap_addr(virt_addr, length) ({ \
|
||||
mm_unmap_proc_table((uint64_t)get_CR3(), true, virt_addr, length); \
|
||||
})
|
||||
#define mm_unmap_addr(virt_addr, length) ({ mm_unmap_proc_table((uint64_t)get_CR3(), true, virt_addr, length); })
|
||||
|
||||
/**
|
||||
* @brief 创建VMA
|
||||
@ -455,7 +452,8 @@ void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_sta
|
||||
* @param res_vma 返回的vma指针
|
||||
* @return int 错误码
|
||||
*/
|
||||
int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags, struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma);
|
||||
int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags,
|
||||
struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma);
|
||||
|
||||
/**
|
||||
* @brief 将指定的物理地址映射到指定的vma处
|
||||
|
@ -1,10 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#if ARCH(X86_64)
|
||||
#include <arch/x86_64/current.h>
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
#include <asm/current.h>
|
||||
|
||||
#include "proc-types.h"
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/wait_queue.h>
|
||||
#include <DragonOS/signal.h>
|
||||
|
||||
// 进程最大可拥有的文件描述符数量
|
||||
#define PROC_MAX_FD_NUM 16
|
||||
@ -73,7 +74,7 @@ struct process_control_block
|
||||
// 进程标志:进程、线程、内核线程
|
||||
unsigned long flags;
|
||||
int64_t preempt_count; // 持有的自旋锁的数量
|
||||
long signal;
|
||||
|
||||
long cpu_id; // 当前进程在哪个CPU核心上运行
|
||||
char name[PCB_NAME_LEN];
|
||||
|
||||
@ -114,6 +115,15 @@ struct process_control_block
|
||||
|
||||
/* PF_kTHREAD | PF_IO_WORKER 的进程,worker_private不为NULL*/
|
||||
void *worker_private;
|
||||
|
||||
// ==== 信号处理相关 =====
|
||||
struct signal_struct *signal;
|
||||
struct sighand_struct *sighand;
|
||||
// 一个bitmap,表示被阻塞的信号
|
||||
sigset_t blocked;
|
||||
// 正在等待的信号的标志位,表示某个信号正在等待处理
|
||||
struct sigpending sig_pending;
|
||||
|
||||
};
|
||||
|
||||
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
||||
|
@ -9,45 +9,27 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <common/cpu.h>
|
||||
#include <common/glib.h>
|
||||
#include <syscall/syscall.h>
|
||||
#include "ptrace.h"
|
||||
#include <common/cpu.h>
|
||||
#include <common/errno.h>
|
||||
#include <filesystem/VFS/VFS.h>
|
||||
#include <common/glib.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <filesystem/VFS/VFS.h>
|
||||
#include <mm/mm-types.h>
|
||||
#include <syscall/syscall.h>
|
||||
|
||||
#if ARCH(I386) || ARCH(X86_64)
|
||||
#include <arch/x86_64/current.h>
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
#include <asm/current.h>
|
||||
|
||||
#include "proc-types.h"
|
||||
|
||||
// 设置初始进程的PCB
|
||||
#define INITIAL_PROC(proc) \
|
||||
{ \
|
||||
.state = PROC_UNINTERRUPTIBLE, \
|
||||
.flags = PF_KTHREAD, \
|
||||
.preempt_count = 0, \
|
||||
.signal = 0, \
|
||||
.cpu_id = 0, \
|
||||
.mm = &initial_mm, \
|
||||
.thread = &initial_thread, \
|
||||
.addr_limit = 0xffffffffffffffff, \
|
||||
.pid = 0, \
|
||||
.priority = 2, \
|
||||
.virtual_runtime = 0, \
|
||||
.fds = {0}, \
|
||||
.next_pcb = &proc, \
|
||||
.parent_pcb = &proc, \
|
||||
.exit_code = 0, \
|
||||
.wait_child_proc_exit = 0, \
|
||||
.worker_private = NULL, \
|
||||
.policy = SCHED_NORMAL \
|
||||
}
|
||||
#define INITIAL_PROC(proc) \
|
||||
{ \
|
||||
.state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0, \
|
||||
.mm = &initial_mm, .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2, \
|
||||
.virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \
|
||||
.wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 任务状态段结构体
|
||||
@ -55,28 +37,19 @@
|
||||
*/
|
||||
|
||||
// 设置初始进程的tss
|
||||
#define INITIAL_TSS \
|
||||
{ \
|
||||
.reserved0 = 0, \
|
||||
.rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.reserved1 = 0, \
|
||||
.ist1 = 0xffff800000007c00, \
|
||||
.ist2 = 0xffff800000007c00, \
|
||||
.ist3 = 0xffff800000007c00, \
|
||||
.ist4 = 0xffff800000007c00, \
|
||||
.ist5 = 0xffff800000007c00, \
|
||||
.ist6 = 0xffff800000007c00, \
|
||||
.ist7 = 0xffff800000007c00, \
|
||||
.reserved2 = 0, \
|
||||
.reserved3 = 0, \
|
||||
.io_map_base_addr = 0 \
|
||||
}
|
||||
#define INITIAL_TSS \
|
||||
{ \
|
||||
.reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \
|
||||
.ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00, \
|
||||
.ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0, \
|
||||
.reserved3 = 0, .io_map_base_addr = 0 \
|
||||
}
|
||||
|
||||
#define GET_CURRENT_PCB \
|
||||
"movq %rsp, %rbx \n\t" \
|
||||
"andq $-32768, %rbx\n\t"
|
||||
#define GET_CURRENT_PCB \
|
||||
"movq %rsp, %rbx \n\t" \
|
||||
"andq $-32768, %rbx\n\t"
|
||||
|
||||
/**
|
||||
* @brief 切换进程上下文
|
||||
@ -84,24 +57,24 @@
|
||||
* 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
|
||||
*/
|
||||
|
||||
#define switch_proc(prev, next) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__("pushq %%rbp \n\t" \
|
||||
"pushq %%rax \n\t" \
|
||||
"movq %%rsp, %0 \n\t" \
|
||||
"movq %2, %%rsp \n\t" \
|
||||
"leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \
|
||||
"movq %%rax, %1 \n\t" \
|
||||
"pushq %3 \n\t" \
|
||||
"jmp __switch_to \n\t" \
|
||||
"switch_proc_ret_addr: \n\t" \
|
||||
"popq %%rax \n\t" \
|
||||
"popq %%rbp \n\t" \
|
||||
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
|
||||
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
#define switch_proc(prev, next) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__("pushq %%rbp \n\t" \
|
||||
"pushq %%rax \n\t" \
|
||||
"movq %%rsp, %0 \n\t" \
|
||||
"movq %2, %%rsp \n\t" \
|
||||
"leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \
|
||||
"movq %%rax, %1 \n\t" \
|
||||
"pushq %3 \n\t" \
|
||||
"jmp __switch_to \n\t" \
|
||||
"switch_proc_ret_addr: \n\t" \
|
||||
"popq %%rax \n\t" \
|
||||
"popq %%rbp \n\t" \
|
||||
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
|
||||
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 初始化系统的第一个进程
|
||||
@ -118,7 +91,8 @@ 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);
|
||||
|
||||
/**
|
||||
* @brief 根据pid获取进程的pcb
|
||||
@ -196,12 +170,11 @@ int process_release_pcb(struct process_control_block *pcb);
|
||||
* @param next 下一个进程的pcb
|
||||
*
|
||||
*/
|
||||
#define process_switch_mm(next_pcb) \
|
||||
do \
|
||||
{ \
|
||||
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
#define process_switch_mm(next_pcb) \
|
||||
do \
|
||||
{ \
|
||||
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) : "memory"); \
|
||||
} while (0)
|
||||
// flush_tlb();
|
||||
|
||||
// 获取当前cpu id
|
||||
|
@ -1,12 +1,13 @@
|
||||
#include "smp.h"
|
||||
#include <common/cpu.h>
|
||||
#include <common/kprint.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <driver/interrupt/apic/apic.h>
|
||||
#include <exception/gate.h>
|
||||
#include <common/cpu.h>
|
||||
#include <mm/slab.h>
|
||||
#include <process/process.h>
|
||||
#include <common/spinlock.h>
|
||||
|
||||
#include <process/preempt.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
#include "ipi.h"
|
||||
@ -36,7 +37,8 @@ void smp_init()
|
||||
}
|
||||
|
||||
// 将引导程序复制到物理地址0x20000处
|
||||
memcpy((unsigned char *)phys_2_virt(0x20000), _apu_boot_start, (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start);
|
||||
memcpy((unsigned char *)phys_2_virt(0x20000), _apu_boot_start,
|
||||
(unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start);
|
||||
io_mfence();
|
||||
// 设置多核IPI中断门
|
||||
for (int i = 200; i < 210; ++i)
|
||||
@ -58,7 +60,9 @@ void smp_init()
|
||||
io_mfence();
|
||||
|
||||
// 跳过BSP
|
||||
kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->local_apic_id, proc_local_apic_structs[i]->flags);
|
||||
kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i,
|
||||
proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->local_apic_id,
|
||||
proc_local_apic_structs[i]->flags);
|
||||
if (proc_local_apic_structs[i]->local_apic_id == 0)
|
||||
{
|
||||
--total_processor_num;
|
||||
@ -73,7 +77,8 @@ void smp_init()
|
||||
// continue;
|
||||
io_mfence();
|
||||
spin_lock(&multi_core_starting_lock);
|
||||
preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt count
|
||||
preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt
|
||||
// count
|
||||
current_starting_cpu = proc_local_apic_structs[i]->ACPI_Processor_UID;
|
||||
io_mfence();
|
||||
// 为每个AP处理器分配栈空间
|
||||
@ -85,8 +90,10 @@ void smp_init()
|
||||
io_mfence();
|
||||
|
||||
// 设置ap处理器的中断栈及内核栈中的cpu_id
|
||||
((struct process_control_block *)(cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE))->cpu_id = proc_local_apic_structs[i]->local_apic_id;
|
||||
((struct process_control_block *)(cpu_core_info[current_starting_cpu].ist_stack_start - STACK_SIZE))->cpu_id = proc_local_apic_structs[i]->local_apic_id;
|
||||
((struct process_control_block *)(cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE))->cpu_id =
|
||||
proc_local_apic_structs[i]->local_apic_id;
|
||||
((struct process_control_block *)(cpu_core_info[current_starting_cpu].ist_stack_start - STACK_SIZE))->cpu_id =
|
||||
proc_local_apic_structs[i]->local_apic_id;
|
||||
|
||||
cpu_core_info[current_starting_cpu].tss_vaddr = (uint64_t)&initial_tss[current_starting_cpu];
|
||||
|
||||
@ -94,15 +101,21 @@ void smp_init()
|
||||
|
||||
set_tss_descriptor(10 + (current_starting_cpu * 2), (void *)(cpu_core_info[current_starting_cpu].tss_vaddr));
|
||||
io_mfence();
|
||||
set_tss64((uint *)cpu_core_info[current_starting_cpu].tss_vaddr, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start);
|
||||
set_tss64(
|
||||
(uint *)cpu_core_info[current_starting_cpu].tss_vaddr, cpu_core_info[current_starting_cpu].stack_start,
|
||||
cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start);
|
||||
io_mfence();
|
||||
|
||||
// 连续发送两次start-up IPI
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand, proc_local_apic_structs[i]->local_apic_id);
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
|
||||
proc_local_apic_structs[i]->local_apic_id);
|
||||
io_mfence();
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand, proc_local_apic_structs[i]->local_apic_id);
|
||||
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
|
||||
proc_local_apic_structs[i]->local_apic_id);
|
||||
}
|
||||
io_mfence();
|
||||
while (num_cpu_started != total_processor_num)
|
||||
@ -130,10 +143,8 @@ void smp_ap_start()
|
||||
|
||||
// 切换栈基地址
|
||||
// uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
|
||||
__asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start)
|
||||
: "memory");
|
||||
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start)
|
||||
: "memory");
|
||||
__asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
|
||||
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
|
||||
|
||||
ksuccess("AP core %d successfully started!", current_starting_cpu);
|
||||
io_mfence();
|
||||
|
@ -140,7 +140,7 @@ rustInstall() {
|
||||
############ 开始执行 ###############
|
||||
banner
|
||||
rustInstall
|
||||
exit
|
||||
|
||||
if [ "Darwin" == "$(uname -s)" ]; then
|
||||
install_osx_pkg "$emulator" || exit 1
|
||||
else
|
||||
@ -174,6 +174,6 @@ else
|
||||
fi
|
||||
|
||||
# 创建磁盘镜像
|
||||
sudo bash create_hdd_image.sh
|
||||
bash create_hdd_image.sh
|
||||
|
||||
congratulations
|
Loading…
x
Reference in New Issue
Block a user