mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 11:13:22 +00:00
* 添加新版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>
225 lines
7.1 KiB
Rust
225 lines
7.1 KiB
Rust
use core::intrinsics::unlikely;
|
||
|
||
use alloc::sync::Arc;
|
||
|
||
use crate::{
|
||
arch::MMArch,
|
||
kerror,
|
||
libs::align::{check_aligned, page_align_up},
|
||
mm::MemoryManagementArch,
|
||
syscall::{Syscall, SystemError},
|
||
};
|
||
|
||
use super::{
|
||
allocator::page_frame::{PageFrameCount, VirtPageFrame},
|
||
ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
|
||
verify_area, VirtAddr,
|
||
};
|
||
|
||
bitflags! {
|
||
/// Memory protection flags
|
||
pub struct ProtFlags: u64 {
|
||
const PROT_NONE = 0x0;
|
||
const PROT_READ = 0x1;
|
||
const PROT_WRITE = 0x2;
|
||
const PROT_EXEC = 0x4;
|
||
}
|
||
|
||
/// Memory mapping flags
|
||
pub struct MapFlags: u64 {
|
||
const MAP_NONE = 0x0;
|
||
/// share changes
|
||
const MAP_SHARED = 0x1;
|
||
/// changes are private
|
||
const MAP_PRIVATE = 0x2;
|
||
/// Interpret addr exactly
|
||
const MAP_FIXED = 0x10;
|
||
/// don't use a file
|
||
const MAP_ANONYMOUS = 0x20;
|
||
// linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
|
||
/// stack-like segment
|
||
const MAP_GROWSDOWN = 0x100;
|
||
/// ETXTBSY
|
||
const MAP_DENYWRITE = 0x800;
|
||
/// Mark it as an executable
|
||
const MAP_EXECUTABLE = 0x1000;
|
||
/// Pages are locked
|
||
const MAP_LOCKED = 0x2000;
|
||
/// don't check for reservations
|
||
const MAP_NORESERVE = 0x4000;
|
||
/// populate (prefault) pagetables
|
||
const MAP_POPULATE = 0x8000;
|
||
/// do not block on IO
|
||
const MAP_NONBLOCK = 0x10000;
|
||
/// give out an address that is best suited for process/thread stacks
|
||
const MAP_STACK = 0x20000;
|
||
/// create a huge page mapping
|
||
const MAP_HUGETLB = 0x40000;
|
||
/// perform synchronous page faults for the mapping
|
||
const MAP_SYNC = 0x80000;
|
||
/// MAP_FIXED which doesn't unmap underlying mapping
|
||
const MAP_FIXED_NOREPLACE = 0x100000;
|
||
|
||
/// For anonymous mmap, memory could be uninitialized
|
||
const MAP_UNINITIALIZED = 0x4000000;
|
||
|
||
}
|
||
}
|
||
|
||
impl Syscall {
|
||
pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
|
||
// kdebug!("brk: new_addr={:?}", new_addr);
|
||
let address_space = AddressSpace::current()?;
|
||
let mut address_space = address_space.write();
|
||
|
||
if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
|
||
return Ok(address_space.brk);
|
||
}
|
||
if new_addr == address_space.brk {
|
||
return Ok(address_space.brk);
|
||
}
|
||
|
||
unsafe {
|
||
address_space
|
||
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
|
||
.ok();
|
||
|
||
return Ok(address_space.sbrk(0).unwrap());
|
||
}
|
||
}
|
||
|
||
pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
|
||
let address_space = AddressSpace::current()?;
|
||
assert!(address_space.read().user_mapper.utable.is_current());
|
||
let mut address_space = address_space.write();
|
||
let r = unsafe { address_space.sbrk(incr) };
|
||
|
||
return r;
|
||
}
|
||
|
||
/// ## mmap系统调用
|
||
///
|
||
/// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `start_vaddr`:映射的起始地址
|
||
/// - `len`:映射的长度
|
||
/// - `prot`:保护标志
|
||
/// - `flags`:映射标志
|
||
/// - `fd`:文件描述符(暂时不支持)
|
||
/// - `offset`:文件偏移量 (暂时不支持)
|
||
///
|
||
/// ## 返回值
|
||
///
|
||
/// 成功时返回映射的起始地址,失败时返回错误码
|
||
pub fn mmap(
|
||
start_vaddr: VirtAddr,
|
||
len: usize,
|
||
prot_flags: usize,
|
||
map_flags: usize,
|
||
_fd: i32,
|
||
_offset: usize,
|
||
) -> Result<usize, SystemError> {
|
||
let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
|
||
let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
|
||
|
||
if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
|
||
&& map_flags.contains(MapFlags::MAP_FIXED)
|
||
{
|
||
kerror!(
|
||
"mmap: MAP_FIXED is not supported for address below {}",
|
||
DEFAULT_MMAP_MIN_ADDR
|
||
);
|
||
return Err(SystemError::EINVAL);
|
||
}
|
||
// 暂时不支持除匿名页以外的映射
|
||
if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
|
||
kerror!("mmap: not support file mapping");
|
||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||
}
|
||
|
||
// 暂时不支持巨页映射
|
||
if map_flags.contains(MapFlags::MAP_HUGETLB) {
|
||
kerror!("mmap: not support huge page mapping");
|
||
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
|
||
}
|
||
let current_address_space = AddressSpace::current()?;
|
||
let start_page = current_address_space.write().map_anonymous(
|
||
start_vaddr,
|
||
len,
|
||
prot_flags,
|
||
map_flags,
|
||
true,
|
||
)?;
|
||
return Ok(start_page.virt_address().data());
|
||
}
|
||
|
||
/// ## munmap系统调用
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
|
||
/// - `len`:取消映射的字节数(已经对齐到页)
|
||
///
|
||
/// ## 返回值
|
||
///
|
||
/// 成功时返回0,失败时返回错误码
|
||
pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
|
||
assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||
assert!(check_aligned(len, MMArch::PAGE_SIZE));
|
||
|
||
if unlikely(verify_area(start_vaddr, len).is_err()) {
|
||
return Err(SystemError::EINVAL);
|
||
}
|
||
if unlikely(len == 0) {
|
||
return Err(SystemError::EINVAL);
|
||
}
|
||
|
||
let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
|
||
let start_frame = VirtPageFrame::new(start_vaddr);
|
||
let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
|
||
|
||
current_address_space
|
||
.write()
|
||
.munmap(start_frame, page_count)
|
||
.map_err(|_| SystemError::EINVAL)?;
|
||
return Ok(0);
|
||
}
|
||
|
||
/// ## mprotect系统调用
|
||
///
|
||
/// ## 参数
|
||
///
|
||
/// - `start_vaddr`:起始地址(已经对齐到页)
|
||
/// - `len`:长度(已经对齐到页)
|
||
/// - `prot_flags`:保护标志
|
||
pub fn mprotect(
|
||
start_vaddr: VirtAddr,
|
||
len: usize,
|
||
prot_flags: usize,
|
||
) -> Result<usize, SystemError> {
|
||
assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||
assert!(check_aligned(len, MMArch::PAGE_SIZE));
|
||
|
||
if unlikely(verify_area(start_vaddr, len).is_err()) {
|
||
return Err(SystemError::EINVAL);
|
||
}
|
||
if unlikely(len == 0) {
|
||
return Err(SystemError::EINVAL);
|
||
}
|
||
|
||
let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
|
||
|
||
let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
|
||
let start_frame = VirtPageFrame::new(start_vaddr);
|
||
let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
|
||
|
||
current_address_space
|
||
.write()
|
||
.mprotect(start_frame, page_count, prot_flags)
|
||
.map_err(|_| SystemError::EINVAL)?;
|
||
return Ok(0);
|
||
}
|
||
}
|