DragonOS/kernel/src/libs/spinlock.rs
LoGin 1496ba7b24
进程管理模块重构完成 (#380)
* 添加新版pcb的数据结构 (#273)

* 将pcb中的内容分类,分别加锁 (#305)

* 进程管理重构:完成fork的主体逻辑 (#309)

1.完成fork的主体逻辑
2.将文件系统接到新的pcb上
3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了

* chdir getcwd pid pgid ppid (#310)


---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 删除旧的fork以及signal的代码,并调整fork/vfork/execve系统调用 (#325)

1.删除旧的fork
2.删除signal相关代码,等进程管理重构结束之后,再重新写.
3.调整了fork/vfork/execve系统调用

* 实现切换进程的代码 (#331)



* 实现切换进程的代码

* Patch modify preempt (#332)

* 修改设置preempt的代码

* 删除rust的list和refcount

* 为每个核心初始化idle进程 (#333)

* 为每个核心初始化idle进程

* 完成了新的内核线程机制 (#335)

* 调度器的pcb替换为新的Arc<ProcessControlBlock>,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336)

* 把调度器的pcb替换为新的Arc<ProcessControlBlock>

* 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译

* 修正一些双重加锁、细节问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* github workflow自动检查代码是否格式化

* cache toolchain yml

* 调整rust版本的waitqueue中的pcb为新版的pcb (#343)

* 解决设置rust workspace带来的“工具链不一致”的问题 (#344)


* 解决设置rust workspace带来的“工具链不一致”的问题

更改workflow

* 调整pcb的sched_info和rwlock,以避免调度器死锁问题 (#341)

* 调整pcb的sched_info和rwlock,以避免调度器死锁问题

* 修改为在 WriterGuard 中维护 Irq_guard

* 修正了 write_irqsave方法

* 优化了代码

* 把 set state 操作从 wakup 移动到 sched_enqueue 中

* 修正为在 wakeup 中设置 running ,以保留 set_state 的私有性

* 移除了 process_wakeup

* 实现进程退出的逻辑 (#340)

实现进程退出的逻辑

* 标志进程sleep

* 修复wakeup的问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* rust 重构 completion (#350)

* 完成了completion的基本结构,待完善上级调用

* 用SpinLock保护结构体并发安全

* 修改原子变量为u32,修复符号错误

* irq guard

* 修改为具有内部可变性的结构体

* temp fix

* 修复了由于进程持有自旋锁导致的不被调度的问题

* 对 complete 系列方法上锁,保护 done 数据并发安全

* 移除了未使用的依赖

* 重写显示刷新驱动 (#363)

* 重构显示刷新驱动

* Patch refactor process management (#366)

* 维护进程树

* 维护进程树

* 更改代码结构

* 新建进程时,设置cwd

* 调整adopt childern函数,降低开销

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* waitqueue兼容C部分 (#351)

* PATH

* safe init

* waitqueue兼容C部分

* waitqueue兼容C部分

* 删除semaphore.c,在ps2_keyboard中使用waitqueue

* 删除semaphore.c,在ps2_keyboard中使用waitqueue

* current_pcb的C兼容

* current_pcb的C兼容

* current_pcb的C兼容

* fmt

* current_pcb的兼容

* 针对修改

* 调整代码

* fmt

* 删除pcb的set flags

* 更改函数名

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* merge master

* Patch debug process management refactor (#372)

* 能够调通,执行完textui_init

* 能跑到initial kernel thread

* fmt

* 能够正常初始化所有服务(尚未能切换到用户程序)

* 删除部分无用的extern

* 存在问题:ap处理器启动后,bsp的smp_init函数return之后就出错了,怀疑是栈损坏

* 解决smp启动由于未换栈导致的内存访问错误

* debug

* 1

* 1

* lock no preempt

* 调通

* 优化代码,删除一些调试日志

* fix

* 使用rust重写wait4 (#377)

* 维护进程树

* 维护进程树

* 更改代码结构

* 新建进程时,设置cwd

* 调整adopt childern函数,降低开销

* wait4

* 删除c_sys_wait4

* 使用userbuffer保护裸指针

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 消除warning

* 1. 修正未设置cpu executing的问题

* 修正kthread机制可能存在的内存泄露问题

* 删除pcb文档

* 删除C的tss struct

---------

Co-authored-by: Bullet <93781792+GP-Bullet@users.noreply.github.com>
Co-authored-by: Chiichen <39649411+Chiichen@users.noreply.github.com>
Co-authored-by: hanjiezhou <zhouhanjie@dragonos.org>
Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com>
Co-authored-by: houmkh <1119644616@qq.com>
2023-09-15 14:58:19 +08:00

203 lines
6.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#![allow(dead_code)]
use core::cell::UnsafeCell;
use core::hint::spin_loop;
use core::mem::ManuallyDrop;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering};
use crate::arch::CurrentIrqArch;
use crate::exception::{InterruptArch, IrqFlagsGuard};
use crate::process::ProcessManager;
use crate::syscall::SystemError;
/// 实现了守卫的SpinLock, 能够支持内部可变性
///
#[derive(Debug)]
pub struct SpinLock<T> {
lock: AtomicBool,
/// 自旋锁保护的数据
data: UnsafeCell<T>,
}
/// SpinLock的守卫
/// 该守卫没有构造器并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
/// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
#[derive(Debug)]
pub struct SpinLockGuard<'a, T: 'a> {
lock: &'a SpinLock<T>,
irq_flag: Option<IrqFlagsGuard>,
flags: SpinLockGuardFlags,
}
impl<'a, T: 'a> SpinLockGuard<'a, T> {
/// 泄露自旋锁的守卫,返回一个可变的引用
///
/// ## Safety
///
/// 由于这样做可能导致守卫在另一个线程中被释放从而导致pcb的preempt count不正确
/// 因此必须小心的手动维护好preempt count。
///
/// 并且leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
#[inline]
pub unsafe fn leak(this: Self) -> &'a mut T {
// Use ManuallyDrop to avoid stacked-borrow invalidation
let this = ManuallyDrop::new(this);
// We know statically that only we are referencing data
unsafe { &mut *this.lock.data.get() }
}
fn unlock_no_preempt(&self) {
unsafe {
self.lock.force_unlock();
}
}
}
/// 向编译器保证SpinLock在线程之间是安全的.
/// 其中要求类型T实现了Send这个Trait
unsafe impl<T> Sync for SpinLock<T> where T: Send {}
impl<T> SpinLock<T> {
pub const fn new(value: T) -> Self {
return Self {
lock: AtomicBool::new(false),
data: UnsafeCell::new(value),
};
}
#[inline(always)]
pub fn lock(&self) -> SpinLockGuard<T> {
loop {
let res = self.try_lock();
if res.is_ok() {
return res.unwrap();
}
spin_loop();
}
}
/// 加锁但是不更改preempt count
#[inline(always)]
pub fn lock_no_preempt(&self) -> SpinLockGuard<T> {
loop {
if let Ok(guard) = self.try_lock_no_preempt() {
return guard;
}
spin_loop();
}
}
pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
loop {
if let Ok(guard) = self.try_lock_irqsave() {
return guard;
}
spin_loop();
}
}
pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
// 先增加自旋锁持有计数
ProcessManager::preempt_disable();
if self.inner_try_lock() {
return Ok(SpinLockGuard {
lock: self,
irq_flag: None,
flags: SpinLockGuardFlags::empty(),
});
}
// 如果加锁失败恢复自旋锁持有计数
ProcessManager::preempt_enable();
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
fn inner_try_lock(&self) -> bool {
let res = self
.lock
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok();
return res;
}
pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::preempt_disable();
if self.inner_try_lock() {
return Ok(SpinLockGuard {
lock: self,
irq_flag: Some(irq_guard),
flags: SpinLockGuardFlags::empty(),
});
}
ProcessManager::preempt_enable();
drop(irq_guard);
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
pub fn try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError> {
if self.inner_try_lock() {
return Ok(SpinLockGuard {
lock: self,
irq_flag: None,
flags: SpinLockGuardFlags::NO_PREEMPT,
});
}
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
/// 强制解锁并且不更改preempt count
///
/// ## Safety
///
/// 由于这样做可能导致preempt count不正确因此必须小心的手动维护好preempt count。
/// 如非必要,请不要使用这个函数。
pub unsafe fn force_unlock(&self) {
self.lock.store(false, Ordering::Release);
}
fn unlock(&self) {
self.lock.store(false, Ordering::Release);
ProcessManager::preempt_enable();
}
}
/// 实现Deref trait支持通过获取SpinLockGuard来获取临界区数据的不可变引用
impl<T> Deref for SpinLockGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
return unsafe { &*self.lock.data.get() };
}
}
/// 实现DerefMut trait支持通过获取SpinLockGuard来获取临界区数据的可变引用
impl<T> DerefMut for SpinLockGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
return unsafe { &mut *self.lock.data.get() };
}
}
/// @brief 为SpinLockGuard实现Drop方法那么一旦守卫的生命周期结束就会自动释放自旋锁避免了忘记放锁的情况
impl<T> Drop for SpinLockGuard<'_, T> {
fn drop(&mut self) {
if self.flags.contains(SpinLockGuardFlags::NO_PREEMPT) {
self.unlock_no_preempt();
} else {
self.lock.unlock();
}
// restore irq
self.irq_flag.take();
}
}
bitflags! {
struct SpinLockGuardFlags: u8 {
/// 守卫是由“*no_preempt”方法获得的
const NO_PREEMPT = (1<<0);
}
}