signal相关数据结构&代码结构优化 (#84)

* 解决由于spinlock.h中包含preempt_enable()带来的循环include问题

* new: 初步实现signal的数据结构
This commit is contained in:
login 2022-11-16 15:18:03 +08:00 committed by GitHub
parent fb6c29d01d
commit cffd7144fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 549 additions and 281 deletions

View File

@ -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": "",

View File

@ -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文件中提供了很多的宏可以方便您的工作。
### 提供的宏
| 宏 | 解释 |

View File

@ -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")

View File

@ -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

View File

@ -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."

View 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."

View 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;
}

View 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();

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -0,0 +1,3 @@
pub mod gfp;
pub mod printk;
pub mod signal;

View File

@ -0,0 +1,6 @@
#pragma once
#include <common/atomic.h>
typedef struct refcount_struct {
atomic_t refs;
} refcount_t;

View 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;
};

View 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,
}

View File

@ -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>

View File

@ -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
View File

@ -0,0 +1 @@
pub mod signal;

0
kernel/src/ipc/signal.rs Normal file
View File

View File

@ -15,6 +15,7 @@ use core::panic::PanicInfo;
mod mm;
mod include;
mod libs;
mod ipc;
extern crate alloc;

View File

@ -1,4 +1,4 @@
#include <common/wait_queue_head.h>
#include <common/wait_queue.h>
#include <process/process.h>
#include <sched/sched.h>

View File

@ -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};

View File

@ -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的操作都会刷新TLBTLB
*/
#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处

View File

@ -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"
/**

View File

@ -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字节对齐

View File

@ -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

View File

@ -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();

View File

@ -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