Compare commits
10 commits
2f9711a3f1
...
8b2f8bf2a3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8b2f8bf2a3 | ||
![]() |
5ab1ca507c | ||
![]() |
7545f393a2 | ||
![]() |
8afce1c1a1 | ||
![]() |
d27f835f3e | ||
![]() |
5a1eb8d01e | ||
![]() |
8595e87779 | ||
![]() |
48b1fcc643 | ||
![]() |
1c7033dafa | ||
![]() |
4dec6a89c6 |
21 changed files with 278 additions and 114 deletions
21
.devcontainer/devcontainer.json
Normal file
21
.devcontainer/devcontainer.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "rcore-tutorial-v3",
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"args": {
|
||||
"QEMU_VERSION": "7.0.0",
|
||||
"DEBIAN_FRONTEND": "noninteractive",
|
||||
"GDB_VERSION": "14.1"
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "rustup show",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"rust-lang.rust-analyzer",
|
||||
"ms-vscode.cpptools",
|
||||
"tamasfe.even-better-toml"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
*/*
|
||||
*/*
|
||||
!rust-toolchain.toml
|
2
.github/workflows/doc-and-test.yml
vendored
2
.github/workflows/doc-and-test.yml
vendored
|
@ -4,7 +4,7 @@ on: [push]
|
|||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
rust_toolchain: nightly-2022-08-05
|
||||
rust_toolchain: nightly-2024-01-18
|
||||
|
||||
jobs:
|
||||
build-doc:
|
||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,9 +1,12 @@
|
|||
.*/*
|
||||
!.github/*
|
||||
!.vscode/settings.json
|
||||
!.devcontainer/devcontainer.json
|
||||
|
||||
.idea
|
||||
Cargo.lock
|
||||
target
|
||||
**/Cargo.lock
|
||||
**/target/
|
||||
|
||||
os/src/link_app.S
|
||||
os/src/linker.ld
|
||||
os/last-*
|
||||
|
|
119
Dockerfile
119
Dockerfile
|
@ -1,85 +1,72 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
# This Dockerfile is adapted from https://github.com/LearningOS/rCore-Tutorial-v3/blob/main/Dockerfile
|
||||
# with the following major updates:
|
||||
# - ubuntu 18.04 -> 20.04
|
||||
# - qemu 5.0.0 -> 7.0.0
|
||||
# - Extensive comments linking to relevant documentation
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# Stage 1 Build QEMU
|
||||
# - https://www.qemu.org/download/
|
||||
# - https://wiki.qemu.org/Hosts/Linux#Building_QEMU_for_Linux
|
||||
# - https://wiki.qemu.org/Documentation/Platforms/RISCV
|
||||
|
||||
FROM ubuntu:20.04 as build_qemu
|
||||
|
||||
ARG QEMU_VERSION=7.0.0
|
||||
ARG HOME=/root
|
||||
|
||||
# 0. Install general tools
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
python3 \
|
||||
wget
|
||||
RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
|
||||
sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
|
||||
apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y wget build-essential libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build
|
||||
|
||||
# 1. Set up QEMU RISC-V
|
||||
# - https://learningos.github.io/rust-based-os-comp2022/0setup-devel-env.html#qemu
|
||||
# - https://www.qemu.org/download/
|
||||
# - https://wiki.qemu.org/Documentation/Platforms/RISCV
|
||||
# - https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html
|
||||
|
||||
# 1.1. Download source
|
||||
WORKDIR ${HOME}
|
||||
RUN wget https://download.qemu.org/qemu-${QEMU_VERSION}.tar.xz && \
|
||||
tar xvJf qemu-${QEMU_VERSION}.tar.xz
|
||||
|
||||
# 1.2. Install dependencies
|
||||
# - https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html#prerequisites
|
||||
RUN apt-get install -y \
|
||||
autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \
|
||||
gawk build-essential bison flex texinfo gperf libtool patchutils bc \
|
||||
zlib1g-dev libexpat-dev git \
|
||||
ninja-build pkg-config libglib2.0-dev libpixman-1-dev libsdl2-dev
|
||||
|
||||
# 1.3. Build and install from source
|
||||
WORKDIR ${HOME}/qemu-${QEMU_VERSION}
|
||||
RUN ./configure --target-list=riscv64-softmmu,riscv64-linux-user && \
|
||||
tar xf qemu-${QEMU_VERSION}.tar.xz && \
|
||||
cd qemu-${QEMU_VERSION} && \
|
||||
./configure --target-list=riscv64-softmmu,riscv64-linux-user && \
|
||||
make -j$(nproc) && \
|
||||
make install
|
||||
|
||||
# 1.4. Clean up
|
||||
WORKDIR ${HOME}
|
||||
RUN rm -rf qemu-${QEMU_VERSION} qemu-${QEMU_VERSION}.tar.xz
|
||||
# Stage 2 Set Lab Environment
|
||||
FROM ubuntu:20.04 as build
|
||||
|
||||
# 1.5. Sanity checking
|
||||
RUN qemu-system-riscv64 --version && \
|
||||
qemu-riscv64 --version
|
||||
WORKDIR /tmp
|
||||
|
||||
# 2. Set up Rust
|
||||
# - https://learningos.github.io/rust-based-os-comp2022/0setup-devel-env.html#qemu
|
||||
# 2.0. Install general tools
|
||||
RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
|
||||
apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y jq curl git python3 wget build-essential \
|
||||
# qemu dependency
|
||||
libglib2.0-0 libfdt1 libpixman-1-0 zlib1g \
|
||||
# gdb
|
||||
gdb-multiarch
|
||||
|
||||
# 2.1. Copy qemu
|
||||
COPY --from=build_qemu /usr/local/bin/* /usr/local/bin
|
||||
|
||||
# 2.2. Install Rust
|
||||
# - https://www.rust-lang.org/tools/install
|
||||
# - https://github.com/rust-lang/docker-rust/blob/master/Dockerfile-debian.template
|
||||
|
||||
# 2.1. Install
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH \
|
||||
RUST_VERSION=nightly
|
||||
RUN set -eux; \
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup-init; \
|
||||
chmod +x rustup-init; \
|
||||
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \
|
||||
rm rustup-init; \
|
||||
chmod -R a+w $RUSTUP_HOME $CARGO_HOME;
|
||||
RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static \
|
||||
RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
|
||||
sh -s -- -y --no-modify-path --profile minimal --default-toolchain nightly
|
||||
|
||||
# 2.2. Sanity checking
|
||||
RUN rustup --version && \
|
||||
cargo --version && \
|
||||
rustc --version
|
||||
|
||||
# 3. Build env for labs
|
||||
# See os1/Makefile `env:` for example.
|
||||
# 2.3. Build env for labs
|
||||
# See os/Makefile `env:` for example.
|
||||
# This avoids having to wait for these steps each time using a new container.
|
||||
COPY rust-toolchain.toml rust-toolchain.toml
|
||||
RUN rustup target add riscv64gc-unknown-none-elf && \
|
||||
cargo install cargo-binutils --vers ~0.2 && \
|
||||
rustup component add rust-src && \
|
||||
rustup component add llvm-tools-preview
|
||||
cargo install toml-cli cargo-binutils && \
|
||||
RUST_VERSION=$(toml get -r rust-toolchain.toml toolchain.channel) && \
|
||||
Components=$(toml get -r rust-toolchain.toml toolchain.components | jq -r 'join(" ")') && \
|
||||
rustup install $RUST_VERSION && \
|
||||
rustup component add --toolchain $RUST_VERSION $Components
|
||||
|
||||
# Ready to go
|
||||
WORKDIR ${HOME}
|
||||
# 2.4. Set GDB
|
||||
RUN ln -s /usr/bin/gdb-multiarch /usr/bin/riscv64-unknown-elf-gdb
|
||||
|
||||
# Stage 3 Sanity checking
|
||||
FROM build as test
|
||||
RUN qemu-system-riscv64 --version && \
|
||||
qemu-riscv64 --version && \
|
||||
rustup --version && \
|
||||
cargo --version && \
|
||||
rustc --version && \
|
||||
riscv64-unknown-elf-gdb --version
|
6
Makefile
6
Makefile
|
@ -1,11 +1,11 @@
|
|||
DOCKER_NAME ?= rcore-tutorial-v3
|
||||
DOCKER_TAG ?= rcore-tutorial-v3:latest
|
||||
.PHONY: docker build_docker
|
||||
|
||||
docker:
|
||||
docker run --rm -it -v ${PWD}:/mnt -w /mnt ${DOCKER_NAME} bash
|
||||
docker run --rm -it -v ${PWD}:/mnt -w /mnt --name rcore-tutorial-v3 ${DOCKER_TAG} bash
|
||||
|
||||
build_docker:
|
||||
docker build -t ${DOCKER_NAME} .
|
||||
docker build -t ${DOCKER_TAG} --target build .
|
||||
|
||||
fmt:
|
||||
cd os ; cargo fmt; cd ..
|
||||
|
|
27
os/Makefile
27
os/Makefile
|
@ -56,25 +56,28 @@ disasm-vim: kernel
|
|||
|
||||
run: run-inner
|
||||
|
||||
|
||||
QEMU_ARGS := -machine virt \
|
||||
-nographic \
|
||||
-bios $(BOOTLOADER) \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)
|
||||
|
||||
run-inner: build
|
||||
@qemu-system-riscv64 \
|
||||
-machine virt \
|
||||
-nographic \
|
||||
-bios $(BOOTLOADER) \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)
|
||||
QEMU_NAME := qemu-system-riscv64
|
||||
qemu-version-check:
|
||||
@sh scripts/qemu-ver-check.sh $(QEMU_NAME)
|
||||
|
||||
debug: build
|
||||
run-inner: qemu-version-check build
|
||||
@qemu-system-riscv64 $(QEMU_ARGS)
|
||||
|
||||
debug: qemu-version-check build
|
||||
@tmux new-session -d \
|
||||
"qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \
|
||||
"qemu-system-riscv64 $(QEMU_ARGS) -s -S" && \
|
||||
tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \
|
||||
tmux -2 attach-session -d
|
||||
|
||||
gdbserver: build
|
||||
@qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S
|
||||
gdbserver: qemu-version-check build
|
||||
@qemu-system-riscv64 $(QEMU_ARGS) -s -S
|
||||
|
||||
gdbclient:
|
||||
@riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
|
||||
|
||||
.PHONY: build env kernel clean disasm disasm-vim run-inner gdbserver gdbclient
|
||||
.PHONY: build env kernel clean disasm disasm-vim run-inner gdbserver gdbclient qemu-version-check
|
||||
|
|
26
os/scripts/qemu-ver-check.sh
Normal file
26
os/scripts/qemu-ver-check.sh
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Argument1: The filename of qemu executable, e.g. qemu-system-riscv64
|
||||
QEMU_PATH=$(which $1)
|
||||
RET=$?
|
||||
MINIMUM_MAJOR_VERSION=7
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
if [ $RET != 0 ]
|
||||
then
|
||||
echo "$1 not found"
|
||||
exit 1
|
||||
else
|
||||
QEMU_VERSION=$($1 --version|head -n 1|awk '{print $4}')
|
||||
MAJOR_VERSION=$(echo $QEMU_VERSION|cut -c1-1)
|
||||
if [ $MAJOR_VERSION -lt $MINIMUM_MAJOR_VERSION ]
|
||||
then
|
||||
echo "${RED}Error: Required major version of QEMU is ${MINIMUM_MAJOR_VERSION}, " \
|
||||
"but current is ${QEMU_VERSION}.${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo "${GREEN}QEMU version is ${QEMU_VERSION}(>=${MINIMUM_MAJOR_VERSION}), OK!${NC}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
|
@ -5,6 +5,7 @@ pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
|
|||
pub const MAX_APP_NUM: usize = 4;
|
||||
pub const APP_BASE_ADDRESS: usize = 0x80400000;
|
||||
pub const APP_SIZE_LIMIT: usize = 0x20000;
|
||||
pub const MAX_SYSCALL_NUM: usize = 500;
|
||||
|
||||
/*
|
||||
#[cfg(feature = "board_k210")]
|
||||
|
|
|
@ -70,10 +70,6 @@ pub fn load_apps() {
|
|||
let num_app_ptr = _num_app as usize as *const usize;
|
||||
let num_app = get_num_app();
|
||||
let app_start = unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) };
|
||||
// clear i-cache first
|
||||
unsafe {
|
||||
asm!("fence.i");
|
||||
}
|
||||
// load apps
|
||||
for i in 0..num_app {
|
||||
let base_i = get_base_i(i);
|
||||
|
@ -87,6 +83,15 @@ pub fn load_apps() {
|
|||
let dst = unsafe { core::slice::from_raw_parts_mut(base_i as *mut u8, src.len()) };
|
||||
dst.copy_from_slice(src);
|
||||
}
|
||||
// Memory fence about fetching the instruction memory
|
||||
// It is guaranteed that a subsequent instruction fetch must
|
||||
// observes all previous writes to the instruction memory.
|
||||
// Therefore, fence.i must be executed after we have loaded
|
||||
// the code of the next app into the instruction memory.
|
||||
// See also: riscv non-priv spec chapter 3, 'Zifencei' extension.
|
||||
unsafe {
|
||||
asm!("fence.i");
|
||||
}
|
||||
}
|
||||
|
||||
/// get app info with entry and sp and save `TrapContext` in kernel stack
|
||||
|
|
|
@ -14,6 +14,7 @@ const SYSCALL_WRITE: usize = 64;
|
|||
const SYSCALL_EXIT: usize = 93;
|
||||
const SYSCALL_YIELD: usize = 124;
|
||||
const SYSCALL_GET_TIME: usize = 169;
|
||||
const SYSCALL_TASK_INFO: usize = 410;
|
||||
|
||||
mod fs;
|
||||
mod process;
|
||||
|
@ -21,13 +22,17 @@ mod process;
|
|||
use fs::*;
|
||||
use process::*;
|
||||
|
||||
use crate::task::TASK_MANAGER;
|
||||
|
||||
/// handle syscall exception with `syscall_id` and other arguments
|
||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||
TASK_MANAGER.mark_syscall(syscall_id);
|
||||
match syscall_id {
|
||||
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
|
||||
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
||||
SYSCALL_YIELD => sys_yield(),
|
||||
SYSCALL_GET_TIME => sys_get_time(),
|
||||
SYSCALL_TASK_INFO => sys_task_info(args[0] as *mut TaskInfo),
|
||||
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
//! Process management syscalls
|
||||
use crate::task::{exit_current_and_run_next, suspend_current_and_run_next};
|
||||
use crate::timer::get_time_ms;
|
||||
use log::trace;
|
||||
|
||||
use crate::task::{exit_current_and_run_next, suspend_current_and_run_next, TaskStatus, TASK_MANAGER};
|
||||
use crate::timer::{get_time, get_time_ms};
|
||||
use crate::config::MAX_SYSCALL_NUM;
|
||||
|
||||
/// Task information
|
||||
#[allow(dead_code)]
|
||||
pub struct TaskInfo {
|
||||
/// Task status in it's life cycle
|
||||
status: TaskStatus,
|
||||
/// The numbers of syscall called by task
|
||||
syscall_times: [u32; MAX_SYSCALL_NUM],
|
||||
/// Total running time of task
|
||||
time: usize,
|
||||
}
|
||||
|
||||
/// task exits and submit an exit code
|
||||
pub fn sys_exit(exit_code: i32) -> ! {
|
||||
|
@ -19,3 +33,14 @@ pub fn sys_yield() -> isize {
|
|||
pub fn sys_get_time() -> isize {
|
||||
get_time_ms() as isize
|
||||
}
|
||||
|
||||
/// YOUR JOB: Finish sys_task_info to pass testcases
|
||||
pub fn sys_task_info(ti: *mut TaskInfo) -> isize {
|
||||
unsafe {
|
||||
(*ti).status = TASK_MANAGER.get_current_status();
|
||||
(*ti).time = get_time();
|
||||
(*ti).syscall_times = TASK_MANAGER.get_current_syscall_times()
|
||||
}
|
||||
trace!("kernel: sys_task_info");
|
||||
0
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ mod switch;
|
|||
#[allow(clippy::module_inception)]
|
||||
mod task;
|
||||
|
||||
use crate::config::MAX_APP_NUM;
|
||||
use crate::config::{MAX_APP_NUM, MAX_SYSCALL_NUM};
|
||||
use crate::loader::{get_num_app, init_app_cx};
|
||||
use crate::sbi::shutdown;
|
||||
use crate::sync::UPSafeCell;
|
||||
use lazy_static::*;
|
||||
use switch::__switch;
|
||||
use task::{TaskControlBlock, TaskStatus};
|
||||
pub use task::{TaskControlBlock, TaskStatus};
|
||||
|
||||
pub use context::TaskContext;
|
||||
|
||||
|
@ -56,6 +56,7 @@ lazy_static! {
|
|||
let mut tasks = [TaskControlBlock {
|
||||
task_cx: TaskContext::zero_init(),
|
||||
task_status: TaskStatus::UnInit,
|
||||
syscall_times: [0; MAX_SYSCALL_NUM]
|
||||
}; MAX_APP_NUM];
|
||||
for (i, task) in tasks.iter_mut().enumerate() {
|
||||
task.task_cx = TaskContext::goto_restore(init_app_cx(i));
|
||||
|
@ -138,6 +139,36 @@ impl TaskManager {
|
|||
shutdown(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// get current task id
|
||||
pub fn get_current_id(&self) -> usize {
|
||||
let inner = self.inner.exclusive_access();
|
||||
inner.current_task
|
||||
}
|
||||
|
||||
/// get current task status
|
||||
pub fn get_current_status(&self) -> TaskStatus {
|
||||
let inner = self.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].task_status
|
||||
}
|
||||
|
||||
/// get current task syscall times
|
||||
pub fn get_current_syscall_times(&self) -> [u32; MAX_SYSCALL_NUM] {
|
||||
let inner = self.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
return inner.tasks[current].syscall_times.clone();
|
||||
}
|
||||
|
||||
/// record syscall
|
||||
pub fn mark_syscall(&self, syscall_id: usize) {
|
||||
if syscall_id >= MAX_SYSCALL_NUM {
|
||||
return;
|
||||
}
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].syscall_times[syscall_id] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// run first task
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
//! Types related to task management
|
||||
|
||||
use crate::config::MAX_SYSCALL_NUM;
|
||||
|
||||
use super::TaskContext;
|
||||
|
||||
/// The task control block (TCB) of a task.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TaskControlBlock {
|
||||
/// The task status in it's lifecycle
|
||||
pub task_status: TaskStatus,
|
||||
/// The task context
|
||||
pub task_cx: TaskContext,
|
||||
/// The numbers of syscall called by task
|
||||
pub syscall_times: [u32; MAX_SYSCALL_NUM],
|
||||
}
|
||||
|
||||
/// The status of a task
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum TaskStatus {
|
||||
/// uninitialized
|
||||
UnInit,
|
||||
/// ready to run
|
||||
Ready,
|
||||
/// running
|
||||
Running,
|
||||
/// exited
|
||||
Exited,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[toolchain]
|
||||
profile = "minimal"
|
||||
# use the nightly version of the last stable toolchain, see <https://forge.rust-lang.org/>
|
||||
channel = "nightly-2022-08-05"
|
||||
components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"]
|
||||
channel = "nightly-2024-05-01"
|
||||
components = ["rust-src", "llvm-tools", "rustfmt", "clippy"]
|
||||
targets = ["riscv64gc-unknown-none-elf"]
|
||||
|
|
|
@ -1,28 +1,16 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
|
||||
const LEN: usize = 100;
|
||||
use user_lib::{
|
||||
println, task_info, TaskInfo,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
let p = 3u64;
|
||||
let m = 998244353u64;
|
||||
let iter: usize = 200000;
|
||||
let mut s = [0u64; LEN];
|
||||
let mut cur = 0usize;
|
||||
s[cur] = 1;
|
||||
for i in 1..=iter {
|
||||
let next = if cur + 1 == LEN { 0 } else { cur + 1 };
|
||||
s[next] = s[cur] * p % m;
|
||||
cur = next;
|
||||
if i % 10000 == 0 {
|
||||
println!("power_3 [{}/{}]", i, iter);
|
||||
}
|
||||
}
|
||||
println!("{}^{} = {}(MOD {})", p, iter, s[cur], m);
|
||||
println!("Test power_3 OK!");
|
||||
pub fn main() -> usize {
|
||||
let info = TaskInfo::new();
|
||||
assert_eq!(0, task_info(&info));
|
||||
println!("task_info {:?}", info);
|
||||
0
|
||||
}
|
||||
|
|
16
user/src/bin/04taskinfo.rs
Normal file
16
user/src/bin/04taskinfo.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate user_lib;
|
||||
|
||||
use user_lib::{
|
||||
println, task_info, TaskInfo,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> usize {
|
||||
let info = TaskInfo::new();
|
||||
assert_eq!(0, task_info(&info));
|
||||
println!("task_info {:?}", info);
|
||||
0
|
||||
}
|
|
@ -45,3 +45,35 @@ pub fn yield_() -> isize {
|
|||
pub fn get_time() -> isize {
|
||||
sys_get_time()
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum TaskStatus {
|
||||
UnInit,
|
||||
Ready,
|
||||
Running,
|
||||
Exited,
|
||||
}
|
||||
|
||||
const MAX_SYSCALL_NUM: usize = 500;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TaskInfo {
|
||||
pub status: TaskStatus,
|
||||
pub syscall_times: [u32; MAX_SYSCALL_NUM],
|
||||
pub time: usize,
|
||||
}
|
||||
|
||||
impl TaskInfo {
|
||||
pub fn new() -> Self {
|
||||
TaskInfo {
|
||||
status: TaskStatus::UnInit,
|
||||
syscall_times: [0; MAX_SYSCALL_NUM],
|
||||
time: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn task_info(info: &TaskInfo) -> isize {
|
||||
sys_task_info(info)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use core::arch::asm;
|
||||
|
||||
use crate::TaskInfo;
|
||||
|
||||
const SYSCALL_WRITE: usize = 64;
|
||||
const SYSCALL_EXIT: usize = 93;
|
||||
const SYSCALL_YIELD: usize = 124;
|
||||
const SYSCALL_GET_TIME: usize = 169;
|
||||
pub const SYSCALL_TASK_INFO: usize = 410;
|
||||
|
||||
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||
let mut ret: isize;
|
||||
|
@ -34,3 +37,7 @@ pub fn sys_yield() -> isize {
|
|||
pub fn sys_get_time() -> isize {
|
||||
syscall(SYSCALL_GET_TIME, [0, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_task_info(info: &TaskInfo) -> isize {
|
||||
syscall(SYSCALL_TASK_INFO, [info as *const _ as usize, 0, 0])
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue