diff --git a/os/Cargo.toml b/os/Cargo.toml index 5652cd26..b8327164 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -12,6 +12,7 @@ lazy_static = { version = "1.4.0", features = ["spin_no_std"] } buddy_system_allocator = "0.6" bitflags = "1.2.1" xmas-elf = "0.7.0" +volatile = "0.3" virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers" } k210-pac = { git = "https://github.com/wyfcyx/k210-pac" } k210-hal = { git = "https://github.com/wyfcyx/k210-hal" } diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs index bf5841b5..8d509a4b 100644 --- a/os/src/boards/qemu.rs +++ b/os/src/boards/qemu.rs @@ -1,42 +1,54 @@ pub const CLOCK_FREQ: usize = 12500000; pub const MMIO: &[(usize, usize)] = &[ - (0x10001000, 0x1000), + (0x1000_0000, 0x1000), + (0x1000_1000, 0x1000), (0xC00_0000, 0x40_0000), ]; pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock; +pub type CharDeviceImpl = crate::drivers::chardev::NS16550a; pub const VIRT_PLIC: usize = 0xC00_0000; +pub const VIRT_UART: usize = 0x1000_0000; -use crate::drivers::plic::{PLIC, IntrTargetPriority}; +use crate::drivers::block::BLOCK_DEVICE; +use crate::drivers::chardev::{CharDevice, UART}; +use crate::drivers::plic::{IntrTargetPriority, PLIC}; pub fn device_init() { use riscv::register::sie; let mut plic = unsafe { PLIC::new(VIRT_PLIC) }; let hart_id: usize = 0; let supervisor = IntrTargetPriority::Supervisor; - let machine = IntrTargetPriority::Machine; + let machine = IntrTargetPriority::Machine; plic.set_threshold(hart_id, supervisor, 0); plic.set_threshold(hart_id, machine, 1); for intr_src_id in [1usize, 10] { - plic.enable(hart_id, supervisor, intr_src_id); + plic.enable(hart_id, supervisor, intr_src_id); plic.set_priority(intr_src_id, 1); } - crate::println!("Hart0M threshold = {}", plic.get_threshold(hart_id, IntrTargetPriority::Machine)); - crate::println!("Hart0S threshold = {}", plic.get_threshold(hart_id, IntrTargetPriority::Supervisor)); + crate::println!( + "Hart0M threshold = {}", + plic.get_threshold(hart_id, IntrTargetPriority::Machine) + ); + crate::println!( + "Hart0S threshold = {}", + plic.get_threshold(hart_id, IntrTargetPriority::Supervisor) + ); crate::println!("1 prio = {}", plic.get_priority(1)); crate::println!("10 prio = {}", plic.get_priority(10)); - unsafe { sie::set_sext(); } + unsafe { + sie::set_sext(); + } } -use crate::drivers::block::BLOCK_DEVICE; - pub fn irq_handler() { let mut plic = unsafe { PLIC::new(VIRT_PLIC) }; let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor); match intr_src_id { 1 => BLOCK_DEVICE.handle_irq(), + 10 => UART.handle_irq(), _ => panic!("unsupported IRQ {}", intr_src_id), } plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id); diff --git a/os/src/config.rs b/os/src/config.rs index c1b2fa45..41fe977c 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -11,4 +11,3 @@ pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1; pub const TRAP_CONTEXT_BASE: usize = TRAMPOLINE - PAGE_SIZE; pub use crate::board::{CLOCK_FREQ, MMIO}; - diff --git a/os/src/console.rs b/os/src/console.rs index c8a5cd4e..31614c64 100644 --- a/os/src/console.rs +++ b/os/src/console.rs @@ -1,4 +1,4 @@ -use crate::sbi::console_putchar; +use crate::drivers::chardev::{CharDevice, UART}; use core::fmt::{self, Write}; struct Stdout; @@ -6,7 +6,7 @@ struct Stdout; impl Write for Stdout { fn write_str(&mut self, s: &str) -> fmt::Result { for c in s.chars() { - console_putchar(c as usize); + UART.write(c as u8); } Ok(()) } diff --git a/os/src/drivers/block/mod.rs b/os/src/drivers/block/mod.rs index 7c1bb55d..7361ec83 100644 --- a/os/src/drivers/block/mod.rs +++ b/os/src/drivers/block/mod.rs @@ -1,13 +1,13 @@ mod sdcard; mod virtio_blk; -pub use virtio_blk::VirtIOBlock; pub use sdcard::SDCardWrapper; +pub use virtio_blk::VirtIOBlock; +use crate::board::BlockDeviceImpl; use alloc::sync::Arc; use easy_fs::BlockDevice; use lazy_static::*; -use crate::board::BlockDeviceImpl; lazy_static! { pub static ref BLOCK_DEVICE: Arc = Arc::new(BlockDeviceImpl::new()); diff --git a/os/src/drivers/block/sdcard.rs b/os/src/drivers/block/sdcard.rs index f7c640b1..32d94431 100644 --- a/os/src/drivers/block/sdcard.rs +++ b/os/src/drivers/block/sdcard.rs @@ -761,5 +761,7 @@ impl BlockDevice for SDCardWrapper { .write_sector(buf, block_id as u32) .unwrap(); } - fn handle_irq(&self) { unimplemented!(); } + fn handle_irq(&self) { + unimplemented!(); + } } diff --git a/os/src/drivers/block/virtio_blk.rs b/os/src/drivers/block/virtio_blk.rs index 19f64f60..67eb0c33 100644 --- a/os/src/drivers/block/virtio_blk.rs +++ b/os/src/drivers/block/virtio_blk.rs @@ -3,12 +3,12 @@ use crate::mm::{ frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum, StepByOne, VirtAddr, }; -use crate::sync::{UPSafeCell, Condvar}; -use lazy_static::*; -use virtio_drivers::{VirtIOBlk, VirtIOHeader, BlkResp, RespStatus}; +use crate::sync::{Condvar, UPSafeCell}; use crate::DEV_NON_BLOCKING_ACCESS; use alloc::collections::BTreeMap; use alloc::vec::Vec; +use lazy_static::*; +use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader}; #[allow(unused)] const VIRTIO0: usize = 0x10001000; @@ -28,12 +28,14 @@ impl BlockDevice for VirtIOBlock { if nb { let mut blk = self.virtio_blk.exclusive_access(); let mut resp = BlkResp::default(); - let token = unsafe { - blk.read_block_nb(block_id, buf, &mut resp).unwrap() - }; + let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() }; drop(blk); self.condvars.get(&token).unwrap().wait(); - assert_eq!(resp.status(), RespStatus::Ok, "Error when reading VirtIOBlk"); + assert_eq!( + resp.status(), + RespStatus::Ok, + "Error when reading VirtIOBlk" + ); } else { self.virtio_blk .exclusive_access() @@ -46,12 +48,14 @@ impl BlockDevice for VirtIOBlock { if nb { let mut blk = self.virtio_blk.exclusive_access(); let mut resp = BlkResp::default(); - let token = unsafe { - blk.write_block_nb(block_id, buf, &mut resp).unwrap() - }; + let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() }; drop(blk); self.condvars.get(&token).unwrap().wait(); - assert_eq!(resp.status(), RespStatus::Ok, "Error when writing VirtIOBlk"); + assert_eq!( + resp.status(), + RespStatus::Ok, + "Error when writing VirtIOBlk" + ); } else { self.virtio_blk .exclusive_access() @@ -60,7 +64,7 @@ impl BlockDevice for VirtIOBlock { } } fn handle_irq(&self) { - let mut blk = self.virtio_blk.exclusive_access(); + let mut blk = self.virtio_blk.exclusive_access(); while let Ok(token) = blk.pop_used() { self.condvars.get(&token).unwrap().signal(); } @@ -69,20 +73,18 @@ impl BlockDevice for VirtIOBlock { impl VirtIOBlock { pub fn new() -> Self { - unsafe { - let virtio_blk = UPSafeCell::new( - VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(), - ); - let mut condvars = BTreeMap::new(); - let channels = virtio_blk.exclusive_access().virt_queue_size(); - for i in 0..channels { - let condvar = Condvar::new(); - condvars.insert(i, condvar); - } - Self { - virtio_blk, - condvars, - } + let virtio_blk = unsafe { + UPSafeCell::new(VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap()) + }; + let mut condvars = BTreeMap::new(); + let channels = virtio_blk.exclusive_access().virt_queue_size(); + for i in 0..channels { + let condvar = Condvar::new(); + condvars.insert(i, condvar); + } + Self { + virtio_blk, + condvars, } } } diff --git a/os/src/drivers/chardev/mod.rs b/os/src/drivers/chardev/mod.rs new file mode 100644 index 00000000..28665769 --- /dev/null +++ b/os/src/drivers/chardev/mod.rs @@ -0,0 +1,17 @@ +mod ns16550a; + +pub use ns16550a::NS16550a; + +use crate::board::CharDeviceImpl; +use alloc::sync::Arc; +use lazy_static::*; + +pub trait CharDevice { + fn read(&self) -> u8; + fn write(&self, ch: u8); + fn handle_irq(&self); +} + +lazy_static! { + pub static ref UART: Arc = Arc::new(CharDeviceImpl::new()); +} diff --git a/os/src/drivers/chardev/ns16550a.rs b/os/src/drivers/chardev/ns16550a.rs new file mode 100644 index 00000000..df3fd809 --- /dev/null +++ b/os/src/drivers/chardev/ns16550a.rs @@ -0,0 +1,174 @@ +use super::CharDevice; +use crate::sync::{Condvar, UPSafeCell}; +use alloc::collections::VecDeque; +use bitflags::*; +use volatile::{ReadOnly, Volatile, WriteOnly}; + +///! Ref: https://www.lammertbies.nl/comm/info/serial-uart +///! Ref: ns16550a datasheet: https://datasheetspdf.com/pdf-file/605590/NationalSemiconductor/NS16550A/1 +///! Ref: ns16450 datasheet: https://datasheetspdf.com/pdf-file/1311818/NationalSemiconductor/NS16450/1 + +bitflags! { + /// InterruptEnableRegister + pub struct IER: u8 { + const RX_AVALIABLE = 1 << 0; + const TX_EMPTY = 1 << 1; + } + + /// LineStatusRegister + pub struct LSR: u8 { + const DATA_AVAILABLE = 1 << 0; + const THR_EMPTY = 1 << 5; + } + + /// Model Control Register + pub struct MCR: u8 { + const DATA_TERMINAL_READY = 1 << 0; + const REQUEST_TO_SEND = 1 << 1; + const AUX_OUTPUT1 = 1 << 2; + const AUX_OUTPUT2 = 1 << 3; + } +} + +#[repr(C)] +#[allow(dead_code)] +struct ReadWithoutDLAB { + /// receiver buffer register + pub rbr: ReadOnly, + /// interrupt enable register + pub ier: Volatile, + /// interrupt identification register + pub iir: ReadOnly, + /// line control register + pub lcr: Volatile, + /// model control register + pub mcr: Volatile, + /// line status register + pub lsr: ReadOnly, + /// ignore MSR + _padding1: ReadOnly, + /// ignore SCR + _padding2: ReadOnly, +} + +#[repr(C)] +#[allow(dead_code)] +struct WriteWithoutDLAB { + /// transmitter holding register + pub thr: WriteOnly, + /// interrupt enable register + pub ier: Volatile, + /// ignore FCR + _padding0: ReadOnly, + /// line control register + pub lcr: Volatile, + /// modem control register + pub mcr: Volatile, + /// line status register + pub lsr: ReadOnly, + /// ignore other registers + _padding1: ReadOnly, +} + +pub struct NS16550aRaw { + base_addr: usize, +} + +impl NS16550aRaw { + fn read_end(&mut self) -> &mut ReadWithoutDLAB { + unsafe { &mut *(self.base_addr as *mut ReadWithoutDLAB) } + } + + fn write_end(&mut self) -> &mut WriteWithoutDLAB { + unsafe { &mut *(self.base_addr as *mut WriteWithoutDLAB) } + } + + pub fn new(base_addr: usize) -> Self { + Self { base_addr } + } + + pub fn init(&mut self) { + let read_end = self.read_end(); + let mut mcr = MCR::empty(); + mcr |= MCR::DATA_TERMINAL_READY; + mcr |= MCR::REQUEST_TO_SEND; + mcr |= MCR::AUX_OUTPUT2; + read_end.mcr.write(mcr); + let ier = IER::RX_AVALIABLE; + read_end.ier.write(ier); + } + + pub fn read(&mut self) -> Option { + let read_end = self.read_end(); + let lsr = read_end.lsr.read(); + if lsr.contains(LSR::DATA_AVAILABLE) { + Some(read_end.rbr.read()) + } else { + None + } + } + + pub fn write(&mut self, ch: u8) { + let write_end = self.write_end(); + loop { + if write_end.lsr.read().contains(LSR::THR_EMPTY) { + write_end.thr.write(ch); + break; + } + } + } +} + +struct NS16550aInner { + ns16550a: NS16550aRaw, + read_buffer: VecDeque, +} + +pub struct NS16550a { + inner: UPSafeCell, + condvar: Condvar, +} + +impl NS16550a { + pub fn new() -> Self { + let mut inner = NS16550aInner { + ns16550a: NS16550aRaw::new(BASE_ADDR), + read_buffer: VecDeque::new(), + }; + inner.ns16550a.init(); + Self { + inner: unsafe { UPSafeCell::new(inner) }, + condvar: Condvar::new(), + } + } +} + +impl CharDevice for NS16550a { + fn read(&self) -> u8 { + loop { + let mut inner = self.inner.exclusive_access(); + if let Some(ch) = inner.read_buffer.pop_front() { + return ch; + } else { + drop(inner); + self.condvar.wait(); + } + } + } + fn write(&self, ch: u8) { + let mut inner = self.inner.exclusive_access(); + inner.ns16550a.write(ch); + } + fn handle_irq(&self) { + let mut inner = self.inner.exclusive_access(); + let mut count = 0; + while let Some(ch) = inner.ns16550a.read() { + count += 1; + inner.read_buffer.push_back(ch); + } + drop(inner); + if count > 0 { + self.condvar.signal(); + } + } +} diff --git a/os/src/drivers/mod.rs b/os/src/drivers/mod.rs index 7a2e4fba..c1b1231f 100644 --- a/os/src/drivers/mod.rs +++ b/os/src/drivers/mod.rs @@ -1,4 +1,6 @@ pub mod block; +pub mod chardev; pub mod plic; pub use block::BLOCK_DEVICE; +pub use chardev::UART; diff --git a/os/src/drivers/plic.rs b/os/src/drivers/plic.rs index fd6aefc3..fa71dbf1 100644 --- a/os/src/drivers/plic.rs +++ b/os/src/drivers/plic.rs @@ -1,5 +1,5 @@ pub struct PLIC { - base_addr: usize, + base_addr: usize, } #[derive(Copy, Clone)] @@ -10,7 +10,7 @@ pub enum IntrTargetPriority { impl IntrTargetPriority { pub fn supported_number() -> usize { - 2 + 2 } } @@ -19,9 +19,7 @@ impl PLIC { assert!(intr_source_id > 0 && intr_source_id <= 132); (self.base_addr + intr_source_id * 4) as *mut u32 } - fn hart_id_with_priority( - hart_id: usize, - target_priority: IntrTargetPriority) -> usize { + fn hart_id_with_priority(hart_id: usize, target_priority: IntrTargetPriority) -> usize { let priority_num = IntrTargetPriority::supported_number(); hart_id * priority_num + target_priority as usize } @@ -31,13 +29,16 @@ impl PLIC { target_priority: IntrTargetPriority, intr_source_id: usize, ) -> (*mut u32, usize) { - let id = Self::hart_id_with_priority(hart_id, target_priority); + let id = Self::hart_id_with_priority(hart_id, target_priority); let (reg_id, reg_shift) = (intr_source_id / 32, intr_source_id % 32); - ((self.base_addr + 0x2000 + 0x80 * id + 0x4 * reg_id) as *mut u32, reg_shift) + ( + (self.base_addr + 0x2000 + 0x80 * id + 0x4 * reg_id) as *mut u32, + reg_shift, + ) } fn threshold_ptr_of_hart_with_priority( &self, - hart_id: usize, + hart_id: usize, target_priority: IntrTargetPriority, ) -> *mut u32 { let id = Self::hart_id_with_priority(hart_id, target_priority); @@ -45,27 +46,23 @@ impl PLIC { } fn claim_comp_ptr_of_hart_with_priority( &self, - hart_id: usize, + hart_id: usize, target_priority: IntrTargetPriority, ) -> *mut u32 { let id = Self::hart_id_with_priority(hart_id, target_priority); (self.base_addr + 0x20_0004 + 0x1000 * id) as *mut u32 } pub unsafe fn new(base_addr: usize) -> Self { - Self { - base_addr, - } + Self { base_addr } } pub fn set_priority(&mut self, intr_source_id: usize, priority: u32) { - assert!(priority < 8); + assert!(priority < 8); unsafe { self.priority_ptr(intr_source_id).write_volatile(priority); } } pub fn get_priority(&mut self, intr_source_id: usize) -> u32 { - unsafe { - self.priority_ptr(intr_source_id).read_volatile() & 7 - } + unsafe { self.priority_ptr(intr_source_id).read_volatile() & 7 } } pub fn enable( &mut self, @@ -78,6 +75,7 @@ impl PLIC { reg_ptr.write_volatile(reg_ptr.read_volatile() | 1 << shift); } } + #[allow(unused)] pub fn disable( &mut self, hart_id: usize, @@ -86,7 +84,7 @@ impl PLIC { ) { let (reg_ptr, shift) = self.enable_ptr(hart_id, target_priority, intr_source_id); unsafe { - reg_ptr.write_volatile(reg_ptr.read_volatile() & (!(1u32 << shift))); + reg_ptr.write_volatile(reg_ptr.read_volatile() & (!(1u32 << shift))); } } pub fn set_threshold( @@ -97,21 +95,15 @@ impl PLIC { ) { assert!(threshold < 8); let threshold_ptr = self.threshold_ptr_of_hart_with_priority(hart_id, target_priority); - unsafe { threshold_ptr.write_volatile(threshold); } + unsafe { + threshold_ptr.write_volatile(threshold); + } } - pub fn get_threshold( - &mut self, - hart_id: usize, - target_priority: IntrTargetPriority, - ) -> u32 { + pub fn get_threshold(&mut self, hart_id: usize, target_priority: IntrTargetPriority) -> u32 { let threshold_ptr = self.threshold_ptr_of_hart_with_priority(hart_id, target_priority); unsafe { threshold_ptr.read_volatile() & 7 } } - pub fn claim( - &mut self, - hart_id: usize, - target_priority: IntrTargetPriority, - ) -> u32 { + pub fn claim(&mut self, hart_id: usize, target_priority: IntrTargetPriority) -> u32 { let claim_comp_ptr = self.claim_comp_ptr_of_hart_with_priority(hart_id, target_priority); unsafe { claim_comp_ptr.read_volatile() } } @@ -122,6 +114,8 @@ impl PLIC { completion: u32, ) { let claim_comp_ptr = self.claim_comp_ptr_of_hart_with_priority(hart_id, target_priority); - unsafe { claim_comp_ptr.write_volatile(completion); } + unsafe { + claim_comp_ptr.write_volatile(completion); + } } } diff --git a/os/src/fs/stdio.rs b/os/src/fs/stdio.rs index 7c74d3e1..7a3adeda 100644 --- a/os/src/fs/stdio.rs +++ b/os/src/fs/stdio.rs @@ -1,10 +1,8 @@ use super::File; +use crate::drivers::chardev::{CharDevice, UART}; use crate::mm::UserBuffer; -use crate::sbi::console_getchar; -use crate::task::suspend_current_and_run_next; pub struct Stdin; - pub struct Stdout; impl File for Stdin { @@ -16,18 +14,7 @@ impl File for Stdin { } fn read(&self, mut user_buf: UserBuffer) -> usize { assert_eq!(user_buf.len(), 1); - // busy loop - let mut c: usize; - loop { - c = console_getchar(); - if c == 0 { - suspend_current_and_run_next(); - continue; - } else { - break; - } - } - let ch = c as u8; + let ch = UART.read(); unsafe { user_buf.buffers[0].as_mut_ptr().write_volatile(ch); } diff --git a/os/src/main.rs b/os/src/main.rs index a506d1a1..77ebbbbc 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -46,17 +46,13 @@ use lazy_static::*; use sync::UPSafeCell; lazy_static! { - pub static ref DEV_NON_BLOCKING_ACCESS: UPSafeCell = unsafe { - UPSafeCell::new(false) - }; + pub static ref DEV_NON_BLOCKING_ACCESS: UPSafeCell = unsafe { UPSafeCell::new(false) }; } #[no_mangle] pub fn rust_main() -> ! { clear_bss(); - println!("[kernel] Hello, world!"); mm::init(); - mm::remap_test(); trap::init(); trap::enable_timer_interrupt(); timer::set_next_trigger(); diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 0d0b0f1d..aba1ae57 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -351,26 +351,20 @@ pub fn remap_test() { let mid_text: VirtAddr = ((stext as usize + etext as usize) / 2).into(); let mid_rodata: VirtAddr = ((srodata as usize + erodata as usize) / 2).into(); let mid_data: VirtAddr = ((sdata as usize + edata as usize) / 2).into(); - assert!( - !kernel_space - .page_table - .translate(mid_text.floor()) - .unwrap() - .writable(), - ); - assert!( - !kernel_space - .page_table - .translate(mid_rodata.floor()) - .unwrap() - .writable(), - ); - assert!( - !kernel_space - .page_table - .translate(mid_data.floor()) - .unwrap() - .executable(), - ); + assert!(!kernel_space + .page_table + .translate(mid_text.floor()) + .unwrap() + .writable(),); + assert!(!kernel_space + .page_table + .translate(mid_rodata.floor()) + .unwrap() + .writable(),); + assert!(!kernel_space + .page_table + .translate(mid_data.floor()) + .unwrap() + .executable(),); println!("remap_test passed!"); } diff --git a/os/src/sync/condvar.rs b/os/src/sync/condvar.rs index fc3f586b..d7943e1d 100644 --- a/os/src/sync/condvar.rs +++ b/os/src/sync/condvar.rs @@ -29,7 +29,7 @@ impl Condvar { } pub fn wait(&self) { - let mut inner =self.inner.exclusive_access(); + let mut inner = self.inner.exclusive_access(); inner.wait_queue.push_back(current_task().unwrap()); drop(inner); block_current_and_run_next(); diff --git a/user/src/bin/huge_write_mt.rs b/user/src/bin/huge_write_mt.rs index 04717c84..63146a58 100644 --- a/user/src/bin/huge_write_mt.rs +++ b/user/src/bin/huge_write_mt.rs @@ -5,50 +5,52 @@ extern crate user_lib; extern crate alloc; -use alloc::vec::Vec; +use alloc::{vec::Vec, string::String, fmt::format}; use user_lib::{exit, thread_create, waittid}; -use user_lib::{close, get_time, open, write, OpenFlags}; +use user_lib::{close, get_time, open, write, OpenFlags, gettid}; fn worker(size_kib: usize) { let mut buffer = [0u8; 1024]; // 1KiB for (i, ch) in buffer.iter_mut().enumerate() { *ch = i as u8; } - for _ in 0..size_kib { - write(3, &buffer); + let filename = format(format_args!("testf{}\0", gettid())); + let f = open(filename.as_str(), OpenFlags::CREATE | OpenFlags::WRONLY); + if f < 0 { + panic!("Open test file failed!"); } + let f = f as usize; + for _ in 0..size_kib { + write(f, &buffer); + } + close(f); exit(0) } #[no_mangle] pub fn main(argc: usize, argv: &[&str]) -> i32 { - let f = open("testf\0", OpenFlags::CREATE | OpenFlags::WRONLY); - if f < 0 { - panic!("Open test file failed!"); - } - let f = f as usize; - assert_eq!(f, 3); assert_eq!(argc, 2, "wrong argument"); + let size_mb = 1usize; + let size_kb = size_mb << 10; let workers = argv[1].parse::().expect("wrong argument"); - assert!(workers >= 1 && 1024 % workers == 0, "wrong argument"); + assert!(workers >= 1 && size_kb % workers == 0, "wrong argument"); let start = get_time(); let mut v = Vec::new(); let size_mb = 1usize; - for i in 0..workers { - v.push(thread_create(worker as usize, size_mb * 1024 / workers)); + for _ in 0..workers { + v.push(thread_create(worker as usize, size_kb / workers)); } for tid in v.iter() { assert_eq!(0, waittid(*tid as usize)); } - close(f); let time_ms = (get_time() - start) as usize; - let speed_kbs = (size_mb << 20) / time_ms; + let speed_kbs = size_kb * 1000 / time_ms; println!( - "{}MiB written, time cost = {}ms, write speed = {}KiB/s", - size_mb, time_ms, speed_kbs + "{}MiB written by {} threads, time cost = {}ms, write speed = {}KiB/s", + size_mb, workers, time_ms, speed_kbs ); 0 }