diff --git a/os/Cargo.toml b/os/Cargo.toml index 89732b9b..fde4b6cb 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -10,7 +10,6 @@ edition = "2021" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } buddy_system_allocator = "0.6" -bit_field = "0.10.0" bitflags = "1.2.1" xmas-elf = "0.7.0" volatile = "0.3" diff --git a/os/Makefile b/os/Makefile index a8bb617f..10c853a6 100644 --- a/os/Makefile +++ b/os/Makefile @@ -24,7 +24,7 @@ ifeq ($(MODE), release) endif # KERNEL ENTRY -KERNEL_ENTRY_PA := 0x80000000 +KERNEL_ENTRY_PA := 0x80200000 # Binutils OBJDUMP := rust-objdump --arch-name=riscv64 @@ -109,18 +109,6 @@ fdt: @qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out fdtdump virt.out -debug-none: build - @tmux new-session -d \ - "qemu-system-riscv64 -machine virt -nographic -bios none -kernel $(KERNEL_ELF) \ - -drive file=$(FS_IMG),if=none,format=raw,id=x0 \ - -device virtio-blk-device,drive=x0 \ - -device virtio-keyboard-device \ - -device virtio-mouse-device \ - -serial stdio \ - -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 - debug: build @tmux new-session -d \ "qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \ diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs index 0c8e9b4e..35ac031b 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -2,9 +2,9 @@ pub const CLOCK_FREQ: usize = 12500000; pub const MMIO: &[(usize, usize)] = &[ (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine - (0x2000000, 0x10000), // core local interrupter (CLINT) - (0xc000000, 0x210000), // VIRT_PLIC in virt machine - (0x10000000, 0x9000), // VIRT_UART0 with GPU in virt machine + (0x2000000, 0x10000), // core local interrupter (CLINT) + (0xc000000, 0x210000), // VIRT_PLIC in virt machine + (0x10000000, 0x9000), // VIRT_UART0 with GPU in virt machine ]; pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock; @@ -52,54 +52,3 @@ pub fn irq_handler() { } plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id); } - - -// core local interrupter (CLINT), which contains the timer -pub const CLINT: usize = 0x2000000; -// pub const fn clint_mtimecmp(hartid: usize) -> usize { -// CLINT + 0x4000 + 8 * hartid -// } -pub const CLINT_MTIME: usize = CLINT + 0xBFF8; // Cycles since boot. -pub const CLINT_MTIMECMP: usize = CLINT + 0x4000; - -#[naked] -#[repr(align(16))] // if miss this alignment, a load access fault will occur. -#[no_mangle] -pub unsafe extern "C" fn timervec() -> ! { - // start.rs has set up the memory that mscratch points to: - // scratch[0,8,16] : register save area. - // scratch[24] : address of CLINT's MTIMECMP register. - // scratch[32] : desired interval between interrupts. - - // Now, mscrach has a pointer to an additional scratch space. - // to aboid overwriting the contents of the integer registers, - // the prologue of an interrupts handler usually begins by swapping - // an integer register(say a0) with mscratch CSR. - // The interrupt handler stores the integer registers - // used for processing in this scratch space. - // a0 saved in mscrach, a1 ~ a3 saved in scratch space. - //loop {} - core::arch::asm!( - "csrrw a0, mscratch, a0", - "sd a1, 0(a0)", - "sd a2, 8(a0)", - "sd a3, 16(a0)", - // schedule the next timer interrupt - // by adding interval to mtimecmp. - "ld a1, 24(a0)", // CLINT_MTIMECMP(hartid) contents - "ld a2, 32(a0)", // interval - "ld a3, 0(a1)", - "add a3, a3, a2", - "sd a3, 0(a1)", - // raise a supervisor software interrupt. - "li a1, 2", - "csrw sip, a1", - // restore and return - "ld a3, 16(a0)", - "ld a2, 8(a0)", - "ld a1, 0(a0)", - "csrrw a0, mscratch, a0", - "mret", - options(noreturn) - ); -} diff --git a/os/src/drivers/block/virtio_blk.rs b/os/src/drivers/block/virtio_blk.rs index fb2c8200..fb89084d 100644 --- a/os/src/drivers/block/virtio_blk.rs +++ b/os/src/drivers/block/virtio_blk.rs @@ -1,10 +1,10 @@ use super::BlockDevice; +use crate::drivers::bus::virtio::VirtioHal; use crate::sync::{Condvar, UPIntrFreeCell}; use crate::task::schedule; use crate::DEV_NON_BLOCKING_ACCESS; use alloc::collections::BTreeMap; use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader}; -use crate::drivers::bus::virtio::VirtioHal; #[allow(unused)] const VIRTIO0: usize = 0x10008000; diff --git a/os/src/drivers/gpu/mod.rs b/os/src/drivers/gpu/mod.rs index 0108f249..759633ff 100644 --- a/os/src/drivers/gpu/mod.rs +++ b/os/src/drivers/gpu/mod.rs @@ -1,10 +1,10 @@ +use crate::drivers::bus::virtio::VirtioHal; use crate::sync::UPIntrFreeCell; use alloc::{sync::Arc, vec::Vec}; use core::any::Any; use embedded_graphics::pixelcolor::Rgb888; use tinybmp::Bmp; use virtio_drivers::{VirtIOGpu, VirtIOHeader}; -use crate::drivers::bus::virtio::VirtioHal; const VIRTIO7: usize = 0x10007000; pub trait GpuDevice: Send + Sync + Any { fn update_cursor(&self); diff --git a/os/src/entry.asm b/os/src/entry.asm index 1d1a1752..c32d68fd 100644 --- a/os/src/entry.asm +++ b/os/src/entry.asm @@ -2,7 +2,7 @@ .globl _start _start: la sp, boot_stack_top - call rust_start + call rust_main .section .bss.stack .globl boot_stack_lower_bound diff --git a/os/src/linker-qemu.ld b/os/src/linker-qemu.ld index 92dd51cd..5baafbd0 100644 --- a/os/src/linker-qemu.ld +++ b/os/src/linker-qemu.ld @@ -1,6 +1,6 @@ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0x80000000; +BASE_ADDRESS = 0x80200000; SECTIONS { diff --git a/os/src/main.rs b/os/src/main.rs index cc194cfb..276aaf52 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -2,8 +2,6 @@ #![no_main] #![feature(panic_info_message)] #![feature(alloc_error_handler)] -#![feature(naked_functions)] -#![feature(fn_align)] //use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE, INPUT_CONDVAR}; use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE}; @@ -14,7 +12,7 @@ extern crate bitflags; #[path = "boards/qemu.rs"] mod board; -use board::*; + #[macro_use] mod console; mod config; @@ -30,15 +28,8 @@ mod task; mod timer; mod trap; -use riscv::register::*; -// mod riscvreg; -// use riscvreg::{ -// mstatus, mepc, satp, medeleg, mideleg, sie, mhartid, tp, clint, -// mscratch, mtvec, mie, sstatus -// }; -// use riscvregs::registers::*; -// use riscvregs::registers::pmpcfg0::*; -//use syscall::create_desktop; //for test +use crate::drivers::chardev::CharDevice; +use crate::drivers::chardev::UART; core::arch::global_asm!(include_str!("entry.asm")); @@ -61,198 +52,9 @@ lazy_static! { unsafe { UPIntrFreeCell::new(false) }; } - -#[repr(C, align(16))] -struct Stack([u8; 4096 * 4 * 1]); - -#[no_mangle] -static mut STACK0: Stack = Stack([0; 4096 * 4 * 1]); - -#[inline] -pub unsafe fn medeleg_write(medeleg: usize){ - core::arch::asm!("csrw medeleg, {}",in(reg)medeleg); -} - -pub unsafe fn mideleg_write(mideleg: usize) { - core::arch::asm!("csrw mideleg, {}", in(reg)mideleg); -} - -pub enum SIE { - SEIE = 1 << 9, // external - STIE = 1 << 5, // timer - SSIE = 1 << 1, // software -} - -#[inline] -pub unsafe fn sie_read() -> usize { - let ret:usize; - core::arch::asm!("csrr {}, sie", out(reg)ret); - ret -} - -#[inline] -pub unsafe fn sie_write(x:usize) { - core::arch::asm!("csrw sie, {}", in(reg)x); -} - -/// enable all software interrupts -/// still need to set SIE bit in sstatus -pub unsafe fn intr_on() { - let mut sie = sie_read(); - sie |= SIE::SSIE as usize | SIE::STIE as usize | SIE::SEIE as usize; - sie_write(sie); -} - -#[no_mangle] -pub unsafe fn rust_start() -> ! { - // set MPP mode to Supervisor, for mret - mstatus::set_mpp(mstatus::MPP::Supervisor); - - // set MEPC to main, for mret - mepc::write(rust_main as usize); - - // disable paging for now. - satp::write(0); - - // delegate all interrupts and exceptions to supervisor mode. - medeleg_write(0xffff); - mideleg_write(0xffff); - intr_on(); - - // configure Physical Memory Protection to give supervisor mode - // access to all of physical memory. - pmpaddr0::write(0x3fffffffffffff); - pmpcfg0::write(0xf); - //pmpcfg0::set_pmp(0, Range::TOR, Permission::RWX, false); // 0 < addr < pmpaddr0 - - // ask for clock interrupts. - timer_init(); - - // keep each CPU's hartid in its tp register, for cpuid(). - // let id = mhartid::read(); - // core::arch::asm!("mv tp, {0}", in(reg) id); - - // switch to supervisor mode and jump to main(). - core::arch::asm!("mret"); - - extern "C" { - fn rust_main() -> !; - } - core::hint::unreachable_unchecked(); -} - -use core::convert::Into; -use core::ptr; - -// a scratch area per CPU for machine-mode timer interrupts. -static mut TIMER_SCRATCH: [u64; 5] = [0; 5]; - -#[inline] -unsafe fn read_mtime() -> u64 { - ptr::read_volatile(Into::::into(CLINT_MTIME) as *const u64) -} - -unsafe fn write_mtimecmp(value: u64) { - let offset = Into::::into(CLINT_MTIMECMP); - ptr::write_volatile(offset as *mut u64, value); -} - -pub unsafe fn add_mtimecmp(interval:u64){ - let value = read_mtime(); - write_mtimecmp(value+interval); -} - -pub fn count_mtiecmp() -> usize{ - let ret:usize; - ret = Into::::into(CLINT) + 0x4000; - ret -} - -#[inline] -pub unsafe fn mtvec_write(x:usize){ - core::arch::asm!("csrw mtvec, {}",in(reg)x); -} - -use bit_field::BitField; - -#[inline] -unsafe fn mstatus_read() -> usize { - let ret:usize; - core::arch::asm!("csrr {}, mstatus",out(reg)ret); - ret -} - -#[inline] -unsafe fn mstatus_write(x: usize) { - core::arch::asm!("csrw mstatus, {}",in(reg)x); -} - -// enable machine-mode interrupts. -pub unsafe fn mstatus_enable_interrupt(){ - let mut mstatus = mstatus_read(); - mstatus.set_bit(3, true); - mstatus_write(mstatus); -} - - -pub enum MIE { - MEIE = 1 << 11, // external - MTIE = 1 << 7, // timer - MSIE = 1 << 3 // software -} - -#[inline] -pub unsafe fn mie_read() -> usize { - let ret:usize; - core::arch::asm!("csrr {}, mie", out(reg)ret); - ret -} - -#[inline] -pub unsafe fn mie_write(x:usize){ - core::arch::asm!("csrw mie, {}",in(reg)x); -} - -unsafe fn timer_init() { - clear_bss(); - // each CPU has a separate source of timer interrupts - //let id = mhartid::read(); - - // ask the CLINT for a timer interrupts - let interval = 1000000u64; // cycles; about 1/10th second in qemu. - add_mtimecmp(interval); - // let mtimecmp = board::clint_mtimecmp(0) as *mut u64; - // let mtime = board::CLINT_MTIME as *const u64; - // mtimecmp.write_volatile(mtime.read_volatile() + interval); - - // prepare information in scratch[] for timervec. - // scratch[0..2] : space for timervec to save registers. - // scratch[3] : address of CLINT MTIMECMP register. - // scratch[4] : desired interval (in cycles) between timer interrupts. - let scratch = &mut TIMER_SCRATCH; - scratch[3] = count_mtiecmp() as u64; - scratch[4] = interval; - mscratch::write(scratch.as_mut_ptr() as usize); - - // set the machine-mode trap handler - mtvec_write(timervec as usize); - //mtvec::write(board::timervec as usize, mtvec::TrapMode::Direct); - - // enable machine-mode interrupts. - mstatus_enable_interrupt(); - //mstatus::set_mie(); - - // enable machine-mode timer interrupts. - mie_write(mie_read() | MIE::MTIE as usize); - //mie::set_mtimer(); -} - -use crate::drivers::chardev::CharDevice; -use crate::drivers::chardev::UART; #[no_mangle] pub fn rust_main() -> ! { - - //clear_bss(); + clear_bss(); mm::init(); UART.init(); println!("KERN: init gpu"); @@ -263,8 +65,8 @@ pub fn rust_main() -> ! { let _mouse = MOUSE_DEVICE.clone(); println!("KERN: init trap"); trap::init(); - //trap::enable_timer_interrupt(); - //timer::set_next_trigger(); + trap::enable_timer_interrupt(); + timer::set_next_trigger(); board::device_init(); fs::list_apps(); task::add_initproc(); diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 3635e18e..163bb57a 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -75,7 +75,7 @@ impl FrameAllocator for StackFrameAllocator { None } else { self.current += pages; - let arr:Vec = (1..pages + 1).collect(); + let arr: Vec = (1..pages + 1).collect(); let v = arr.iter().map(|x| (self.current - x).into()).collect(); Some(v) } @@ -144,7 +144,6 @@ pub fn frame_allocator_test() { println!("frame_allocator_test passed!"); } - #[allow(unused)] pub fn frame_allocator_alloc_more_test() { let mut v: Vec = Vec::new(); diff --git a/os/src/net/mod.rs b/os/src/net/mod.rs index f98f5662..469a3651 100644 --- a/os/src/net/mod.rs +++ b/os/src/net/mod.rs @@ -1,7 +1,7 @@ +pub mod port_table; pub mod socket; pub mod tcp; pub mod udp; -pub mod port_table; pub use lose_net_stack::IPv4; @@ -95,7 +95,7 @@ pub fn net_interrupt_handler() { if let Some(socket_index) = get_socket(target, lport, rport) { push_data(socket_index, tcp_packet.data.to_vec()); set_s_a_by_index(socket_index, tcp_packet.seq, tcp_packet.ack); - } + } } _ => {} } diff --git a/os/src/net/port_table.rs b/os/src/net/port_table.rs index fa178cf1..bcda046b 100644 --- a/os/src/net/port_table.rs +++ b/os/src/net/port_table.rs @@ -1,4 +1,4 @@ -use alloc::{vec::Vec, sync::Arc}; +use alloc::{sync::Arc, vec::Vec}; use lazy_static::lazy_static; use lose_net_stack::packets::tcp::TCPPacket; @@ -11,7 +11,7 @@ use super::tcp::TCP; pub struct Port { pub port: u16, pub receivable: bool, - pub schedule: Option> + pub schedule: Option>, } lazy_static! { @@ -32,7 +32,7 @@ pub fn listen(port: u16) -> Option { let listen_port = Port { port, receivable: false, - schedule: None + schedule: None, }; if index == usize::MAX { @@ -66,10 +66,13 @@ pub fn port_acceptable(listen_index: usize) -> bool { // check whether it can accept request pub fn check_accept(port: u16, tcp_packet: &TCPPacket) -> Option<()> { LISTEN_TABLE.exclusive_session(|listen_table| { - let mut listen_ports: Vec<&mut Option> = listen_table.iter_mut().filter(|x| match x { - Some(t) => t.port == port && t.receivable == true, - None => false, - }).collect(); + let mut listen_ports: Vec<&mut Option> = listen_table + .iter_mut() + .filter(|x| match x { + Some(t) => t.port == port && t.receivable == true, + None => false, + }) + .collect(); if listen_ports.len() == 0 { None } else { @@ -90,7 +93,13 @@ pub fn accept_connection(_port: u16, tcp_packet: &TCPPacket, task: Arc>, // datas pub seq: u32, - pub ack: u32 + pub ack: u32, } lazy_static! { @@ -26,11 +26,9 @@ pub fn get_s_a_by_index(index: usize) -> Option<(u32, u32)> { assert!(index < socket_table.len()); - socket_table.get(index).map_or(None, |x| { - match x { - Some(x) => Some((x.seq, x.ack)), - None => None, - } + socket_table.get(index).map_or(None, |x| match x { + Some(x) => Some((x.seq, x.ack)), + None => None, }) } @@ -40,9 +38,7 @@ pub fn set_s_a_by_index(index: usize, seq: u32, ack: u32) { assert!(socket_table.len() > index); assert!(socket_table[index].is_some()); - let sock = socket_table[index] - .as_mut() - .unwrap(); + let sock = socket_table[index].as_mut().unwrap(); sock.ack = ack; sock.seq = seq; @@ -84,7 +80,7 @@ pub fn add_socket(raddr: IPv4, lport: u16, rport: u16) -> Option { rport, buffers: VecDeque::new(), seq: 0, - ack: 0 + ack: 0, }; if index == usize::MAX { diff --git a/os/src/net/tcp.rs b/os/src/net/tcp.rs index 5cd7cb32..d1f7bd2d 100644 --- a/os/src/net/tcp.rs +++ b/os/src/net/tcp.rs @@ -1,8 +1,8 @@ use alloc::vec; -use lose_net_stack::MacAddress; -use lose_net_stack::IPv4; -use lose_net_stack::TcpFlags; use lose_net_stack::packets::tcp::TCPPacket; +use lose_net_stack::IPv4; +use lose_net_stack::MacAddress; +use lose_net_stack::TcpFlags; use crate::{drivers::NET_DEVICE, fs::File}; diff --git a/os/src/riscvregs.rs b/os/src/riscvregs.rs deleted file mode 100644 index 18712422..00000000 --- a/os/src/riscvregs.rs +++ /dev/null @@ -1,614 +0,0 @@ -// RISC-V registers -pub mod registers { - // hart (core) id registers - pub mod mhartid { - use core::arch::asm; - - #[inline] - pub fn read() -> usize { - let id: usize; - unsafe { - asm!("csrr {}, mhartid", out(reg) id); - } - id - } - } - - // Machine Status Register, mstatus - pub mod mstatus { - use core::arch::asm; - - // Machine Status Register bit - const MPP_MASK: usize = 3 << 11; - const MIE: usize = 1 << 3; - - // Machine Previous Privilege mode - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub enum MPP { - Machine = 3, - Supervisor = 1, - User = 0, - } - - #[inline] - unsafe fn _read() -> usize { - let bits: usize; - asm!("csrr {}, mstatus", out(reg) bits); - bits - } - - #[inline] - unsafe fn _write(bits: usize) { - asm!("csrw mstatus, {}", in(reg) bits); - } - - // Machine Previous Privilege Mode - #[inline] - pub fn set_mpp(mpp: MPP) { - unsafe { - let mut value = _read(); - value &= !MPP_MASK; - value |= (mpp as usize) << 11; - _write(value); - } - } - - #[inline] - pub fn set_mie() { - unsafe { - asm!("csrs mstatus, {}", in(reg) MIE); - } - } - } - - // machine exception program counter, holds the - // instruction address to which a return from - // exception will go. - pub mod mepc { - use core::arch::asm; - - #[inline] - pub fn write(x: usize) { - unsafe { - asm!("csrw mepc, {}", in(reg) x); - } - } - } - - // Supervisor Status Register, sstatus - pub mod sstatus { - use core::arch::asm; - - // Supervisor Status Register bit - const SPP: usize = 1 << 8; // Previous mode, 1=Supervisor, 0=user - const SPIE: usize = 1 << 5; // Supervisor Previous Interrupt Enable - const SIE: usize = 1 << 1; // Supervisor Interrupt Enable - - #[derive(Clone, Copy, Debug)] - pub struct Sstatus { - bits: usize, - } - - impl Sstatus { - // Supervisor Interrupt Enable - #[inline] - pub(in crate::riscvregs) fn sie(&self) -> bool { - self.bits & SIE != 0 - } - - // Supervisor Previous Privilege mode - #[inline] - pub fn spp(&self) -> SPP { - match self.bits & SPP { - 0 => SPP::User, - _ => SPP::Supervisor, - } - } - - // restore status bits - #[inline] - pub fn restore(&self) { - unsafe { - _write(self.bits); - } - } - } - - // Supervisor Previous Privilege Mode - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub enum SPP { - Supervisor = 1, - User = 0, - } - - #[inline] - pub fn read() -> Sstatus { - let bits: usize; - unsafe { asm!("csrr {}, sstatus", out(reg) bits) } - Sstatus { bits } - } - - #[inline] - unsafe fn _write(bits: usize) { - asm!("csrw sstatus, {}", in(reg) bits); - } - - // bit set - #[inline] - unsafe fn _set(bits: usize) { - asm!("csrs sstatus, {}", in(reg) bits); - } - - // bit clear - #[inline] - unsafe fn _clear(bits: usize) { - asm!("csrc sstatus, {}", in(reg) bits); - } - - #[inline] - pub(in crate::riscvregs) unsafe fn set_sie() { - _set(SIE) - } - - #[inline] - pub(in crate::riscvregs) unsafe fn clear_sie() { - _clear(SIE) - } - - #[inline] - pub unsafe fn set_spie() { - _set(SPIE); - } - - #[inline] - pub unsafe fn set_spp(spp: SPP) { - match spp { - SPP::Supervisor => _set(SPP), - SPP::User => _clear(SPP), - } - } - } - - // Supervisor Interrupt Pending - pub mod sip { - use core::arch::asm; - - const SSIP: usize = 1 << 1; - - // Supervisor Software Interrupt Pending - #[inline] - pub unsafe fn clear_ssoft() { - asm!("csrc sip, {}", in(reg) SSIP); - } - } - - // Supervisor Interrupt Enable - pub mod sie { - use core::arch::asm; - - const SEIE: usize = 1 << 9; // external - const STIE: usize = 1 << 5; // timer - const SSIE: usize = 1 << 1; // software - - #[inline] - unsafe fn _set(bits: usize) { - asm!("csrs sie, {}", in(reg) bits); - } - - #[inline] - pub unsafe fn set_sext() { - _set(SEIE); - } - - #[inline] - pub unsafe fn set_stimer() { - _set(STIE); - } - - #[inline] - pub unsafe fn set_ssoft() { - _set(SSIE); - } - } - - // Machine-mode Interrupt Enable - pub mod mie { - use core::arch::asm; - - const MTIE: usize = 1 << 7; - - #[inline] - pub unsafe fn set_mtimer() { - asm!("csrs mie, {}", in(reg) MTIE); - } - } - - // supervisor exceptions program counter, holds the - // instruction address to which a return from - // exception will go. - pub mod sepc { - use core::arch::asm; - - #[inline] - pub fn read() -> usize { - let bits: usize; - unsafe { - asm!("csrr {}, sepc", out(reg) bits); - } - bits - } - - #[inline] - pub fn write(bits: usize) { - unsafe { - asm!("csrw sepc, {}", in(reg) bits); - } - } - } - - // Machine Exception Delegation - pub mod medeleg { - use core::arch::asm; - - pub unsafe fn set_all() { - asm!("csrw medeleg, {}", in(reg) 0xffff); - } - } - - // Machine Interrupt Delegation - pub mod mideleg { - use core::arch::asm; - - #[inline] - pub unsafe fn set_all() { - asm!("csrw mideleg, {}", in(reg) 0xffff); - } - } - - // Supervisor Trap-Vector Base Address - // low two bits are mode. - pub mod stvec { - pub use super::mtvec::TrapMode; - use core::arch::asm; - - #[inline] - pub unsafe fn write(addr: usize, mode: TrapMode) { - asm!("csrw stvec, {}", in(reg) addr + mode as usize); - } - } - - // Machine-mode interrupt vector - pub mod mtvec { - use core::arch::asm; - - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub enum TrapMode { - Direct = 0, - Vectored = 1, - } - - #[inline] - pub unsafe fn write(addr: usize, mode: TrapMode) { - asm!("csrw mtvec, {}", in(reg) addr + mode as usize); - } - } - - // Physical Memory Protection Configuration - pub mod pmpcfg0 { - use core::arch::asm; - - // Permission enum contains all possible permission modes for pmp registers - #[derive(Clone, Copy, Debug)] - pub enum Permission { - NONE = 0b000, - R = 0b001, - W = 0b010, - RW = 0b011, - X = 0b100, - RX = 0b101, - WX = 0b110, - RWX = 0b111, - } - - // Range enum contains all possible addressing modes for pmp registers - pub enum Range { - OFF = 0b00, - TOR = 0b01, - NA4 = 0b10, - NAPOT = 0b11, - } - - // Set the pmp configuration corresponging to the index - #[inline] - pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) { - assert!(index < 8); - let mut value = _read(); - let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize); - value |= byte << (8 * index); - _write(value); - } - - #[inline] - unsafe fn _read() -> usize { - let bits: usize; - asm!("csrr {}, pmpcfg0", out(reg) bits); - bits - } - - #[inline] - unsafe fn _write(bits: usize) { - asm!("csrw pmpcfg0, {}", in(reg) bits); - } - } - - // Physical memory protection address register - pub mod pmpaddr0 { - use core::arch::asm; - - pub fn write(bits: usize) { - unsafe { - asm!("csrw pmpaddr0, {}", in(reg) bits); - } - } - } - - // Supervisor address translation and protection; - // holds the address of the page table. - pub mod satp { - use core::arch::asm; - - // stap register - #[derive(Clone, Copy, Debug)] - pub struct Satp { - bits: usize, - } - - // 64-bit satp mode - pub enum Mode { - // No translation or protection - Bare = 0, - // Page-based 39-bit virtual addressing - Sv39 = 8, - // Page-based 48-bit virtual addressing - Sv48 = 9, - // Page-based 57-bit virtual addressing - Sv57 = 10, - // Page-based 64-bit virtual addressing - Sv64 = 11, - } - - impl Satp { - // Return the contents of the register as raw bits - #[inline] - pub fn bits(&self) -> usize { - self.bits - } - } - - #[inline] - pub unsafe fn read() -> Satp { - let bits: usize; - asm!("csrr {}, satp", out(reg) bits); - Satp { bits } - } - - #[inline] - pub unsafe fn write(bits: usize) { - asm!("csrw satp, {}", in(reg) bits); - } - - #[inline] - pub fn make(mode: Mode, asid: usize, ppn: usize) -> usize { - let mut bits: usize = 0; - bits |= (mode as usize) << 60; - bits |= asid << 44; - bits |= ppn >> 12; - bits - } - } - - // mscratch register - pub mod mscratch { - use core::arch::asm; - - #[inline] - pub fn write(bits: usize) { - unsafe { - asm!("csrw mscratch, {}", in(reg) bits); - } - } - } - - // Supervisor Trap Cause - pub mod scause { - use core::{arch::asm, mem::size_of}; - - // scause register - #[derive(Clone, Copy)] - pub struct Scause { - bits: usize, - } - - // Trap Cause - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub enum Trap { - Interrupt(Interrupt), - Exception(Exception), - } - - // Interrupt - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub enum Interrupt { - UserSoft, - SupervisorSoft, - UserTimer, - SupervisorTimer, - UserExternal, - SupervisorExternal, - Unknown, - } - - // Exception - #[derive(Copy, Clone, Debug, Eq, PartialEq)] - pub enum Exception { - InstructionMisaligned, - InstructionFault, - IllegalInstruction, - Breakpoint, - LoadFault, - StoreMisaligned, - StoreFault, - UserEnvCall, - InstructionPageFault, - LoadPageFault, - StorePageFault, - Unknown, - } - - impl Interrupt { - #[inline] - pub fn from(nr: usize) -> Self { - match nr { - 0 => Interrupt::UserSoft, - 1 => Interrupt::SupervisorSoft, - 4 => Interrupt::UserTimer, - 5 => Interrupt::SupervisorTimer, - 8 => Interrupt::UserExternal, - 9 => Interrupt::SupervisorExternal, - _ => Interrupt::Unknown, - } - } - } - - impl Exception { - #[inline] - pub fn from(nr: usize) -> Self { - match nr { - 0 => Exception::InstructionMisaligned, - 1 => Exception::InstructionFault, - 2 => Exception::IllegalInstruction, - 3 => Exception::Breakpoint, - 5 => Exception::LoadFault, - 6 => Exception::StoreMisaligned, - 7 => Exception::StoreFault, - 8 => Exception::UserEnvCall, - 12 => Exception::InstructionPageFault, - 13 => Exception::LoadPageFault, - 15 => Exception::StorePageFault, - _ => Exception::Unknown, - } - } - } - - impl Scause { - // Returns the contents of the register as raw bits - #[inline] - pub fn bits(&self) -> usize { - self.bits - } - - // Returns the code field - #[inline] - pub fn code(&self) -> usize { - let bit = 1 << (size_of::() * 8 - 1); - self.bits & !bit - } - - // Trap cause - #[inline] - pub fn cause(&self) -> Trap { - if self.is_interrupt() { - Trap::Interrupt(Interrupt::from(self.code())) - } else { - Trap::Exception(Exception::from(self.code())) - } - } - - // Is trap cause an interrupt. - #[inline] - pub fn is_interrupt(&self) -> bool { - self.bits & (1 << (size_of::() * 8 - 1)) != 0 - } - - // Is trap cause an exception. - #[inline] - pub fn is_exception(&self) -> bool { - !self.is_interrupt() - } - } - - #[inline] - pub fn read() -> Scause { - let bits: usize; - unsafe { - asm!("csrr {}, scause", out(reg) bits); - } - Scause { bits } - } - } - - // Supervisor Trap Value - pub mod stval { - use core::arch::asm; - - #[inline] - pub fn read() -> usize { - let bits: usize; - unsafe { asm!("csrr {}, stval", out(reg) bits) } - bits - } - } -} - -use core::arch::asm; - -use registers::*; - -// enable device interrupts -#[inline] -pub fn intr_on() { - unsafe { - sstatus::set_sie(); - } -} - -// disable device interrupts -#[inline] -pub fn intr_off() { - unsafe { - sstatus::clear_sie(); - } -} - -// are device interrupts enabled? -#[inline] -pub fn intr_get() -> bool { - sstatus::read().sie() -} - -// flush the TLB. -#[inline] -pub unsafe fn sfence_vma() { - // the zero, zero means flush all TLB entries - asm!("sfence.vma zero, zero"); -} - -pub const PGSIZE: usize = 4096; // bytes per page -pub const PGSHIFT: usize = 12; // bits of offset within a page - -pub const fn pgroundup(sz: usize) -> usize { - (sz + PGSIZE - 1) & !(PGSIZE - 1) -} - -pub const fn pgrounddown(sz: usize) -> usize { - sz & !(PGSIZE - 1) -} - -// PTE flags -pub mod pteflags { - pub const PTE_V: usize = 1 << 0; // valid - pub const PTE_R: usize = 1 << 1; - pub const PTE_W: usize = 1 << 2; - pub const PTE_X: usize = 1 << 3; - pub const PTE_U: usize = 1 << 4; // user can access -} diff --git a/os/src/start.rs b/os/src/start.rs deleted file mode 100644 index 3a6d3912..00000000 --- a/os/src/start.rs +++ /dev/null @@ -1,86 +0,0 @@ -//use crate::kernelvec::*; -//use crate::memlayout::*; -//use crate::param::NCPU; -//use super::main::*; -//use crate::riscv::registers::{pmpcfg0::*, *}; -use core::arch::asm; -use core::hint::unreachable_unchecked; - -mod riscv; - -#[repr(C, align(16))] -struct Stack([u8; 4096 * 4 * NCPU]); - -#[no_mangle] -static mut STACK0: Stack = Stack([0; 4096 * 4 * NCPU]); - -#[no_mangle] -pub unsafe fn rust_start() -> ! { - // set MPP mode to Supervisor, for mret - mstatus::set_mpp(mstatus::MPP::Supervisor); - - // set MEPC to main, for mret - mepc::write(rust_main as usize); - - // disable paging for now. - satp::write(0); - - // delegate all interrupts and exceptions to supervisor mode. - medeleg::set_all(); - mideleg::set_all(); - sie::set_sext(); - sie::set_ssoft(); - sie::set_stimer(); - - // configure Physical Memory Protection to give supervisor mode - // access to all of physical memory. - pmpaddr0::write(0x3fffffffffffff); - pmpcfg0::set_pmp(0, Range::TOR, Permission::RWX, false); // 0 < addr < pmpaddr0 - - // ask for clock interrupts. - timerinit(); - - // keep each CPU's hartid in its tp register, for cpuid(). - let id = mhartid::read(); - asm!("mv tp, {0}", in(reg) id); - - // switch to supervisor mode and jump to main(). - asm!("mret"); - - extern "C" { - fn rust_main() -> !; - } - unreachable_unchecked(); -} - -// a scratch area per CPU for machine-mode timer interrupts. -static mut TIMER_SCRATCH: [[u64; 5]; 1] = [[0; 5]; 1]; - -unsafe fn timerinit() { - // each CPU has a separate source of timer interrupts - let id = mhartid::read(); - - // ask the CLINT for a timer interrupts - let interval = 1000000u64; // cycles; about 1/10th second in qemu. - let mtimecmp = clint_mtimecmp(id) as *mut u64; - let mtime = CLINT_MTIME as *const u64; - mtimecmp.write_volatile(mtime.read_volatile() + interval); - - // prepare information in scratch[] for timervec. - // scratch[0..2] : space for timervec to save registers. - // scratch[3] : address of CLINT MTIMECMP register. - // scratch[4] : desired interval (in cycles) between timer interrupts. - let scratch = &mut TIMER_SCRATCH[id]; - scratch[3] = mtimecmp as u64; - scratch[4] = interval; - mscratch::write(scratch.as_mut_ptr() as usize); - - // set the machine-mode trap handler - mtvec::write(timervec as usize, mtvec::TrapMode::Direct); - - // enable machine-mode interrupts. - mstatus::set_mie(); - - // enable machime-mode timer interrupts. - mie::set_mtimer(); -} \ No newline at end of file diff --git a/os/src/sync/condvar.rs b/os/src/sync/condvar.rs index b8ad07b7..d13652f2 100644 --- a/os/src/sync/condvar.rs +++ b/os/src/sync/condvar.rs @@ -1,6 +1,6 @@ use crate::sync::{Mutex, UPIntrFreeCell}; use crate::task::{ - wakeup_task, block_current_and_run_next, block_current_task, current_task, TaskContext, + block_current_and_run_next, block_current_task, current_task, wakeup_task, TaskContext, TaskControlBlock, }; use alloc::{collections::VecDeque, sync::Arc}; diff --git a/os/src/sync/mutex.rs b/os/src/sync/mutex.rs index 2b2db108..aaf15711 100644 --- a/os/src/sync/mutex.rs +++ b/os/src/sync/mutex.rs @@ -1,7 +1,7 @@ use super::UPIntrFreeCell; use crate::task::TaskControlBlock; -use crate::task::{wakeup_task, current_task}; use crate::task::{block_current_and_run_next, suspend_current_and_run_next}; +use crate::task::{current_task, wakeup_task}; use alloc::{collections::VecDeque, sync::Arc}; pub trait Mutex: Sync + Send { diff --git a/os/src/sync/semaphore.rs b/os/src/sync/semaphore.rs index cb62c201..bdad319e 100644 --- a/os/src/sync/semaphore.rs +++ b/os/src/sync/semaphore.rs @@ -1,5 +1,5 @@ use crate::sync::UPIntrFreeCell; -use crate::task::{wakeup_task, block_current_and_run_next, current_task, TaskControlBlock}; +use crate::task::{block_current_and_run_next, current_task, wakeup_task, TaskControlBlock}; use alloc::{collections::VecDeque, sync::Arc}; pub struct Semaphore { diff --git a/os/src/syscall/net.rs b/os/src/syscall/net.rs index f34b047a..c16b9ce8 100644 --- a/os/src/syscall/net.rs +++ b/os/src/syscall/net.rs @@ -1,6 +1,6 @@ -use crate::net::port_table::{listen, PortFd, accept, port_acceptable}; +use crate::net::port_table::{accept, listen, port_acceptable, PortFd}; use crate::net::udp::UDP; -use crate::net::{IPv4, net_interrupt_handler}; +use crate::net::{net_interrupt_handler, IPv4}; use crate::task::{current_process, current_task, current_trap_cx}; use alloc::sync::Arc; @@ -34,11 +34,11 @@ pub fn sys_listen(port: u16) -> isize { // accept a tcp connection pub fn sys_accept(port_index: usize) -> isize { println!("accepting port {}", port_index); - + let task = current_task().unwrap(); accept(port_index, task); // block_current_and_run_next(); - + // NOTICE: There does not have interrupt handler, just call it munually. loop { net_interrupt_handler(); diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index a8b9b7b4..ca97e21f 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -19,7 +19,7 @@ use switch::__switch; pub use context::TaskContext; pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle, IDLE_PID}; -pub use manager::{add_task, wakeup_task, pid2process, remove_from_pid2process}; +pub use manager::{add_task, pid2process, remove_from_pid2process, wakeup_task}; pub use processor::{ current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va, current_user_token, run_tasks, schedule, take_current_task, diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 6040c7fa..32870115 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -11,7 +11,7 @@ use core::arch::{asm, global_asm}; use riscv::register::{ mtvec::TrapMode, scause::{self, Exception, Interrupt, Trap}, - sie, sscratch, sstatus, stval, stvec,sip + sie, sip, sscratch, sstatus, stval, stvec, }; global_asm!(include_str!("trap.S")); @@ -95,20 +95,10 @@ pub fn trap_handler() -> ! { Trap::Exception(Exception::IllegalInstruction) => { current_add_signal(SignalFlags::SIGILL); } - // Trap::Interrupt(Interrupt::SupervisorTimer) => { - // set_next_trigger(); - // check_timer(); - // suspend_current_and_run_next(); - // } - Trap::Interrupt(Interrupt::SupervisorSoft) => { - //set_next_trigger(); - const SSIP: usize = 1 << 1; - unsafe { - asm!("csrc sip, {}", in(reg) SSIP); - } - //println!("TRAP: ssoft in Kern"); + Trap::Interrupt(Interrupt::SupervisorTimer) => { + set_next_trigger(); check_timer(); - // do not schedule now + suspend_current_and_run_next(); } Trap::Interrupt(Interrupt::SupervisorExternal) => { crate::board::irq_handler(); @@ -161,18 +151,8 @@ pub fn trap_from_kernel(_trap_cx: &TrapContext) { Trap::Interrupt(Interrupt::SupervisorExternal) => { crate::board::irq_handler(); } - // Trap::Interrupt(Interrupt::SupervisorTimer) => { - // //set_next_trigger(); - // check_timer(); - // // do not schedule now - // } - Trap::Interrupt(Interrupt::SupervisorSoft) => { - //set_next_trigger(); - const SSIP: usize = 1 << 1; - unsafe { - asm!("csrc sip, {}", in(reg) SSIP); - } - //println!("TRAP: ssoft in Kern"); + Trap::Interrupt(Interrupt::SupervisorTimer) => { + set_next_trigger(); check_timer(); // do not schedule now } diff --git a/user/src/bin/adder.rs b/user/src/bin/adder.rs index e7b16117..d1addf16 100644 --- a/user/src/bin/adder.rs +++ b/user/src/bin/adder.rs @@ -40,7 +40,9 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 { per_thread = argv[2].parse().unwrap(); } } - unsafe { PER_THREAD = per_thread; } + unsafe { + PER_THREAD = per_thread; + } let start = get_time(); let mut v = Vec::new(); for _ in 0..thread_count { diff --git a/user/src/bin/adder_atomic.rs b/user/src/bin/adder_atomic.rs index fe2cdb17..8fb56399 100644 --- a/user/src/bin/adder_atomic.rs +++ b/user/src/bin/adder_atomic.rs @@ -26,8 +26,8 @@ unsafe fn critical_section(t: &mut usize) { fn lock() { while OCCUPIED - .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) - .is_err() + .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) + .is_err() { yield_(); } @@ -57,7 +57,9 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 { per_thread = argv[2].parse().unwrap(); } } - unsafe { PER_THREAD = per_thread; } + unsafe { + PER_THREAD = per_thread; + } let start = get_time(); let mut v = Vec::new(); for _ in 0..thread_count { diff --git a/user/src/bin/adder_mutex_blocking.rs b/user/src/bin/adder_mutex_blocking.rs index 963dd753..79bb3c36 100644 --- a/user/src/bin/adder_mutex_blocking.rs +++ b/user/src/bin/adder_mutex_blocking.rs @@ -42,7 +42,9 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 { per_thread = argv[2].parse().unwrap(); } } - unsafe { PER_THREAD = per_thread; } + unsafe { + PER_THREAD = per_thread; + } let start = get_time(); assert_eq!(mutex_blocking_create(), 0); diff --git a/user/src/bin/adder_mutex_spin.rs b/user/src/bin/adder_mutex_spin.rs index b96f933c..315a338b 100644 --- a/user/src/bin/adder_mutex_spin.rs +++ b/user/src/bin/adder_mutex_spin.rs @@ -43,7 +43,9 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 { per_thread = argv[2].parse().unwrap(); } } - unsafe { PER_THREAD = per_thread; } + unsafe { + PER_THREAD = per_thread; + } let start = get_time(); assert_eq!(mutex_create(), 0); diff --git a/user/src/bin/adder_peterson_spin.rs b/user/src/bin/adder_peterson_spin.rs index bba1f239..35fd0d3f 100644 --- a/user/src/bin/adder_peterson_spin.rs +++ b/user/src/bin/adder_peterson_spin.rs @@ -1,90 +1,95 @@ -//! It only works on a single CPU! - -#![no_std] -#![no_main] -#![feature(core_intrinsics)] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid}; -use core::sync::atomic::{compiler_fence, Ordering}; - -static mut A: usize = 0; -static mut FLAG: [bool; 2] = [false; 2]; -static mut TURN: usize = 0; -const PER_THREAD_DEFAULT: usize = 2000; -const THREAD_COUNT_DEFAULT: usize = 2; -static mut PER_THREAD: usize = 0; - -unsafe fn critical_section(t: &mut usize) { - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - *t = (*t) * (*t) % 10007; - } - a.write_volatile(cur + 1); -} - -unsafe fn lock(id: usize) { - FLAG[id] = true; - let j = 1 - id; - TURN = j; - // Tell the compiler not to reorder memory operations - // across this fence. - compiler_fence(Ordering::SeqCst); - // Why do we need to use volatile_read here? - // Otherwise the compiler will assume that they will never - // be changed on this thread. Thus, they will be accessed - // only once! - while vload!(&FLAG[j]) && vload!(&TURN) == j {} -} - -unsafe fn unlock(id: usize) { - FLAG[id] = false; -} - -unsafe fn f(id: usize) -> ! { - let mut t = 2usize; - for _iter in 0..PER_THREAD { - lock(id); - critical_section(&mut t); - unlock(id); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main(argc: usize, argv: &[&str]) -> i32 { - let mut thread_count = THREAD_COUNT_DEFAULT; - let mut per_thread = PER_THREAD_DEFAULT; - if argc >= 2 { - thread_count = argv[1].parse().unwrap(); - if argc >= 3 { - per_thread = argv[2].parse().unwrap(); - } - } - unsafe { PER_THREAD = per_thread; } - - // uncomment this if you want to check the assembly - // println!( - // "addr: lock={:#x}, unlock={:#x}", - // lock as usize, - // unlock as usize - // ); - let start = get_time(); - let mut v = Vec::new(); - assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads."); - for id in 0..thread_count { - v.push(thread_create(f as usize, id) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); - 0 -} +//! It only works on a single CPU! + +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use core::sync::atomic::{compiler_fence, Ordering}; +use user_lib::{exit, get_time, thread_create, waittid}; + +static mut A: usize = 0; +static mut FLAG: [bool; 2] = [false; 2]; +static mut TURN: usize = 0; +const PER_THREAD_DEFAULT: usize = 2000; +const THREAD_COUNT_DEFAULT: usize = 2; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock(id: usize) { + FLAG[id] = true; + let j = 1 - id; + TURN = j; + // Tell the compiler not to reorder memory operations + // across this fence. + compiler_fence(Ordering::SeqCst); + // Why do we need to use volatile_read here? + // Otherwise the compiler will assume that they will never + // be changed on this thread. Thus, they will be accessed + // only once! + while vload!(&FLAG[j]) && vload!(&TURN) == j {} +} + +unsafe fn unlock(id: usize) { + FLAG[id] = false; +} + +unsafe fn f(id: usize) -> ! { + let mut t = 2usize; + for _iter in 0..PER_THREAD { + lock(id); + critical_section(&mut t); + unlock(id); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { + PER_THREAD = per_thread; + } + + // uncomment this if you want to check the assembly + // println!( + // "addr: lock={:#x}, unlock={:#x}", + // lock as usize, + // unlock as usize + // ); + let start = get_time(); + let mut v = Vec::new(); + assert_eq!( + thread_count, 2, + "Peterson works when there are only 2 threads." + ); + for id in 0..thread_count { + v.push(thread_create(f as usize, id) as usize); + } + let mut time_cost = Vec::new(); + for tid in v.iter() { + time_cost.push(waittid(*tid)); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_peterson_yield.rs b/user/src/bin/adder_peterson_yield.rs index fc5ff189..7b905e38 100644 --- a/user/src/bin/adder_peterson_yield.rs +++ b/user/src/bin/adder_peterson_yield.rs @@ -1,89 +1,94 @@ -//! It only works on a single CPU! - -#![no_std] -#![no_main] -#![feature(core_intrinsics)] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid, yield_}; -use core::sync::atomic::{compiler_fence, Ordering}; - -static mut A: usize = 0; -static mut FLAG: [bool; 2] = [false; 2]; -static mut TURN: usize = 0; -const PER_THREAD_DEFAULT: usize = 2000; -const THREAD_COUNT_DEFAULT: usize = 2; -static mut PER_THREAD: usize = 0; - -unsafe fn critical_section(t: &mut usize) { - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - *t = (*t) * (*t) % 10007; - } - a.write_volatile(cur + 1); -} - -unsafe fn lock(id: usize) { - FLAG[id] = true; - let j = 1 - id; - TURN = j; - // Tell the compiler not to reorder memory operations - // across this fence. - compiler_fence(Ordering::SeqCst); - while FLAG[j] && TURN == j { - yield_(); - } -} - -unsafe fn unlock(id: usize) { - FLAG[id] = false; -} - -unsafe fn f(id: usize) -> ! { - let mut t = 2usize; - for _iter in 0..PER_THREAD { - lock(id); - critical_section(&mut t); - unlock(id); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main(argc: usize, argv: &[&str]) -> i32 { - let mut thread_count = THREAD_COUNT_DEFAULT; - let mut per_thread = PER_THREAD_DEFAULT; - if argc >= 2 { - thread_count = argv[1].parse().unwrap(); - if argc >= 3 { - per_thread = argv[2].parse().unwrap(); - } - } - unsafe { PER_THREAD = per_thread; } - - // uncomment this if you want to check the assembly - // println!( - // "addr: lock={:#x}, unlock={:#x}", - // lock as usize, - // unlock as usize - // ); - - let start = get_time(); - let mut v = Vec::new(); - assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads."); - for id in 0..thread_count { - v.push(thread_create(f as usize, id) as usize); - } - let mut time_cost = Vec::new(); - for tid in v.iter() { - time_cost.push(waittid(*tid)); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); - 0 -} +//! It only works on a single CPU! + +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use core::sync::atomic::{compiler_fence, Ordering}; +use user_lib::{exit, get_time, thread_create, waittid, yield_}; + +static mut A: usize = 0; +static mut FLAG: [bool; 2] = [false; 2]; +static mut TURN: usize = 0; +const PER_THREAD_DEFAULT: usize = 2000; +const THREAD_COUNT_DEFAULT: usize = 2; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock(id: usize) { + FLAG[id] = true; + let j = 1 - id; + TURN = j; + // Tell the compiler not to reorder memory operations + // across this fence. + compiler_fence(Ordering::SeqCst); + while FLAG[j] && TURN == j { + yield_(); + } +} + +unsafe fn unlock(id: usize) { + FLAG[id] = false; +} + +unsafe fn f(id: usize) -> ! { + let mut t = 2usize; + for _iter in 0..PER_THREAD { + lock(id); + critical_section(&mut t); + unlock(id); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { + PER_THREAD = per_thread; + } + + // uncomment this if you want to check the assembly + // println!( + // "addr: lock={:#x}, unlock={:#x}", + // lock as usize, + // unlock as usize + // ); + + let start = get_time(); + let mut v = Vec::new(); + assert_eq!( + thread_count, 2, + "Peterson works when there are only 2 threads." + ); + for id in 0..thread_count { + v.push(thread_create(f as usize, id) as usize); + } + let mut time_cost = Vec::new(); + for tid in v.iter() { + time_cost.push(waittid(*tid)); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/adder_simple_spin.rs b/user/src/bin/adder_simple_spin.rs index d950eca5..ad5b3284 100644 --- a/user/src/bin/adder_simple_spin.rs +++ b/user/src/bin/adder_simple_spin.rs @@ -53,7 +53,9 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 { per_thread = argv[2].parse().unwrap(); } } - unsafe { PER_THREAD = per_thread; } + unsafe { + PER_THREAD = per_thread; + } let start = get_time(); let mut v = Vec::new(); for _ in 0..thread_count { diff --git a/user/src/bin/adder_simple_yield.rs b/user/src/bin/adder_simple_yield.rs index 1c777779..355b401b 100644 --- a/user/src/bin/adder_simple_yield.rs +++ b/user/src/bin/adder_simple_yield.rs @@ -1,70 +1,72 @@ -#![no_std] -#![no_main] -#![feature(core_intrinsics)] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use alloc::vec::Vec; -use user_lib::{exit, get_time, thread_create, waittid, yield_}; - -static mut A: usize = 0; -static mut OCCUPIED: bool = false; -const PER_THREAD_DEFAULT: usize = 10000; -const THREAD_COUNT_DEFAULT: usize = 16; -static mut PER_THREAD: usize = 0; - -unsafe fn critical_section(t: &mut usize) { - let a = &mut A as *mut usize; - let cur = a.read_volatile(); - for _ in 0..500 { - *t = (*t) * (*t) % 10007; - } - a.write_volatile(cur + 1); -} - -unsafe fn lock() { - while OCCUPIED { - yield_(); - } - OCCUPIED = true; -} - -unsafe fn unlock() { - OCCUPIED = false; -} - -unsafe fn f() -> ! { - let mut t = 2usize; - for _ in 0..PER_THREAD { - lock(); - critical_section(&mut t); - unlock(); - } - exit(t as i32) -} - -#[no_mangle] -pub fn main(argc: usize, argv: &[&str]) -> i32 { - let mut thread_count = THREAD_COUNT_DEFAULT; - let mut per_thread = PER_THREAD_DEFAULT; - if argc >= 2 { - thread_count = argv[1].parse().unwrap(); - if argc >= 3 { - per_thread = argv[2].parse().unwrap(); - } - } - unsafe { PER_THREAD = per_thread; } - let start = get_time(); - let mut v = Vec::new(); - for _ in 0..thread_count { - v.push(thread_create(f as usize, 0) as usize); - } - for tid in v.into_iter() { - waittid(tid); - } - println!("time cost is {}ms", get_time() - start); - assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); - 0 -} +#![no_std] +#![no_main] +#![feature(core_intrinsics)] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, get_time, thread_create, waittid, yield_}; + +static mut A: usize = 0; +static mut OCCUPIED: bool = false; +const PER_THREAD_DEFAULT: usize = 10000; +const THREAD_COUNT_DEFAULT: usize = 16; +static mut PER_THREAD: usize = 0; + +unsafe fn critical_section(t: &mut usize) { + let a = &mut A as *mut usize; + let cur = a.read_volatile(); + for _ in 0..500 { + *t = (*t) * (*t) % 10007; + } + a.write_volatile(cur + 1); +} + +unsafe fn lock() { + while OCCUPIED { + yield_(); + } + OCCUPIED = true; +} + +unsafe fn unlock() { + OCCUPIED = false; +} + +unsafe fn f() -> ! { + let mut t = 2usize; + for _ in 0..PER_THREAD { + lock(); + critical_section(&mut t); + unlock(); + } + exit(t as i32) +} + +#[no_mangle] +pub fn main(argc: usize, argv: &[&str]) -> i32 { + let mut thread_count = THREAD_COUNT_DEFAULT; + let mut per_thread = PER_THREAD_DEFAULT; + if argc >= 2 { + thread_count = argv[1].parse().unwrap(); + if argc >= 3 { + per_thread = argv[2].parse().unwrap(); + } + } + unsafe { + PER_THREAD = per_thread; + } + let start = get_time(); + let mut v = Vec::new(); + for _ in 0..thread_count { + v.push(thread_create(f as usize, 0) as usize); + } + for tid in v.into_iter() { + waittid(tid); + } + println!("time cost is {}ms", get_time() - start); + assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count); + 0 +} diff --git a/user/src/bin/barrier_condvar.rs b/user/src/bin/barrier_condvar.rs index ca0953b3..71577723 100644 --- a/user/src/bin/barrier_condvar.rs +++ b/user/src/bin/barrier_condvar.rs @@ -1,72 +1,83 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use user_lib::{thread_create, exit, waittid, mutex_create, mutex_lock, mutex_unlock, condvar_create, condvar_signal, condvar_wait}; -use alloc::vec::Vec; -use core::cell::UnsafeCell; -use lazy_static::*; - -const THREAD_NUM: usize = 3; - -struct Barrier { - mutex_id: usize, - condvar_id: usize, - count: UnsafeCell, -} - -impl Barrier { - pub fn new() -> Self { - Self { - mutex_id: mutex_create() as usize, - condvar_id: condvar_create() as usize, - count: UnsafeCell::new(0), - } - } - pub fn block(&self) { - mutex_lock(self.mutex_id); - let count = self.count.get(); - // SAFETY: Here, the accesses of the count is in the - // critical section protected by the mutex. - unsafe { *count = *count + 1; } - if unsafe { *count } == THREAD_NUM { - condvar_signal(self.condvar_id); - } else { - condvar_wait(self.condvar_id, self.mutex_id); - condvar_signal(self.condvar_id); - } - mutex_unlock(self.mutex_id); - } -} - -unsafe impl Sync for Barrier {} - -lazy_static! { - static ref BARRIER_AB: Barrier = Barrier::new(); - static ref BARRIER_BC: Barrier = Barrier::new(); -} - -fn thread_fn() { - for _ in 0..300 { print!("a"); } - BARRIER_AB.block(); - for _ in 0..300 { print!("b"); } - BARRIER_BC.block(); - for _ in 0..300 { print!("c"); } - exit(0) -} - -#[no_mangle] -pub fn main() -> i32 { - let mut v: Vec = Vec::new(); - for _ in 0..THREAD_NUM { - v.push(thread_create(thread_fn as usize, 0)); - } - for tid in v.into_iter() { - waittid(tid as usize); - } - println!("\nOK!"); - 0 -} +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use core::cell::UnsafeCell; +use lazy_static::*; +use user_lib::{ + condvar_create, condvar_signal, condvar_wait, exit, mutex_create, mutex_lock, mutex_unlock, + thread_create, waittid, +}; + +const THREAD_NUM: usize = 3; + +struct Barrier { + mutex_id: usize, + condvar_id: usize, + count: UnsafeCell, +} + +impl Barrier { + pub fn new() -> Self { + Self { + mutex_id: mutex_create() as usize, + condvar_id: condvar_create() as usize, + count: UnsafeCell::new(0), + } + } + pub fn block(&self) { + mutex_lock(self.mutex_id); + let count = self.count.get(); + // SAFETY: Here, the accesses of the count is in the + // critical section protected by the mutex. + unsafe { + *count = *count + 1; + } + if unsafe { *count } == THREAD_NUM { + condvar_signal(self.condvar_id); + } else { + condvar_wait(self.condvar_id, self.mutex_id); + condvar_signal(self.condvar_id); + } + mutex_unlock(self.mutex_id); + } +} + +unsafe impl Sync for Barrier {} + +lazy_static! { + static ref BARRIER_AB: Barrier = Barrier::new(); + static ref BARRIER_BC: Barrier = Barrier::new(); +} + +fn thread_fn() { + for _ in 0..300 { + print!("a"); + } + BARRIER_AB.block(); + for _ in 0..300 { + print!("b"); + } + BARRIER_BC.block(); + for _ in 0..300 { + print!("c"); + } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/barrier_fail.rs b/user/src/bin/barrier_fail.rs index 0eb4b17f..11604cab 100644 --- a/user/src/bin/barrier_fail.rs +++ b/user/src/bin/barrier_fail.rs @@ -1,33 +1,33 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; -extern crate alloc; - -use user_lib::{thread_create, exit, waittid}; -use alloc::vec::Vec; - -const THREAD_NUM: usize = 3; - -fn thread_fn() { - for ch in 'a'..='c' { - for _ in 0..300 { - print!("{}", ch); - } - } - exit(0) -} - -#[no_mangle] -pub fn main() -> i32 { - let mut v: Vec = Vec::new(); - for _ in 0..THREAD_NUM { - v.push(thread_create(thread_fn as usize, 0)); - } - for tid in v.into_iter() { - waittid(tid as usize); - } - println!("\nOK!"); - 0 -} +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use alloc::vec::Vec; +use user_lib::{exit, thread_create, waittid}; + +const THREAD_NUM: usize = 3; + +fn thread_fn() { + for ch in 'a'..='c' { + for _ in 0..300 { + print!("{}", ch); + } + } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/condsync_sem.rs b/user/src/bin/condsync_sem.rs index d7b875a7..ee08face 100644 --- a/user/src/bin/condsync_sem.rs +++ b/user/src/bin/condsync_sem.rs @@ -1,64 +1,64 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -extern crate alloc; - -use alloc::vec; -use user_lib::exit; -use user_lib::{ - semaphore_create, semaphore_down, semaphore_up, mutex_blocking_create, mutex_lock, mutex_unlock, -}; -use user_lib::{sleep, thread_create, waittid}; - -static mut A: usize = 0; - -const SEM_ID: usize = 0; -const MUTEX_ID: usize = 0; - -unsafe fn first() -> ! { - sleep(10); - println!("First work, Change A --> 1 and wakeup Second"); - mutex_lock(MUTEX_ID); - A = 1; - semaphore_up(SEM_ID); - mutex_unlock(MUTEX_ID); - exit(0) -} - -unsafe fn second() -> ! { - println!("Second want to continue,but need to wait A=1"); - loop { - mutex_lock(MUTEX_ID); - if A == 0 { - println!("Second: A is {}", A); - mutex_unlock(MUTEX_ID); - semaphore_down(SEM_ID); - } else { - mutex_unlock(MUTEX_ID); - break; - } - } - println!("A is {}, Second can work now", A); - exit(0) -} - -#[no_mangle] -pub fn main() -> i32 { - // create semaphore & mutex - assert_eq!(semaphore_create(0) as usize, SEM_ID); - assert_eq!(mutex_blocking_create() as usize, MUTEX_ID); - // create threads - let threads = vec![ - thread_create(first as usize, 0), - thread_create(second as usize, 0), - ]; - // wait for all threads to complete - for thread in threads.iter() { - waittid(*thread as usize); - } - println!("test_condvar passed!"); - 0 -} +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +extern crate alloc; + +use alloc::vec; +use user_lib::exit; +use user_lib::{ + mutex_blocking_create, mutex_lock, mutex_unlock, semaphore_create, semaphore_down, semaphore_up, +}; +use user_lib::{sleep, thread_create, waittid}; + +static mut A: usize = 0; + +const SEM_ID: usize = 0; +const MUTEX_ID: usize = 0; + +unsafe fn first() -> ! { + sleep(10); + println!("First work, Change A --> 1 and wakeup Second"); + mutex_lock(MUTEX_ID); + A = 1; + semaphore_up(SEM_ID); + mutex_unlock(MUTEX_ID); + exit(0) +} + +unsafe fn second() -> ! { + println!("Second want to continue,but need to wait A=1"); + loop { + mutex_lock(MUTEX_ID); + if A == 0 { + println!("Second: A is {}", A); + mutex_unlock(MUTEX_ID); + semaphore_down(SEM_ID); + } else { + mutex_unlock(MUTEX_ID); + break; + } + } + println!("A is {}, Second can work now", A); + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + // create semaphore & mutex + assert_eq!(semaphore_create(0) as usize, SEM_ID); + assert_eq!(mutex_blocking_create() as usize, MUTEX_ID); + // create threads + let threads = vec![ + thread_create(first as usize, 0), + thread_create(second as usize, 0), + ]; + // wait for all threads to complete + for thread in threads.iter() { + waittid(*thread as usize); + } + println!("test_condvar passed!"); + 0 +} diff --git a/user/src/bin/gui_rect.rs b/user/src/bin/gui_rect.rs index b7af3ee7..1f377dec 100644 --- a/user/src/bin/gui_rect.rs +++ b/user/src/bin/gui_rect.rs @@ -8,7 +8,7 @@ use user_lib::{Display, VIRTGPU_XRES, VIRTGPU_YRES}; use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::{DrawTarget, Drawable, Point, RgbColor, Size}; -use embedded_graphics::primitives::{Circle, Primitive, PrimitiveStyle, Rectangle,Triangle}; +use embedded_graphics::primitives::{Circle, Primitive, PrimitiveStyle, Rectangle, Triangle}; const INIT_X: i32 = 80; const INIT_Y: i32 = 400; @@ -35,10 +35,14 @@ impl DrawingBoard { .into_styled(PrimitiveStyle::with_fill(Rgb888::BLUE)) .draw(&mut self.disp) .ok(); - Triangle::new(self.latest_pos + Point::new(0, 150), self.latest_pos + Point::new(80, 200), self.latest_pos + Point::new(-120, 300)) - .into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 10)) - .draw(&mut self.disp) - .ok(); + Triangle::new( + self.latest_pos + Point::new(0, 150), + self.latest_pos + Point::new(80, 200), + self.latest_pos + Point::new(-120, 300), + ) + .into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 10)) + .draw(&mut self.disp) + .ok(); } fn unpaint(&mut self) { Rectangle::with_center(self.latest_pos, Size::new(RECT_SIZE, RECT_SIZE)) diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs index ccf5b89d..f30b1fc8 100644 --- a/user/src/bin/gui_simple.rs +++ b/user/src/bin/gui_simple.rs @@ -3,8 +3,8 @@ extern crate user_lib; -use user_lib::{VIRTGPU_XRES, VIRTGPU_YRES, Display}; use embedded_graphics::prelude::Size; +use user_lib::{Display, VIRTGPU_XRES, VIRTGPU_YRES}; #[no_mangle] pub fn main() -> i32 { diff --git a/user/src/bin/gui_snake.rs b/user/src/bin/gui_snake.rs index 080c4725..0411824f 100644 --- a/user/src/bin/gui_snake.rs +++ b/user/src/bin/gui_snake.rs @@ -1,11 +1,11 @@ #![no_std] #![no_main] -extern crate user_lib; extern crate alloc; +extern crate user_lib; use user_lib::console::getchar; -use user_lib::{Display, key_pressed, sleep, VIRTGPU_XRES, VIRTGPU_YRES}; +use user_lib::{key_pressed, sleep, Display, VIRTGPU_XRES, VIRTGPU_YRES}; use embedded_graphics::pixelcolor::*; use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; diff --git a/user/src/bin/gui_uart.rs b/user/src/bin/gui_uart.rs index c9577a4f..8e9c9b8c 100644 --- a/user/src/bin/gui_uart.rs +++ b/user/src/bin/gui_uart.rs @@ -113,7 +113,7 @@ pub fn main() -> i32 { let mut board = DrawingBoard::new(); let _ = board.disp.clear(Rgb888::BLACK).unwrap(); for i in 0..20 { - let c=getchar(); + let c = getchar(); if c == LF || c == CR { break; } diff --git a/user/src/bin/inputdev_event.rs b/user/src/bin/inputdev_event.rs index 5b820d80..ea56f3a4 100644 --- a/user/src/bin/inputdev_event.rs +++ b/user/src/bin/inputdev_event.rs @@ -22,4 +22,4 @@ pub fn main() -> i32 { } } 0 -} \ No newline at end of file +} diff --git a/user/src/bin/peterson.rs b/user/src/bin/peterson.rs index 1fa2c416..ee8ff934 100644 --- a/user/src/bin/peterson.rs +++ b/user/src/bin/peterson.rs @@ -77,4 +77,4 @@ pub fn main() -> i32 { } println!("main thread exited."); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/random_num.rs b/user/src/bin/random_num.rs index dd9ac00d..d68bb137 100644 --- a/user/src/bin/random_num.rs +++ b/user/src/bin/random_num.rs @@ -13,4 +13,4 @@ pub fn main() -> i32 { println!("OORandom: Random number 32bit: {}", rng.rand_i32()); println!("OORandom: Random number range: {}", rng.rand_range(1..100)); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/stackful_coroutine.rs b/user/src/bin/stackful_coroutine.rs index d9f3b947..3f619790 100644 --- a/user/src/bin/stackful_coroutine.rs +++ b/user/src/bin/stackful_coroutine.rs @@ -69,7 +69,7 @@ impl Task { // we can allocate memory for it later, but it keeps complexity down and lets us focus on more interesting parts // to do it here. The important part is that once allocated it MUST NOT move in memory. Task { - id:id, + id: id, stack: vec![0_u8; DEFAULT_STACK_SIZE], ctx: TaskContext::default(), state: State::Available, diff --git a/user/src/bin/tcp_simplehttp.rs b/user/src/bin/tcp_simplehttp.rs index c615d1de..3e619505 100644 --- a/user/src/bin/tcp_simplehttp.rs +++ b/user/src/bin/tcp_simplehttp.rs @@ -10,7 +10,7 @@ extern crate alloc; // use http://localhost:6201/ to access the http server -use user_lib::{read, write, listen, accept}; +use user_lib::{accept, listen, read, write}; // get url from the tcp request list. fn get_url_from_tcp_request(req: &[u8]) -> String { @@ -35,8 +35,8 @@ fn handle_tcp_client(client_fd: usize) -> bool { println!("receive {} bytes", len); hexdump(&buf[..len as usize]); - // verify whether it is a valid HTTP request simply, [0x47,0x45,0x54, 0x20] is GET - if len < 4 || buf[..4] != [0x47,0x45,0x54, 0x20] { + // verify whether it is a valid HTTP request simply, [0x47,0x45,0x54, 0x20] is GET + if len < 4 || buf[..4] != [0x47, 0x45, 0x54, 0x20] { println!("it's not a valid http request"); return false; } @@ -136,12 +136,12 @@ pub fn main() -> i32 { loop { let client = accept(tcp_fd as usize); println!("client connected: {}", client); - + if client < 1 { println!("Failed to accept a client on port 80"); return -1; } - + if handle_tcp_client(client as usize) { break; } diff --git a/user/src/io.rs b/user/src/io.rs index baaa3382..30e7a1c1 100644 --- a/user/src/io.rs +++ b/user/src/io.rs @@ -1,7 +1,7 @@ use super::*; +use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::{RgbColor, Size}; use embedded_graphics::{draw_target::DrawTarget, prelude::OriginDimensions}; -use embedded_graphics::pixelcolor::Rgb888; use virtio_input_decoder::Decoder; pub use virtio_input_decoder::{DecodeType, Key, KeyType, Mouse}; @@ -24,9 +24,8 @@ pub struct Display { impl Display { pub fn new(size: Size) -> Self { let fb_ptr = framebuffer() as *mut u8; - let fb = - unsafe { core::slice::from_raw_parts_mut(fb_ptr, VIRTGPU_LEN as usize) }; - Self { size, fb} + let fb = unsafe { core::slice::from_raw_parts_mut(fb_ptr, VIRTGPU_LEN as usize) }; + Self { size, fb } } pub fn framebuffer(&mut self) -> &mut [u8] { self.fb @@ -53,9 +52,7 @@ impl DrawTarget for Display { I: IntoIterator>, { pixels.into_iter().for_each(|px| { - let idx = (px.0.y * VIRTGPU_XRES as i32 + px.0.x) - as usize - * 4; + let idx = (px.0.y * VIRTGPU_XRES as i32 + px.0.x) as usize * 4; if idx + 2 >= self.fb.len() { return; } @@ -113,6 +110,7 @@ impl InputEvent { self.event_type as usize, self.code as usize, self.value as usize, - ).ok() + ) + .ok() } -} \ No newline at end of file +} diff --git a/user/src/task.rs b/user/src/task.rs index 46eee79c..9e72b32f 100644 --- a/user/src/task.rs +++ b/user/src/task.rs @@ -80,4 +80,4 @@ pub fn waittid(tid: usize) -> isize { exit_code => return exit_code, } } -} \ No newline at end of file +}