diff --git a/.dockerignore b/.dockerignore
index df3359d..8971c06 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1 +1,2 @@
-*/*
\ No newline at end of file
+*/*
+!rust-toolchain.toml
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index a365475..30731a7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,88 +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 GDB_VERSION=14.1
-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
-
-RUN wget https://ftp.gnu.org/gnu/gdb/gdb-${GDB_VERSION}.tar.xz && \
- tar xvJf gdb-${GDB_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 \
- libncurses5-dev python2 python2-dev libreadline-dev tmux
-
-
-# 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
-WORKDIR ${HOME}/gdb-${GDB_VERSION}
-RUN ./configure --prefix=/usr/local --target=riscv64-unknown-elf --enable-tui=yes && \
- make -j$(nproc) && \
- make install
+# Stage 2 Set Lab Environment
+FROM ubuntu:20.04 as build
-# 1.4. Clean up
-WORKDIR ${HOME}
-RUN rm -rf qemu-${QEMU_VERSION} qemu-${QEMU_VERSION}.tar.xz ${HOME}/gdb-${GDB_VERSION} gdb-${GDB_VERSION}.tar.xz
+WORKDIR /tmp
-# 1.5. Sanity checking
-RUN qemu-system-riscv64 --version && \
- qemu-riscv64 --version
+# 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. Set up Rust
-# - https://learningos.github.io/rust-based-os-comp2022/0setup-devel-env.html#qemu
+# 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 && \
+# 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 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
+
+# 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
-
-# Ready to go
-WORKDIR ${HOME}
+ rustc --version && \
+ riscv64-unknown-elf-gdb --version
\ No newline at end of file
diff --git a/Makefile b/Makefile
index bd267f4..ee4d7d1 100644
--- a/Makefile
+++ b/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 easy-fs; cargo fmt; cd ../easy-fs-fuse cargo fmt; cd ../os ; cargo fmt; cd ../user; cargo fmt; cd ..
diff --git a/os/.cargo/config b/os/.cargo/config.toml
similarity index 100%
rename from os/.cargo/config
rename to os/.cargo/config.toml
diff --git a/os/Makefile b/os/Makefile
index 5956c0e..b0c3463 100644
--- a/os/Makefile
+++ b/os/Makefile
@@ -90,20 +90,23 @@ fdt:
@qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out
fdtdump virt.out
-run-inner: build
+QEMU_NAME := qemu-system-riscv64
+qemu-version-check:
+ @sh scripts/qemu-ver-check.sh $(QEMU_NAME)
+
+run-inner: qemu-version-check build
@qemu-system-riscv64 $(QEMU_ARGS)
-debug: build
+debug: qemu-version-check build
@tmux new-session -d \
"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
+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 fs-img gdbserver gdbclient fdt
+.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient fdt qemu-version-check
diff --git a/os/scripts/qemu-ver-check.sh b/os/scripts/qemu-ver-check.sh
new file mode 100644
index 0000000..8c20456
--- /dev/null
+++ b/os/scripts/qemu-ver-check.sh
@@ -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
diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs
index 7cdd394..d607c88 100644
--- a/os/src/mm/memory_set.rs
+++ b/os/src/mm/memory_set.rs
@@ -77,7 +77,7 @@ impl MemorySet {
pub fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) {
map_area.map(&mut self.page_table);
if let Some(data) = data {
- map_area.copy_data(&mut self.page_table, data);
+ map_area.copy_data(&self.page_table, data);
}
self.areas.push(map_area);
}
@@ -316,7 +316,7 @@ impl MapArea {
}
/// data: start-aligned but maybe with shorter length
/// assume that all frames were cleared before
- pub fn copy_data(&mut self, page_table: &mut PageTable, data: &[u8]) {
+ pub fn copy_data(&mut self, page_table: &PageTable, data: &[u8]) {
assert_eq!(self.map_type, MapType::Framed);
let mut start: usize = 0;
let mut current_vpn = self.vpn_range.get_start();
diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs
index ca97e21..fe1343b 100644
--- a/os/src/task/mod.rs
+++ b/os/src/task/mod.rs
@@ -127,6 +127,13 @@ pub fn exit_current_and_run_next(exit_code: i32) {
process_inner.memory_set.recycle_data_pages();
// drop file descriptors
process_inner.fd_table.clear();
+ // Remove all tasks except for the main thread itself.
+ // This is because we are still using the kstack under the TCB
+ // of the main thread. This TCB, including its kstack, will be
+ // deallocated when the process is reaped via waitpid.
+ while process_inner.tasks.len() > 1 {
+ process_inner.tasks.pop();
+ }
}
drop(process);
// we do not have to save task context
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 61bbf13..c65d258 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,6 +1,6 @@
[toolchain]
profile = "minimal"
# use the nightly version of the last stable toolchain, see
-channel = "nightly-2024-01-18"
-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"]
diff --git a/user/.cargo/config b/user/.cargo/config.toml
similarity index 100%
rename from user/.cargo/config
rename to user/.cargo/config.toml
diff --git a/user/src/bin/adder_peterson_spin.rs b/user/src/bin/adder_peterson_spin.rs
index 1e9af5d..44e8096 100644
--- a/user/src/bin/adder_peterson_spin.rs
+++ b/user/src/bin/adder_peterson_spin.rs
@@ -8,7 +8,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
-use core::ptr::{addr_of, addr_of_mut, read_volatile};
+use core::ptr::addr_of_mut;
use core::sync::atomic::{compiler_fence, Ordering};
use user_lib::{exit, get_time, thread_create, waittid};
@@ -39,7 +39,7 @@ unsafe fn lock(id: usize) {
// Otherwise the compiler will assume that they will never
// be changed on this thread. Thus, they will be accessed
// only once!
- while read_volatile(addr_of!(FLAG[j])) && read_volatile(addr_of!(TURN)) == j {}
+ while vload!(FLAG[j]) && vload!(TURN) == j {}
}
unsafe fn unlock(id: usize) {
diff --git a/user/src/bin/adder_simple_spin.rs b/user/src/bin/adder_simple_spin.rs
index 57d9fa5..be99d28 100644
--- a/user/src/bin/adder_simple_spin.rs
+++ b/user/src/bin/adder_simple_spin.rs
@@ -6,7 +6,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
-use core::ptr::{addr_of, addr_of_mut, read_volatile};
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
static mut A: usize = 0;
@@ -25,7 +25,7 @@ unsafe fn critical_section(t: &mut usize) {
}
unsafe fn lock() {
- while read_volatile(addr_of!(OCCUPIED)) {}
+ while vload!(OCCUPIED) {}
OCCUPIED = true;
}
diff --git a/user/src/bin/eisenberg.rs b/user/src/bin/eisenberg.rs
index b16d3a7..49a1d45 100644
--- a/user/src/bin/eisenberg.rs
+++ b/user/src/bin/eisenberg.rs
@@ -8,7 +8,6 @@ extern crate core;
use alloc::vec::Vec;
use core::{
- ptr::{addr_of, addr_of_mut, read_volatile, write_volatile},
sync::atomic::{AtomicUsize, Ordering},
};
use user_lib::{exit, sleep, thread_create, waittid};
@@ -44,15 +43,15 @@ unsafe fn eisenberg_enter_critical(id: usize) {
/* announce that we want to enter */
loop {
println!("Thread[{}] try enter", id);
- write_volatile(addr_of_mut!(FLAG[id]), FlagState::Want);
+ vstore!(FLAG[id], FlagState::Want);
loop {
/* check if any with higher priority is `Want` or `In` */
let mut prior_thread: Option = None;
- let turn = read_volatile(addr_of!(TURN));
+ let turn = vload!(TURN);
let ring_id = if id < turn { id + THREAD_NUM } else { id };
// FLAG.iter() may lead to some errors, use for-loop instead
for i in turn..ring_id {
- if read_volatile(addr_of!(FLAG[i % THREAD_NUM])) != FlagState::Out {
+ if vload!(FLAG[i % THREAD_NUM]) != FlagState::Out {
prior_thread = Some(i % THREAD_NUM);
break;
}
@@ -68,13 +67,13 @@ unsafe fn eisenberg_enter_critical(id: usize) {
sleep(1);
}
/* now tentatively claim the resource */
- write_volatile(addr_of_mut!(FLAG[id]), FlagState::In);
+ vstore!(FLAG[id], FlagState::In);
/* enforce the order of `claim` and `conflict check`*/
memory_fence!();
/* check if anthor thread is also `In`, which imply a conflict*/
let mut conflict = false;
for i in 0..THREAD_NUM {
- if i != id && read_volatile(addr_of!(FLAG[i])) == FlagState::In {
+ if i != id && vload!(FLAG[i]) == FlagState::In {
conflict = true;
}
}
@@ -85,7 +84,7 @@ unsafe fn eisenberg_enter_critical(id: usize) {
/* no need to sleep */
}
/* clain the trun */
- write_volatile(addr_of_mut!(TURN), id);
+ vstore!(TURN, id);
println!("Thread[{}] enter", id);
}
@@ -95,14 +94,14 @@ unsafe fn eisenberg_exit_critical(id: usize) {
let ring_id = id + THREAD_NUM;
for i in (id + 1)..ring_id {
let idx = i % THREAD_NUM;
- if read_volatile(addr_of!(FLAG[idx])) == FlagState::Want {
+ if vload!(FLAG[idx]) == FlagState::Want {
next = idx;
break;
}
}
- write_volatile(addr_of_mut!(TURN), next);
+ vstore!(TURN, next);
/* All done */
- write_volatile(addr_of_mut!(FLAG[id]), FlagState::Out);
+ vstore!(FLAG[id], FlagState::Out);
println!("Thread[{}] exit, give turn to {}", id, next);
}
diff --git a/user/src/bin/gui_move.rs b/user/src/bin/gui_move.rs
new file mode 100644
index 0000000..240ff8f
--- /dev/null
+++ b/user/src/bin/gui_move.rs
@@ -0,0 +1,82 @@
+#![no_std]
+#![no_main]
+
+extern crate user_lib;
+extern crate alloc;
+
+use user_lib::console::getchar;
+use user_lib::{Display, VIRTGPU_XRES, VIRTGPU_YRES};
+
+use embedded_graphics::pixelcolor::Rgb888;
+use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size};
+use embedded_graphics::primitives::Primitive;
+use embedded_graphics::primitives::{PrimitiveStyle, Rectangle};
+use embedded_graphics::draw_target::DrawTarget;
+
+const INIT_X: i32 = 640;
+const INIT_Y: i32 = 400;
+const RECT_SIZE: u32 = 40;
+
+pub struct DrawingBoard {
+ disp: Display,
+ latest_pos: Point,
+}
+
+impl DrawingBoard {
+ pub fn new() -> Self {
+ Self {
+ disp: Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES)),
+ latest_pos: Point::new(INIT_X, INIT_Y),
+ }
+ }
+ fn paint(&mut self) {
+ Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
+ .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1))
+ .draw(&mut self.disp)
+ .ok();
+ }
+ fn unpaint(&mut self) {
+ Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
+ .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1))
+ .draw(&mut self.disp)
+ .ok();
+ }
+ pub fn move_rect(&mut self, dx: i32, dy: i32) {
+ let new_x = self.latest_pos.x + dx;
+ let new_y = self.latest_pos.y + dy;
+ let r = (RECT_SIZE / 2) as i32;
+ if new_x > r && new_x + r < (VIRTGPU_XRES as i32) && new_y > r && new_y + r < (VIRTGPU_YRES as i32) {
+ self.unpaint();
+ self.latest_pos.x = new_x;
+ self.latest_pos.y = new_y;
+ self.paint();
+ }
+ }
+}
+
+const LF: u8 = 0x0au8;
+const CR: u8 = 0x0du8;
+#[no_mangle]
+pub fn main() -> i32 {
+ let mut board = DrawingBoard::new();
+ let _ = board.disp.clear(Rgb888::BLACK).unwrap();
+ board.disp.flush();
+ loop {
+ let c = getchar();
+ if c == LF || c == CR {
+ break;
+ }
+ let mut moved = true;
+ match c {
+ b'w' => board.move_rect(0, -10),
+ b'a' => board.move_rect(-10, 0),
+ b's' => board.move_rect(0, 10),
+ b'd' => board.move_rect(10, 0),
+ _ => moved = false,
+ }
+ if moved {
+ board.disp.flush();
+ }
+ }
+ 0
+}
diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_shape.rs
similarity index 78%
rename from user/src/bin/gui_rect.rs
rename to user/src/bin/gui_shape.rs
index 1f377de..df03df3 100644
--- a/user/src/bin/gui_rect.rs
+++ b/user/src/bin/gui_shape.rs
@@ -44,18 +44,6 @@ impl DrawingBoard {
.draw(&mut self.disp)
.ok();
}
- fn unpaint(&mut self) {
- Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
- .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 10))
- .draw(&mut self.disp)
- .ok();
- }
- pub fn move_rect(&mut self, dx: i32, dy: i32) {
- self.unpaint();
- self.latest_pos.x += dx;
- self.latest_pos.y += dy;
- self.paint();
- }
}
#[no_mangle]
@@ -64,8 +52,8 @@ pub fn main() -> i32 {
let _ = board.disp.clear(Rgb888::BLACK).unwrap();
for _ in 0..5 {
board.latest_pos.x += RECT_SIZE as i32 + 20;
- //board.latest_pos.y += i;
board.paint();
}
+ board.disp.flush();
0
}
diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs
index 0411824..6dd4052 100644
--- a/user/src/bin/gui_snake.rs
+++ b/user/src/bin/gui_snake.rs
@@ -328,7 +328,7 @@ const CR: u8 = 0x0du8;
#[no_mangle]
pub fn main() -> i32 {
let mut disp = Display::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES));
- let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 50);
+ let mut game = SnakeGame::<20, Rgb888>::new(1280, 800, 20, 20, Rgb888::RED, Rgb888::YELLOW, 200);
let _ = disp.clear(Rgb888::BLACK).unwrap();
loop {
if key_pressed() {
@@ -345,7 +345,8 @@ pub fn main() -> i32 {
}
let _ = disp.clear(Rgb888::BLACK).unwrap();
game.draw(&mut disp);
- sleep(10);
+ disp.flush();
+ sleep(40);
}
0
}
diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_tri.rs
similarity index 97%
rename from user/src/bin/gui_simple.rs
rename to user/src/bin/gui_tri.rs
index f30b1fc..69d47f5 100644
--- a/user/src/bin/gui_simple.rs
+++ b/user/src/bin/gui_tri.rs
@@ -19,5 +19,6 @@ pub fn main() -> i32 {
}
}
});
+ disp.flush();
0
}
diff --git a/user/src/bin/gui_uart.rs b/user/src/bin/gui_uart.rs
deleted file mode 100644
index 8e9c9b8..0000000
--- a/user/src/bin/gui_uart.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-#![no_std]
-#![no_main]
-
-#[macro_use]
-extern crate user_lib;
-extern crate alloc;
-
-use user_lib::console::getchar;
-use user_lib::{framebuffer, framebuffer_flush};
-
-use embedded_graphics::pixelcolor::Rgb888;
-use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size};
-use embedded_graphics::primitives::Primitive;
-use embedded_graphics::primitives::{PrimitiveStyle, Rectangle};
-use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions};
-
-pub const VIRTGPU_XRES: usize = 1280;
-pub const VIRTGPU_YRES: usize = 800;
-pub const VIRTGPU_LEN: usize = VIRTGPU_XRES * VIRTGPU_YRES * 4;
-
-const INIT_X: i32 = 640;
-const INIT_Y: i32 = 400;
-const RECT_SIZE: u32 = 40;
-
-pub struct Display {
- pub size: Size,
- pub point: Point,
- //pub fb: Arc<&'static mut [u8]>,
- pub fb: &'static mut [u8],
-}
-
-impl Display {
- pub fn new(size: Size, point: Point) -> Self {
- let fb_ptr = framebuffer() as *mut u8;
- println!(
- "Hello world from user mode program! 0x{:X} , len {}",
- fb_ptr as usize, VIRTGPU_LEN
- );
- let fb =
- unsafe { core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_LEN as usize) };
- Self { size, point, fb }
- }
-}
-
-impl OriginDimensions for Display {
- fn size(&self) -> Size {
- self.size
- }
-}
-
-impl DrawTarget for Display {
- type Color = Rgb888;
-
- type Error = core::convert::Infallible;
-
- fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error>
- where
- I: IntoIterator- >,
- {
- pixels.into_iter().for_each(|px| {
- let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x)
- as usize
- * 4;
- if idx + 2 >= self.fb.len() {
- return;
- }
- self.fb[idx] = px.1.b();
- self.fb[idx + 1] = px.1.g();
- self.fb[idx + 2] = px.1.r();
- });
- framebuffer_flush();
- Ok(())
- }
-}
-
-pub struct DrawingBoard {
- disp: Display,
- latest_pos: Point,
-}
-
-impl DrawingBoard {
- pub fn new() -> Self {
- Self {
- disp: Display::new(Size::new(1280, 800), Point::new(0, 0)),
- latest_pos: Point::new(INIT_X, INIT_Y),
- }
- }
- fn paint(&mut self) {
- Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
- .into_styled(PrimitiveStyle::with_stroke(Rgb888::WHITE, 1))
- .draw(&mut self.disp)
- .ok();
- }
- fn unpaint(&mut self) {
- Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE))
- .into_styled(PrimitiveStyle::with_stroke(Rgb888::BLACK, 1))
- .draw(&mut self.disp)
- .ok();
- }
- pub fn move_rect(&mut self, dx: i32, dy: i32) {
- self.unpaint();
- self.latest_pos.x += dx;
- self.latest_pos.y += dy;
- self.paint();
- }
-}
-
-const LF: u8 = 0x0au8;
-const CR: u8 = 0x0du8;
-#[no_mangle]
-pub fn main() -> i32 {
- // let fb_ptr = framebuffer() as *mut u8;
- let mut board = DrawingBoard::new();
- let _ = board.disp.clear(Rgb888::BLACK).unwrap();
- for i in 0..20 {
- let c = getchar();
- if c == LF || c == CR {
- break;
- }
- board.latest_pos.x += i;
- board.latest_pos.y += i;
- board.paint();
- }
- 0
-}
diff --git a/user/src/bin/peterson.rs b/user/src/bin/peterson.rs
index c370c87..e03e2a4 100644
--- a/user/src/bin/peterson.rs
+++ b/user/src/bin/peterson.rs
@@ -7,7 +7,6 @@ extern crate alloc;
extern crate core;
use alloc::vec::Vec;
-use core::ptr::{addr_of, addr_of_mut, read_volatile, write_volatile};
use core::sync::atomic::{AtomicUsize, Ordering};
use user_lib::{exit, sleep, thread_create, waittid};
const N: usize = 1000;
@@ -30,10 +29,10 @@ fn critical_test_exit() {
unsafe fn peterson_enter_critical(id: usize, peer_id: usize) {
// println!("Thread[{}] try enter", id);
- write_volatile(addr_of_mut!(FLAG[id]), true);
- write_volatile(addr_of_mut!(TURN), peer_id);
+ vstore!(FLAG[id], true);
+ vstore!(TURN, peer_id);
memory_fence!();
- while read_volatile(addr_of!(FLAG[peer_id])) && read_volatile(addr_of!(TURN)) == peer_id {
+ while vload!(FLAG[peer_id]) && vload!(TURN) == peer_id {
// println!("Thread[{}] enter fail", id);
sleep(1);
// println!("Thread[{}] retry enter", id);
@@ -42,7 +41,7 @@ unsafe fn peterson_enter_critical(id: usize, peer_id: usize) {
}
unsafe fn peterson_exit_critical(id: usize) {
- write_volatile(addr_of_mut!(FLAG[id]), false);
+ vstore!(FLAG[id], false);
// println!("Thread[{}] exit", id);
}
diff --git a/user/src/io.rs b/user/src/io.rs
index 30e7a1c..d2c2a0a 100644
--- a/user/src/io.rs
+++ b/user/src/io.rs
@@ -32,6 +32,8 @@ impl Display {
}
pub fn paint_on_framebuffer(&mut self, p: impl FnOnce(&mut [u8]) -> ()) {
p(self.framebuffer());
+ }
+ pub fn flush(&self) {
framebuffer_flush();
}
}
@@ -60,7 +62,6 @@ impl DrawTarget for Display {
self.fb[idx + 1] = px.1.g();
self.fb[idx + 2] = px.1.r();
});
- framebuffer_flush();
Ok(())
}
}
diff --git a/user/src/lib.rs b/user/src/lib.rs
index ca6181f..8c709fc 100644
--- a/user/src/lib.rs
+++ b/user/src/lib.rs
@@ -70,15 +70,17 @@ fn main(_argc: usize, _argv: &[&str]) -> i32 {
#[macro_export]
macro_rules! vstore {
- ($var_ref: expr, $value: expr) => {
- unsafe { core::intrinsics::volatile_store($var_ref as *const _ as _, $value) }
+ ($var: expr, $value: expr) => {
+ // unsafe { core::intrinsics::volatile_store($var_ref as *const _ as _, $value) }
+ unsafe { core::ptr::write_volatile(core::ptr::addr_of_mut!($var), $value); }
};
}
#[macro_export]
macro_rules! vload {
- ($var_ref: expr) => {
- unsafe { core::intrinsics::volatile_load($var_ref as *const _ as _) }
+ ($var: expr) => {
+ // unsafe { core::intrinsics::volatile_load($var_ref as *const _ as _) }
+ unsafe { core::ptr::read_volatile(core::ptr::addr_of!($var)) }
};
}