mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
Merge pull request #59 from rcore-os/EatenBagpipe-master
Eaten bagpipe master
This commit is contained in:
commit
43f6d9d695
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@ -21,7 +21,8 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
arch: [x86_64, riscv32, riscv64, aarch64, mipsel]
|
||||
# we will bring back mipsel later
|
||||
arch: [x86_64, riscv32, riscv64, aarch64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout submodules
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,3 +29,4 @@ Cargo.lock
|
||||
modules/*/objs
|
||||
# Rust
|
||||
modules/*/target
|
||||
test/
|
@ -68,6 +68,7 @@ This is a project of THU courses:
|
||||
* [Operating System Train (2018 Autumn)](http://os.cs.tsinghua.edu.cn/oscourse/OsTrain2018)
|
||||
* [Operating System (2019 Spring)](http://os.cs.tsinghua.edu.cn/oscourse/OS2019spring/projects)
|
||||
* [Operating System Train (2019 Autumn)](http://os.cs.tsinghua.edu.cn/oscourse/OsTrain2019)
|
||||
* [Operating System (2020 Spring)](http://os.cs.tsinghua.edu.cn/oscourse/OS2020spring/projects)
|
||||
|
||||
[Reports](./docs) and [Dev docs](https://rucore.gitbook.io/rust-os-docs/) (in Chinese)
|
||||
|
||||
|
@ -252,7 +252,7 @@ impl<T: PageTableExt> MemorySet<T> {
|
||||
// subset
|
||||
let area = self.areas.remove(i);
|
||||
area.unmap(&mut self.page_table);
|
||||
i -= 1;
|
||||
i = i.wrapping_sub(1);
|
||||
} else if self.areas[i].start_addr >= start_addr
|
||||
&& self.areas[i].start_addr < end_addr
|
||||
{
|
||||
@ -324,7 +324,7 @@ impl<T: PageTableExt> MemorySet<T> {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
i = i.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
51
docs/2020_OS/g2/issues.md
Normal file
51
docs/2020_OS/g2/issues.md
Normal file
@ -0,0 +1,51 @@
|
||||
# 问题记录
|
||||
|
||||
## 找不到 xbuild
|
||||
|
||||
- 报错
|
||||
|
||||
```
|
||||
error: no such subcommand: `xbuild`
|
||||
|
||||
Did you mean `build`?
|
||||
Makefile:41: recipe for target 'rust' failed
|
||||
```
|
||||
|
||||
- 解决
|
||||
|
||||
```bash
|
||||
cargo install cargo-xbuild
|
||||
```
|
||||
|
||||
## 找不到 autoreconf
|
||||
|
||||
- 报错
|
||||
|
||||
```
|
||||
/bin/sh: 1: autoreconf: not found
|
||||
```
|
||||
|
||||
- 解决
|
||||
|
||||
```bash
|
||||
sudo apt install autoconf
|
||||
```
|
||||
|
||||
- 再报错
|
||||
|
||||
```
|
||||
cd build/x86_64/iperf-3.6 && autoreconf
|
||||
configure.ac:48: error: possibly undefined macro: AC_PROG_LIBTOOL
|
||||
If this token and others are legitimate, please use m4_pattern_allow.
|
||||
See the Autoconf documentation.
|
||||
```
|
||||
|
||||
- 再解决
|
||||
|
||||
[https://github.com/maxmind/libmaxminddb/issues/9](ref)
|
||||
|
||||
```bash
|
||||
sudo apt install libtool
|
||||
```
|
||||
|
||||
##
|
50
docs/2020_OS/g2/libc-test.md
Normal file
50
docs/2020_OS/g2/libc-test.md
Normal file
@ -0,0 +1,50 @@
|
||||
## libc-test
|
||||
|
||||
### 安装
|
||||
|
||||
直接使用我们的 `user` 子模块即可。如果要自己设置,在 `user` 目录下执行
|
||||
|
||||
```bash
|
||||
$ git clone git://repo.or.cz/libc-test
|
||||
$ rm -r libc-test/.git
|
||||
```
|
||||
|
||||
### 编译
|
||||
|
||||
考虑到在 rCore 中编译所有测例耗费时间过长,所以选择在本机用 musl-gcc 编译。请确保自己已经安装好了`x86_64-linux-musl-gcc` 工具链,且在 path 中,在 `config.make` 制定了 `CC` 的值。
|
||||
在本机执行:
|
||||
|
||||
```bash
|
||||
$ make
|
||||
$ rm src/*/*.err
|
||||
```
|
||||
|
||||
随后修改 `user` 目录下的 `Makefile` 文件,将 `libc-test`打包进入文件系统。
|
||||
|
||||
### 在 rCore 中测试
|
||||
|
||||
进入 `libc-test` 目录,执行脚本
|
||||
|
||||
```bash
|
||||
$ ash runtest.sh
|
||||
```
|
||||
|
||||
在测试测例前控制台会先打印当前测例名。若测试成功则顺次测试下一个测例,若失败则会打印额外信息,当遇到更严重的错误时可能导致 rCore 卡死或崩溃。例如在测试 `math` 库中的 `sqrt` 时,若测试失败,则输出为
|
||||
|
||||
```
|
||||
run sqrt
|
||||
sqrt failed
|
||||
```
|
||||
|
||||
在结束后,可前往对应测例所在目录下,通过查看测例所对应的 `.err` 文件查看失败的原因。
|
||||
|
||||
当遇到使得 rCore 崩溃的测例时,手动记录当前测例在 `runtest.sh` 中的位置,手动更新 `user` 中的文件,使其从下一个测例开始测试,并记录中间若干测例的测试结果。如此反复,直到测试过所有测例。
|
||||
|
||||
### 目前测试的结果
|
||||
|
||||
- [ ] 尚未通过的测例 (215/473)
|
||||
- [ ] `pthread` 相关:可能由于缺少相关信号
|
||||
- [ ] `math` 相关:由于缺少对 `mxcsr` 寄存器的支持,导致获取 `FP Exceptions` 失败,从而无法通过相关测例中对 `FP Exceptions` 的校验。极少数情况出现对于 bad cases 的计算错误。
|
||||
- [ ] `sync` 相关
|
||||
|
||||
具体的测试结果可参考 `user/libc-test/` 目录下的三个 `RECORD.txt` 文件。
|
8
docs/2020_OS/g2/slides/.gitignore
vendored
Normal file
8
docs/2020_OS/g2/slides/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.aux
|
||||
*.log
|
||||
*.nav
|
||||
*.snm
|
||||
*.gz
|
||||
*.out
|
||||
*.toc
|
||||
_minted*
|
BIN
docs/2020_OS/g2/slides/13周最终报告.pdf
Normal file
BIN
docs/2020_OS/g2/slides/13周最终报告.pdf
Normal file
Binary file not shown.
152
docs/2020_OS/g2/slides/13周最终报告.tex
Normal file
152
docs/2020_OS/g2/slides/13周最终报告.tex
Normal file
@ -0,0 +1,152 @@
|
||||
\documentclass{beamer}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usefonttheme{serif}
|
||||
|
||||
\usepackage{ctex}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{minted}
|
||||
\usepackage{graphics}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{xeCJK}
|
||||
\setCJKmainfont[ItalicFont={楷体}, BoldFont={黑体}]{宋体}
|
||||
|
||||
\usepackage{booktabs}
|
||||
|
||||
\newcommand{\E}{\text{E}}
|
||||
\newcommand{\var}{\text{Var}}
|
||||
\newcommand{\cov}{\text{Cov}}
|
||||
\renewcommand{\d}{\text{d}}
|
||||
|
||||
\setbeamertemplate{footline}[frame number]
|
||||
|
||||
\title{为 rCore 实现更多系统调用}
|
||||
|
||||
\author{罗崚骁 \quad 宋香君}
|
||||
|
||||
\begin{document}
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{课程设计目标}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item rCore 自编译
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item musl-libc 完善
|
||||
\item Make, CMake
|
||||
\item Rustc, Cargo
|
||||
\item 文件系统支持
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{目前进展}
|
||||
{运行 shell 脚本}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item ash + 脚本文件名运行脚本(sys\_dup,fcntl)
|
||||
\item 命令替换(Command Substitution)
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 诸如 echo \$(echo 233) 这样的命令
|
||||
\item 需要对管道增加阻塞
|
||||
\end{itemize}
|
||||
\item 可以跑通 make 的 configure 脚本和构建脚本
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{目前进展}
|
||||
{GNU Make}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 能够在 rCore 内部缺少 make 的情况下构建,configure+build.sh
|
||||
\item 基本功能正常运行,可以使用 3.78.1 的 make 构建出3.79 的 make
|
||||
\item 支持增量构建
|
||||
\begin{itemize}
|
||||
\item 增加了文件系统对修改时间的记录,完善了对 stat 的实现,顺便还能支持 touch
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{目前进展}
|
||||
{libc-test}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item Makefile 正常执行
|
||||
\item 给出了所有测例的执行结果
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 258 个测例成功
|
||||
\item 215 个测例失败,其中 18 个测例无法正常结束
|
||||
\item 失败的测例主要是 pthread(缺少信号机制支持)、math(大量计算错误,140 个左右) 相关
|
||||
\item 修好了全部信号量相关的测例
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{后续任务}
|
||||
{Cargo}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 目前只能新建项目,还无法成功使用 Cargo 构建
|
||||
\includegraphics[width=\linewidth]{assets/cargo.png}
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
% \caption{}
|
||||
% \label{}
|
||||
\end{figure}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{后续任务}
|
||||
{libc-test}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 主要针对 pthread 和数学的相关测例进行修复
|
||||
\item 增加信号机制,实现一些和信号相关的系统调用
|
||||
\item 编写文档,总结 rCore 开发微小的经验
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{调试方法}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 除了可以开启记录模式打印每条系统调用外,还可以用 gdb 通过
|
||||
相应端口连接到 qemu 进行调试
|
||||
\item 使用 CLion 提供的 gdb remote debug 可以在 IDE 中更方便地定位到错误
|
||||
\item 不过目前 rCore 的 Debug 版也开了 O2,调试时困难变大
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{调试方法}
|
||||
\includegraphics[width=\linewidth]{assets/gdb.png}
|
||||
\begin{figure}[]
|
||||
\centering
|
||||
|
||||
% \caption{}
|
||||
% \label{}
|
||||
\end{figure}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{问题选讲}
|
||||
{IO 阻塞与进程死锁}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 在有阻塞的 IO 中,目前的设计里 inode 的实现中看不见进程,
|
||||
并不能释放进程锁
|
||||
\item 于是,设想有如下情景:进程 2 由进程 1 fork 出来,并且有连接他们的管道,进程1读进程2写。
|
||||
进程1先读,保持着锁进入阻塞;进程2在写之前需要调用 getppid 获取父进程 id,便发生了死锁。
|
||||
\item 解决方法:考虑到进程的 pid 其实是定值,不必要用锁保护,可以和进程并列保存。
|
||||
\item 后续:IO 阻塞时释放进程锁
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{结束}
|
||||
谢谢观看
|
||||
\end{frame}
|
||||
|
||||
\end{document}
|
BIN
docs/2020_OS/g2/slides/assets/cargo.png
Normal file
BIN
docs/2020_OS/g2/slides/assets/cargo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
docs/2020_OS/g2/slides/assets/gdb.png
Normal file
BIN
docs/2020_OS/g2/slides/assets/gdb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 KiB |
BIN
docs/2020_OS/g2/slides/assets/syscall0.png
Normal file
BIN
docs/2020_OS/g2/slides/assets/syscall0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
docs/2020_OS/g2/slides/assets/syscall1.png
Normal file
BIN
docs/2020_OS/g2/slides/assets/syscall1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
docs/2020_OS/g2/slides/方案设计报告.pdf
Normal file
BIN
docs/2020_OS/g2/slides/方案设计报告.pdf
Normal file
Binary file not shown.
BIN
docs/2020_OS/g2/slides/方案设计报告.pptx
Normal file
BIN
docs/2020_OS/g2/slides/方案设计报告.pptx
Normal file
Binary file not shown.
BIN
docs/2020_OS/g2/slides/方案设计报告幻灯片.pdf
Normal file
BIN
docs/2020_OS/g2/slides/方案设计报告幻灯片.pdf
Normal file
Binary file not shown.
156
docs/2020_OS/g2/slides/方案设计报告幻灯片.tex
Normal file
156
docs/2020_OS/g2/slides/方案设计报告幻灯片.tex
Normal file
@ -0,0 +1,156 @@
|
||||
\documentclass{beamer}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usefonttheme{serif}
|
||||
|
||||
\usepackage{ctex}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{minted}
|
||||
\usepackage{graphics}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{xeCJK}
|
||||
\setCJKmainfont[ItalicFont={楷体}, BoldFont={黑体}]{宋体}
|
||||
|
||||
\usepackage{booktabs}
|
||||
|
||||
\newcommand{\E}{\text{E}}
|
||||
\newcommand{\var}{\text{Var}}
|
||||
\newcommand{\cov}{\text{Cov}}
|
||||
\renewcommand{\d}{\text{d}}
|
||||
|
||||
\setbeamertemplate{footline}[frame number]
|
||||
|
||||
\title{rCore 的基本开发环境的搭建}
|
||||
|
||||
\author{罗崚骁 \quad 宋香君}
|
||||
|
||||
\begin{document}
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{课程设计目标}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item \textbf{C/C++ 开发}:基于 musl libc 的 gcc 工具链
|
||||
\item \textbf{工程构建}:GNU make, CMake
|
||||
\item \textbf{Rust 开发}:Rust 工具链
|
||||
\item \textbf{版本控制系统}:git
|
||||
\item \textbf{编辑器}:vi, vim
|
||||
\item \textbf{软件包管理器}:cargo
|
||||
\end{itemize}
|
||||
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{课程设计背景}
|
||||
rCore 已经具备了运行一些软件的能力。但是,rCore 的软件开发能力还稍显不足。
|
||||
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 编译器支持不足,目前仅支持 musl-gcc
|
||||
\item C/C++,Rust 标准库实现支持不详,缺少测试,目前仅支持 musl-libc
|
||||
\item 没有版本控制系统
|
||||
\item 缺少项目构建工具
|
||||
\item 编辑器只能说勉勉强强(vi)
|
||||
\item 没有软件包管理器,甚至不能从源码安装软件
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{已有工作}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item rCore 已经实现了相当数量的系统调用,能够支持 \href{https://github.com/rcore-os/rcore-user}{rcore-user} 中的软件,
|
||||
\item 考虑到编译器是我们的课程设计中重要的一环,尤其可以参考此前 rCore 对 musl-gcc 的支持历程
|
||||
\item 可以设法获取的各种满足我们需求的开源软件,这一点决定了我们的工作思路是对 rCore 针对软件进行完善,而非针对 rCore 开发软件
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{工作计划及目前进展}
|
||||
工作计划按如下顺序开展:
|
||||
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 完善对 gcc 的支持,测试 C/C++ 标准库实现
|
||||
\item 支持 make,使 rCore 具备从源码安装软件的能力
|
||||
\begin{itemize}
|
||||
\item 还可考虑支持 CMake
|
||||
\end{itemize}
|
||||
\item 支持 Git
|
||||
\item 支持 Rust 工具链,主要包括:
|
||||
\begin{itemize}
|
||||
\item rustc
|
||||
\item cargo
|
||||
\item 测试 rust 标准库实现
|
||||
\end{itemize}
|
||||
\item 支持更多的编辑器
|
||||
\begin{itemize}
|
||||
\item nano
|
||||
\item vim
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{软件支持过程}
|
||||
{安装}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 寻找官方发布的预编译版本
|
||||
\item 外部源码构建
|
||||
\item rCore 内部源码构建(目前估计难以达到较好效果)
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{软件支持过程}
|
||||
{测试}
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item 对于C/C++,Rust 标准库的测试,似乎没有找到官方公开的测例,运行大规模工程
|
||||
\item 对于各种软件,决定选取其重要功能进行测试
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{10pt}
|
||||
\item make 是否能顺利构建项目、是否支持增量构建等
|
||||
\item Git 的 add,commit,log,status,branch 等功能
|
||||
\item 当然如果能找到测例的话就最好了
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{软件支持过程}
|
||||
{系统调用}
|
||||
\begin{itemize}
|
||||
\item 利用 rCore 的 log 信息
|
||||
\end{itemize}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{assets/syscall0.png}
|
||||
% \caption{}
|
||||
% \label{}
|
||||
\end{figure}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{小组分工}
|
||||
\begin{itemize}
|
||||
\item 罗崚骁
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{8pt}
|
||||
\item 实现和完善系统调用
|
||||
\item 完成对 Git 支持
|
||||
\item 完成对 cargo 离线版的支持
|
||||
\item 测试 C++ 和 Rust 项目
|
||||
\end{itemize}
|
||||
\item 宋香君
|
||||
\begin{itemize}
|
||||
\setlength{\itemsep}{8pt}
|
||||
\item 实现和完善系统调用
|
||||
\item 完成对 make,CMake 的支持
|
||||
\item 测试 C 项目
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{结束}
|
||||
谢谢观看
|
||||
\end{frame}
|
||||
|
||||
\end{document}
|
BIN
docs/2020_OS/g2/slides/方案设计文档.pdf
Normal file
BIN
docs/2020_OS/g2/slides/方案设计文档.pdf
Normal file
Binary file not shown.
136
docs/2020_OS/g2/slides/方案设计文档.tex
Normal file
136
docs/2020_OS/g2/slides/方案设计文档.tex
Normal file
@ -0,0 +1,136 @@
|
||||
\documentclass{article}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{minted}
|
||||
\usepackage{ctex}
|
||||
\usepackage{xeCJK}
|
||||
\usepackage{graphics}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{authblk}
|
||||
\usepackage[colorlinks,linkcolor=blue]{hyperref}
|
||||
|
||||
\pgfplotsset{compat=1.15}
|
||||
|
||||
\setCJKmainfont[ItalicFont={楷体}, BoldFont={黑体}]{宋体}
|
||||
|
||||
|
||||
\title{rCore 中开发环境的搭建}
|
||||
\author{罗崚骁\quad 宋香君}
|
||||
% \author[1]{罗崚骁}
|
||||
% \author[2] {宋香君}
|
||||
\affil{\texttt {\{luolx17, songxj17\}@mails.tsinghua.edu.cn}}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\section{课程设计目标}
|
||||
本组致力于为 rCore 增加相关的软件支持,使得 rCore 具有一定软件开发能力,为此需要对 rCore 的功能进行进一步完善,尤其是系统调用的完善。
|
||||
|
||||
设想的开发环境包含的软件工具有:
|
||||
\begin{itemize}
|
||||
\item C/C++ 开发:基于 musl libc 的 gcc 工具链
|
||||
\item 工程构建:GNU make, CMake
|
||||
\item Rust 开发:rust 工具链
|
||||
\item 版本控制系统:git
|
||||
\item 编辑器:vi, vim
|
||||
\item 软件包管理器:cargo,apk
|
||||
\end{itemize}
|
||||
|
||||
\section{课程设计背景}
|
||||
随着 rCore 开发团队的不懈努力,rCore 已经具备了运行一些软件的能力。但是,rCore 的软件开发能力还稍显不足,比如:
|
||||
\begin{itemize}
|
||||
\item 编译器支持不足,目前仅支持 musl-gcc
|
||||
\item C/C++,Rust 标准库实现支持不详,缺少测试,目前仅支持 musl-libc
|
||||
\item 没有版本控制系统
|
||||
\item 缺少项目构建工具
|
||||
\item 编辑器只能勉强使用(vi)
|
||||
\item 没有软件包管理器,甚至不太有从源码安装软件的能力
|
||||
\end{itemize}
|
||||
|
||||
这些显然不是一个优秀的操作系统应该具有的状态,因此我们小组决定为 rCore 支持上述类型的软件使其具有软件开发的能力。
|
||||
|
||||
\section{已有相关工作}
|
||||
\begin{itemize}
|
||||
\item rCore 已经实现了相当数量的系统调用,能够支持 \href{https://github.com/rcore-os/rcore-user}{rcore-user} 中的软件,
|
||||
\item 考虑到编译器是我们的课程设计中重要的一环,尤其可以参考此前 rCore 对 musl-gcc 的支持历程
|
||||
\item 可以设法获取的各种满足我们需求的开源软件,这一点决定了我们的工作思路是对 rCore 针对软件进行完善,而非针对 rCore 开发软件
|
||||
\end{itemize}
|
||||
|
||||
\section{工作计划及目前进展}
|
||||
|
||||
工作计划按如下顺序开展:
|
||||
|
||||
\begin{itemize}
|
||||
\item 完善对 gcc 的支持,测试 C/C++ 标准库实现
|
||||
\item 支持 make,使 rCore 具备从源码安装软件的能力(除此之外,还可考虑支持 CMake)
|
||||
\item 支持 Git
|
||||
\item 支持 Rust 工具链,主要包括:
|
||||
\begin{itemize}
|
||||
\item rustc
|
||||
\item cargo
|
||||
\item 测试 rust 标准库实现
|
||||
\end{itemize}
|
||||
\item 支持更多的编辑器(nano,vim 等)
|
||||
\end{itemize}
|
||||
|
||||
\section{待解决的问题}
|
||||
|
||||
如果想要从源码安装软件,首先需要有执行脚本文件的能力。经测试使用 sh 命令执行脚本文件时,
|
||||
会卡在一处对 stdin 的读入上,调研
|
||||
|
||||
|
||||
\section{软件支持流程}
|
||||
\subsection{安装}
|
||||
|
||||
由于现在还不能使用包管理器,因此如何将软件安装到 rCore 中是一个值得拿出来考虑的问题。可能尝试的途径有:
|
||||
\begin{itemize}
|
||||
\item 寻找官方发布的预编译版本(比如 musl-rust),这种做法是最方便的
|
||||
\item 下载软件源码,在外部操作系统编译好后复制到 rCore 的文件系统中
|
||||
\item 当 rCore 支持 Make 后,也可以尝试直接在 rCore 中从源码安装软件(关于这一点,受制于编译器运行速度,虽然这是我们设想的软件开发环境应该具有的一个特质,但是目前这个想法看起来很难达到较好的效果)
|
||||
\end{itemize}
|
||||
|
||||
\subsection{测试}
|
||||
|
||||
软件测试似乎本来就是一个不可能做到完美的工作。受制于各方面因素,目前我们决定采用一些较为勉强的方法对 rCore 中的软件进行测试。
|
||||
|
||||
\begin{itemize}
|
||||
\item 对于C/C++,Rust 标准库的测试,似乎没有找到官方公开的测例,我们决定测试以编译并运行一些具有一定规模的使用了大量标准库的工程的形式进行
|
||||
\item 对于各种软件,决定选取其重要功能进行测试,例如:
|
||||
\begin{itemize}
|
||||
\item make 是否能顺利构建项目、是否支持增量构建等
|
||||
\item Git 的 add,commit,log,status,branch 等功能
|
||||
\item 当然如果能找到测例的话就最好了
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
||||
需要指出的是,通常的软件测试是在给定的操作系统上测试其表现,是软件对操作系统的适应,
|
||||
而本次课程设计中是针对软件完善操作系统使操作系统能适应软件的运行。
|
||||
|
||||
\newpage
|
||||
至于如何做到这一点,
|
||||
可以利用 rCore 的记录功能查看哪些系统调用尚未实现或实现不完全,以此来补充和调试系统
|
||||
调用的实现。
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{assets/syscall0.png}
|
||||
% \caption{}
|
||||
% \label{}
|
||||
\end{figure}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{assets/syscall1.png}
|
||||
% \caption{}
|
||||
% \label{}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\section{小组分工}
|
||||
两人都需要对各种系统调用进行实现和完善。在具体支持的软件上分工如下:
|
||||
\begin{itemize}
|
||||
\item 罗崚骁:Git,Cargo 离线版, 测试 C++ 与 Rust 项目
|
||||
\item 宋香君:make, CMake, 测试 C 项目
|
||||
\end{itemize}
|
||||
\end{document}
|
233
kernel/Cargo.lock
generated
233
kernel/Cargo.lock
generated
@ -20,7 +20,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -98,7 +98,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.17.2"
|
||||
version = "0.17.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -116,7 +116,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.2"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -129,7 +129,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
version = "1.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -168,16 +168,16 @@ name = "embedded-graphics"
|
||||
version = "0.6.0-alpha.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -204,7 +204,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.68"
|
||||
version = "0.2.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -234,6 +234,66 @@ name = "nodrop"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.11"
|
||||
@ -244,22 +304,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "0.1.6"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paste-impl 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste-impl"
|
||||
version = "0.1.6"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -277,17 +337,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.11"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.8"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -295,10 +350,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -312,7 +367,7 @@ version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -322,7 +377,7 @@ version = "7.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -332,7 +387,7 @@ version = "0.1.2"
|
||||
dependencies = [
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uefi 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x86_64 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xmas-elf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -348,33 +403,36 @@ dependencies = [
|
||||
"bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)",
|
||||
"bitvec 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"buddy_system_allocator 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compression 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"device_tree 1.0.3 (git+https://github.com/rcore-os/device_tree-rs)",
|
||||
"isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mips 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)",
|
||||
"raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rboot 0.1.2",
|
||||
"rcore-console 0.1.0 (git+https://github.com/rcore-os/rcore-console?rev=b7bacf9)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs-devfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs-mountfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs-ramfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"rcore-fs-devfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"rcore-fs-mountfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"rcore-fs-ramfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"rcore-memory 0.1.0",
|
||||
"rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread?rev=d727949b)",
|
||||
"rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread?rev=e00f5ed)",
|
||||
"riscv 0.5.0 (git+https://github.com/rcore-os/riscv)",
|
||||
"rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smoltcp 0.5.0 (git+https://github.com/rcore-os/smoltcp?rev=5bd87c7c)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uart_16550 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uart_16550 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"virtio-drivers 0.1.0 (git+https://github.com/rcore-os/virtio-drivers?rev=dfa70e14)",
|
||||
"volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x86_64 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -393,9 +451,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rcore-fs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a#7e7c74a921803d6c8edc99b8ebb6fc85774819b9"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee#1fb7c0ee2eedb37516344e93c271c3e6795f9a89"
|
||||
dependencies = [
|
||||
"filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -403,42 +461,42 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rcore-fs-devfs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a#7e7c74a921803d6c8edc99b8ebb6fc85774819b9"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee#1fb7c0ee2eedb37516344e93c271c3e6795f9a89"
|
||||
dependencies = [
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcore-fs-mountfs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a#7e7c74a921803d6c8edc99b8ebb6fc85774819b9"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee#1fb7c0ee2eedb37516344e93c271c3e6795f9a89"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcore-fs-ramfs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a#7e7c74a921803d6c8edc99b8ebb6fc85774819b9"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee#1fb7c0ee2eedb37516344e93c271c3e6795f9a89"
|
||||
dependencies = [
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcore-fs-sfs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a#7e7c74a921803d6c8edc99b8ebb6fc85774819b9"
|
||||
source = "git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee#1fb7c0ee2eedb37516344e93c271c3e6795f9a89"
|
||||
dependencies = [
|
||||
"bitvec 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)",
|
||||
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)",
|
||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -453,7 +511,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rcore-thread"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rcore-os/rcore-thread?rev=d727949b#d727949b8ea20c2e3a94f8ba015652c9eff8b53c"
|
||||
source = "git+https://github.com/rcore-os/rcore-thread?rev=e00f5ed#e00f5ed11479e5436470497ec9ce49510fee94e1"
|
||||
dependencies = [
|
||||
"deque 0.3.2 (git+https://github.com/rcore-os/deque.git?branch=no_std)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -502,9 +560,9 @@ name = "rustversion"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -526,7 +584,7 @@ version = "0.5.0"
|
||||
source = "git+https://github.com/rcore-os/smoltcp?rev=5bd87c7c#5bd87c7cf01e0a36eb92102e4b52876a9e0ba889"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -543,11 +601,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.14"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -558,16 +616,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.11.2"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "uart_16550"
|
||||
version = "0.2.2"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x86_64 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -594,9 +652,9 @@ name = "uefi-macros"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -684,12 +742,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.8.3"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -718,43 +775,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)" = "<none>"
|
||||
"checksum bitvec 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1fe4300c1d7a9ea6f3e3f39c10b39862bb79e1175c0572b6b49539a30e5562f5"
|
||||
"checksum bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)" = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c"
|
||||
"checksum buddy_system_allocator 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e953b958d83e13a44b1ead5b6aaa2a5f854bd5170239a66b606e030a14d018f"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
|
||||
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
"checksum cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum compression 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3a82b366ae14633c67a1cbb4aa3738210a23f77d2868a0fd50faa23a956f9ec4"
|
||||
"checksum deque 0.3.2 (git+https://github.com/rcore-os/deque.git?branch=no_std)" = "<none>"
|
||||
"checksum device_tree 1.0.3 (git+https://github.com/rcore-os/device_tree-rs)" = "<none>"
|
||||
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
"checksum embedded-graphics 0.6.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e784539ee7c085de51439a0a584d11d0f4ab20baf86aa83de6bb8d0f401e6b4"
|
||||
"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d"
|
||||
"checksum filetime 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e"
|
||||
"checksum isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)" = "<none>"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
||||
"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
|
||||
"checksum mips 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053a14b59d7b828efefebf92b557015d99383264f4714a959b1d970d8c6c32fb"
|
||||
"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
|
||||
"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
|
||||
"checksum num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746"
|
||||
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||
"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
|
||||
"checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
|
||||
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49"
|
||||
"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
|
||||
"checksum paste 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a"
|
||||
"checksum paste-impl 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a"
|
||||
"checksum pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48392db76c4e9a69e0b3be356c5f97ebb7b14413c5e4fd0af4755dbf86e2fce"
|
||||
"checksum pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)" = "<none>"
|
||||
"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
|
||||
"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
|
||||
"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
|
||||
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||
"checksum radium 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
|
||||
"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d"
|
||||
"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf"
|
||||
"checksum rcore-console 0.1.0 (git+https://github.com/rcore-os/rcore-console?rev=b7bacf9)" = "<none>"
|
||||
"checksum rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)" = "<none>"
|
||||
"checksum rcore-fs-devfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)" = "<none>"
|
||||
"checksum rcore-fs-mountfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)" = "<none>"
|
||||
"checksum rcore-fs-ramfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)" = "<none>"
|
||||
"checksum rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=7e7c74a)" = "<none>"
|
||||
"checksum rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread?rev=d727949b)" = "<none>"
|
||||
"checksum rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)" = "<none>"
|
||||
"checksum rcore-fs-devfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)" = "<none>"
|
||||
"checksum rcore-fs-mountfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)" = "<none>"
|
||||
"checksum rcore-fs-ramfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)" = "<none>"
|
||||
"checksum rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs?rev=1fb7c0ee)" = "<none>"
|
||||
"checksum rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread?rev=e00f5ed)" = "<none>"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb"
|
||||
"checksum riscv 0.5.0 (git+https://github.com/rcore-os/riscv)" = "<none>"
|
||||
@ -766,10 +829,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum smoltcp 0.5.0 (git+https://github.com/rcore-os/smoltcp?rev=5bd87c7c)" = "<none>"
|
||||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
|
||||
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
|
||||
"checksum syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
|
||||
"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
|
||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||
"checksum uart_16550 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc0bc8ff1beb1436e8c4ce9c4b47f6f6c1376b56fb91505fabeef13743eb33"
|
||||
"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
"checksum uart_16550 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e983688170873ec9a3f21a6afc751fb706cf02836ed9d28a68d2e247dff7ae52"
|
||||
"checksum ucs2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85061f4e43545a613c0da6b87725bf23f8da8613cf2473719c4f71a270c4ce8a"
|
||||
"checksum uefi 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5cec6a2850639f588cc8042140b5deaa2f2170c23db5adb08f4316fa04cdb4a0"
|
||||
"checksum uefi-macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d4a1b0215dc72e83d8d501b3275eb59477d3b595be8861abfb8ab110180955"
|
||||
@ -785,6 +848,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
"checksum x86 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f21eecbd666e3a8edbf0b26d36f270f7a613d8986ca0eafb8205e324f7336dab"
|
||||
"checksum x86_64 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f27d9168654aee1b0c1b73746caeb4aa33248f8b8c8f6e100e697fcc2a794b2"
|
||||
"checksum x86_64 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5d9e3e26fcb51976eafa310e8f2b7a5a83ae8c185443efe50cbc6534a4fffa0d"
|
||||
"checksum x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4206b60c9f99766329b66962aa8ddc01df6c7edd02edc046b7a69d5df9fcdbcf"
|
||||
"checksum xmas-elf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e74de9a366f6ab8c405fa6b371d9ac24943921fa14b3d64afcb202065c405f11"
|
||||
"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"
|
||||
|
@ -65,14 +65,17 @@ smoltcp = { git = "https://github.com/rcore-os/smoltcp", rev = "5bd87c7c", defau
|
||||
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator" }
|
||||
rcore-console = { git = "https://github.com/rcore-os/rcore-console", rev = "b7bacf9", default-features = false }
|
||||
rcore-memory = { path = "../crate/memory" }
|
||||
rcore-thread = { git = "https://github.com/rcore-os/rcore-thread", rev = "d727949b" }
|
||||
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7e7c74a" }
|
||||
rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7e7c74a" }
|
||||
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7e7c74a" }
|
||||
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7e7c74a" }
|
||||
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "7e7c74a" }
|
||||
rcore-thread = { git = "https://github.com/rcore-os/rcore-thread", rev = "e00f5ed" }
|
||||
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1fb7c0ee" }
|
||||
rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1fb7c0ee" }
|
||||
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1fb7c0ee" }
|
||||
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1fb7c0ee" }
|
||||
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1fb7c0ee" }
|
||||
compression = { version = "0.1.4", default-features = false, features = ["gzip"] }
|
||||
|
||||
num = { version = "0.2.1", default-features = false }
|
||||
num-traits = { version = "0.2.11", default-features = false }
|
||||
num-derive = "0.3"
|
||||
pc-keyboard = "0.5"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
rboot = { path = "../rboot", default-features = false }
|
||||
@ -80,7 +83,6 @@ apic = { git = "https://github.com/rcore-os/apic-rs" }
|
||||
x86_64 = "0.7"
|
||||
raw-cpuid = "7.0"
|
||||
uart_16550 = "0.2"
|
||||
pc-keyboard = "0.5"
|
||||
acpi = "0.4"
|
||||
aml = "0.4"
|
||||
|
||||
|
@ -283,8 +283,8 @@ endif
|
||||
|
||||
$(kernel_img): kernel bootloader
|
||||
ifeq ($(ARCH), x86_64)
|
||||
@mkdir -p $(ESP)/EFI/rCore $(ESP)/EFI/Boot
|
||||
@cp ../rboot/target/x86_64-unknown-uefi/release/rboot.efi $(ESP)/EFI/Boot/BootX64.efi
|
||||
mkdir -p $(ESP)/EFI/rCore $(ESP)/EFI/Boot
|
||||
@cp ../rboot/target/x86_64-unknown-uefi/$(MODE)/rboot.efi $(ESP)/EFI/Boot/BootX64.efi
|
||||
@cp ../rboot/rboot.conf $(ESP)/EFI/Boot/rboot.conf
|
||||
@cp $(kernel) $(ESP)/EFI/rCore/kernel.elf
|
||||
else ifeq ($(ARCH), $(filter $(ARCH), riscv32 riscv64))
|
||||
|
@ -31,6 +31,7 @@ impl TrapFrame {
|
||||
tf.spsr = 0b1101_00_0101; // To EL 1, enable IRQ
|
||||
tf
|
||||
}
|
||||
|
||||
pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
|
||||
use core::mem::zeroed;
|
||||
let mut tf: Self = unsafe { zeroed() };
|
||||
@ -39,6 +40,10 @@ impl TrapFrame {
|
||||
tf.spsr = 0b1101_00_0000; // To EL 0, enable IRQ
|
||||
tf
|
||||
}
|
||||
|
||||
pub fn get_sp(&self) -> usize {
|
||||
self.sp
|
||||
}
|
||||
}
|
||||
|
||||
/// 新线程的内核栈初始内容
|
||||
|
@ -87,6 +87,10 @@ fn handle_syscall(num: u16, tf: &mut TrapFrame) {
|
||||
crate::trap::error(tf);
|
||||
}
|
||||
|
||||
syscall(tf)
|
||||
}
|
||||
|
||||
pub fn syscall(tf: &mut TrapFrame) {
|
||||
// svc instruction has been skipped in syscall (ref: J1.1.2, page 6152)
|
||||
let ret = crate::syscall::syscall(
|
||||
tf.x1to29[7] as usize,
|
||||
|
@ -11,6 +11,7 @@ pub mod io;
|
||||
pub mod memory;
|
||||
pub mod paging;
|
||||
pub mod rand;
|
||||
pub mod signal;
|
||||
pub mod syscall;
|
||||
pub mod timer;
|
||||
|
||||
@ -66,3 +67,17 @@ const LOGO: &str = r#"
|
||||
/ _, _// /_/ /(__ )/ /_ / /_/ /___/ /
|
||||
/_/ |_| \__,_//____/ \__/ \____//____/
|
||||
"#;
|
||||
|
||||
pub fn get_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
asm!("mov sp, $0" : "=r"(sp));
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
pub fn set_sp(sp: usize) {
|
||||
unsafe {
|
||||
asm!("mov $0, sp" :: "r" (sp) : "memory");
|
||||
}
|
||||
}
|
||||
|
40
kernel/src/arch/aarch64/signal.rs
Normal file
40
kernel/src/arch/aarch64/signal.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rdi: usize,
|
||||
pub rsi: usize,
|
||||
pub rbp: usize,
|
||||
pub rbx: usize,
|
||||
pub rdx: usize,
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rsp: usize,
|
||||
pub rip: usize,
|
||||
pub eflags: usize,
|
||||
pub cs: u16,
|
||||
pub gs: u16,
|
||||
pub fs: u16,
|
||||
pub _pad: u16,
|
||||
pub err: usize,
|
||||
pub trapno: usize,
|
||||
pub oldmask: usize,
|
||||
pub cr2: usize,
|
||||
pub fpstate: usize,
|
||||
pub _reserved1: [usize; 8],
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn from_tf(tf: &TrapFrame) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -52,6 +52,11 @@ impl TrapFrame {
|
||||
tf.sstatus.set_spp(sstatus::SPP::User);
|
||||
tf
|
||||
}
|
||||
|
||||
pub fn get_sp(&self) -> usize {
|
||||
// sp is x2
|
||||
self.x[2]
|
||||
}
|
||||
}
|
||||
|
||||
use core::fmt::{Debug, Error, Formatter};
|
||||
|
@ -112,7 +112,7 @@ fn timer() {
|
||||
crate::trap::timer();
|
||||
}
|
||||
|
||||
fn syscall(tf: &mut TrapFrame) {
|
||||
pub fn syscall(tf: &mut TrapFrame) {
|
||||
tf.sepc += 4; // Must before syscall, because of fork.
|
||||
let ret = crate::syscall::syscall(
|
||||
tf.x[17],
|
||||
|
@ -17,6 +17,7 @@ pub mod memory;
|
||||
pub mod paging;
|
||||
pub mod rand;
|
||||
mod sbi;
|
||||
pub mod signal;
|
||||
pub mod syscall;
|
||||
pub mod timer;
|
||||
|
||||
@ -119,3 +120,17 @@ global_asm!(include_str!("boot/entry64.asm"));
|
||||
#[cfg(feature = "board_k210")]
|
||||
global_asm!(include_str!("boot/entry_k210.asm"));
|
||||
global_asm!(include_str!("boot/trap.asm"));
|
||||
|
||||
pub fn get_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
asm!("mv $0, sp" : "=r"(sp));
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
pub fn set_sp(sp: usize) {
|
||||
unsafe {
|
||||
asm!("mv sp, $0" :: "r" (sp) : "memory");
|
||||
}
|
||||
}
|
||||
|
40
kernel/src/arch/riscv/signal.rs
Normal file
40
kernel/src/arch/riscv/signal.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rdi: usize,
|
||||
pub rsi: usize,
|
||||
pub rbp: usize,
|
||||
pub rbx: usize,
|
||||
pub rdx: usize,
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rsp: usize,
|
||||
pub rip: usize,
|
||||
pub eflags: usize,
|
||||
pub cs: u16,
|
||||
pub gs: u16,
|
||||
pub fs: u16,
|
||||
pub _pad: u16,
|
||||
pub err: usize,
|
||||
pub trapno: usize,
|
||||
pub oldmask: usize,
|
||||
pub cr2: usize,
|
||||
pub fpstate: usize,
|
||||
pub _reserved1: [usize; 8],
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn from_tf(tf: &TrapFrame) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -67,6 +67,9 @@
|
||||
use super::consts::*;
|
||||
use super::TrapFrame;
|
||||
use crate::drivers::IRQ_MANAGER;
|
||||
use crate::process::current_thread;
|
||||
use crate::processor;
|
||||
use crate::signal::do_signal;
|
||||
use bitflags::*;
|
||||
use log::*;
|
||||
|
||||
@ -81,6 +84,11 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
|
||||
tf.trap_num,
|
||||
super::super::cpu::id()
|
||||
);
|
||||
if processor().tid_option().is_some() {
|
||||
unsafe {
|
||||
current_thread().tf = tf as *mut TrapFrame;
|
||||
}
|
||||
}
|
||||
// Dispatch
|
||||
match tf.trap_num as u8 {
|
||||
Breakpoint => breakpoint(),
|
||||
@ -90,7 +98,12 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
|
||||
let irq = tf.trap_num as u8 - IRQ0;
|
||||
super::ack(irq); // must ack before switching
|
||||
match irq {
|
||||
Timer => crate::trap::timer(),
|
||||
Timer => {
|
||||
crate::trap::timer();
|
||||
if processor().tid_option().is_some() {
|
||||
do_signal(tf);
|
||||
}
|
||||
}
|
||||
Keyboard => keyboard(),
|
||||
COM1 => com1(),
|
||||
COM2 => com2(),
|
||||
@ -204,6 +217,7 @@ pub extern "C" fn syscall(tf: &mut TrapFrame) {
|
||||
trace!("\nInterupt: Syscall {:#x?}", tf.rax);
|
||||
let ret = crate::syscall::syscall(tf.rax, [tf.rdi, tf.rsi, tf.rdx, tf.r10, tf.r8, tf.r9], tf);
|
||||
tf.rax = ret as usize;
|
||||
do_signal(tf);
|
||||
}
|
||||
|
||||
fn syscall32(tf: &mut TrapFrame) {
|
||||
|
@ -20,6 +20,9 @@ __alltraps:
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, 8
|
||||
stmxcsr [rsp]
|
||||
|
||||
# push fs.base
|
||||
xor rax, rax
|
||||
mov ecx, 0xC0000100
|
||||
@ -34,9 +37,7 @@ __alltraps:
|
||||
mov rax, rsp
|
||||
and rax, 0xFFFFFFFFFFFFFFF0
|
||||
# fxsave (rax)
|
||||
.byte 0x0f
|
||||
.byte 0xae
|
||||
.byte 0x00
|
||||
.byte 0x0f, 0xae, 0x00
|
||||
mov rcx, rsp
|
||||
sub rcx, rax
|
||||
# push fp state offset
|
||||
@ -60,9 +61,7 @@ trap_ret:
|
||||
add rax, 16
|
||||
sub rax, rcx
|
||||
# fxrstor (rax)
|
||||
.byte 0x0f
|
||||
.byte 0xae
|
||||
.byte 0x08
|
||||
.byte 0x0f, 0xae, 0x08
|
||||
skip_fxrstor:
|
||||
add rsp, 16+512
|
||||
|
||||
@ -73,6 +72,9 @@ skip_fxrstor:
|
||||
mov ecx, 0xC0000100
|
||||
wrmsr # msr[ecx] <= edx:eax
|
||||
|
||||
ldmxcsr [rsp]
|
||||
add rsp, 8
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
@ -142,6 +144,9 @@ syscall_entry:
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, 8
|
||||
stmxcsr [rsp]
|
||||
|
||||
# push fs.base
|
||||
xor rax, rax
|
||||
mov ecx, 0xC0000100
|
||||
@ -156,9 +161,7 @@ syscall_entry:
|
||||
mov rax, rsp
|
||||
and rax, 0xFFFFFFFFFFFFFFF0
|
||||
# fxsave (rax)
|
||||
.byte 0x0f
|
||||
.byte 0xae
|
||||
.byte 0x00
|
||||
.byte 0x0f, 0xae, 0x00
|
||||
mov rcx, rsp
|
||||
sub rcx, rax
|
||||
# push fp state offset
|
||||
@ -184,9 +187,7 @@ syscall_return:
|
||||
add rax, 16
|
||||
sub rax, rcx
|
||||
# fxrstor (rax)
|
||||
.byte 0x0f
|
||||
.byte 0xae
|
||||
.byte 0x08
|
||||
.byte 0x0f, 0xae, 0x08
|
||||
skip_fxrstor1:
|
||||
add rsp, 16+512
|
||||
|
||||
@ -197,6 +198,9 @@ skip_fxrstor1:
|
||||
mov ecx, 0xC0000100
|
||||
wrmsr # msr[ecx] <= edx:eax
|
||||
|
||||
ldmxcsr [rsp]
|
||||
add rsp, 8
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::arch::signal::MachineContext;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
|
||||
@ -28,6 +29,7 @@ pub struct TrapFrame {
|
||||
// Pushed by __alltraps at 'trap.asm'
|
||||
pub fsbase: usize,
|
||||
|
||||
pub mxcsr: usize,
|
||||
pub r15: usize,
|
||||
pub r14: usize,
|
||||
pub r13: usize,
|
||||
@ -71,6 +73,7 @@ impl TrapFrame {
|
||||
tf.rsp = rsp;
|
||||
tf.rflags = 0x282;
|
||||
tf.fpstate_offset = 16; // skip restoring for first time
|
||||
tf.mxcsr = 0x1f80;
|
||||
tf
|
||||
}
|
||||
pub fn new_user_thread(entry_addr: usize, rsp: usize) -> Self {
|
||||
@ -82,8 +85,45 @@ impl TrapFrame {
|
||||
tf.rsp = rsp;
|
||||
tf.rflags = 0x282;
|
||||
tf.fpstate_offset = 16; // skip restoring for first time
|
||||
tf.mxcsr = 0x1f80;
|
||||
tf
|
||||
}
|
||||
|
||||
pub fn get_sp(&self) -> usize {
|
||||
self.rsp
|
||||
}
|
||||
|
||||
pub fn from_mcontext(mc: &MachineContext) -> Self {
|
||||
// FIXME: missing fields
|
||||
TrapFrame {
|
||||
fpstate_offset: 16,
|
||||
fpstate: Default::default(),
|
||||
fsbase: mc.fs as usize,
|
||||
mxcsr: 0x1f80,
|
||||
r15: mc.r15,
|
||||
r14: mc.r14,
|
||||
r13: mc.r13,
|
||||
r12: mc.r12,
|
||||
rbp: mc.rbp,
|
||||
rbx: mc.rbx,
|
||||
r11: mc.r11,
|
||||
r10: mc.r10,
|
||||
r9: mc.r9,
|
||||
r8: mc.r8,
|
||||
rsi: mc.rsi,
|
||||
rdi: mc.rdi,
|
||||
rdx: mc.rdx,
|
||||
rcx: mc.rcx,
|
||||
rax: mc.rax,
|
||||
trap_num: 0,
|
||||
error_code: 0,
|
||||
rip: mc.rip,
|
||||
cs: mc.cs as usize,
|
||||
rflags: 0,
|
||||
rsp: mc.rsp,
|
||||
ss: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@ -154,6 +194,8 @@ impl Context {
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
// save page table
|
||||
mov r15, cr3
|
||||
push r15
|
||||
|
||||
@ -161,19 +203,18 @@ impl Context {
|
||||
mov [rdi], rsp // rdi = from_rsp
|
||||
mov rsp, [rsi] // rsi = to_rsp
|
||||
|
||||
// Save old callee-save registers
|
||||
// restore page table
|
||||
pop r15
|
||||
mov cr3, r15
|
||||
|
||||
// restore old callee-save registers
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbp
|
||||
pop rbx
|
||||
|
||||
// pop rip
|
||||
ret"
|
||||
: : : : "intel" "volatile" )
|
||||
": : : : "intel" "volatile");
|
||||
}
|
||||
|
||||
pub unsafe fn null() -> Self {
|
||||
|
@ -15,6 +15,7 @@ pub mod ipi;
|
||||
pub mod memory;
|
||||
pub mod paging;
|
||||
pub mod rand;
|
||||
pub mod signal;
|
||||
pub mod syscall;
|
||||
pub mod timer;
|
||||
|
||||
@ -92,3 +93,17 @@ fn other_start() -> ! {
|
||||
// call the first main function in kernel.
|
||||
crate::kmain();
|
||||
}
|
||||
|
||||
pub fn get_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
asm!("mov %rsp, $0" : "=r"(sp));
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
pub fn set_sp(sp: usize) {
|
||||
unsafe {
|
||||
asm!("mov $0, %rsp" :: "r" (sp) : "memory");
|
||||
}
|
||||
}
|
||||
|
69
kernel/src/arch/x86_64/signal.rs
Normal file
69
kernel/src/arch/x86_64/signal.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rdi: usize,
|
||||
pub rsi: usize,
|
||||
pub rbp: usize,
|
||||
pub rbx: usize,
|
||||
pub rdx: usize,
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rsp: usize,
|
||||
pub rip: usize,
|
||||
pub eflags: usize,
|
||||
pub cs: u16,
|
||||
pub gs: u16,
|
||||
pub fs: u16,
|
||||
pub _pad: u16,
|
||||
pub err: usize,
|
||||
pub trapno: usize,
|
||||
pub oldmask: usize,
|
||||
pub cr2: usize,
|
||||
pub fpstate: usize,
|
||||
pub _reserved1: [usize; 8],
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn from_tf(tf: &TrapFrame) -> Self {
|
||||
MachineContext {
|
||||
r8: tf.r8,
|
||||
r9: tf.r9,
|
||||
r10: tf.r10,
|
||||
r11: tf.r11,
|
||||
r12: tf.r12,
|
||||
r13: tf.r13,
|
||||
r14: tf.r14,
|
||||
r15: tf.r15,
|
||||
rdi: tf.rdi,
|
||||
rsi: tf.rsi,
|
||||
rbp: tf.rbp,
|
||||
rbx: tf.rbx,
|
||||
rdx: tf.rdx,
|
||||
rax: tf.rax,
|
||||
rcx: tf.rcx,
|
||||
rsp: tf.rsp,
|
||||
rip: tf.rip,
|
||||
eflags: 0,
|
||||
cs: tf.cs as u16,
|
||||
gs: 0,
|
||||
fs: 0,
|
||||
_pad: 0,
|
||||
err: 0,
|
||||
trapno: 0,
|
||||
oldmask: 0,
|
||||
cr2: 0,
|
||||
fpstate: 0,
|
||||
_reserved1: [0; 8],
|
||||
}
|
||||
}
|
||||
}
|
@ -3,12 +3,21 @@
|
||||
pub use crate::arch::consts::*;
|
||||
|
||||
pub const MAX_CPU_NUM: usize = 64;
|
||||
pub const MAX_PROCESS_NUM: usize = 128;
|
||||
pub const MAX_PROCESS_NUM: usize = 512;
|
||||
|
||||
pub const USEC_PER_TICK: usize = 10000;
|
||||
|
||||
pub const INFORM_PER_MSEC: usize = 50;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub const ARCH: &'static str = "x86_64";
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub const ARCH: &'static str = "riscv64";
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub const ARCH: &'static str = "riscv32";
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const ARCH: &'static str = "aarch64";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SMP_CORES: usize = {
|
||||
if let Some(smp_str) = option_env!("SMP") {
|
||||
|
@ -2,8 +2,12 @@
|
||||
|
||||
mod fbdev;
|
||||
mod random;
|
||||
mod shm;
|
||||
mod stdio;
|
||||
mod tty;
|
||||
|
||||
pub use fbdev::*;
|
||||
pub use random::*;
|
||||
pub use shm::*;
|
||||
pub use stdio::*;
|
||||
pub use tty::*;
|
||||
|
56
kernel/src/fs/devfs/shm.rs
Normal file
56
kernel/src/fs/devfs/shm.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use core::any::Any;
|
||||
use rcore_fs::vfs::*;
|
||||
|
||||
pub use super::{STDIN, STDOUT};
|
||||
use rcore_fs::vfs::FsError::NotSupported;
|
||||
|
||||
// try to create directory under /dev
|
||||
// do not have enough time to come up with a better way.
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ShmINode;
|
||||
|
||||
impl INode for ShmINode {
|
||||
/// Read bytes at `offset` into `buf`, return the number of bytes read.
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
Err(NotSupported)
|
||||
}
|
||||
|
||||
/// Write bytes at `offset` from `buf`, return the number of bytes written.
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
Err(NotSupported)
|
||||
}
|
||||
|
||||
/// Poll the events, return a bitmap of events.
|
||||
fn poll(&self) -> Result<PollStatus> {
|
||||
Ok(PollStatus {
|
||||
read: false,
|
||||
write: false,
|
||||
error: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get metadata of the INode
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 1,
|
||||
inode: 2,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::Dir,
|
||||
mode: 0o666,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
rdev: make_rdev(0, 40),
|
||||
})
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
@ -5,20 +5,52 @@ use core::any::Any;
|
||||
|
||||
use rcore_fs::vfs::*;
|
||||
|
||||
use super::tty::TTY;
|
||||
use crate::fs::devfs::foreground_pgid;
|
||||
use crate::fs::ioctl::*;
|
||||
use crate::process::process_group;
|
||||
use crate::processor;
|
||||
use crate::signal::{send_signal, Siginfo, Signal, SI_KERNEL};
|
||||
use crate::sync::Condvar;
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
use spin::RwLock;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Stdin {
|
||||
buf: Mutex<VecDeque<char>>,
|
||||
pub pushed: Condvar,
|
||||
winsize: RwLock<Winsize>,
|
||||
termios: RwLock<Termois>,
|
||||
}
|
||||
|
||||
impl Stdin {
|
||||
pub fn push(&self, c: char) {
|
||||
self.buf.lock().push_back(c);
|
||||
self.pushed.notify_one();
|
||||
let lflag = LocalModes::from_bits_truncate(self.termios.read().lflag);
|
||||
if lflag.contains(LocalModes::ISIG) && [0o3, 0o34, 0o32, 0o31].contains(&(c as i32)) {
|
||||
use Signal::*;
|
||||
let foregroud_processes = process_group(foreground_pgid());
|
||||
match c as i32 {
|
||||
// INTR
|
||||
0o3 => {
|
||||
for proc in foregroud_processes {
|
||||
send_signal(
|
||||
proc,
|
||||
-1,
|
||||
Siginfo {
|
||||
signo: SIGINT as i32,
|
||||
errno: 0,
|
||||
code: SI_KERNEL,
|
||||
field: Default::default(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => warn!("special char {} is unimplented", c),
|
||||
}
|
||||
} else {
|
||||
self.buf.lock().push_back(c);
|
||||
self.pushed.notify_one();
|
||||
}
|
||||
}
|
||||
pub fn pop(&self) -> char {
|
||||
#[cfg(feature = "board_k210")]
|
||||
@ -46,7 +78,9 @@ impl Stdin {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Stdout;
|
||||
pub struct Stdout {
|
||||
winsize: RwLock<Winsize>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref STDIN: Arc<Stdin> = Arc::new(Stdin::default());
|
||||
@ -74,16 +108,45 @@ impl INode for Stdin {
|
||||
}
|
||||
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
|
||||
match cmd as usize {
|
||||
TCGETS | TIOCGWINSZ | TIOCSPGRP => {
|
||||
// pretend to be tty
|
||||
TIOCGWINSZ => {
|
||||
let winsize = data as *mut Winsize;
|
||||
unsafe {
|
||||
*winsize = *self.winsize.read();
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
TCGETS => {
|
||||
let termois = data as *mut Termois;
|
||||
unsafe {
|
||||
*termois = *self.termios.read();
|
||||
}
|
||||
let lflag = LocalModes::from_bits_truncate(self.termios.read().lflag);
|
||||
info!("get lfags: {:?}", lflag);
|
||||
Ok(0)
|
||||
}
|
||||
TCSETS => {
|
||||
let termois = data as *const Termois;
|
||||
unsafe {
|
||||
*self.termios.write() = *termois;
|
||||
}
|
||||
let lflag = LocalModes::from_bits_truncate(self.termios.read().lflag);
|
||||
info!("set lfags: {:?}", lflag);
|
||||
Ok(0)
|
||||
}
|
||||
TIOCGPGRP => {
|
||||
// pretend to be have a tty process group
|
||||
// Get the process group ID of the foreground process group on
|
||||
// this terminal.
|
||||
// TODO: verify pointer
|
||||
unsafe { *(data as *mut u32) = 0 };
|
||||
Ok(0)
|
||||
}
|
||||
TIOCSPGRP => {
|
||||
let gid = unsafe { *(data as *const i32) };
|
||||
info!("set foreground process group id to {}", gid);
|
||||
Ok(0)
|
||||
// println!(pid)
|
||||
}
|
||||
_ => Err(FsError::NotSupported),
|
||||
}
|
||||
}
|
||||
@ -112,7 +175,14 @@ impl INode for Stdout {
|
||||
}
|
||||
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
|
||||
match cmd as usize {
|
||||
TCGETS | TIOCGWINSZ | TIOCSPGRP => {
|
||||
TIOCGWINSZ => {
|
||||
let winsize = data as *mut Winsize;
|
||||
unsafe {
|
||||
*winsize = *self.winsize.read();
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
TCSETS | TCGETS | TIOCSPGRP => {
|
||||
// pretend to be tty
|
||||
Ok(0)
|
||||
}
|
||||
|
90
kernel/src/fs/devfs/tty.rs
Normal file
90
kernel/src/fs/devfs/tty.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use core::any::Any;
|
||||
use rcore_fs::vfs::*;
|
||||
|
||||
pub use super::{STDIN, STDOUT};
|
||||
use crate::fs::ioctl::*;
|
||||
use crate::process::current_thread;
|
||||
use crate::processor;
|
||||
use crate::syscall::SysError;
|
||||
use alloc::sync::Arc;
|
||||
use rcore_fs::vfs::FsError::NotSupported;
|
||||
use rcore_thread::std_thread::current;
|
||||
use spin::RwLock;
|
||||
|
||||
// Ref: [https://linux.die.net/man/4/tty]
|
||||
#[derive(Default)]
|
||||
pub struct TtyINode {
|
||||
pub foreground_pgid: RwLock<i32>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TTY: Arc<TtyINode> = Arc::new(TtyINode::default());
|
||||
}
|
||||
|
||||
pub fn foreground_pgid() -> i32 {
|
||||
*TTY.foreground_pgid.read()
|
||||
}
|
||||
|
||||
impl INode for TtyINode {
|
||||
/// Read bytes at `offset` into `buf`, return the number of bytes read.
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
STDIN.read_at(offset, buf)
|
||||
}
|
||||
|
||||
/// Write bytes at `offset` from `buf`, return the number of bytes written.
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
STDOUT.write_at(offset, buf)
|
||||
}
|
||||
|
||||
/// Poll the events, return a bitmap of events.
|
||||
fn poll(&self) -> Result<PollStatus> {
|
||||
Ok(PollStatus {
|
||||
read: STDIN.can_read(),
|
||||
write: true,
|
||||
error: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
|
||||
let cmd = cmd as usize;
|
||||
match cmd {
|
||||
TIOCGPGRP => {
|
||||
// TODO: check the pointer?
|
||||
let argp = data as *mut i32; // pid_t
|
||||
unsafe { *argp = *self.foreground_pgid.read() };
|
||||
Ok(0)
|
||||
}
|
||||
TIOCSPGRP => {
|
||||
let fpgid = unsafe { *(data as *const i32) };
|
||||
*self.foreground_pgid.write() = fpgid;
|
||||
info!("tty: set foreground process group to {}", fpgid);
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(NotSupported),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metadata of the INode
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 1,
|
||||
inode: 13,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::CharDevice,
|
||||
mode: 0o666,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
rdev: make_rdev(5, 0),
|
||||
})
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
22
kernel/src/fs/fcntl.rs
Normal file
22
kernel/src/fs/fcntl.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// currently support x86_64 only
|
||||
// copy from fcntl.h
|
||||
|
||||
pub const F_DUPFD: usize = 0; /* dup */
|
||||
pub const F_GETFD: usize = 1; /* get close_on_exec */
|
||||
pub const F_SETFD: usize = 2; /* set/clear close_on_exec */
|
||||
pub const F_GETFL: usize = 3; /* get file->f_flags */
|
||||
pub const F_SETFL: usize = 4; /* set file->f_flags */
|
||||
pub const F_GETLK: usize = 5; /* Get record locking info. */
|
||||
pub const F_SETLK: usize = 6; /* Set record locking info (non-blocking). */
|
||||
pub const F_SETLKW: usize = 7; /* Set record locking info (blocking). */
|
||||
|
||||
const F_LINUX_SPECIFIC_BASE: usize = 1024;
|
||||
|
||||
pub const FD_CLOEXEC: usize = 1;
|
||||
pub const F_DUPFD_CLOEXEC: usize = F_LINUX_SPECIFIC_BASE + 6;
|
||||
|
||||
pub const O_NONBLOCK: usize = 0o4000;
|
||||
pub const O_APPEND: usize = 0o2000;
|
||||
pub const O_CLOEXEC: usize = 0o2000000; /* set close_on_exec */
|
||||
|
||||
pub const AT_SYMLINK_NOFOLLOW: usize = 0x100;
|
@ -2,23 +2,55 @@
|
||||
|
||||
use crate::memory::GlobalFrameAlloc;
|
||||
use crate::process::{current_thread, INodeForMap};
|
||||
use crate::syscall::MmapProt;
|
||||
use crate::syscall::{MmapProt, SysResult, TimeSpec};
|
||||
use crate::thread;
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use core::fmt;
|
||||
|
||||
use rcore_fs::vfs::FsError::{Interrupted, NotSupported};
|
||||
use rcore_fs::vfs::{FileType, FsError, INode, MMapArea, Metadata, PollStatus, Result};
|
||||
use rcore_memory::memory_set::handler::File;
|
||||
|
||||
use crate::fs::fcntl::{O_APPEND, O_NONBLOCK};
|
||||
use crate::signal::{do_signal, has_signal_to_do};
|
||||
use crate::sync::SpinLock as Mutex;
|
||||
use crate::syscall::SysError::{EAGAIN, ESPIPE};
|
||||
use bitflags::_core::cell::Cell;
|
||||
use rcore_thread::std_thread::current;
|
||||
use spin::RwLock;
|
||||
|
||||
enum Flock {
|
||||
None = 0,
|
||||
Shared = 1,
|
||||
Exclusive = 2,
|
||||
}
|
||||
|
||||
struct OpenFileDescription {
|
||||
offset: u64,
|
||||
options: OpenOptions,
|
||||
flock: Flock,
|
||||
}
|
||||
|
||||
impl OpenFileDescription {
|
||||
fn create(options: OpenOptions) -> Arc<RwLock<Self>> {
|
||||
Arc::new(RwLock::new(OpenFileDescription {
|
||||
offset: 0,
|
||||
options,
|
||||
flock: Flock::None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileHandle {
|
||||
inode: Arc<dyn INode>,
|
||||
offset: u64,
|
||||
options: OpenOptions,
|
||||
description: Arc<RwLock<OpenFileDescription>>,
|
||||
pub path: String,
|
||||
pub pipe: bool, // specify if this is pipe, socket, or FIFO
|
||||
pub fd_cloexec: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct OpenOptions {
|
||||
pub read: bool,
|
||||
pub write: bool,
|
||||
@ -35,26 +67,57 @@ pub enum SeekFrom {
|
||||
}
|
||||
|
||||
impl FileHandle {
|
||||
pub fn new(inode: Arc<dyn INode>, options: OpenOptions, path: String) -> Self {
|
||||
pub fn new(
|
||||
inode: Arc<dyn INode>,
|
||||
options: OpenOptions,
|
||||
path: String,
|
||||
pipe: bool,
|
||||
fd_cloexec: bool,
|
||||
) -> Self {
|
||||
return FileHandle {
|
||||
inode,
|
||||
offset: 0,
|
||||
options,
|
||||
description: OpenFileDescription::create(options),
|
||||
path,
|
||||
pipe,
|
||||
fd_cloexec,
|
||||
};
|
||||
}
|
||||
|
||||
// do almost as default clone does, but with fd_cloexec specified
|
||||
pub fn dup(&self, fd_cloexec: bool) -> Self {
|
||||
FileHandle {
|
||||
inode: self.inode.clone(),
|
||||
description: self.description.clone(),
|
||||
path: self.path.clone(),
|
||||
pipe: self.pipe,
|
||||
fd_cloexec, // this field do not share
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_options(&self, arg: usize) {
|
||||
let options = &mut self.description.write().options;
|
||||
options.nonblock = (arg & O_NONBLOCK) != 0;
|
||||
// TODO: handle append
|
||||
// options.append = (arg & O_APPEND) != 0;
|
||||
}
|
||||
|
||||
// pub fn get_options(&self) -> usize {
|
||||
// let options = self.description.read().options;
|
||||
// let mut ret = 0 as usize;
|
||||
// }
|
||||
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
let len = self.read_at(self.offset as usize, buf)?;
|
||||
self.offset += len as u64;
|
||||
let len = self.read_at(self.description.read().offset as usize, buf)?;
|
||||
self.description.write().offset += len as u64;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
if !self.options.read {
|
||||
pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
// let options = &self.description.read().options;
|
||||
if !self.description.read().options.read {
|
||||
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
||||
}
|
||||
if !self.options.nonblock {
|
||||
if !self.description.read().options.nonblock {
|
||||
// block
|
||||
loop {
|
||||
match self.inode.read_at(offset, buf) {
|
||||
@ -62,6 +125,9 @@ impl FileHandle {
|
||||
return Ok(read_len);
|
||||
}
|
||||
Err(FsError::Again) => {
|
||||
if has_signal_to_do() {
|
||||
return Err(Interrupted);
|
||||
}
|
||||
thread::yield_now();
|
||||
}
|
||||
Err(err) => {
|
||||
@ -76,34 +142,38 @@ impl FileHandle {
|
||||
}
|
||||
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
let offset = match self.options.append {
|
||||
let description = self.description.read();
|
||||
let offset = match description.options.append {
|
||||
true => self.inode.metadata()?.size as u64,
|
||||
false => self.offset,
|
||||
false => description.offset,
|
||||
} as usize;
|
||||
drop(description);
|
||||
let len = self.write_at(offset, buf)?;
|
||||
self.offset = (offset + len) as u64;
|
||||
self.description.write().offset += len as u64;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn write_at(&mut self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
if !self.options.write {
|
||||
pub fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
if !self.description.read().options.write {
|
||||
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
||||
}
|
||||
let len = self.inode.write_at(offset, buf)?;
|
||||
TimeSpec::update(&self.inode);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
|
||||
self.offset = match pos {
|
||||
let mut description = self.description.write();
|
||||
description.offset = match pos {
|
||||
SeekFrom::Start(offset) => offset,
|
||||
SeekFrom::End(offset) => (self.inode.metadata()?.size as i64 + offset) as u64,
|
||||
SeekFrom::Current(offset) => (self.offset as i64 + offset) as u64,
|
||||
SeekFrom::Current(offset) => (description.offset as i64 + offset) as u64,
|
||||
};
|
||||
Ok(self.offset)
|
||||
Ok(description.offset)
|
||||
}
|
||||
|
||||
pub fn set_len(&mut self, len: u64) -> Result<()> {
|
||||
if !self.options.write {
|
||||
if !self.description.read().options.write {
|
||||
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
||||
}
|
||||
self.inode.resize(len as usize)?;
|
||||
@ -127,14 +197,27 @@ impl FileHandle {
|
||||
}
|
||||
|
||||
pub fn read_entry(&mut self) -> Result<String> {
|
||||
if !self.options.read {
|
||||
let mut description = self.description.write();
|
||||
if !description.options.read {
|
||||
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
||||
}
|
||||
let name = self.inode.get_entry(self.offset as usize)?;
|
||||
self.offset += 1;
|
||||
let mut offset = &mut description.offset;
|
||||
let name = self.inode.get_entry(*offset as usize)?;
|
||||
*offset += 1;
|
||||
Ok(name)
|
||||
}
|
||||
|
||||
pub fn read_entry_with_metadata(&mut self) -> Result<(Metadata, String)> {
|
||||
let mut description = self.description.write();
|
||||
if !description.options.read {
|
||||
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
||||
}
|
||||
let mut offset = &mut description.offset;
|
||||
let ret = self.inode.get_entry_with_metadata(*offset as usize)?;
|
||||
*offset += 1;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn poll(&self) -> Result<PollStatus> {
|
||||
self.inode.poll()
|
||||
}
|
||||
@ -172,21 +255,15 @@ impl FileHandle {
|
||||
pub fn inode(&self) -> Arc<dyn INode> {
|
||||
self.inode.clone()
|
||||
}
|
||||
|
||||
pub fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<()> {
|
||||
if arg & 0x800 > 0 && cmd == 4 {
|
||||
self.options.nonblock = true;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let description = self.description.read();
|
||||
return f
|
||||
.debug_struct("FileHandle")
|
||||
.field("offset", &self.offset)
|
||||
.field("options", &self.options)
|
||||
.field("offset", &description.offset)
|
||||
.field("options", &description.options)
|
||||
.field("path", &self.path)
|
||||
.finish();
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use alloc::boxed::Box;
|
||||
use rcore_fs::vfs::{MMapArea, PollStatus};
|
||||
|
||||
// TODO: merge FileLike to FileHandle ?
|
||||
// TODO: fix dup and remove Clone
|
||||
#[derive(Clone)]
|
||||
pub enum FileLike {
|
||||
File(FileHandle),
|
||||
@ -18,6 +17,15 @@ pub enum FileLike {
|
||||
}
|
||||
|
||||
impl FileLike {
|
||||
pub fn dup(&self, fd_cloexec: bool) -> FileLike {
|
||||
use FileLike::*;
|
||||
match self {
|
||||
File(file) => File(file.dup(fd_cloexec)),
|
||||
Socket(s) => Socket(s.clone()),
|
||||
EpollInstance(e) => EpollInstance(e.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> SysResult {
|
||||
let len = match self {
|
||||
FileLike::File(file) => file.read(buf)?,
|
||||
@ -39,17 +47,12 @@ impl FileLike {
|
||||
Ok(len)
|
||||
}
|
||||
pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
|
||||
match request {
|
||||
// TODO: place flags & path in FileLike instead of FileHandle/Socket
|
||||
FIOCLEX => Ok(0),
|
||||
FIONBIO => Ok(0),
|
||||
_ => match self {
|
||||
FileLike::File(file) => file.io_control(request as u32, arg1).map_err(Into::into),
|
||||
FileLike::Socket(socket) => socket.ioctl(request, arg1, arg2, arg3),
|
||||
FileLike::EpollInstance(_) => {
|
||||
return Err(SysError::ENOSYS);
|
||||
}
|
||||
},
|
||||
match self {
|
||||
FileLike::File(file) => file.io_control(request as u32, arg1).map_err(Into::into),
|
||||
FileLike::Socket(socket) => socket.ioctl(request, arg1, arg2, arg3),
|
||||
FileLike::EpollInstance(_) => {
|
||||
return Err(SysError::ENOSYS);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn mmap(&mut self, area: MMapArea) -> SysResult {
|
||||
@ -72,16 +75,6 @@ impl FileLike {
|
||||
};
|
||||
Ok(status)
|
||||
}
|
||||
pub fn fcntl(&mut self, cmd: usize, arg: usize) -> SysResult {
|
||||
match self {
|
||||
FileLike::File(file) => file.fcntl(cmd, arg)?,
|
||||
FileLike::Socket(_) => {
|
||||
//TODO
|
||||
}
|
||||
FileLike::EpollInstance(_) => {}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileLike {
|
||||
|
@ -3,11 +3,18 @@
|
||||
// higher 2 bits: 01 = write, 10 = read
|
||||
#![allow(dead_code)]
|
||||
|
||||
use bitflags::*;
|
||||
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
pub const TCGETS: usize = 0x5401;
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub const TCGETS: usize = 0x540D;
|
||||
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
pub const TCSETS: usize = 0x5402;
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub const TCGETS: usize = 0x540E;
|
||||
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
pub const TIOCGPGRP: usize = 0x540F;
|
||||
// _IOR('t', 119, int)
|
||||
@ -39,3 +46,65 @@ pub const FIOCLEX: usize = 0x6601;
|
||||
// rustc using pipe and ioctl pipe file with this request id
|
||||
// for non-blocking/blocking IO control setting
|
||||
pub const FIONBIO: usize = 0x5421;
|
||||
|
||||
bitflags! {
|
||||
pub struct LocalModes : u32 {
|
||||
const ISIG = 0o000001;
|
||||
const ICANON = 0o000002;
|
||||
const ECHO = 0o000010;
|
||||
const ECHOE = 0o000020;
|
||||
const ECHOK = 0o000040;
|
||||
const ECHONL = 0o000100;
|
||||
const NOFLSH = 0o000200;
|
||||
const TOSTOP = 0o000400;
|
||||
const IEXTEN = 0o100000;
|
||||
const XCASE = 0o000004;
|
||||
const ECHOCTL = 0o001000;
|
||||
const ECHOPRT = 0o002000;
|
||||
const ECHOKE = 0o004000;
|
||||
const FLUSHO = 0o010000;
|
||||
const PENDIN = 0o040000;
|
||||
const EXTPROC = 0o200000;
|
||||
}
|
||||
}
|
||||
|
||||
// Ref: https://www.man7.org/linux/man-pages/man3/termios.3.html
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Termois {
|
||||
pub iflag: u32,
|
||||
pub oflag: u32,
|
||||
pub cflag: u32,
|
||||
pub lflag: u32,
|
||||
pub line: u8,
|
||||
pub cc: [u8; 32],
|
||||
pub ispeed: u32,
|
||||
pub ospeed: u32,
|
||||
}
|
||||
|
||||
impl Default for Termois {
|
||||
fn default() -> Self {
|
||||
Termois {
|
||||
iflag: 27906,
|
||||
oflag: 5,
|
||||
cflag: 1215,
|
||||
lflag: 35387,
|
||||
line: 0,
|
||||
cc: [
|
||||
3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 255, 18, 15, 23, 22, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
],
|
||||
ispeed: 0,
|
||||
ospeed: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Winsize {
|
||||
row: u16,
|
||||
ws_col: u16,
|
||||
xpixel: u16,
|
||||
ypixel: u16,
|
||||
}
|
||||
|
@ -7,11 +7,11 @@ use rcore_fs_devfs::{
|
||||
};
|
||||
use rcore_fs_mountfs::MountFS;
|
||||
use rcore_fs_ramfs::RamFS;
|
||||
use rcore_fs_sfs::SimpleFileSystem;
|
||||
use rcore_fs_sfs::{INodeImpl, SimpleFileSystem};
|
||||
|
||||
use self::devfs::{Fbdev, RandomINode};
|
||||
|
||||
pub use self::devfs::{STDIN, STDOUT};
|
||||
pub use self::devfs::{ShmINode, STDIN, STDOUT, TTY};
|
||||
pub use self::file::*;
|
||||
pub use self::file_like::*;
|
||||
pub use self::pipe::Pipe;
|
||||
@ -20,9 +20,10 @@ pub use self::pseudo::*;
|
||||
mod devfs;
|
||||
mod device;
|
||||
pub mod epoll;
|
||||
pub mod fcntl;
|
||||
mod file;
|
||||
mod file_like;
|
||||
mod ioctl;
|
||||
pub mod ioctl;
|
||||
mod pipe;
|
||||
mod pseudo;
|
||||
|
||||
@ -86,13 +87,20 @@ lazy_static! {
|
||||
devfs.add("zero", Arc::new(ZeroINode::default())).expect("failed to mknod /dev/zero");
|
||||
devfs.add("random", Arc::new(RandomINode::new(false))).expect("failed to mknod /dev/random");
|
||||
devfs.add("urandom", Arc::new(RandomINode::new(true))).expect("failed to mknod /dev/urandom");
|
||||
devfs.add("tty", TTY.clone()).expect("failed to mknod /dev/tty");
|
||||
devfs.add("fb0", Arc::new(Fbdev::default())).expect("failed to mknod /dev/fb0");
|
||||
devfs.add("shm", Arc::new(ShmINode::default())).expect("failed to mkdir shm");
|
||||
|
||||
// mount DevFS at /dev
|
||||
let dev = root.find(true, "dev").unwrap_or_else(|_| {
|
||||
root.create("dev", FileType::Dir, 0o666).expect("failed to mkdir /dev")
|
||||
});
|
||||
dev.mount(devfs).expect("failed to mount DevFS");
|
||||
let devfs = dev.mount(devfs).expect("failed to mount DevFS");
|
||||
|
||||
// mount RamFS at /dev/shm
|
||||
let shm = devfs.root_inode().find(true, "shm").expect("cannot find shm");
|
||||
let shmfs = RamFS::new();
|
||||
shm.mount(shmfs).expect("failed to mount /dev/shm");
|
||||
|
||||
// mount RamFS at /tmp
|
||||
let ramfs = RamFS::new();
|
||||
@ -105,7 +113,7 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
pub const FOLLOW_MAX_DEPTH: usize = 1;
|
||||
pub const FOLLOW_MAX_DEPTH: usize = 3;
|
||||
|
||||
pub trait INodeExt {
|
||||
fn read_as_vec(&self) -> Result<Vec<u8>>;
|
||||
|
@ -7,8 +7,14 @@ use rcore_fs::vfs::*;
|
||||
|
||||
use crate::sync::Condvar;
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
use crate::syscall::SysError::EAGAIN;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeSet;
|
||||
use core::cmp::min;
|
||||
use rcore_fs::vfs::FsError::Again;
|
||||
use rcore_thread::std_thread::{park, yield_now};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum PipeEnd {
|
||||
Read,
|
||||
Write,
|
||||
@ -16,7 +22,8 @@ pub enum PipeEnd {
|
||||
|
||||
pub struct PipeData {
|
||||
buf: VecDeque<u8>,
|
||||
new_data: Condvar,
|
||||
new_data: Arc<Condvar>,
|
||||
end_cnt: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -25,12 +32,21 @@ pub struct Pipe {
|
||||
direction: PipeEnd,
|
||||
}
|
||||
|
||||
impl Drop for Pipe {
|
||||
fn drop(&mut self) {
|
||||
let mut data = self.data.lock();
|
||||
data.end_cnt -= 1;
|
||||
data.new_data.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipe {
|
||||
/// Create a pair of INode: (read, write)
|
||||
pub fn create_pair() -> (Pipe, Pipe) {
|
||||
let inner = PipeData {
|
||||
buf: VecDeque::new(),
|
||||
new_data: Condvar::new(),
|
||||
new_data: Arc::new(Condvar::new()),
|
||||
end_cnt: 2,
|
||||
};
|
||||
let data = Arc::new(Mutex::new(inner));
|
||||
(
|
||||
@ -47,7 +63,9 @@ impl Pipe {
|
||||
|
||||
fn can_read(&self) -> bool {
|
||||
if let PipeEnd::Read = self.direction {
|
||||
self.data.lock().buf.len() > 0 || self.is_broken()
|
||||
// true
|
||||
let data = self.data.lock();
|
||||
data.buf.len() > 0 || data.end_cnt < 2
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -55,26 +73,29 @@ impl Pipe {
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
if let PipeEnd::Write = self.direction {
|
||||
!self.is_broken()
|
||||
self.data.lock().end_cnt == 2
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_broken(&self) -> bool {
|
||||
Arc::strong_count(&self.data) < 2
|
||||
}
|
||||
}
|
||||
|
||||
impl INode for Pipe {
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
if buf.len() == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
if let PipeEnd::Read = self.direction {
|
||||
// TODO: release on process lock? Or maybe remove the condvar
|
||||
let mut data = self.data.lock();
|
||||
if let Some(ch) = data.buf.pop_front() {
|
||||
buf[0] = ch;
|
||||
Ok(1)
|
||||
if data.buf.len() == 0 && data.end_cnt == 2 {
|
||||
Err(Again)
|
||||
} else {
|
||||
Ok(0)
|
||||
let len = min(buf.len(), data.buf.len());
|
||||
for i in 0..len {
|
||||
buf[i] = data.buf.pop_front().unwrap();
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
} else {
|
||||
Ok(0)
|
||||
@ -83,14 +104,12 @@ impl INode for Pipe {
|
||||
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
if let PipeEnd::Write = self.direction {
|
||||
if buf.len() > 0 {
|
||||
let mut data = self.data.lock();
|
||||
data.buf.push_back(buf[0]);
|
||||
data.new_data.notify_all();
|
||||
Ok(1)
|
||||
} else {
|
||||
Ok(0)
|
||||
let mut data = self.data.lock();
|
||||
for c in buf {
|
||||
data.buf.push_back(*c);
|
||||
}
|
||||
data.new_data.notify_all();
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -1,11 +1,34 @@
|
||||
use crate::sync::Semaphore;
|
||||
use crate::syscall::{SemBuf, SysResult, TimeSpec};
|
||||
use alloc::{collections::BTreeMap, sync::Arc, sync::Weak, vec::Vec};
|
||||
use core::ops::Index;
|
||||
use spin::RwLock;
|
||||
use spin::{Mutex, RwLock};
|
||||
|
||||
// structure specifies the access permissions on the semaphore set
|
||||
// key_t?
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct IpcPerm {
|
||||
pub key: usize, /* Key supplied to semget(2) */
|
||||
pub uid: u32, /* Effective UID of owner */
|
||||
pub gid: u32, /* Effective GID of owner */
|
||||
pub cuid: u32, /* Effective UID of creator */
|
||||
pub cgid: u32, /* Effective GID of creator */
|
||||
pub mode: u16, /* Permissions */
|
||||
pub __seq: u16, /* Sequence number */
|
||||
}
|
||||
|
||||
// semid data structure
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SemidDs {
|
||||
pub perm: IpcPerm, /* Ownership and permissions */
|
||||
pub otime: usize, /* Last semop time */
|
||||
pub ctime: usize, /* Last change time */
|
||||
pub nsems: usize, /* number of semaphores in set */
|
||||
}
|
||||
|
||||
/// A System V semaphore set
|
||||
pub struct SemArray {
|
||||
_key: usize,
|
||||
pub semid_ds: Mutex<SemidDs>,
|
||||
sems: Vec<Semaphore>,
|
||||
}
|
||||
|
||||
@ -21,9 +44,24 @@ lazy_static! {
|
||||
}
|
||||
|
||||
impl SemArray {
|
||||
// remove semaphores
|
||||
pub fn remove(&self) {
|
||||
for sem in self.sems.iter() {
|
||||
sem.remove();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn otime(&self) {
|
||||
self.semid_ds.lock().otime = TimeSpec::get_epoch().sec;
|
||||
}
|
||||
|
||||
pub fn ctime(&self) {
|
||||
self.semid_ds.lock().ctime = TimeSpec::get_epoch().sec;
|
||||
}
|
||||
|
||||
/// Get the semaphore array with `key`.
|
||||
/// If not exist, create a new one with `nsems` elements.
|
||||
pub fn get_or_create(key: usize, nsems: usize, _flags: usize) -> Arc<Self> {
|
||||
pub fn get_or_create(key: usize, nsems: usize, flags: usize) -> Arc<Self> {
|
||||
let mut key2sem = KEY2SEM.write();
|
||||
|
||||
// found in the map
|
||||
@ -39,7 +77,20 @@ impl SemArray {
|
||||
}
|
||||
// insert to global map
|
||||
let array = Arc::new(SemArray {
|
||||
_key: key,
|
||||
semid_ds: Mutex::new(SemidDs {
|
||||
perm: IpcPerm {
|
||||
key,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
cuid: 0,
|
||||
cgid: 0,
|
||||
mode: (flags as u16) & 0x1ff,
|
||||
__seq: 0,
|
||||
},
|
||||
otime: 0,
|
||||
ctime: TimeSpec::get_epoch().sec,
|
||||
nsems,
|
||||
}),
|
||||
sems: semaphores,
|
||||
});
|
||||
key2sem.insert(key, Arc::downgrade(&array));
|
||||
|
@ -21,7 +21,10 @@ extern crate alloc;
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate num;
|
||||
extern crate rlibc;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
pub use crate::process::{new_kernel_context, processor};
|
||||
pub use buddy_system_allocator::LockedHeapWithRescue;
|
||||
@ -42,6 +45,7 @@ pub mod memory;
|
||||
pub mod net;
|
||||
pub mod process;
|
||||
pub mod shell;
|
||||
pub mod signal;
|
||||
pub mod sync;
|
||||
pub mod syscall;
|
||||
pub mod trap;
|
||||
|
@ -1,4 +1,7 @@
|
||||
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec};
|
||||
use alloc::{
|
||||
boxed::Box, collections::BTreeMap, collections::VecDeque, string::String, sync::Arc,
|
||||
sync::Weak, vec::Vec,
|
||||
};
|
||||
use core::fmt;
|
||||
|
||||
use core::str;
|
||||
@ -18,12 +21,16 @@ use crate::ipc::SemProc;
|
||||
use crate::memory::{
|
||||
ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read,
|
||||
};
|
||||
use crate::sync::{Condvar, SpinNoIrqLock as Mutex};
|
||||
use crate::sync::{Condvar, SpinLock, SpinNoIrqLock as Mutex};
|
||||
|
||||
use super::abi::{self, ProcInitInfo};
|
||||
use crate::process::thread_manager;
|
||||
use crate::signal::{Siginfo, Signal, SignalAction, SignalStack, Sigset};
|
||||
use bitflags::_core::cell::Ref;
|
||||
use core::mem::MaybeUninit;
|
||||
use pc_keyboard::KeyCode::BackTick;
|
||||
use rcore_fs::vfs::INode;
|
||||
use rcore_thread::std_thread::yield_now;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Thread {
|
||||
@ -35,6 +42,11 @@ pub struct Thread {
|
||||
// This is same as `proc.vm`
|
||||
pub vm: Arc<Mutex<MemorySet>>,
|
||||
pub proc: Arc<Mutex<Process>>,
|
||||
pub sig_mask: Sigset,
|
||||
// set tf every time enter trap to access current trap frame everywhere when the thread is in the kernel
|
||||
// using pointer to circumvent lifetime check, probably safe(确信)
|
||||
// TODO: better implementation?
|
||||
pub tf: *mut TrapFrame,
|
||||
}
|
||||
|
||||
/// Pid type
|
||||
@ -43,13 +55,15 @@ pub struct Thread {
|
||||
pub struct Pid(usize);
|
||||
|
||||
impl Pid {
|
||||
pub const INIT: usize = 1;
|
||||
|
||||
pub fn get(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Return whether this pid represents the init process
|
||||
pub fn is_init(&self) -> bool {
|
||||
self.0 == 0
|
||||
self.0 == Self::INIT
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,13 +84,23 @@ pub struct Process {
|
||||
|
||||
// relationship
|
||||
pub pid: Pid, // i.e. tgid, usually the tid of first thread
|
||||
pub parent: Weak<Mutex<Process>>,
|
||||
pub children: Vec<Weak<Mutex<Process>>>,
|
||||
pub pgid: i32,
|
||||
// avoid deadlock, put pid out
|
||||
pub parent: (Pid, Weak<Mutex<Process>>),
|
||||
pub children: Vec<(Pid, Weak<Mutex<Process>>)>,
|
||||
pub threads: Vec<Tid>, // threads in the same process
|
||||
|
||||
// for waiting child
|
||||
pub child_exit: Arc<Condvar>, // notified when the a child process is going to terminate
|
||||
pub child_exit_code: BTreeMap<usize, usize>, // child process store its exit code here
|
||||
|
||||
// delivered signals, tid specified thread, -1 stands for any thread
|
||||
// TODO: implement with doubly linked list, but how to do it in rust safely? [doggy]
|
||||
pub sig_queue: VecDeque<(Siginfo, isize)>,
|
||||
pub pending_sigset: Sigset,
|
||||
|
||||
pub dispositions: [SignalAction; Signal::RTMAX + 1],
|
||||
pub sigaltstack: SignalStack,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
@ -85,6 +109,28 @@ lazy_static! {
|
||||
RwLock::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
/// return the process which thread tid is in
|
||||
pub fn process_of(tid: usize) -> Option<Arc<Mutex<Process>>> {
|
||||
PROCESSES
|
||||
.read()
|
||||
.iter()
|
||||
.filter_map(|(_, weak)| weak.upgrade())
|
||||
.find(|proc| proc.lock().threads.contains(&tid))
|
||||
}
|
||||
|
||||
pub fn process(pid: usize) -> Option<Arc<Mutex<Process>>> {
|
||||
PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade())
|
||||
}
|
||||
|
||||
pub fn process_group(pgid: i32) -> Vec<Arc<Mutex<Process>>> {
|
||||
PROCESSES
|
||||
.read()
|
||||
.iter()
|
||||
.filter_map(|(_, proc)| proc.upgrade())
|
||||
.filter(|proc| proc.lock().pgid == pgid)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Let `rcore_thread` can switch between our `Thread`
|
||||
impl rcore_thread::Context for Thread {
|
||||
unsafe fn switch_to(&mut self, target: &mut dyn rcore_thread::Context) {
|
||||
@ -131,13 +177,20 @@ impl Thread {
|
||||
semaphores: SemProc::default(),
|
||||
futexes: BTreeMap::default(),
|
||||
pid: Pid(0),
|
||||
parent: Weak::new(),
|
||||
pgid: -1, // kernel thread do not have a process?
|
||||
parent: (Pid(0), Weak::new()),
|
||||
children: Vec::new(),
|
||||
threads: Vec::new(),
|
||||
child_exit: Arc::new(Condvar::new()),
|
||||
child_exit_code: BTreeMap::new(),
|
||||
sig_queue: VecDeque::new(),
|
||||
pending_sigset: Sigset::empty(),
|
||||
dispositions: [SignalAction::default(); Signal::RTMAX + 1],
|
||||
sigaltstack: SignalStack::default(),
|
||||
}
|
||||
.add_to_table(),
|
||||
sig_mask: Sigset::empty(),
|
||||
tf: 0 as _,
|
||||
})
|
||||
}
|
||||
|
||||
@ -222,7 +275,7 @@ impl Thread {
|
||||
vm.push(
|
||||
ustack_buttom,
|
||||
ustack_top - PAGE_SIZE * 4,
|
||||
MemoryAttr::default().user(),
|
||||
MemoryAttr::default().user().execute(),
|
||||
Delay::new(GlobalFrameAlloc),
|
||||
"user_stack_delay",
|
||||
);
|
||||
@ -230,7 +283,7 @@ impl Thread {
|
||||
vm.push(
|
||||
ustack_top - PAGE_SIZE * 4,
|
||||
ustack_top,
|
||||
MemoryAttr::default().user(),
|
||||
MemoryAttr::default().user().execute(), // feature
|
||||
ByFrame::new(GlobalFrameAlloc),
|
||||
"user_stack",
|
||||
);
|
||||
@ -271,6 +324,8 @@ impl Thread {
|
||||
nonblock: false,
|
||||
},
|
||||
String::from("stdin"),
|
||||
false,
|
||||
false,
|
||||
)),
|
||||
);
|
||||
files.insert(
|
||||
@ -284,6 +339,8 @@ impl Thread {
|
||||
nonblock: false,
|
||||
},
|
||||
String::from("stdout"),
|
||||
false,
|
||||
false,
|
||||
)),
|
||||
);
|
||||
files.insert(
|
||||
@ -297,6 +354,8 @@ impl Thread {
|
||||
nonblock: false,
|
||||
},
|
||||
String::from("stderr"),
|
||||
false,
|
||||
false,
|
||||
)),
|
||||
);
|
||||
|
||||
@ -315,13 +374,20 @@ impl Thread {
|
||||
futexes: BTreeMap::default(),
|
||||
semaphores: SemProc::default(),
|
||||
pid: Pid(0),
|
||||
parent: Weak::new(),
|
||||
pgid: 0,
|
||||
parent: (Pid(0), Weak::new()),
|
||||
children: Vec::new(),
|
||||
threads: Vec::new(),
|
||||
child_exit: Arc::new(Condvar::new()),
|
||||
child_exit_code: BTreeMap::new(),
|
||||
pending_sigset: Sigset::empty(),
|
||||
sig_queue: VecDeque::new(),
|
||||
dispositions: [SignalAction::default(); Signal::RTMAX + 1],
|
||||
sigaltstack: SignalStack::default(),
|
||||
}
|
||||
.add_to_table(),
|
||||
sig_mask: Sigset::default(),
|
||||
tf: 0 as _,
|
||||
})
|
||||
}
|
||||
|
||||
@ -334,30 +400,43 @@ impl Thread {
|
||||
let context = unsafe { Context::new_fork(tf, kstack.top(), vm_token) };
|
||||
|
||||
let mut proc = self.proc.lock();
|
||||
|
||||
let new_proc = Process {
|
||||
vm: vm.clone(),
|
||||
files: proc.files.clone(),
|
||||
files: proc.files.clone(), // share open file descriptions
|
||||
cwd: proc.cwd.clone(),
|
||||
exec_path: proc.exec_path.clone(),
|
||||
futexes: BTreeMap::default(),
|
||||
semaphores: proc.semaphores.clone(),
|
||||
pid: Pid(0),
|
||||
parent: Arc::downgrade(&self.proc),
|
||||
pgid: proc.pgid,
|
||||
parent: (proc.pid.clone(), Arc::downgrade(&self.proc)),
|
||||
children: Vec::new(),
|
||||
threads: Vec::new(),
|
||||
child_exit: Arc::new(Condvar::new()),
|
||||
child_exit_code: BTreeMap::new(),
|
||||
pending_sigset: Sigset::empty(),
|
||||
sig_queue: VecDeque::new(),
|
||||
dispositions: proc.dispositions.clone(),
|
||||
sigaltstack: Default::default(),
|
||||
}
|
||||
.add_to_table();
|
||||
// link to parent
|
||||
proc.children.push(Arc::downgrade(&new_proc));
|
||||
proc.children
|
||||
.push((new_proc.lock().pid.clone(), Arc::downgrade(&new_proc)));
|
||||
|
||||
// this part in linux manpage seems ambiguous:
|
||||
// Each of the threads in a process has its own signal mask.
|
||||
// A child created via fork(2) inherits a copy of its parent's signal
|
||||
// mask; the signal mask is preserved across execve(2).
|
||||
Box::new(Thread {
|
||||
context,
|
||||
kstack,
|
||||
clear_child_tid: 0,
|
||||
vm,
|
||||
proc: new_proc,
|
||||
sig_mask: self.sig_mask,
|
||||
tf: 0 as _,
|
||||
})
|
||||
}
|
||||
|
||||
@ -377,6 +456,8 @@ impl Thread {
|
||||
clear_child_tid,
|
||||
vm: self.vm.clone(),
|
||||
proc: self.proc.clone(),
|
||||
sig_mask: self.sig_mask,
|
||||
tf: 0 as _,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -386,8 +467,10 @@ impl Process {
|
||||
fn add_to_table(mut self) -> Arc<Mutex<Self>> {
|
||||
let mut process_table = PROCESSES.write();
|
||||
|
||||
// assign pid
|
||||
let pid = (0..).find(|i| process_table.get(i).is_none()).unwrap();
|
||||
// assign pid, do not start from 0
|
||||
let pid = (Pid::INIT..)
|
||||
.find(|i| process_table.get(i).is_none())
|
||||
.unwrap();
|
||||
self.pid = Pid(pid);
|
||||
|
||||
// put to process table
|
||||
@ -399,6 +482,11 @@ impl Process {
|
||||
fn get_free_fd(&self) -> usize {
|
||||
(0..).find(|i| !self.files.contains_key(i)).unwrap()
|
||||
}
|
||||
|
||||
// get the lowest available fd great than or equal to arg
|
||||
pub fn get_free_fd_from(&self, arg: usize) -> usize {
|
||||
(arg..).find(|i| !self.files.contains_key(i)).unwrap()
|
||||
}
|
||||
/// Add a file to the process, return its fd.
|
||||
pub fn add_file(&mut self, file_like: FileLike) -> usize {
|
||||
let fd = self.get_free_fd();
|
||||
@ -415,16 +503,34 @@ impl Process {
|
||||
/// Exit the process.
|
||||
/// Kill all threads and notify parent with the exit code.
|
||||
pub fn exit(&mut self, exit_code: usize) {
|
||||
// quit all threads
|
||||
for tid in self.threads.iter() {
|
||||
thread_manager().exit(*tid, 1);
|
||||
// avoid some strange dead lock
|
||||
// self.files.clear(); this does not work sometime, for unknown reason
|
||||
// manually drop
|
||||
let fds = self.files.iter().map(|(fd, _)| *fd).collect::<Vec<_>>();
|
||||
for fd in fds.iter() {
|
||||
let file = self.files.remove(fd).unwrap();
|
||||
drop(file);
|
||||
}
|
||||
|
||||
// notify parent and fill exit code
|
||||
if let Some(parent) = self.parent.upgrade() {
|
||||
let mut parent = parent.lock();
|
||||
if let Some(parent) = self.parent.1.upgrade() {
|
||||
let mut parent = parent.busy_lock();
|
||||
parent.child_exit_code.insert(self.pid.get(), exit_code);
|
||||
parent.child_exit.notify_one();
|
||||
}
|
||||
|
||||
// quit all threads
|
||||
// this must be after setting the value of subprocess, or the threads will be treated exit before actually exits
|
||||
for tid in self.threads.iter() {
|
||||
thread_manager().exit(*tid, 1);
|
||||
}
|
||||
self.threads.clear();
|
||||
|
||||
info!("process {} exist with {}", self.pid.get(), exit_code);
|
||||
}
|
||||
|
||||
pub fn exited(&self) -> bool {
|
||||
self.threads.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
|
108
kernel/src/signal/action.rs
Normal file
108
kernel/src/signal/action.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use crate::signal::Signal;
|
||||
use bitflags::_core::fmt::Debug;
|
||||
use bitflags::*;
|
||||
use core::fmt::Formatter;
|
||||
|
||||
pub const SIG_ERR: usize = usize::max_value() - 1;
|
||||
pub const SIG_DFL: usize = 0;
|
||||
pub const SIG_IGN: usize = 1;
|
||||
|
||||
pub const SI_ASYNCNL: i32 = -60;
|
||||
pub const SI_TKILL: i32 = -6;
|
||||
pub const SI_SIGIO: i32 = -5;
|
||||
pub const SI_ASYNCIO: i32 = -4;
|
||||
pub const SI_MESGQ: i32 = -3;
|
||||
pub const SI_TIMER: i32 = -2;
|
||||
pub const SI_QUEUE: i32 = -1;
|
||||
pub const SI_USER: i32 = 0;
|
||||
pub const SI_KERNEL: i32 = 128;
|
||||
|
||||
// yet there's a bug because of mismatching bits: https://sourceware.org/bugzilla/show_bug.cgi?id=25657
|
||||
// just support 64bits size sigset
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Sigset(u64);
|
||||
|
||||
impl Sigset {
|
||||
pub fn empty() -> Self {
|
||||
Sigset(0)
|
||||
}
|
||||
|
||||
pub fn contains(&self, sig: Signal) -> bool {
|
||||
(self.0 >> sig as u64 & 1) != 0
|
||||
}
|
||||
|
||||
pub fn add(&mut self, sig: Signal) {
|
||||
self.0 |= 1 << sig as u64;
|
||||
}
|
||||
pub fn add_set(&mut self, sigset: &Sigset) {
|
||||
self.0 |= sigset.0;
|
||||
}
|
||||
pub fn remove(&mut self, sig: Signal) {
|
||||
self.0 ^= self.0 & (1 << sig as u64);
|
||||
}
|
||||
pub fn remove_set(&mut self, sigset: &Sigset) {
|
||||
self.0 ^= self.0 & sigset.0;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct SignalAction {
|
||||
pub handler: usize, // this field may be an union
|
||||
pub flags: usize,
|
||||
pub restorer: usize,
|
||||
pub mask: Sigset,
|
||||
}
|
||||
|
||||
impl Debug for SignalAction {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), core::fmt::Error> {
|
||||
f.debug_struct("signal action")
|
||||
.field("handler", &format!("{:#x}", self.handler))
|
||||
.field("mask", &self.mask)
|
||||
.field("flags", &SignalActionFlags::from_bits_truncate(self.flags))
|
||||
.field("restorer", &format!("{:#x}", self.restorer))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union SiginfoFields {
|
||||
pad: [u8; Self::PAD_SIZE],
|
||||
// TODO: fill this union
|
||||
}
|
||||
|
||||
impl SiginfoFields {
|
||||
const PAD_SIZE: usize = 128 - 2 * core::mem::size_of::<i32>() - core::mem::size_of::<usize>();
|
||||
}
|
||||
|
||||
impl Default for SiginfoFields {
|
||||
fn default() -> Self {
|
||||
SiginfoFields {
|
||||
pad: [0; Self::PAD_SIZE],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Siginfo {
|
||||
pub signo: i32,
|
||||
pub errno: i32,
|
||||
pub code: i32,
|
||||
pub field: SiginfoFields,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SignalActionFlags : usize {
|
||||
const NOCLDSTOP = 1;
|
||||
const NOCLDWAIT = 2;
|
||||
const SIGINFO = 4;
|
||||
const ONSTACK = 0x08000000;
|
||||
const RESTART = 0x10000000;
|
||||
const NODEFER = 0x40000000;
|
||||
const RESETHAND = 0x80000000;
|
||||
const RESTORER = 0x04000000;
|
||||
}
|
||||
}
|
301
kernel/src/signal/mod.rs
Normal file
301
kernel/src/signal/mod.rs
Normal file
@ -0,0 +1,301 @@
|
||||
use crate::process::{current_thread, process, process_of, thread_manager, Process};
|
||||
use crate::sync::{MutexGuard, SpinNoIrq, SpinNoIrqLock as Mutex};
|
||||
use alloc::sync::Arc;
|
||||
use bitflags::*;
|
||||
use num::FromPrimitive;
|
||||
|
||||
mod action;
|
||||
|
||||
pub use self::action::*;
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
use crate::arch::signal::MachineContext;
|
||||
use crate::arch::syscall::SYS_RT_SIGRETURN;
|
||||
use rcore_thread::std_thread::{current, yield_now};
|
||||
|
||||
#[derive(Eq, PartialEq, FromPrimitive, Debug, Copy, Clone)]
|
||||
pub enum Signal {
|
||||
SIGHUP = 1,
|
||||
SIGINT = 2,
|
||||
SIGQUIT = 3,
|
||||
SIGILL = 4,
|
||||
SIGTRAP = 5,
|
||||
SIGABRT = 6,
|
||||
SIGBUS = 7,
|
||||
SIGFPE = 8,
|
||||
SIGKILL = 9,
|
||||
SIGUSR1 = 10,
|
||||
SIGSEGV = 11,
|
||||
SIGUSR2 = 12,
|
||||
SIGPIPE = 13,
|
||||
SIGALRM = 14,
|
||||
SIGTERM = 15,
|
||||
SIGSTKFLT = 16,
|
||||
SIGCHLD = 17,
|
||||
SIGCONT = 18,
|
||||
SIGSTOP = 19,
|
||||
SIGTSTP = 20,
|
||||
SIGTTIN = 21,
|
||||
SIGTTOU = 22,
|
||||
SIGURG = 23,
|
||||
SIGXCPU = 24,
|
||||
SIGXFSZ = 25,
|
||||
SIGVTALRM = 26,
|
||||
SIGPROF = 27,
|
||||
SIGWINCH = 28,
|
||||
SIGIO = 29,
|
||||
SIGPWR = 30,
|
||||
SIGSYS = 31,
|
||||
// real time signals
|
||||
SIGRT32 = 32,
|
||||
SIGRT33 = 33,
|
||||
SIGRT34 = 34,
|
||||
SIGRT35 = 35,
|
||||
SIGRT36 = 36,
|
||||
SIGRT37 = 37,
|
||||
SIGRT38 = 38,
|
||||
SIGRT39 = 39,
|
||||
SIGRT40 = 40,
|
||||
SIGRT41 = 41,
|
||||
SIGRT42 = 42,
|
||||
SIGRT43 = 43,
|
||||
SIGRT44 = 44,
|
||||
SIGRT45 = 45,
|
||||
SIGRT46 = 46,
|
||||
SIGRT47 = 47,
|
||||
SIGRT48 = 48,
|
||||
SIGRT49 = 49,
|
||||
SIGRT50 = 50,
|
||||
SIGRT51 = 51,
|
||||
SIGRT52 = 52,
|
||||
SIGRT53 = 53,
|
||||
SIGRT54 = 54,
|
||||
SIGRT55 = 55,
|
||||
SIGRT56 = 56,
|
||||
SIGRT57 = 57,
|
||||
SIGRT58 = 58,
|
||||
SIGRT59 = 59,
|
||||
SIGRT60 = 60,
|
||||
SIGRT61 = 61,
|
||||
SIGRT62 = 62,
|
||||
SIGRT63 = 63,
|
||||
SIGRT64 = 64,
|
||||
}
|
||||
|
||||
impl Signal {
|
||||
pub const RTMIN: usize = 32;
|
||||
pub const RTMAX: usize = 64;
|
||||
|
||||
pub fn is_standard(self) -> bool {
|
||||
(self as usize) < Self::RTMIN
|
||||
}
|
||||
}
|
||||
|
||||
// process and tid must be checked
|
||||
pub fn send_signal(process: Arc<Mutex<Process>>, tid: isize, info: Siginfo) {
|
||||
let signal: Signal = <Signal as FromPrimitive>::from_i32(info.signo).unwrap();
|
||||
let mut process = process.lock();
|
||||
if signal.is_standard() && process.pending_sigset.contains(signal) {
|
||||
return;
|
||||
}
|
||||
process.sig_queue.push_back((info, tid));
|
||||
process.pending_sigset.add(signal);
|
||||
if tid == -1 {
|
||||
info!("send {:?} to process {}", signal, process.pid.get());
|
||||
for &tid in process.threads.iter() {
|
||||
// TODO: check mask here
|
||||
thread_manager().wakeup(tid);
|
||||
}
|
||||
} else {
|
||||
info!("send {:?} to thread {}", signal, tid);
|
||||
// TODO: check mask here
|
||||
thread_manager().wakeup(tid as usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct UserContext {
|
||||
pub flags: usize,
|
||||
pub link: usize,
|
||||
pub stack: SignalStack,
|
||||
pub mcontext: MachineContext,
|
||||
pub sig_mask: Sigset,
|
||||
pub _fpregs_mem: [usize; 64],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct SignalFrame {
|
||||
pub ret_code_addr: usize, // point to ret_code
|
||||
pub tf: TrapFrame,
|
||||
pub info: Siginfo,
|
||||
pub ucontext: UserContext, // adapt interface, a little bit waste
|
||||
pub ret_code: [u8; 7], // call sys_sigreturn
|
||||
}
|
||||
|
||||
pub fn has_signal_to_do() -> bool {
|
||||
let thread = unsafe { current_thread() };
|
||||
unsafe {
|
||||
current_thread()
|
||||
.proc
|
||||
.lock()
|
||||
.sig_queue
|
||||
.iter()
|
||||
.find(|(info, tid)| {
|
||||
let tid = *tid;
|
||||
(tid == -1 || tid as usize == current().id())
|
||||
&& !thread
|
||||
.sig_mask
|
||||
.contains(FromPrimitive::from_i32(info.signo).unwrap())
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_signal(tf: &mut TrapFrame) {
|
||||
let thread = unsafe { current_thread() };
|
||||
let mut process = unsafe { current_thread().proc.lock() };
|
||||
while let Some((idx, info)) =
|
||||
process
|
||||
.sig_queue
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(idx, &(info, tid))| {
|
||||
if (tid == -1 || tid as usize == current().id())
|
||||
&& !thread
|
||||
.sig_mask
|
||||
.contains(FromPrimitive::from_i32(info.signo).unwrap())
|
||||
{
|
||||
Some((idx, info))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
{
|
||||
use crate::signal::SignalActionFlags;
|
||||
use Signal::*;
|
||||
|
||||
let signal: Signal = <Signal as FromPrimitive>::from_i32(info.signo).unwrap();
|
||||
info!("received signal: {:?}", signal);
|
||||
|
||||
process.sig_queue.remove(idx);
|
||||
process.pending_sigset.remove(signal);
|
||||
|
||||
let action = process.dispositions[info.signo as usize];
|
||||
let action_flags = SignalActionFlags::from_bits_truncate(action.flags);
|
||||
|
||||
// enter signal handler
|
||||
match action.handler {
|
||||
// TODO: complete default actions
|
||||
x if x == SIG_DFL => {
|
||||
match signal {
|
||||
SIGALRM | SIGHUP | SIGINT => {
|
||||
info!("default action: Term");
|
||||
// FIXME: exit code ref please?
|
||||
process.exit(info.signo as usize + 128);
|
||||
yield_now();
|
||||
unreachable!()
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
x if x == SIG_IGN => {
|
||||
// TODO: handle SIGCHLD
|
||||
info!("ignore");
|
||||
}
|
||||
x if x == SIG_ERR => {
|
||||
// TODO
|
||||
unimplemented!();
|
||||
}
|
||||
_ => {
|
||||
info!("goto handler at {:#x}", action.handler);
|
||||
process.sigaltstack.flags |= SignalStackFlags::ONSTACK.bits();
|
||||
let stack = process.sigaltstack;
|
||||
let sig_sp = {
|
||||
if action_flags.contains(SignalActionFlags::ONSTACK) {
|
||||
let stack_flags = SignalStackFlags::from_bits_truncate(stack.flags);
|
||||
if stack_flags.contains(SignalStackFlags::DISABLE) {
|
||||
tf.get_sp()
|
||||
} else {
|
||||
stack.sp + stack.size
|
||||
}
|
||||
} else {
|
||||
tf.get_sp()
|
||||
}
|
||||
} - core::mem::size_of::<SignalFrame>();
|
||||
let frame = if let Ok(frame) = unsafe {
|
||||
process
|
||||
.vm
|
||||
.lock()
|
||||
.check_write_ptr(sig_sp as *mut SignalFrame)
|
||||
} {
|
||||
frame
|
||||
} else {
|
||||
unimplemented!()
|
||||
};
|
||||
frame.tf = tf.clone();
|
||||
frame.info = info;
|
||||
frame.ucontext = UserContext {
|
||||
flags: 0,
|
||||
link: 0,
|
||||
stack,
|
||||
mcontext: MachineContext::from_tf(tf),
|
||||
sig_mask: thread.sig_mask,
|
||||
_fpregs_mem: [0; 64],
|
||||
};
|
||||
if action_flags.contains(SignalActionFlags::RESTORER) {
|
||||
frame.ret_code_addr = action.restorer; // legacy
|
||||
} else {
|
||||
frame.ret_code_addr = frame.ret_code.as_ptr() as usize;
|
||||
// mov SYS_RT_SIGRETURN, %eax
|
||||
frame.ret_code[0] = 0xb8;
|
||||
// TODO: ref plz
|
||||
unsafe {
|
||||
*(frame.ret_code.as_ptr().add(1) as *mut u32) = SYS_RT_SIGRETURN as u32;
|
||||
}
|
||||
// syscall
|
||||
frame.ret_code[5] = 0x0f;
|
||||
frame.ret_code[6] = 0x05;
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
tf.rsp = sig_sp;
|
||||
tf.rip = action.handler;
|
||||
|
||||
// pass handler argument
|
||||
tf.rdi = info.signo as usize;
|
||||
tf.rsi = &frame.info as *const Siginfo as usize;
|
||||
// TODO: complete context
|
||||
tf.rdx = &frame.ucontext as *const UserContext as usize;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SignalStackFlags : u32 {
|
||||
const ONSTACK = 1;
|
||||
const DISABLE = 2;
|
||||
const AUTODISARM = 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SignalStack {
|
||||
pub sp: usize,
|
||||
pub flags: u32,
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
impl Default for SignalStack {
|
||||
fn default() -> Self {
|
||||
SignalStack {
|
||||
sp: 0,
|
||||
flags: SignalStackFlags::DISABLE.bits,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
use super::*;
|
||||
use crate::consts::{INFORM_PER_MSEC, USEC_PER_TICK};
|
||||
use crate::process::thread_manager;
|
||||
use crate::process::Process;
|
||||
use crate::thread;
|
||||
use crate::syscall::TimeSpec;
|
||||
use crate::{processor, thread};
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use rcore_thread::std_thread::Thread;
|
||||
use rcore_thread::std_thread::{sleep, Thread};
|
||||
|
||||
pub struct RegisteredProcess {
|
||||
proc: Arc<SpinNoIrqLock<Process>>,
|
||||
@ -25,6 +27,10 @@ impl Condvar {
|
||||
Condvar::default()
|
||||
}
|
||||
|
||||
pub fn wait_queue_len(&self) -> usize {
|
||||
self.wait_queue.lock().len()
|
||||
}
|
||||
|
||||
/// Park current thread and wait for this condvar to be notified.
|
||||
#[deprecated(note = "this may leads to lost wakeup problem. please use `wait` instead.")]
|
||||
pub fn _wait(&self) {
|
||||
@ -69,11 +75,14 @@ impl Condvar {
|
||||
if let Some(res) = condition() {
|
||||
let _ = FlagsGuard::no_irq_region();
|
||||
thread_manager().cancel_sleeping(tid);
|
||||
for condvar in condvars {
|
||||
let mut lock = condvar.wait_queue.lock();
|
||||
lock.retain(|t| !Arc::ptr_eq(t, &token));
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
for condvar in condvars {
|
||||
let mut queue = condvar.wait_queue.lock();
|
||||
if queue.iter().find(|&t| Arc::ptr_eq(t, &token)).is_none() {
|
||||
queue.push_front(token.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
thread::yield_now();
|
||||
}
|
||||
@ -93,39 +102,77 @@ impl Condvar {
|
||||
drop(lock);
|
||||
drop(guard);
|
||||
});
|
||||
let ret = mutex.lock();
|
||||
// let mut lock = self.wait_queue.lock();
|
||||
// lock.retain(|t| !Arc::ptr_eq(&t, &token));
|
||||
mutex.lock()
|
||||
}
|
||||
|
||||
/// Park current thread and wait for this condvar to be notified or timeout.
|
||||
pub fn wait_timeout<'a, T, S>(
|
||||
&self,
|
||||
guard: MutexGuard<'a, T, S>,
|
||||
timeout: TimeSpec,
|
||||
) -> Option<MutexGuard<'a, T, S>>
|
||||
where
|
||||
S: MutexSupport,
|
||||
{
|
||||
let mutex = guard.mutex;
|
||||
let token = Arc::new(thread::current());
|
||||
let mut lock = self.wait_queue.lock();
|
||||
lock.retain(|t| !Arc::ptr_eq(&t, &token));
|
||||
ret
|
||||
lock.push_back(token.clone());
|
||||
drop(lock);
|
||||
drop(guard);
|
||||
|
||||
let timeout = core::time::Duration::new(timeout.sec as u64, timeout.nsec as u32);
|
||||
let begin = crate::trap::uptime_msec();
|
||||
if timeout.as_millis() != 0 {
|
||||
sleep(timeout);
|
||||
}
|
||||
// let mut lock = self.wait_queue.lock();
|
||||
// lock.retain(|t| !Arc::ptr_eq(&t, &token));
|
||||
let end = crate::trap::uptime_msec();
|
||||
if end - begin >= timeout.as_millis() as usize {
|
||||
None
|
||||
} else {
|
||||
Some(mutex.lock())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notify_one(&self) {
|
||||
if let Some(t) = self.wait_queue.lock().front() {
|
||||
let mut queue = self.wait_queue.lock();
|
||||
if let Some(t) = queue.front() {
|
||||
self.epoll_callback(t);
|
||||
// info!("nofity thread: {}", t.id());
|
||||
t.unpark();
|
||||
queue.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notify_all(&self) {
|
||||
let queue = self.wait_queue.lock();
|
||||
let mut queue = self.wait_queue.lock();
|
||||
for t in queue.iter() {
|
||||
self.epoll_callback(t);
|
||||
t.unpark();
|
||||
}
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
/// Notify up to `n` waiters.
|
||||
/// Return the number of waiters that were woken up.
|
||||
pub fn notify_n(&self, n: usize) -> usize {
|
||||
let mut count = 0;
|
||||
let queue = self.wait_queue.lock();
|
||||
let mut queue = self.wait_queue.lock();
|
||||
for t in queue.iter() {
|
||||
if count >= n {
|
||||
break;
|
||||
}
|
||||
self.epoll_callback(t);
|
||||
t.unpark();
|
||||
count += 1;
|
||||
}
|
||||
|
||||
for _ in 0..count {
|
||||
queue.pop_front();
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ use core::fmt;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use rcore_thread::std_thread::yield_now;
|
||||
|
||||
pub type SpinLock<T> = Mutex<T, Spin>;
|
||||
pub type SpinNoIrqLock<T> = Mutex<T, SpinNoIrq>;
|
||||
@ -145,6 +146,16 @@ impl<T: ?Sized, S: MutexSupport> Mutex<T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// lock using busy waiting
|
||||
pub fn busy_lock(&self) -> MutexGuard<T, S> {
|
||||
loop {
|
||||
if let Some(x) = self.try_lock() {
|
||||
break x;
|
||||
}
|
||||
yield_now();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_support(&self) {
|
||||
let initialization = self.support_initialization.load(Ordering::Relaxed);
|
||||
if initialization == 2 {
|
||||
|
@ -4,13 +4,23 @@
|
||||
|
||||
use super::Condvar;
|
||||
use super::SpinNoIrqLock as Mutex;
|
||||
use crate::syscall::SysError;
|
||||
use core::cell::Cell;
|
||||
use core::ops::Deref;
|
||||
|
||||
/// A counting, blocking, semaphore.
|
||||
pub struct Semaphore {
|
||||
lock: Mutex<isize>,
|
||||
// value and removed
|
||||
lock: Mutex<SemaphoreInner>,
|
||||
cvar: Condvar,
|
||||
}
|
||||
|
||||
struct SemaphoreInner {
|
||||
count: isize,
|
||||
pid: usize,
|
||||
removed: bool,
|
||||
}
|
||||
|
||||
/// An RAII guard which will release a resource acquired from a semaphore when
|
||||
/// dropped.
|
||||
pub struct SemaphoreGuard<'a> {
|
||||
@ -25,22 +35,36 @@ impl Semaphore {
|
||||
/// available. It is valid to initialize a semaphore with a negative count.
|
||||
pub fn new(count: isize) -> Semaphore {
|
||||
Semaphore {
|
||||
lock: Mutex::new(count),
|
||||
lock: Mutex::new(SemaphoreInner {
|
||||
count,
|
||||
removed: false,
|
||||
pid: 0,
|
||||
}),
|
||||
cvar: Condvar::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&self) {
|
||||
self.lock.lock().removed = false;
|
||||
self.cvar.notify_all();
|
||||
}
|
||||
|
||||
/// Acquires a resource of this semaphore, blocking the current thread until
|
||||
/// it can do so.
|
||||
///
|
||||
/// This method will block until the internal count of the semaphore is at
|
||||
/// least 1.
|
||||
pub fn acquire(&self) {
|
||||
let mut count = self.lock.lock();
|
||||
while *count <= 0 {
|
||||
count = self.cvar.wait(count);
|
||||
pub fn acquire(&self) -> Result<(), SysError> {
|
||||
let mut inner = self.lock.lock();
|
||||
while !inner.removed && inner.count <= 0 {
|
||||
inner = self.cvar.wait(inner);
|
||||
}
|
||||
if inner.removed {
|
||||
Err(SysError::EIDRM)
|
||||
} else {
|
||||
inner.count -= 1;
|
||||
Ok(())
|
||||
}
|
||||
*count -= 1;
|
||||
}
|
||||
|
||||
/// Release a resource from this semaphore.
|
||||
@ -48,7 +72,7 @@ impl Semaphore {
|
||||
/// This will increment the number of resources in this semaphore by 1 and
|
||||
/// will notify any pending waiters in `acquire` or `access` if necessary.
|
||||
pub fn release(&self) {
|
||||
*self.lock.lock() += 1;
|
||||
self.lock.lock().count += 1;
|
||||
self.cvar.notify_one();
|
||||
}
|
||||
|
||||
@ -57,41 +81,49 @@ impl Semaphore {
|
||||
///
|
||||
/// This function is semantically equivalent to an `acquire` followed by a
|
||||
/// `release` when the guard returned is dropped.
|
||||
pub fn access(&self) -> SemaphoreGuard {
|
||||
self.acquire();
|
||||
SemaphoreGuard { sem: self }
|
||||
pub fn access(&self) -> Result<SemaphoreGuard, SysError> {
|
||||
self.acquire()?;
|
||||
Ok(SemaphoreGuard { sem: self })
|
||||
}
|
||||
|
||||
/// Get the current count
|
||||
pub fn get(&self) -> isize {
|
||||
let count = self.lock.lock();
|
||||
*count
|
||||
self.lock.lock().count
|
||||
}
|
||||
pub fn get_ncnt(&self) -> usize {
|
||||
self.cvar.wait_queue_len()
|
||||
}
|
||||
|
||||
pub fn get_pid(&self) -> usize {
|
||||
self.lock.lock().pid
|
||||
}
|
||||
pub fn set_pid(&self, pid: usize) {
|
||||
self.lock.lock().pid = pid;
|
||||
}
|
||||
|
||||
/// Set the current count
|
||||
pub fn set(&self, value: isize) {
|
||||
let mut count = self.lock.lock();
|
||||
*count = value;
|
||||
self.lock.lock().count = value;
|
||||
}
|
||||
|
||||
/// Modify by k atomically. when wait is false avoid waiting. unused
|
||||
pub fn modify(&self, k: isize, wait: bool) -> Result<usize, ()> {
|
||||
if k > 0 {
|
||||
*(self.lock.lock()) += k;
|
||||
self.lock.lock().count += k;
|
||||
self.cvar.notify_one();
|
||||
} else if k <= 0 {
|
||||
let mut count = self.lock.lock();
|
||||
let mut inner = self.lock.lock();
|
||||
let mut temp_k = k;
|
||||
while *count + temp_k < 0 {
|
||||
while inner.count + temp_k < 0 {
|
||||
if wait == false {
|
||||
return Err(());
|
||||
}
|
||||
temp_k += *count;
|
||||
*count = 0;
|
||||
count = self.cvar.wait(count);
|
||||
temp_k += inner.count;
|
||||
inner.count = 0;
|
||||
inner = self.cvar.wait(inner);
|
||||
}
|
||||
*count += temp_k;
|
||||
if *count > 0 {
|
||||
inner.count += temp_k;
|
||||
if inner.count > 0 {
|
||||
self.cvar.notify_one();
|
||||
}
|
||||
}
|
||||
@ -104,3 +136,11 @@ impl<'a> Drop for SemaphoreGuard<'a> {
|
||||
self.sem.release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for SemaphoreGuard<'a> {
|
||||
type Target = Semaphore;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
return self.sem;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,13 @@ use bitvec::prelude::{BitSlice, BitVec, Lsb0};
|
||||
|
||||
use super::*;
|
||||
use crate::fs::epoll::EpollInstance;
|
||||
use crate::fs::fcntl::{FD_CLOEXEC, F_SETFD, O_CLOEXEC, O_NONBLOCK};
|
||||
use crate::fs::FileLike;
|
||||
use crate::process::Process;
|
||||
use crate::signal::has_signal_to_do;
|
||||
use crate::syscall::SysError::{EINTR, EINVAL, ESPIPE};
|
||||
use rcore_fs::vfs::PollStatus;
|
||||
use rcore_thread::std_thread::current;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_read(&mut self, fd: usize, base: *mut u8, len: usize) -> SysResult {
|
||||
@ -29,7 +34,8 @@ impl Syscall<'_> {
|
||||
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
||||
}
|
||||
let slice = unsafe { self.vm().check_write_array(base, len)? };
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
|
||||
let file_like = unsafe { (*UnsafeCell::new(proc).get()).get_file_like(fd)? };
|
||||
let len = file_like.read(slice)?;
|
||||
Ok(len)
|
||||
}
|
||||
@ -37,7 +43,7 @@ impl Syscall<'_> {
|
||||
pub fn sys_write(&mut self, fd: usize, base: *const u8, len: usize) -> SysResult {
|
||||
let mut proc = self.process();
|
||||
if !proc.pid.is_init() {
|
||||
// we trust pid 0 process
|
||||
//we trust pid 0 process
|
||||
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
||||
}
|
||||
let slice = unsafe { self.vm().check_read_array(base, len)? };
|
||||
@ -83,6 +89,12 @@ impl Syscall<'_> {
|
||||
timeout: *const TimeSpec,
|
||||
) -> SysResult {
|
||||
let proc = self.process();
|
||||
if !proc.pid.is_init() {
|
||||
info!(
|
||||
"ppoll: ufds: {:#x}, nfds: {}, timeout: {:#x}",
|
||||
ufds as usize, nfds, timeout as usize
|
||||
);
|
||||
}
|
||||
let timeout_msecs = if timeout.is_null() {
|
||||
1 << 31 // infinity
|
||||
} else {
|
||||
@ -109,10 +121,18 @@ impl Syscall<'_> {
|
||||
|
||||
let polls = unsafe { self.vm().check_write_array(ufds, nfds)? };
|
||||
|
||||
if !proc.pid.is_init() {
|
||||
info!("poll: fds: {:?}", polls);
|
||||
}
|
||||
|
||||
drop(proc);
|
||||
|
||||
let begin_time_ms = crate::trap::uptime_msec();
|
||||
Condvar::wait_events(condvars.as_slice(), move || {
|
||||
if has_signal_to_do() {
|
||||
return Some(Err(EINTR));
|
||||
}
|
||||
|
||||
use PollEvents as PE;
|
||||
let proc = self.process();
|
||||
let mut events = 0;
|
||||
@ -511,6 +531,11 @@ impl Syscall<'_> {
|
||||
"writev: fd: {}, iov: {:?}, count: {}",
|
||||
fd, iov_ptr, iov_count
|
||||
);
|
||||
} else {
|
||||
// info!(
|
||||
// "writev: fd: {}, iov: {:?}, count: {}",
|
||||
// fd, iov_ptr, iov_count
|
||||
// );
|
||||
}
|
||||
let iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &self.vm(), false)? };
|
||||
|
||||
@ -548,10 +573,18 @@ impl Syscall<'_> {
|
||||
if flags.contains(OpenFlags::EXCLUSIVE) {
|
||||
return Err(SysError::EEXIST);
|
||||
}
|
||||
if flags.contains(OpenFlags::TRUNCATE) {
|
||||
if let Err(e) = file_inode.resize(0) {
|
||||
// TODO: do something? what about device file?
|
||||
}
|
||||
}
|
||||
file_inode
|
||||
}
|
||||
Err(FsError::EntryNotFound) => {
|
||||
dir_inode.create(file_name, FileType::File, mode as u32)?
|
||||
let inode = dir_inode.create(file_name, FileType::File, mode as u32)?;
|
||||
TimeSpec::update(&inode);
|
||||
TimeSpec::update(&dir_inode);
|
||||
inode
|
||||
}
|
||||
Err(e) => return Err(SysError::from(e)),
|
||||
}
|
||||
@ -559,7 +592,13 @@ impl Syscall<'_> {
|
||||
proc.lookup_inode_at(dir_fd, &path, true)?
|
||||
};
|
||||
|
||||
let file = FileHandle::new(inode, flags.to_options(), String::from(path));
|
||||
let file = FileHandle::new(
|
||||
inode,
|
||||
flags.to_options(),
|
||||
String::from(path),
|
||||
false,
|
||||
flags.contains(OpenFlags::CLOEXEC),
|
||||
);
|
||||
|
||||
// for debugging
|
||||
if cfg!(debug_assertions) {
|
||||
@ -633,7 +672,8 @@ impl Syscall<'_> {
|
||||
let mut proc = self.process();
|
||||
let stat_ref = unsafe { self.vm().check_write_ptr(stat_ptr)? };
|
||||
let file = proc.get_file(fd)?;
|
||||
let stat = Stat::from(file.metadata()?);
|
||||
let metadata = file.metadata()?;
|
||||
let stat = Stat::from(metadata);
|
||||
*stat_ref = stat;
|
||||
Ok(0)
|
||||
}
|
||||
@ -705,8 +745,12 @@ impl Syscall<'_> {
|
||||
|
||||
let mut proc = self.process();
|
||||
let file = proc.get_file(fd)?;
|
||||
let offset = file.seek(pos)?;
|
||||
Ok(offset as usize)
|
||||
if file.pipe {
|
||||
Err(ESPIPE)
|
||||
} else {
|
||||
let offset = file.seek(pos)?;
|
||||
Ok(offset as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_fsync(&mut self, fd: usize) -> SysResult {
|
||||
@ -715,6 +759,23 @@ impl Syscall<'_> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_flock(&mut self, fd: usize, operation: usize) -> SysResult {
|
||||
bitflags! {
|
||||
struct Operation: u8 {
|
||||
const LOCK_SH = 1;
|
||||
const LOCK_EX = 2;
|
||||
const LOCK_NB = 4;
|
||||
const LOCK_UN = 8;
|
||||
}
|
||||
}
|
||||
let operation = Operation::from_bits(operation as u8).unwrap();
|
||||
info!("flock: fd: {}, operation: {:?}", fd, operation);
|
||||
let mut proc = self.process();
|
||||
// let file_like = proc.get_file_like(fd)?;
|
||||
let file = proc.get_file(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_fdatasync(&mut self, fd: usize) -> SysResult {
|
||||
info!("fdatasync: fd: {}", fd);
|
||||
self.process().get_file(fd)?.sync_data()?;
|
||||
@ -754,13 +815,17 @@ impl Syscall<'_> {
|
||||
}
|
||||
let mut writer = DirentBufWriter::new(buf);
|
||||
loop {
|
||||
let name = match file.read_entry() {
|
||||
let (info, name) = match file.read_entry_with_metadata() {
|
||||
Err(FsError::EntryNotFound) => break,
|
||||
r => r,
|
||||
}?;
|
||||
// TODO: get ino from dirent
|
||||
let ok = writer.try_write(0, DirentType::from_type(&info.type_).bits(), &name);
|
||||
let ok = writer.try_write(
|
||||
info.inode as u64,
|
||||
DirentType::from_type(&info.type_).bits(),
|
||||
&name,
|
||||
);
|
||||
if !ok {
|
||||
file.seek(SeekFrom::Current(-1))?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -769,15 +834,24 @@ impl Syscall<'_> {
|
||||
|
||||
pub fn sys_dup2(&mut self, fd1: usize, fd2: usize) -> SysResult {
|
||||
info!("dup2: from {} to {}", fd1, fd2);
|
||||
self.dup_impl(fd1, fd2, 0)
|
||||
}
|
||||
|
||||
fn dup_impl(&mut self, fd1: usize, fd2: usize, flags: usize) -> SysResult {
|
||||
let mut proc = self.process();
|
||||
// close fd2 first if it is opened
|
||||
proc.files.remove(&fd2);
|
||||
|
||||
let file_like = proc.get_file_like(fd1)?.clone();
|
||||
let mut file_like = proc.get_file_like(fd1)?.dup(flags != 0);
|
||||
proc.files.insert(fd2, file_like);
|
||||
Ok(fd2)
|
||||
}
|
||||
|
||||
pub fn sys_dup3(&mut self, fd1: usize, fd2: usize, flags: usize) -> SysResult {
|
||||
info!("dup3: from {} to {} with flags = {:#x}", fd1, fd2, flags);
|
||||
self.dup_impl(fd1, fd2, flags)
|
||||
}
|
||||
|
||||
pub fn sys_ioctl(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
@ -790,9 +864,25 @@ impl Syscall<'_> {
|
||||
"ioctl: fd: {}, request: {:#x}, args: {:#x} {:#x} {:#x}",
|
||||
fd, request, arg1, arg2, arg3
|
||||
);
|
||||
let mut proc = self.process();
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
file_like.ioctl(request, arg1, arg2, arg3)
|
||||
use crate::fs::ioctl::*;
|
||||
match request {
|
||||
FIOCLEX => self.sys_fcntl(fd, F_SETFD, FD_CLOEXEC),
|
||||
FIONCLEX => self.sys_fcntl(fd, F_SETFD, 0),
|
||||
FIONBIO => {
|
||||
let data = arg1 as *const i32;
|
||||
let val = unsafe { *data };
|
||||
if val == 0 {
|
||||
self.sys_fcntl(fd, F_SETFD, 0)
|
||||
} else {
|
||||
self.sys_fcntl(fd, F_SETFD, O_NONBLOCK)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mut proc = self.process();
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
file_like.ioctl(request, arg1, arg2, arg3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_chdir(&mut self, path: *const u8) -> SysResult {
|
||||
@ -879,11 +969,13 @@ impl Syscall<'_> {
|
||||
);
|
||||
|
||||
let (dir_path, file_name) = split_path(&path);
|
||||
let inode = proc.lookup_inode_at(dirfd, dir_path, true)?;
|
||||
if inode.find(file_name).is_ok() {
|
||||
let dir_inode = proc.lookup_inode_at(dirfd, dir_path, true)?;
|
||||
if dir_inode.find(file_name).is_ok() {
|
||||
return Err(SysError::EEXIST);
|
||||
}
|
||||
inode.create(file_name, FileType::Dir, mode as u32)?;
|
||||
let inode = dir_inode.create(file_name, FileType::Dir, mode as u32)?;
|
||||
TimeSpec::update(&inode);
|
||||
TimeSpec::update(&dir_inode);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -934,6 +1026,42 @@ impl Syscall<'_> {
|
||||
self.sys_unlinkat(AT_FDCWD, path, 0)
|
||||
}
|
||||
|
||||
pub fn sys_symlink(&mut self, target: *const u8, linkpath: *const u8) -> SysResult {
|
||||
self.sys_symlinkat(target, AT_FDCWD, linkpath)
|
||||
}
|
||||
|
||||
pub fn sys_symlinkat(
|
||||
&mut self,
|
||||
target: *const u8,
|
||||
newdirfd: usize,
|
||||
linkpath: *const u8,
|
||||
) -> SysResult {
|
||||
let proc = self.process();
|
||||
let target = check_and_clone_cstr(target)?;
|
||||
let linkpath = check_and_clone_cstr(linkpath)?;
|
||||
info!(
|
||||
"symlinkat: target: {} , newdirfd: {}, linkpath: {}",
|
||||
target, newdirfd as isize, linkpath,
|
||||
);
|
||||
let (dir_path, filename) = split_path(&linkpath);
|
||||
let dir_inode = proc.lookup_inode_at(newdirfd, dir_path, true)?;
|
||||
|
||||
// If linkpath exists, it will not be overwritten.
|
||||
match dir_inode.find(filename) {
|
||||
Ok(_) => Err(SysError::EEXIST),
|
||||
Err(e) => match e {
|
||||
FsError::EntryNotFound => {
|
||||
let symlink = dir_inode.create(filename, FileType::SymLink, 0o777)?;
|
||||
symlink.write_at(0, target.as_bytes())?;
|
||||
TimeSpec::update(&symlink);
|
||||
TimeSpec::update(&dir_inode);
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(e.into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_unlinkat(&mut self, dirfd: usize, path: *const u8, flags: usize) -> SysResult {
|
||||
let proc = self.process();
|
||||
let path = check_and_clone_cstr(path)?;
|
||||
@ -954,7 +1082,11 @@ impl Syscall<'_> {
|
||||
}
|
||||
|
||||
pub fn sys_pipe(&mut self, fds: *mut u32) -> SysResult {
|
||||
info!("pipe: fds: {:?}", fds);
|
||||
self.sys_pipe2(fds, 0)
|
||||
}
|
||||
|
||||
pub fn sys_pipe2(&mut self, fds: *mut u32, flags: usize) -> SysResult {
|
||||
info!("pipe2: fds: {:?}, flags: {:#x}", fds, flags);
|
||||
|
||||
let mut proc = self.process();
|
||||
let fds = unsafe { self.vm().check_write_array(fds, 2)? };
|
||||
@ -966,9 +1098,11 @@ impl Syscall<'_> {
|
||||
read: true,
|
||||
write: false,
|
||||
append: false,
|
||||
nonblock: false,
|
||||
nonblock: (flags & O_NONBLOCK) != 0,
|
||||
},
|
||||
String::from("pipe_r:[]"),
|
||||
true,
|
||||
(flags & O_CLOEXEC) != 0,
|
||||
)));
|
||||
|
||||
let write_fd = proc.add_file(FileLike::File(FileHandle::new(
|
||||
@ -980,6 +1114,8 @@ impl Syscall<'_> {
|
||||
nonblock: false,
|
||||
},
|
||||
String::from("pipe_w:[]"),
|
||||
true,
|
||||
(flags & O_CLOEXEC) != 0,
|
||||
)));
|
||||
|
||||
fds[0] = read_fd as u32;
|
||||
@ -990,6 +1126,67 @@ impl Syscall<'_> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_utimensat(
|
||||
&mut self,
|
||||
dirfd: usize,
|
||||
pathname: *const u8,
|
||||
times: *const TimeSpec,
|
||||
flags: usize,
|
||||
) -> SysResult {
|
||||
info!(
|
||||
"utimensat(raw): dirfd: {}, pathname: {}, times: {}, flags: {:#x}",
|
||||
dirfd as i64, pathname as usize, times as usize, flags
|
||||
);
|
||||
const UTIME_NOW: usize = 0x3fffffff;
|
||||
const UTIME_OMIT: usize = 0x3ffffffe;
|
||||
let mut proc = self.process();
|
||||
let mut times = if times.is_null() {
|
||||
let epoch = TimeSpec::get_epoch();
|
||||
[epoch, epoch]
|
||||
} else {
|
||||
let times = unsafe { self.vm().check_read_array(times, 2)? };
|
||||
[times[0], times[1]]
|
||||
};
|
||||
let mut inode = if pathname.is_null() {
|
||||
let fd = dirfd;
|
||||
info!("futimens: fd: {}, times: {:?}", fd, times);
|
||||
proc.get_file(fd)?.inode()
|
||||
} else {
|
||||
let pathname = check_and_clone_cstr(pathname)?;
|
||||
info!(
|
||||
"utimensat: dirfd: {}, pathname: {}, times: {:?}, flags: {:#x}",
|
||||
dirfd as i64, pathname, times, flags
|
||||
);
|
||||
let follow = match flags {
|
||||
0 => true,
|
||||
fcntl::AT_SYMLINK_NOFOLLOW => false,
|
||||
_ => return Err(EINVAL),
|
||||
};
|
||||
proc.lookup_inode_at(dirfd, &pathname, follow)?
|
||||
};
|
||||
let mut metadata = inode.metadata()?;
|
||||
if times[0].nsec != UTIME_OMIT {
|
||||
if times[0].nsec == UTIME_NOW {
|
||||
times[0] = TimeSpec::get_epoch();
|
||||
}
|
||||
metadata.atime = Timespec {
|
||||
sec: times[0].sec as i64,
|
||||
nsec: times[0].nsec as i32,
|
||||
};
|
||||
}
|
||||
if times[1].nsec != UTIME_OMIT {
|
||||
if times[1].nsec == UTIME_NOW {
|
||||
times[1] = TimeSpec::get_epoch();
|
||||
}
|
||||
metadata.mtime = Timespec {
|
||||
sec: times[1].sec as i64,
|
||||
nsec: times[1].nsec as i32,
|
||||
};
|
||||
}
|
||||
inode.set_metadata(&metadata)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_sync(&mut self) -> SysResult {
|
||||
ROOT_INODE.fs().sync()?;
|
||||
Ok(0)
|
||||
@ -1023,6 +1220,7 @@ impl Syscall<'_> {
|
||||
let proc_cell = UnsafeCell::new(proc);
|
||||
let in_file = unsafe { (*proc_cell.get()).get_file(in_fd)? };
|
||||
let out_file = unsafe { (*proc_cell.get()).get_file(out_fd)? };
|
||||
drop(proc_cell);
|
||||
let mut buffer = [0u8; 1024];
|
||||
|
||||
// for in_offset and out_offset
|
||||
@ -1095,23 +1293,38 @@ impl Syscall<'_> {
|
||||
}
|
||||
|
||||
pub fn sys_fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> SysResult {
|
||||
info!("fcntl: fd: {}, cmd: {:x}, arg: {}", fd, cmd, arg);
|
||||
info!("fcntl: fd: {}, cmd: {:#x}, arg: {}", fd, cmd, arg);
|
||||
let mut proc = self.process();
|
||||
const F_DUPFD_CLOEXEC: usize = 1030;
|
||||
if cmd == F_DUPFD_CLOEXEC {
|
||||
// dupfd with close on exec
|
||||
// TODO: close on exec
|
||||
let file_like = proc.get_file_like(fd)?.clone();
|
||||
for new_fd in arg.. {
|
||||
if proc.files.get(&new_fd).is_none() {
|
||||
proc.files.insert(new_fd, file_like);
|
||||
return Ok(new_fd);
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
match file_like {
|
||||
FileLike::File(file) => {
|
||||
use crate::fs::fcntl::*;
|
||||
match cmd {
|
||||
F_SETFD => {
|
||||
file.fd_cloexec = (arg & 1) != 0;
|
||||
Ok(0)
|
||||
}
|
||||
F_GETFD => Ok(file.fd_cloexec as usize),
|
||||
F_SETFL => {
|
||||
file.set_options(arg);
|
||||
Ok(0)
|
||||
}
|
||||
F_GETFL => self.unimplemented("F_GETFL", Ok(0)),
|
||||
F_DUPFD_CLOEXEC => {
|
||||
info!("fcntl: dupfd_cloexec: arg: {:#x}", arg);
|
||||
// let file_like = proc.get_file_like(fd1)?.clone();
|
||||
let new_fd = proc.get_free_fd_from(arg);
|
||||
core::mem::drop(proc);
|
||||
self.dup_impl(fd, new_fd, 1)
|
||||
}
|
||||
_ => Ok(0),
|
||||
}
|
||||
}
|
||||
panic!("no available fd found")
|
||||
} else {
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
file_like.fcntl(cmd, arg)
|
||||
FileLike::Socket(_) => {
|
||||
Ok(0)
|
||||
//TODO
|
||||
}
|
||||
FileLike::EpollInstance(_) => Ok(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1221,6 +1434,7 @@ impl From<FsError> for SysError {
|
||||
FsError::Again => SysError::EAGAIN,
|
||||
FsError::SymLoop => SysError::ELOOP,
|
||||
FsError::Busy => SysError::EBUSY,
|
||||
FsError::Interrupted => SysError::EINTR,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1248,6 +1462,8 @@ bitflags! {
|
||||
const TRUNCATE = 1 << 9;
|
||||
/// append on each write
|
||||
const APPEND = 1 << 10;
|
||||
/// close on exec
|
||||
const CLOEXEC = 1 << 19;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1274,7 +1490,7 @@ impl OpenFlags {
|
||||
pub struct LinuxDirent64 {
|
||||
/// Inode number
|
||||
ino: u64,
|
||||
/// Offset to next structure
|
||||
/// Offset to next structure, an opaque value
|
||||
offset: u64,
|
||||
/// Size of this dirent
|
||||
reclen: u16,
|
||||
@ -1390,11 +1606,11 @@ pub struct Stat {
|
||||
blocks: u64,
|
||||
|
||||
/// last access time
|
||||
atime: Timespec,
|
||||
atime: TimeSpec,
|
||||
/// last modification time
|
||||
mtime: Timespec,
|
||||
mtime: TimeSpec,
|
||||
/// last status change time
|
||||
ctime: Timespec,
|
||||
ctime: TimeSpec,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
@ -1567,9 +1783,18 @@ impl From<Metadata> for Stat {
|
||||
size: info.size as u64,
|
||||
blksize: info.blk_size as u64,
|
||||
blocks: info.blocks as u64,
|
||||
atime: info.atime,
|
||||
mtime: info.mtime,
|
||||
ctime: info.ctime,
|
||||
atime: TimeSpec {
|
||||
sec: info.atime.sec as usize,
|
||||
nsec: info.atime.nsec as usize,
|
||||
},
|
||||
mtime: TimeSpec {
|
||||
sec: info.mtime.sec as usize,
|
||||
nsec: info.mtime.nsec as usize,
|
||||
},
|
||||
ctime: TimeSpec {
|
||||
sec: info.ctime.sec as usize,
|
||||
nsec: info.ctime.nsec as usize,
|
||||
},
|
||||
_pad0: 0,
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ impl Syscall<'_> {
|
||||
let ops = unsafe { self.vm().check_read_array(ops, num_ops)? };
|
||||
|
||||
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
|
||||
sem_array.otime();
|
||||
for &SemBuf { num, op, flags } in ops.iter() {
|
||||
let flags = SemFlags::from_bits_truncate(flags);
|
||||
if flags.contains(SemFlags::IPC_NOWAIT) {
|
||||
@ -37,9 +38,10 @@ impl Syscall<'_> {
|
||||
|
||||
let _result = match op {
|
||||
1 => sem.release(),
|
||||
-1 => sem.acquire(),
|
||||
-1 => sem.acquire()?,
|
||||
_ => unimplemented!("Semaphore: semop.(Not 1/-1)"),
|
||||
};
|
||||
sem.set_pid(self.process().pid.get());
|
||||
if flags.contains(SemFlags::SEM_UNDO) {
|
||||
self.process().semaphores.add_undo(id, num, op);
|
||||
}
|
||||
@ -50,18 +52,49 @@ impl Syscall<'_> {
|
||||
pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: isize) -> SysResult {
|
||||
info!("semctl: id: {}, num: {}, cmd: {}", id, num, cmd);
|
||||
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
|
||||
let sem = &sem_array[num as usize];
|
||||
|
||||
const IPC_RMID: usize = 0;
|
||||
const IPC_SET: usize = 1;
|
||||
const IPC_STAT: usize = 2;
|
||||
const GETPID: usize = 11;
|
||||
const GETVAL: usize = 12;
|
||||
const GETALL: usize = 13;
|
||||
const GETNCNT: usize = 14;
|
||||
const GETZCNT: usize = 15;
|
||||
const SETVAL: usize = 16;
|
||||
const SETALL: usize = 17;
|
||||
|
||||
match cmd {
|
||||
SETVAL => sem.set(arg),
|
||||
_ => unimplemented!("Semaphore: Semctl.(Not setval)"),
|
||||
IPC_RMID => {
|
||||
sem_array.remove();
|
||||
Ok(0)
|
||||
}
|
||||
IPC_SET => {
|
||||
// TODO: update IpcPerm
|
||||
sem_array.ctime();
|
||||
Ok(0)
|
||||
}
|
||||
IPC_STAT => {
|
||||
*unsafe { self.vm().check_write_ptr(arg as *mut SemidDs)? } =
|
||||
*sem_array.semid_ds.lock();
|
||||
Ok(0)
|
||||
}
|
||||
_ => {
|
||||
let sem = &sem_array[num as usize];
|
||||
match cmd {
|
||||
GETPID => Ok(sem.get_pid()),
|
||||
GETVAL => Ok(sem.get() as usize),
|
||||
GETNCNT => Ok(sem.get_ncnt()),
|
||||
GETZCNT => Ok(0),
|
||||
SETVAL => {
|
||||
sem.set(arg);
|
||||
sem.set_pid(self.process().pid.get());
|
||||
sem_array.ctime();
|
||||
Ok(0)
|
||||
}
|
||||
_ => unimplemented!("Semaphore Semctl cmd: {}", cmd),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl Syscall<'_> {
|
||||
let flags = MmapFlags::from_bits_truncate(flags);
|
||||
info!(
|
||||
"mmap: addr={:#x}, size={:#x}, prot={:?}, flags={:?}, fd={}, offset={:#x}",
|
||||
addr, len, prot, flags, fd, offset
|
||||
addr, len, prot, flags, fd as isize, offset
|
||||
);
|
||||
|
||||
let mut proc = self.process();
|
||||
@ -46,7 +46,7 @@ impl Syscall<'_> {
|
||||
self.vm().push(
|
||||
addr,
|
||||
addr + len,
|
||||
prot.to_attr(),
|
||||
prot.to_attr().execute(),
|
||||
Delay::new(GlobalFrameAlloc),
|
||||
"mmap_anon",
|
||||
);
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
use super::*;
|
||||
use crate::arch::cpu;
|
||||
use crate::consts::USER_STACK_SIZE;
|
||||
use crate::consts::{ARCH, USER_STACK_SIZE};
|
||||
use crate::syscall::SysError::ETIMEDOUT;
|
||||
use crate::trap::TICK_ACTIVITY;
|
||||
use core::mem::size_of;
|
||||
use core::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
@ -24,7 +26,7 @@ impl Syscall<'_> {
|
||||
info!("uname: buf: {:?}", buf);
|
||||
|
||||
let offset = 65;
|
||||
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
|
||||
let strings = ["Linux", "orz", "0.1.0", "1", ARCH, "domain"];
|
||||
let buf = unsafe { self.vm().check_write_array(buf, strings.len() * offset)? };
|
||||
|
||||
for i in 0..strings.len() {
|
||||
@ -45,6 +47,9 @@ impl Syscall<'_> {
|
||||
// we only have 4 cpu at most.
|
||||
// so just set it.
|
||||
mask[0] = 0b1111;
|
||||
mask[1] = 0;
|
||||
mask[2] = 0;
|
||||
mask[3] = 0;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -88,18 +93,21 @@ impl Syscall<'_> {
|
||||
|
||||
match op & 0xf {
|
||||
OP_WAIT => {
|
||||
let _timeout = if timeout.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { *self.vm().check_read_ptr(timeout)? })
|
||||
};
|
||||
|
||||
if atomic.load(Ordering::Acquire) != val {
|
||||
return Err(SysError::EAGAIN);
|
||||
}
|
||||
// FIXME: support timeout
|
||||
queue.wait(proc);
|
||||
Ok(0)
|
||||
if timeout.is_null() {
|
||||
queue.wait(proc);
|
||||
Ok(0)
|
||||
} else {
|
||||
let timeout = unsafe { *self.vm().check_read_ptr(timeout)? };
|
||||
info!("futex wait timeout: {:?}", timeout);
|
||||
if queue.wait_timeout(proc, timeout).is_some() {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ETIMEDOUT)
|
||||
}
|
||||
}
|
||||
}
|
||||
OP_WAKE => {
|
||||
let woken_up_count = queue.notify_n(val as usize);
|
||||
@ -185,7 +193,8 @@ impl Syscall<'_> {
|
||||
let mut i = 0;
|
||||
for elm in slice {
|
||||
unsafe {
|
||||
*elm = i + crate::trap::TICK as u8;
|
||||
// to prevent overflow
|
||||
*elm = (i + crate::trap::TICK as u8 as u16) as u8;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ pub use self::mem::*;
|
||||
pub use self::misc::*;
|
||||
pub use self::net::*;
|
||||
pub use self::proc::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use self::signal::*;
|
||||
pub use self::time::*;
|
||||
|
||||
mod custom;
|
||||
@ -35,10 +37,14 @@ mod mem;
|
||||
mod misc;
|
||||
mod net;
|
||||
mod proc;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod signal;
|
||||
mod time;
|
||||
|
||||
use crate::signal::{Signal, SignalAction, SignalFrame, SignalStack, Sigset};
|
||||
#[cfg(feature = "profile")]
|
||||
use alloc::collections::BTreeMap;
|
||||
use rcore_thread::std_thread::yield_now;
|
||||
#[cfg(feature = "profile")]
|
||||
use spin::Mutex;
|
||||
|
||||
@ -51,7 +57,8 @@ lazy_static! {
|
||||
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
||||
let thread = unsafe { current_thread() };
|
||||
let mut syscall = Syscall { thread, tf };
|
||||
syscall.syscall(id, args)
|
||||
let ret = syscall.syscall(id, args);
|
||||
ret
|
||||
}
|
||||
|
||||
/// All context needed for syscall
|
||||
@ -62,8 +69,9 @@ struct Syscall<'a> {
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Get current process
|
||||
/// spinlock is tend to deadlock, use busy waiting
|
||||
pub fn process(&self) -> MutexGuard<'_, Process, SpinNoIrq> {
|
||||
self.thread.proc.lock()
|
||||
self.thread.proc.busy_lock()
|
||||
}
|
||||
|
||||
/// Get current virtual memory
|
||||
@ -108,12 +116,12 @@ impl Syscall<'_> {
|
||||
SYS_SENDFILE => self.sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
|
||||
SYS_FCNTL => {
|
||||
info!(
|
||||
"SYS_FCNTL : {} {} {} {}",
|
||||
"SYS_FCNTL : {} {:#x} {} {}",
|
||||
args[0], args[1], args[2], args[3]
|
||||
);
|
||||
self.sys_fcntl(args[0], args[1], args[2])
|
||||
}
|
||||
SYS_FLOCK => self.unimplemented("flock", Ok(0)),
|
||||
SYS_FLOCK => self.sys_flock(args[0], args[1]),
|
||||
SYS_FSYNC => self.sys_fsync(args[0]),
|
||||
SYS_FDATASYNC => self.sys_fdatasync(args[0]),
|
||||
SYS_TRUNCATE => self.sys_truncate(args[0] as *const u8, args[1]),
|
||||
@ -133,7 +141,9 @@ impl Syscall<'_> {
|
||||
args[4],
|
||||
),
|
||||
SYS_UNLINKAT => self.sys_unlinkat(args[0], args[1] as *const u8, args[2]),
|
||||
SYS_SYMLINKAT => self.unimplemented("symlinkat", Err(SysError::EACCES)),
|
||||
SYS_SYMLINKAT => {
|
||||
self.sys_symlinkat(args[0] as *const u8, args[1] as usize, args[2] as *const u8)
|
||||
}
|
||||
SYS_READLINKAT => {
|
||||
self.sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
|
||||
}
|
||||
@ -142,9 +152,16 @@ impl Syscall<'_> {
|
||||
SYS_FCHOWN => self.unimplemented("fchown", Ok(0)),
|
||||
SYS_FCHOWNAT => self.unimplemented("fchownat", Ok(0)),
|
||||
SYS_FACCESSAT => self.sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
|
||||
SYS_DUP3 => self.sys_dup2(args[0], args[1]), // TODO: handle `flags`
|
||||
SYS_PIPE2 => self.sys_pipe(args[0] as *mut u32), // TODO: handle `flags`
|
||||
SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
|
||||
SYS_DUP3 => self.sys_dup3(args[0], args[1], args[2]),
|
||||
SYS_PIPE2 => self.sys_pipe2(args[0] as *mut u32, args[1]), // TODO: handle `flags`
|
||||
SYS_SET_ROBUST_LIST => self.unimplemented("set_robuts_list", Ok(0)),
|
||||
SYS_GET_ROBUST_LIST => self.unimplemented("get_robust_list", Ok(0)),
|
||||
SYS_UTIMENSAT => self.sys_utimensat(
|
||||
args[0],
|
||||
args[1] as *const u8,
|
||||
args[2] as *const TimeSpec,
|
||||
args[3],
|
||||
),
|
||||
SYS_COPY_FILE_RANGE => self.sys_copy_file_range(
|
||||
args[0],
|
||||
args[1] as *mut usize,
|
||||
@ -195,10 +212,28 @@ impl Syscall<'_> {
|
||||
SYS_MADVISE => self.unimplemented("madvise", Ok(0)),
|
||||
|
||||
// signal
|
||||
SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)),
|
||||
SYS_RT_SIGPROCMASK => self.unimplemented("sigprocmask", Ok(0)),
|
||||
SYS_SIGALTSTACK => self.unimplemented("sigaltstack", Ok(0)),
|
||||
SYS_KILL => self.sys_kill(args[0], args[1]),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_RT_SIGACTION => self.sys_rt_sigaction(
|
||||
args[0],
|
||||
args[1] as *const SignalAction,
|
||||
args[2] as *mut SignalAction,
|
||||
args[3],
|
||||
),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_RT_SIGRETURN => self.sys_rt_sigreturn(),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_RT_SIGPROCMASK => self.sys_rt_sigprocmask(
|
||||
args[0],
|
||||
args[1] as *const Sigset,
|
||||
args[2] as *mut Sigset,
|
||||
args[3],
|
||||
),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_SIGALTSTACK => {
|
||||
self.sys_sigaltstack(args[0] as *const SignalStack, args[1] as *mut SignalStack)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_KILL => self.sys_kill(args[0] as isize, args[1]),
|
||||
|
||||
// schedule
|
||||
SYS_SCHED_YIELD => self.sys_yield(),
|
||||
@ -272,7 +307,8 @@ impl Syscall<'_> {
|
||||
args[2] as i32,
|
||||
args[3] as *const TimeSpec,
|
||||
),
|
||||
SYS_TKILL => self.unimplemented("tkill", Ok(0)),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_TKILL => self.sys_tkill(args[0], args[1]),
|
||||
|
||||
// time
|
||||
SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec),
|
||||
@ -289,6 +325,8 @@ impl Syscall<'_> {
|
||||
SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]),
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3] as isize),
|
||||
SYS_MSGGET => self.unimplemented("msgget", Ok(0)),
|
||||
SYS_SHMGET => self.unimplemented("shmget", Ok(0)),
|
||||
|
||||
// system
|
||||
SYS_GETPID => self.sys_getpid(),
|
||||
@ -296,7 +334,7 @@ impl Syscall<'_> {
|
||||
SYS_UNAME => self.sys_uname(args[0] as *mut u8),
|
||||
SYS_UMASK => self.unimplemented("umask", Ok(0o777)),
|
||||
// SYS_GETRLIMIT => self.sys_getrlimit(),
|
||||
// SYS_SETRLIMIT => self.sys_setrlimit(),
|
||||
SYS_SETRLIMIT => self.unimplemented("setrlimit", Ok(0)),
|
||||
SYS_GETRUSAGE => self.sys_getrusage(args[0], args[1] as *mut RUsage),
|
||||
SYS_SYSINFO => self.sys_sysinfo(args[0] as *mut SysInfo),
|
||||
SYS_TIMES => self.sys_times(args[0] as *mut Tms),
|
||||
@ -305,12 +343,16 @@ impl Syscall<'_> {
|
||||
SYS_SETUID => self.unimplemented("setuid", Ok(0)),
|
||||
SYS_GETEUID => self.unimplemented("geteuid", Ok(0)),
|
||||
SYS_GETEGID => self.unimplemented("getegid", Ok(0)),
|
||||
SYS_SETPGID => self.unimplemented("setpgid", Ok(0)),
|
||||
SYS_GETPPID => self.sys_getppid(),
|
||||
SYS_SETSID => self.unimplemented("setsid", Ok(0)),
|
||||
SYS_GETPGID => self.unimplemented("getpgid", Ok(0)),
|
||||
SYS_GETPGID => self.sys_getpgid(args[0]),
|
||||
SYS_SETPGID => self.sys_setpgid(args[0], args[1]),
|
||||
SYS_GETGROUPS => self.unimplemented("getgroups", Ok(0)),
|
||||
SYS_RT_SIGTIMEDWAIT => self.unimplemented("rt_sigtimedwait", Ok(0)),
|
||||
SYS_SETGROUPS => self.unimplemented("setgroups", Ok(0)),
|
||||
SYS_SETRESUID => self.unimplemented("setresuid", Ok(0)),
|
||||
SYS_SETRESGID => self.unimplemented("setresgid", Ok(0)),
|
||||
SYS_SETGID => self.unimplemented("setgid", Ok(0)),
|
||||
SYS_SETPRIORITY => self.sys_set_priority(args[0]),
|
||||
SYS_PRCTL => self.unimplemented("prctl", Ok(0)),
|
||||
SYS_MEMBARRIER => self.unimplemented("membarrier", Ok(0)),
|
||||
@ -346,6 +388,7 @@ impl Syscall<'_> {
|
||||
SYS_GET_PADDR => {
|
||||
self.sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2])
|
||||
}
|
||||
SYS_MSGCTL => self.unimplemented("msgctl", Ok(0)),
|
||||
|
||||
_ => {
|
||||
let ret = match () {
|
||||
@ -470,6 +513,7 @@ impl Syscall<'_> {
|
||||
SYS_RMDIR => self.sys_rmdir(args[0] as *const u8),
|
||||
SYS_LINK => self.sys_link(args[0] as *const u8, args[1] as *const u8),
|
||||
SYS_UNLINK => self.sys_unlink(args[0] as *const u8),
|
||||
SYS_SYMLINK => self.sys_symlink(args[0] as *const u8, args[1] as *const u8),
|
||||
SYS_READLINK => self.sys_readlink(args[0] as *const u8, args[1] as *mut u8, args[2]),
|
||||
SYS_CHMOD => self.unimplemented("chmod", Ok(0)),
|
||||
SYS_CHOWN => self.unimplemented("chown", Ok(0)),
|
||||
@ -489,7 +533,7 @@ pub type SysResult = Result<usize, SysError>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(isize)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, FromPrimitive)]
|
||||
pub enum SysError {
|
||||
EUNDEF = 0,
|
||||
EPERM = 1,
|
||||
@ -532,6 +576,7 @@ pub enum SysError {
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
EIDRM = 43,
|
||||
ENOTSOCK = 80,
|
||||
ENOPROTOOPT = 92,
|
||||
EPFNOSUPPORT = 96,
|
||||
@ -539,6 +584,7 @@ pub enum SysError {
|
||||
ENOBUFS = 105,
|
||||
EISCONN = 106,
|
||||
ENOTCONN = 107,
|
||||
ETIMEDOUT = 110,
|
||||
ECONNREFUSED = 111,
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
//! Syscalls for process
|
||||
|
||||
use super::*;
|
||||
use crate::fs::FileLike;
|
||||
use crate::signal::{has_signal_to_do, send_signal, Signal};
|
||||
use crate::syscall::SysError::{EINTR, ESRCH};
|
||||
use alloc::sync::Weak;
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Fork the current process. Return the child's PID.
|
||||
@ -9,7 +13,7 @@ impl Syscall<'_> {
|
||||
let pid = new_thread.proc.lock().pid.get();
|
||||
let tid = thread_manager().add(new_thread);
|
||||
thread_manager().detach(tid);
|
||||
info!("fork: {} -> {}", thread::current().id(), pid);
|
||||
info!("fork: {} -> {}", self.process().pid, pid);
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
@ -50,15 +54,19 @@ impl Syscall<'_> {
|
||||
//return Err(SysError::ENOSYS);
|
||||
}
|
||||
let parent_tid_ref = unsafe { self.vm().check_write_ptr(parent_tid)? };
|
||||
let child_tid_ref = unsafe { self.vm().check_write_ptr(child_tid)? };
|
||||
let new_thread = self
|
||||
// child_tid buffer should not be set because CLONE_CHILD_SETTID flag is not specified in the current implementation
|
||||
// let child_tid_ref = unsafe { self.vm().check_write_ptr(child_tid)? };
|
||||
let mut new_thread = self
|
||||
.thread
|
||||
.clone(self.tf, newsp, newtls, child_tid as usize);
|
||||
if clone_flags.contains(CloneFlags::CHILD_CLEARTID) {
|
||||
new_thread.clear_child_tid = child_tid as usize;
|
||||
}
|
||||
let tid = thread_manager().add(new_thread);
|
||||
thread_manager().detach(tid);
|
||||
info!("clone: {} -> {}", thread::current().id(), tid);
|
||||
*parent_tid_ref = tid as u32;
|
||||
*child_tid_ref = tid as u32;
|
||||
// *child_tid_ref = tid as u32;
|
||||
Ok(tid)
|
||||
}
|
||||
|
||||
@ -108,17 +116,20 @@ impl Syscall<'_> {
|
||||
}
|
||||
// if not, check pid
|
||||
let invalid = {
|
||||
let children: Vec<_> = proc
|
||||
let children = proc
|
||||
.children
|
||||
.iter()
|
||||
.filter_map(|weak| weak.upgrade())
|
||||
.collect();
|
||||
.filter_map(|(pid, weak)| {
|
||||
if weak.upgrade().is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(pid)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
match target {
|
||||
WaitFor::AnyChild | WaitFor::AnyChildInGroup => children.len() == 0,
|
||||
WaitFor::Pid(pid) => children
|
||||
.iter()
|
||||
.find(|p| p.lock().pid.get() == pid)
|
||||
.is_none(),
|
||||
WaitFor::Pid(pid) => children.iter().find(|p| p.get() == pid).is_none(),
|
||||
}
|
||||
};
|
||||
if invalid {
|
||||
@ -186,6 +197,26 @@ impl Syscall<'_> {
|
||||
let (mut vm, entry_addr, ustack_top) =
|
||||
Thread::new_user_vm(&inode, &path, args, envs).map_err(|_| SysError::EINVAL)?;
|
||||
|
||||
// close file that FD_CLOEXEC is set
|
||||
let close_fds = proc
|
||||
.files
|
||||
.iter()
|
||||
.filter_map(|(fd, file_like)| {
|
||||
if let FileLike::File(file) = file_like {
|
||||
if file.fd_cloexec {
|
||||
Some(*fd)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
for fd in close_fds {
|
||||
proc.files.remove(&fd);
|
||||
}
|
||||
|
||||
// Activate new page table
|
||||
core::mem::swap(&mut *self.vm(), &mut vm);
|
||||
unsafe {
|
||||
@ -208,35 +239,48 @@ impl Syscall<'_> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Kill the process
|
||||
pub fn sys_kill(&mut self, pid: usize, sig: usize) -> SysResult {
|
||||
info!(
|
||||
"kill: thread {} kill process {} with signal {}",
|
||||
thread::current().id(),
|
||||
pid,
|
||||
sig
|
||||
);
|
||||
let current_pid = self.process().pid.get().clone();
|
||||
if current_pid == pid {
|
||||
// killing myself
|
||||
self.sys_exit_group(sig);
|
||||
} else {
|
||||
if let Some(proc_arc) = PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade()) {
|
||||
let mut proc = proc_arc.lock();
|
||||
proc.exit(sig);
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(SysError::EINVAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current process id
|
||||
pub fn sys_getpid(&mut self) -> SysResult {
|
||||
info!("getpid");
|
||||
Ok(self.process().pid.get())
|
||||
}
|
||||
|
||||
pub fn sys_getpgid(&self, mut pid: usize) -> SysResult {
|
||||
if pid == 0 {
|
||||
pid = self.process().pid.get();
|
||||
}
|
||||
info!("getpgid: get pgid of process {}", pid);
|
||||
let process_table = PROCESSES.read();
|
||||
// let process_table: BTreeMap<usize, Weak<Mutex<Process>>> = BTreeMap::new();
|
||||
let proc = process_table.get(&pid);
|
||||
if let Some(proc) = proc {
|
||||
let lock = proc.upgrade().unwrap();
|
||||
let proc = lock.lock();
|
||||
Ok(proc.pgid as usize)
|
||||
} else {
|
||||
Err(ESRCH)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_setpgid(&self, mut pid: usize, pgid: usize) -> SysResult {
|
||||
if pid == 0 {
|
||||
pid = self.process().pid.get();
|
||||
}
|
||||
info!("setpgid: set pgid of process {} to {}", pid, pgid);
|
||||
let process_table = PROCESSES.read();
|
||||
let proc = process_table.get(&pid);
|
||||
if let Some(proc) = proc {
|
||||
// TODO: check process pid is the child of calling process
|
||||
if let Some(proc) = proc.upgrade() {
|
||||
let mut proc = proc.lock();
|
||||
proc.pgid = pgid as i32;
|
||||
}
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ESRCH)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current thread id
|
||||
pub fn sys_gettid(&mut self) -> SysResult {
|
||||
info!("gettid");
|
||||
@ -246,8 +290,10 @@ impl Syscall<'_> {
|
||||
|
||||
/// Get the parent process id
|
||||
pub fn sys_getppid(&mut self) -> SysResult {
|
||||
if let Some(parent) = self.process().parent.upgrade() {
|
||||
Ok(parent.lock().pid.get())
|
||||
info!("getppid");
|
||||
let (pid, parent) = self.process().parent.clone();
|
||||
if parent.upgrade().is_some() {
|
||||
Ok(pid.get())
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
@ -292,7 +338,7 @@ impl Syscall<'_> {
|
||||
info!("exit_group: {}, code: {}", proc.pid, exit_code);
|
||||
|
||||
proc.exit(exit_code);
|
||||
|
||||
drop(proc);
|
||||
thread::yield_now();
|
||||
unreachable!();
|
||||
}
|
||||
@ -303,6 +349,9 @@ impl Syscall<'_> {
|
||||
if !time.is_zero() {
|
||||
// TODO: handle spurious wakeup
|
||||
thread::sleep(time.to_duration());
|
||||
if has_signal_to_do() {
|
||||
return Err(EINTR);
|
||||
}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
229
kernel/src/syscall/signal.rs
Normal file
229
kernel/src/syscall/signal.rs
Normal file
@ -0,0 +1,229 @@
|
||||
use crate::process::{current_thread, process_of, thread_manager, PROCESSES};
|
||||
use crate::process::{process, process_group};
|
||||
use crate::signal::*;
|
||||
use crate::syscall::SysError::{EINVAL, ENOMEM, EPERM, ESRCH};
|
||||
use crate::syscall::{SysResult, Syscall};
|
||||
use num::FromPrimitive;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_rt_sigaction(
|
||||
&self,
|
||||
signum: usize,
|
||||
act: *const SignalAction,
|
||||
oldact: *mut SignalAction,
|
||||
sigsetsize: usize,
|
||||
) -> SysResult {
|
||||
if let Some(signal) = <Signal as FromPrimitive>::from_usize(signum) {
|
||||
info!(
|
||||
"rt_sigaction: signum: {:?}, act: {:?}, oldact: {:?}, sigsetsize: {}",
|
||||
signal, act, oldact, sigsetsize
|
||||
);
|
||||
use Signal::*;
|
||||
if signal == SIGKILL
|
||||
|| signal == SIGSTOP
|
||||
|| sigsetsize != core::mem::size_of::<Sigset>()
|
||||
{
|
||||
Err(EINVAL)
|
||||
} else {
|
||||
let mut proc = self.process();
|
||||
if !oldact.is_null() {
|
||||
let oldact = unsafe { self.vm().check_write_ptr(oldact)? };
|
||||
*oldact = proc.dispositions[signum];
|
||||
}
|
||||
if !act.is_null() {
|
||||
let act = unsafe { self.vm().check_read_ptr(act)? };
|
||||
info!("new action: {:?}", act);
|
||||
proc.dispositions[signum] = *act;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
} else {
|
||||
info!(
|
||||
"rt_sigaction: sigal: UNKNOWN, act: {:?}, oldact: {:?}, sigsetsize: {}",
|
||||
act, oldact, sigsetsize
|
||||
);
|
||||
Err(EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_rt_sigreturn(&mut self) -> SysResult {
|
||||
info!("rt_sigreturn");
|
||||
// FIXME: adapt arch
|
||||
let frame = unsafe { &*((self.tf.get_sp() - 8) as *mut SignalFrame) };
|
||||
// frame.info.signo
|
||||
{
|
||||
let mut process = self.process();
|
||||
process.sigaltstack.flags ^=
|
||||
process.sigaltstack.flags & SignalStackFlags::ONSTACK.bits();
|
||||
}
|
||||
|
||||
// *self.tf = TrapFrame::from_mcontext(&frame.ucontext.mcontext);
|
||||
*self.tf = frame.tf.clone();
|
||||
let mc = &frame.ucontext.mcontext;
|
||||
self.tf.r15 = mc.r15;
|
||||
self.tf.r14 = mc.r14;
|
||||
self.tf.r13 = mc.r13;
|
||||
self.tf.r12 = mc.r12;
|
||||
self.tf.rbp = mc.rbp;
|
||||
self.tf.rbx = mc.rbx;
|
||||
self.tf.r11 = mc.r11;
|
||||
self.tf.r10 = mc.r10;
|
||||
self.tf.r9 = mc.r9;
|
||||
self.tf.r8 = mc.r8;
|
||||
self.tf.rsi = mc.rsi;
|
||||
self.tf.rdi = mc.rdi;
|
||||
self.tf.rdx = mc.rdx;
|
||||
self.tf.rcx = mc.rcx;
|
||||
self.tf.rax = mc.rax;
|
||||
self.tf.rip = mc.rip;
|
||||
self.tf.rsp = mc.rsp;
|
||||
|
||||
let ret = self.tf.rax as isize;
|
||||
if ret >= 0 {
|
||||
Ok(ret as usize)
|
||||
} else {
|
||||
Err(FromPrimitive::from_isize(-ret).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_rt_sigprocmask(
|
||||
&mut self,
|
||||
how: usize,
|
||||
set: *const Sigset,
|
||||
oldset: *mut Sigset,
|
||||
sigsetsize: usize,
|
||||
) -> SysResult {
|
||||
info!(
|
||||
"rt_sigprocmask: how: {}, set: {:?}, oldset: {:?}, sigsetsize: {}",
|
||||
how, set, oldset, sigsetsize
|
||||
);
|
||||
if sigsetsize != 8 {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
if !oldset.is_null() {
|
||||
let oldset = unsafe { self.vm().check_write_ptr(oldset)? };
|
||||
*oldset = self.thread.sig_mask;
|
||||
}
|
||||
if !set.is_null() {
|
||||
let set = unsafe { self.vm().check_read_ptr(set)? };
|
||||
const BLOCK: usize = 0;
|
||||
const UNBLOCK: usize = 1;
|
||||
const SETMASK: usize = 2;
|
||||
match how {
|
||||
BLOCK => self.thread.sig_mask.add_set(set),
|
||||
UNBLOCK => self.thread.sig_mask.remove_set(set),
|
||||
SETMASK => self.thread.sig_mask = *set,
|
||||
_ => return Err(EINVAL),
|
||||
}
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// sending signal sig to process pid
|
||||
pub fn sys_kill(&mut self, pid: isize, signum: usize) -> SysResult {
|
||||
if let Some(signal) = <Signal as FromPrimitive>::from_usize(signum) {
|
||||
info!("kill: pid: {}, signal: {:?}", pid, signal);
|
||||
let info = Siginfo {
|
||||
signo: signum as i32,
|
||||
errno: 0,
|
||||
code: SI_USER,
|
||||
field: Default::default(),
|
||||
};
|
||||
match pid {
|
||||
pid if pid > 0 => {
|
||||
if let Some(process) = process(pid as usize) {
|
||||
send_signal(process, -1, info);
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ESRCH)
|
||||
}
|
||||
}
|
||||
0 => {
|
||||
let pgid = self.process().pgid;
|
||||
for process in process_group(pgid) {
|
||||
send_signal(process, -1, info);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
-1 => {
|
||||
// TODO: check permissions
|
||||
// sig is sent to every process for which the calling process
|
||||
// has permission to send signals, except for process 1 (init)
|
||||
for process in PROCESSES.read().values() {
|
||||
if let Some(process) = process.upgrade() {
|
||||
send_signal(process, -1, info);
|
||||
}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
_ => {
|
||||
let process_group = process_group((-pid) as i32);
|
||||
if process_group.is_empty() {
|
||||
Err(ESRCH)
|
||||
} else {
|
||||
for process in process_group {
|
||||
send_signal(process, -1, info);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("kill: pid: {}, signal: UNKNOWN", pid);
|
||||
Err(EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_tkill(&mut self, tid: usize, signum: usize) -> SysResult {
|
||||
if let Some(signal) = <Signal as FromPrimitive>::from_usize(signum) {
|
||||
info!("tkill: tid: {}, signal: {:?}", tid, signal);
|
||||
if let Some(process) = process_of(tid) {
|
||||
send_signal(
|
||||
process,
|
||||
tid as isize,
|
||||
Siginfo {
|
||||
signo: signum as i32,
|
||||
errno: 0,
|
||||
code: SI_TKILL,
|
||||
field: Default::default(),
|
||||
},
|
||||
);
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ESRCH)
|
||||
}
|
||||
} else {
|
||||
info!("tkill: tid: {}, signum: {}", tid, signum);
|
||||
Err(EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_sigaltstack(&self, ss: *const SignalStack, old_ss: *mut SignalStack) -> SysResult {
|
||||
info!("sigaltstack: ss: {:?}, old_ss: {:?}", ss, old_ss);
|
||||
const MINSIGSTKSZ: usize = 2048;
|
||||
if !old_ss.is_null() {
|
||||
let old_ss = unsafe { self.vm().check_write_ptr(old_ss)? };
|
||||
*old_ss = self.process().sigaltstack;
|
||||
}
|
||||
if !ss.is_null() {
|
||||
let ss = unsafe { self.vm().check_read_ptr(ss)? };
|
||||
info!("new stack: {:?}", ss);
|
||||
|
||||
if ss.flags & 2 != 0 && ss.size < MINSIGSTKSZ {
|
||||
return Err(ENOMEM);
|
||||
}
|
||||
// only allow SS_AUTODISARM or SS_DISABLE
|
||||
if ss.flags ^ (ss.flags & 0x8000002) != 0 {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
let old_ss = &mut self.process().sigaltstack;
|
||||
let flags = SignalStackFlags::from_bits_truncate(old_ss.flags);
|
||||
if flags.contains(SignalStackFlags::ONSTACK) {
|
||||
return Err(EPERM);
|
||||
}
|
||||
*old_ss = *ss;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ use super::*;
|
||||
use crate::consts::USEC_PER_TICK;
|
||||
use core::time::Duration;
|
||||
use lazy_static::lazy_static;
|
||||
use rcore_fs::vfs::Timespec;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_gettimeofday(&mut self, tv: *mut TimeVal, tz: *const u8) -> SysResult {
|
||||
@ -129,8 +130,8 @@ impl TimeVal {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TimeSpec {
|
||||
sec: usize,
|
||||
nsec: usize,
|
||||
pub sec: usize,
|
||||
pub nsec: usize,
|
||||
}
|
||||
|
||||
impl TimeSpec {
|
||||
@ -150,11 +151,31 @@ impl TimeSpec {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: more precise; update when write
|
||||
pub fn update(inode: &Arc<dyn INode>) {
|
||||
let now = TimeSpec::get_epoch().into();
|
||||
if let Ok(mut metadata) = inode.metadata() {
|
||||
metadata.atime = now;
|
||||
metadata.mtime = now;
|
||||
metadata.ctime = now;
|
||||
inode.set_metadata(&metadata).expect("set metadata failed");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.sec == 0 && self.nsec == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Timespec> for TimeSpec {
|
||||
fn into(self) -> Timespec {
|
||||
Timespec {
|
||||
sec: self.sec as i64,
|
||||
nsec: self.nsec as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ignore other fields for now
|
||||
#[repr(C)]
|
||||
pub struct RUsage {
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::arch::cpu;
|
||||
use crate::arch::interrupt::TrapFrame;
|
||||
use crate::arch::interrupt::{syscall, TrapFrame};
|
||||
use crate::consts::INFORM_PER_MSEC;
|
||||
use crate::process::*;
|
||||
use crate::sync::Condvar;
|
||||
use rcore_thread::std_thread as thread;
|
||||
use rcore_thread::std_thread::current;
|
||||
|
||||
pub static mut TICK: usize = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user