From b77a52dccb2586260df2ad6a083e5a6759c6fd89 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 4 Apr 2019 12:45:55 +0800 Subject: [PATCH] move bit-allocator and rcore-thread crate to remote --- Cargo.toml | 2 - crate/bit-allocator/Cargo.toml | 7 - crate/bit-allocator/src/lib.rs | 221 -------------------- crate/thread/Cargo.toml | 11 - crate/thread/build.rs | 1 - crate/thread/example/Cargo.toml | 19 -- crate/thread/example/README.md | 5 - crate/thread/example/src/main.rs | 204 ------------------ crate/thread/example/x86_64-blog_os.json | 15 -- crate/thread/src/interrupt.rs | 63 ------ crate/thread/src/lib.rs | 19 -- crate/thread/src/processor.rs | 127 ----------- crate/thread/src/scheduler/mod.rs | 34 --- crate/thread/src/scheduler/o1.rs | 65 ------ crate/thread/src/scheduler/rr.rs | 109 ---------- crate/thread/src/scheduler/stride.rs | 113 ---------- crate/thread/src/scheduler/work_stealing.rs | 80 ------- crate/thread/src/std_thread.rs | 165 --------------- crate/thread/src/thread_pool.rs | 221 -------------------- crate/thread/src/timer.rs | 65 ------ kernel/Cargo.lock | 22 +- kernel/Cargo.toml | 4 +- kernel/src/arch/x86_64/memory.rs | 2 +- kernel/src/memory.rs | 8 +- 24 files changed, 20 insertions(+), 1562 deletions(-) delete mode 100644 crate/bit-allocator/Cargo.toml delete mode 100644 crate/bit-allocator/src/lib.rs delete mode 100644 crate/thread/Cargo.toml delete mode 100644 crate/thread/build.rs delete mode 100644 crate/thread/example/Cargo.toml delete mode 100644 crate/thread/example/README.md delete mode 100644 crate/thread/example/src/main.rs delete mode 100644 crate/thread/example/x86_64-blog_os.json delete mode 100644 crate/thread/src/interrupt.rs delete mode 100644 crate/thread/src/lib.rs delete mode 100644 crate/thread/src/processor.rs delete mode 100644 crate/thread/src/scheduler/mod.rs delete mode 100644 crate/thread/src/scheduler/o1.rs delete mode 100644 crate/thread/src/scheduler/rr.rs delete mode 100644 crate/thread/src/scheduler/stride.rs delete mode 100644 crate/thread/src/scheduler/work_stealing.rs delete mode 100644 crate/thread/src/std_thread.rs delete mode 100644 crate/thread/src/thread_pool.rs delete mode 100644 crate/thread/src/timer.rs diff --git a/Cargo.toml b/Cargo.toml index 00d2e95..68779bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,6 @@ [workspace] members = [ - "crate/bit-allocator", "crate/memory", "crate/sync", - "crate/thread", ] exclude = ["kernel", "bootloader", "user/rust"] diff --git a/crate/bit-allocator/Cargo.toml b/crate/bit-allocator/Cargo.toml deleted file mode 100644 index fb4d6dd..0000000 --- a/crate/bit-allocator/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "bit-allocator" -version = "0.1.0" -authors = ["WangRunji "] - -[dependencies] -bit_field = "0.9" diff --git a/crate/bit-allocator/src/lib.rs b/crate/bit-allocator/src/lib.rs deleted file mode 100644 index 6c30948..0000000 --- a/crate/bit-allocator/src/lib.rs +++ /dev/null @@ -1,221 +0,0 @@ -#![no_std] -#![feature(asm)] - -extern crate bit_field; - -use bit_field::BitField; -use core::ops::Range; - -/// Allocator of a bitmap, able to allocate / free bits. -/// -/// CAP: the bitmap has a total of CAP bits, numbered from 0 to CAP-1 inclusively. -/// -/// alloc: allocate a free bit. -/// dealloc: free an allocated bit. -/// -/// insert: mark bits in the range as allocated (available) -/// remove: reverse of insert -/// -/// any: whether there are free bits remaining -/// test: whether a specific bit is free -pub trait BitAlloc: Default { - const CAP: usize; - fn alloc(&mut self) -> Option; - fn dealloc(&mut self, key: usize); - fn insert(&mut self, range: Range); - fn remove(&mut self, range: Range); - fn any(&self) -> bool; - fn test(&self, key: usize) -> bool; -} - -pub type BitAlloc256 = BitAllocCascade16; -pub type BitAlloc4K = BitAllocCascade16; -pub type BitAlloc64K = BitAllocCascade16; -pub type BitAlloc1M = BitAllocCascade16; -pub type BitAlloc16M = BitAllocCascade16; -pub type BitAlloc256M = BitAllocCascade16; - -/// Implement the bit allocator by segment tree algorithm. -#[derive(Default)] -pub struct BitAllocCascade16 { - bitset: u16, // for each bit, 1 indicates available, 0 indicates inavailable - sub: [T; 16], -} - -impl BitAlloc for BitAllocCascade16 { - const CAP: usize = T::CAP * 16; - - fn alloc(&mut self) -> Option { - if self.any() { - let i = log2(self.bitset); - let res = self.sub[i].alloc().unwrap() + i * T::CAP; - self.bitset.set_bit(i, self.sub[i].any()); - Some(res) - } else { - None - } - } - fn dealloc(&mut self, key: usize) { - let i = key / T::CAP; - self.sub[i].dealloc(key % T::CAP); - self.bitset.set_bit(i, true); - } - fn insert(&mut self, range: Range) { - self.for_range(range, |sub: &mut T, range| sub.insert(range)); - } - fn remove(&mut self, range: Range) { - self.for_range(range, |sub: &mut T, range| sub.remove(range)); - } - fn any(&self) -> bool { - self.bitset != 0 - } - fn test(&self, key: usize) -> bool { - self.sub[key / T::CAP].test(key % T::CAP) - } -} - -impl BitAllocCascade16 { - fn for_range(&mut self, range: Range, f: impl Fn(&mut T, Range)) { - let Range { start, end } = range; - assert!(start <= end); - assert!(end <= Self::CAP); - for i in start / T::CAP..=(end - 1) / T::CAP { - let begin = if start / T::CAP == i { - start % T::CAP - } else { - 0 - }; - let end = if end / T::CAP == i { - end % T::CAP - } else { - T::CAP - }; - f(&mut self.sub[i], begin..end); - self.bitset.set_bit(i, self.sub[i].any()); - } - } -} - -#[derive(Default)] -pub struct BitAlloc16(u16); - -/// BitAlloc16 acts as the leaf (except the leaf bits of course) nodes -/// in the segment trees. -impl BitAlloc for BitAlloc16 { - const CAP: usize = 16; - - fn alloc(&mut self) -> Option { - if self.any() { - let i = log2(self.0); - self.0.set_bit(i, false); - Some(i) - } else { - None - } - } - fn dealloc(&mut self, key: usize) { - assert!(!self.test(key)); - self.0.set_bit(key, true); - } - fn insert(&mut self, range: Range) { - self.0.set_bits(range.clone(), 0xffff.get_bits(range)); - } - fn remove(&mut self, range: Range) { - self.0.set_bits(range, 0); - } - fn any(&self) -> bool { - self.0 != 0 - } - fn test(&self, key: usize) -> bool { - self.0.get_bit(key) - } -} - -#[inline(always)] -#[cfg(target_arch = "x86_64")] -fn log2(x: u16) -> usize { - assert_ne!(x, 0); - let pos: u16; - unsafe { asm!("bsrw $1, $0" :"=r"(pos) :"r"(x) : :"volatile") }; - pos as usize -} - -#[inline(always)] -#[cfg(not(target_arch = "x86_64"))] -fn log2(x: u16) -> usize { - log2_naive(x) -} - -#[cfg(not(target_arch = "x86_64"))] -#[inline(always)] -fn log2_naive(mut x: u16) -> usize { - //a naive implement - assert_ne!(x, 0); - let mut pos = -1; - while x != 0 { - pos += 1; - x >>= 1; - } - pos as usize -} - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(not(target_arch = "x86_64"))] - #[test] - fn log2_() { - for x in 1..=0xffff { - assert_eq!(log2(x), log2_naive(x), "log2 failed: {}", x); - } - } - - #[test] - fn bitalloc16() { - let mut ba = BitAlloc16::default(); - assert_eq!(BitAlloc16::CAP, 16); - ba.insert(0..16); - for i in 0..16 { - assert_eq!(ba.test(i), true); - } - ba.remove(8..14); - assert_eq!(ba.alloc(), Some(15)); - assert_eq!(ba.alloc(), Some(14)); - assert_eq!(ba.alloc(), Some(7)); - ba.dealloc(14); - ba.dealloc(15); - ba.dealloc(7); - - for _ in 0..10 { - assert!(ba.alloc().is_some()); - } - assert!(!ba.any()); - assert!(ba.alloc().is_none()); - } - - #[test] - fn bitalloc4k() { - let mut ba = BitAlloc4K::default(); - assert_eq!(BitAlloc4K::CAP, 4096); - ba.insert(0..4096); - for i in 0..4096 { - assert_eq!(ba.test(i), true); - } - ba.remove(8..4094); - for i in 0..4096 { - assert_eq!(ba.test(i), i < 8 || i >= 4094); - } - assert_eq!(ba.alloc(), Some(4095)); - assert_eq!(ba.alloc(), Some(4094)); - assert_eq!(ba.alloc(), Some(7)); - ba.dealloc(4095); - ba.dealloc(4094); - ba.dealloc(7); - - for _ in 0..10 { - assert!(ba.alloc().is_some()); - } - assert!(ba.alloc().is_none()); - } -} diff --git a/crate/thread/Cargo.toml b/crate/thread/Cargo.toml deleted file mode 100644 index e8aa1c3..0000000 --- a/crate/thread/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "rcore-thread" -version = "0.1.0" -authors = ["WangRunji "] -description = "Bare-metal thread scheduler and executor" -edition = "2018" - -[dependencies] -log = "0.4" -spin = "0.5" -deque = { git = "https://github.com/rcore-os/deque.git", branch = "no_std" } \ No newline at end of file diff --git a/crate/thread/build.rs b/crate/thread/build.rs deleted file mode 100644 index f328e4d..0000000 --- a/crate/thread/build.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/crate/thread/example/Cargo.toml b/crate/thread/example/Cargo.toml deleted file mode 100644 index 0ecc867..0000000 --- a/crate/thread/example/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "example" -version = "0.1.0" -authors = ["WangRunji "] -edition = "2018" - -[dependencies] -log = "0.4" -linked_list_allocator = "0.6" -blog_os = { git = "https://github.com/phil-opp/blog_os.git" } -rcore-thread = { path = ".." } - -[package.metadata.bootimage] -default-target = "x86_64-blog_os.json" -run-command = ["qemu-system-x86_64", - "-drive", "format=raw,file={}", - "-serial", "mon:stdio", - "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04" -] \ No newline at end of file diff --git a/crate/thread/example/README.md b/crate/thread/example/README.md deleted file mode 100644 index 2b14623..0000000 --- a/crate/thread/example/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Example of `rcore-thread` crate - -```bash -bootimage run --release -``` \ No newline at end of file diff --git a/crate/thread/example/src/main.rs b/crate/thread/example/src/main.rs deleted file mode 100644 index 2462998..0000000 --- a/crate/thread/example/src/main.rs +++ /dev/null @@ -1,204 +0,0 @@ -#![no_std] -#![no_main] -#![feature(asm)] -#![feature(alloc)] -#![feature(naked_functions)] -#![feature(lang_items)] - -extern crate alloc; - -use core::alloc::Layout; -use core::panic::PanicInfo; -use alloc::{boxed::Box, sync::Arc}; - -use blog_os::{exit_qemu, gdt, interrupts::init_idt, serial_println}; -use linked_list_allocator::LockedHeap; -use rcore_thread::{*, std_thread as thread}; - -const STACK_SIZE: usize = 0x2000; -const HEAP_SIZE: usize = 0x100000; -const MAX_CPU_NUM: usize = 1; -const MAX_PROC_NUM: usize = 32; - - -/// The entry of the kernel -#[no_mangle] -pub extern "C" fn _start() -> ! { - // init x86 - gdt::init(); - init_idt(); - // init log - init_log(); - // init heap - unsafe { HEAP_ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); } - // init processor - let scheduler = scheduler::RRScheduler::new(5); - let thread_pool = Arc::new(ThreadPool::new(scheduler, MAX_PROC_NUM)); - unsafe { processor().init(0, Thread::init(), thread_pool); } - // init threads - thread::spawn(|| { - let tid = processor().tid(); - serial_println!("[{}] yield", tid); - thread::yield_now(); - serial_println!("[{}] spawn", tid); - let t2 = thread::spawn(|| { - let tid = processor().tid(); - serial_println!("[{}] yield", tid); - thread::yield_now(); - serial_println!("[{}] return 8", tid); - 8 - }); - serial_println!("[{}] join", tid); - let ret = t2.join(); - serial_println!("[{}] get {:?}", tid, ret); - serial_println!("[{}] exit", tid); - }); - // run threads - processor().run(); -} - -fn init_log() { - use log::*; - struct SimpleLogger; - impl Log for SimpleLogger { - fn enabled(&self, _metadata: &Metadata) -> bool { - true - } - fn log(&self, record: &Record) { - serial_println!("[{:>5}] {}", record.level(), record.args()); - } - fn flush(&self) {} - } - static LOGGER: SimpleLogger = SimpleLogger; - set_logger(&LOGGER).unwrap(); - set_max_level(LevelFilter::Trace); -} - -/// The context of a thread. -/// -/// When a thread yield, its context will be stored at its stack. -#[derive(Debug, Default)] -#[repr(C)] -struct ContextData { - rdi: usize, // arg0 - r15: usize, - r14: usize, - r13: usize, - r12: usize, - rbp: usize, - rbx: usize, - rip: usize, -} - -impl ContextData { - fn new(entry: extern fn(usize) -> !, arg0: usize) -> Self { - ContextData { - rip: entry as usize, - rdi: arg0, - ..ContextData::default() - } - } -} - -#[repr(C)] -struct Thread { - rsp: usize, - stack: [u8; STACK_SIZE], -} - -impl Thread { - unsafe fn init() -> Box { - Box::new(core::mem::uninitialized()) - } - fn new(entry: extern fn(usize) -> !, arg0: usize) -> Box { - let mut thread = unsafe { Thread::init() }; - let rsp = thread.stack.as_ptr() as usize + STACK_SIZE - core::mem::size_of::(); - // push a Context at stack top - let init_context = ContextData::new(entry, arg0); - unsafe { (rsp as *mut ContextData).write(init_context); } - thread.rsp = rsp; - thread - } -} - -/// Implement `switch_to` for a thread -impl Context for Thread { - /// Switch to another thread. - unsafe fn switch_to(&mut self, target: &mut Context) { - let (to, _): (*mut Thread, usize) = core::mem::transmute(target); - inner(self, to); - - #[naked] - #[inline(never)] - unsafe extern "C" fn inner(_from: *mut Thread, _to: *mut Thread) { - asm!( - " - // push rip (by caller) - - // Save self callee-save registers - push rbx - push rbp - push r12 - push r13 - push r14 - push r15 - push rdi - - // Switch stacks - mov [rdi], rsp // *rdi = from_rsp - mov rsp, [rsi] // *rsi = to_rsp - - // Restore target callee-save registers - pop rdi - pop r15 - pop r14 - pop r13 - pop r12 - pop rbp - pop rbx - - // pop rip - ret" - : : : : "intel" "volatile" ) - } - } - - fn set_tid(&mut self, _tid: usize) { - } -} - -/// Define global `Processor` for each core. -static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new()]; - -/// Now we only have one core. -fn cpu_id() -> usize { 0 } - -/// Implement dependency for `rcore_thread::std_thread` -#[no_mangle] -pub fn processor() -> &'static Processor { - &PROCESSORS[cpu_id()] -} - -/// Implement dependency for `rcore_thread::std_thread` -#[no_mangle] -pub fn new_kernel_context(entry: extern fn(usize) -> !, arg0: usize) -> Box { - Thread::new(entry, arg0) -} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - serial_println!("\n{}", info); - - unsafe { exit_qemu(); } - loop {} -} - -#[global_allocator] -static HEAP_ALLOCATOR: LockedHeap = LockedHeap::empty(); - -static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE]; - -#[lang = "oom"] -fn oom(_: Layout) -> ! { - panic!("out of memory"); -} \ No newline at end of file diff --git a/crate/thread/example/x86_64-blog_os.json b/crate/thread/example/x86_64-blog_os.json deleted file mode 100644 index 7d2110d..0000000 --- a/crate/thread/example/x86_64-blog_os.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "arch": "x86_64", - "target-endian": "little", - "target-pointer-width": "64", - "target-c-int-width": "32", - "os": "none", - "executables": true, - "linker-flavor": "ld.lld", - "linker": "rust-lld", - "panic-strategy": "abort", - "disable-redzone": true, - "features": "-mmx,-sse,+soft-float" -} diff --git a/crate/thread/src/interrupt.rs b/crate/thread/src/interrupt.rs deleted file mode 100644 index d7c1d3c..0000000 --- a/crate/thread/src/interrupt.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Enable and disable interrupt for each architecture. - -#[inline(always)] -#[cfg(target_arch = "x86_64")] -pub unsafe fn disable_and_store() -> usize { - let rflags: usize; - asm!("pushfq; popq $0; cli" : "=r"(rflags) ::: "volatile"); - rflags & (1 << 9) -} - -#[inline(always)] -#[cfg(target_arch = "x86_64")] -pub unsafe fn restore(flags: usize) { - if flags != 0 { - asm!("sti" :::: "volatile"); - } -} - -#[inline(always)] -#[cfg(target_arch = "x86_64")] -pub unsafe fn enable_and_wfi() { - asm!("sti; hlt" :::: "volatile"); -} - -#[inline(always)] -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -pub unsafe fn disable_and_store() -> usize { - let sstatus: usize; - asm!("csrci sstatus, 1 << 1" : "=r"(sstatus) ::: "volatile"); - sstatus & (1 << 1) -} - -#[inline(always)] -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -pub unsafe fn restore(flags: usize) { - asm!("csrs sstatus, $0" :: "r"(flags) :: "volatile"); -} - -#[inline(always)] -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -pub unsafe fn enable_and_wfi() { - asm!("csrsi sstatus, 1 << 1; wfi" :::: "volatile"); -} - -#[inline(always)] -#[cfg(target_arch = "aarch64")] -pub unsafe fn disable_and_store() -> usize { - let daif: u32; - asm!("mrs $0, DAIF; msr daifset, #2": "=r"(daif) ::: "volatile"); - daif as usize -} - -#[inline(always)] -#[cfg(target_arch = "aarch64")] -pub unsafe fn restore(flags: usize) { - asm!("msr DAIF, $0" :: "r"(flags as u32) :: "volatile"); -} - -#[inline(always)] -#[cfg(target_arch = "aarch64")] -pub unsafe fn enable_and_wfi() { - asm!("msr daifclr, #2; wfi" :::: "volatile"); -} diff --git a/crate/thread/src/lib.rs b/crate/thread/src/lib.rs deleted file mode 100644 index 1a66d6a..0000000 --- a/crate/thread/src/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![cfg_attr(not(test), no_std)] -#![feature(alloc)] -#![feature(const_fn)] -#![feature(linkage)] -#![feature(vec_resize_default)] -#![feature(asm)] -#![feature(exact_size_is_empty)] - -extern crate alloc; - -mod interrupt; -mod processor; -pub mod scheduler; -pub mod std_thread; -mod thread_pool; -mod timer; - -pub use crate::processor::Processor; -pub use crate::thread_pool::*; diff --git a/crate/thread/src/processor.rs b/crate/thread/src/processor.rs deleted file mode 100644 index e935087..0000000 --- a/crate/thread/src/processor.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::interrupt; -use crate::thread_pool::*; -use alloc::boxed::Box; -use alloc::sync::Arc; -use core::cell::UnsafeCell; -use log::*; - -/// Thread executor -/// -/// Per-CPU struct. Defined at global. -/// Only accessed by associated CPU with interrupt disabled. -#[derive(Default)] -pub struct Processor { - inner: UnsafeCell>, -} - -unsafe impl Sync for Processor {} - -struct ProcessorInner { - id: usize, - proc: Option<(Tid, Box)>, - loop_context: Box, - manager: Arc, -} - -impl Processor { - pub const fn new() -> Self { - Processor { - inner: UnsafeCell::new(None), - } - } - - pub unsafe fn init(&self, id: usize, context: Box, manager: Arc) { - *self.inner.get() = Some(ProcessorInner { - id, - proc: None, - loop_context: context, - manager, - }); - } - - fn inner(&self) -> &mut ProcessorInner { - unsafe { &mut *self.inner.get() } - .as_mut() - .expect("Processor is not initialized") - } - - /// Begin running processes after CPU setup. - /// - /// This function never returns. It loops, doing: - /// - choose a process to run - /// - switch to start running that process - /// - eventually that process transfers control - /// via switch back to the scheduler. - pub fn run(&self) -> ! { - let inner = self.inner(); - unsafe { - interrupt::disable_and_store(); - } - loop { - if let Some(proc) = inner.manager.run(inner.id) { - trace!("CPU{} begin running thread {}", inner.id, proc.0); - inner.proc = Some(proc); - unsafe { - inner - .loop_context - .switch_to(&mut *inner.proc.as_mut().unwrap().1); - } - let (tid, context) = inner.proc.take().unwrap(); - trace!("CPU{} stop running thread {}", inner.id, tid); - inner.manager.stop(tid, context); - } else { - trace!("CPU{} idle", inner.id); - unsafe { - interrupt::enable_and_wfi(); - } - // wait for a timer interrupt - unsafe { - interrupt::disable_and_store(); - } - } - } - } - - /// Called by process running on this Processor. - /// Yield and reschedule. - /// - /// The interrupt may be enabled. - pub fn yield_now(&self) { - let inner = self.inner(); - unsafe { - let flags = interrupt::disable_and_store(); - inner - .proc - .as_mut() - .unwrap() - .1 - .switch_to(&mut *inner.loop_context); - interrupt::restore(flags); - } - } - - pub fn tid(&self) -> Tid { - self.inner().proc.as_ref().unwrap().0 - } - - pub fn context(&self) -> &Context { - &*self.inner().proc.as_ref().unwrap().1 - } - - pub fn manager(&self) -> &ThreadPool { - &*self.inner().manager - } - - /// Called by timer interrupt handler. - /// - /// The interrupt should be disabled in the handler. - pub fn tick(&self) { - // If I'm idle, tid == None, need_reschedule == false. - // Will go back to `run()` after interrupt return. - let tid = self.inner().proc.as_ref().map(|p| p.0); - let need_reschedule = self.manager().tick(self.inner().id, tid); - if need_reschedule { - self.yield_now(); - } - } -} diff --git a/crate/thread/src/scheduler/mod.rs b/crate/thread/src/scheduler/mod.rs deleted file mode 100644 index bc42450..0000000 --- a/crate/thread/src/scheduler/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -use alloc::{collections::BinaryHeap, vec::Vec}; - -use log::*; -use spin::Mutex; - -pub use self::o1::O1Scheduler; -pub use self::rr::RRScheduler; -pub use self::stride::StrideScheduler; -pub use self::work_stealing::WorkStealingScheduler; - -mod o1; -mod rr; -mod stride; -mod work_stealing; - -type Tid = usize; - -/// The scheduler for a ThreadPool -pub trait Scheduler: 'static { - /// Push a thread to the back of ready queue. - fn push(&self, tid: Tid); - /// Select a thread to run, pop it from the queue. - fn pop(&self, cpu_id: usize) -> Option; - /// Got a tick from CPU. - /// Return true if need reschedule. - fn tick(&self, current_tid: Tid) -> bool; - /// Set priority of a thread. - fn set_priority(&self, tid: Tid, priority: u8); -} - -fn expand(vec: &mut Vec, id: usize) { - let len = vec.len(); - vec.resize(len.max(id + 1), T::default()); -} diff --git a/crate/thread/src/scheduler/o1.rs b/crate/thread/src/scheduler/o1.rs deleted file mode 100644 index f2e273c..0000000 --- a/crate/thread/src/scheduler/o1.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! O(1) scheduler introduced in Linux 2.6 -//! -//! Two queues are maintained, one is active, another is inactive. -//! Take the first task from the active queue to run. When it is empty, swap active and inactive queues. - -use super::*; - -pub struct O1Scheduler { - inner: Mutex, -} - -struct O1SchedulerInner { - active_queue: usize, - queues: [Vec; 2], -} - -impl Scheduler for O1Scheduler { - fn push(&self, tid: usize) { - self.inner.lock().push(tid); - } - fn pop(&self, _cpu_id: usize) -> Option { - self.inner.lock().pop() - } - fn tick(&self, current_tid: usize) -> bool { - self.inner.lock().tick(current_tid) - } - fn set_priority(&self, _tid: usize, _priority: u8) {} -} - -impl O1Scheduler { - pub fn new() -> Self { - let inner = O1SchedulerInner { - active_queue: 0, - queues: [Vec::new(), Vec::new()], - }; - O1Scheduler { - inner: Mutex::new(inner), - } - } -} - -impl O1SchedulerInner { - fn push(&mut self, tid: Tid) { - let inactive_queue = 1 - self.active_queue; - self.queues[inactive_queue].push(tid); - trace!("o1 push {}", tid - 1); - } - - fn pop(&mut self) -> Option { - let ret = match self.queues[self.active_queue].pop() { - Some(tid) => return Some(tid), - None => { - // active queue is empty, swap 'em - self.active_queue = 1 - self.active_queue; - self.queues[self.active_queue].pop() - } - }; - trace!("o1 pop {:?}", ret); - ret - } - - fn tick(&mut self, _current: Tid) -> bool { - true - } -} diff --git a/crate/thread/src/scheduler/rr.rs b/crate/thread/src/scheduler/rr.rs deleted file mode 100644 index d111dab..0000000 --- a/crate/thread/src/scheduler/rr.rs +++ /dev/null @@ -1,109 +0,0 @@ -use super::*; - -pub struct RRScheduler { - inner: Mutex, -} - -struct RRSchedulerInner { - max_time_slice: usize, - infos: Vec, -} - -#[derive(Debug, Default, Copy, Clone)] -struct RRProcInfo { - present: bool, - rest_slice: usize, - prev: Tid, - next: Tid, -} - -impl Scheduler for RRScheduler { - fn push(&self, tid: usize) { - self.inner.lock().push(tid); - } - fn pop(&self, _cpu_id: usize) -> Option { - self.inner.lock().pop() - } - fn tick(&self, current_tid: usize) -> bool { - self.inner.lock().tick(current_tid) - } - fn set_priority(&self, _tid: usize, _priority: u8) {} -} - -impl RRScheduler { - pub fn new(max_time_slice: usize) -> Self { - let inner = RRSchedulerInner { - max_time_slice, - infos: Vec::default(), - }; - RRScheduler { - inner: Mutex::new(inner), - } - } -} - -impl RRSchedulerInner { - fn push(&mut self, tid: Tid) { - let tid = tid + 1; - expand(&mut self.infos, tid); - { - let info = &mut self.infos[tid]; - assert!(!info.present); - info.present = true; - if info.rest_slice == 0 { - info.rest_slice = self.max_time_slice; - } - } - self._list_add_before(tid, 0); - trace!("rr push {}", tid - 1); - } - - fn pop(&mut self) -> Option { - let ret = match self.infos[0].next { - 0 => None, - tid => { - self.infos[tid].present = false; - self._list_remove(tid); - Some(tid - 1) - } - }; - trace!("rr pop {:?}", ret); - ret - } - - fn tick(&mut self, current: Tid) -> bool { - let current = current + 1; - expand(&mut self.infos, current); - assert!(!self.infos[current].present); - - let rest = &mut self.infos[current].rest_slice; - if *rest > 0 { - *rest -= 1; - } else { - warn!("current process rest_slice = 0, need reschedule") - } - *rest == 0 - } -} - -impl RRSchedulerInner { - fn _list_add_before(&mut self, i: Tid, at: Tid) { - let prev = self.infos[at].prev; - self.infos[i].next = at; - self.infos[i].prev = prev; - self.infos[prev].next = i; - self.infos[at].prev = i; - } - fn _list_add_after(&mut self, i: Tid, at: Tid) { - let next = self.infos[at].next; - self._list_add_before(i, next); - } - fn _list_remove(&mut self, i: Tid) { - let next = self.infos[i].next; - let prev = self.infos[i].prev; - self.infos[next].prev = prev; - self.infos[prev].next = next; - self.infos[i].next = 0; - self.infos[i].prev = 0; - } -} diff --git a/crate/thread/src/scheduler/stride.rs b/crate/thread/src/scheduler/stride.rs deleted file mode 100644 index 3ac0ffd..0000000 --- a/crate/thread/src/scheduler/stride.rs +++ /dev/null @@ -1,113 +0,0 @@ -//! Stride scheduler -//! -//! Each task is assigned a priority. Each task has a running stride. -//! The task with least stride is selected to run. -//! When a task is rescheduled, its stride is added to proportional to 1 / priority. - -use super::*; - -pub struct StrideScheduler { - inner: Mutex, -} - -pub struct StrideSchedulerInner { - max_time_slice: usize, - infos: Vec, - queue: BinaryHeap<(Stride, Tid)>, // It's max heap, so pass < 0 -} - -#[derive(Debug, Default, Copy, Clone)] -struct StrideProcInfo { - present: bool, - rest_slice: usize, - stride: Stride, - priority: u8, -} - -impl StrideProcInfo { - fn pass(&mut self) { - const BIG_STRIDE: Stride = 1 << 20; - let pass = if self.priority == 0 { - BIG_STRIDE - } else { - BIG_STRIDE / self.priority as Stride - }; - // FIXME: overflowing_add is not working ??? - // self.stride.overflowing_add(pass); - self.stride += pass; - } -} - -type Stride = i32; - -impl Scheduler for StrideScheduler { - fn push(&self, tid: usize) { - self.inner.lock().push(tid); - } - fn pop(&self, _cpu_id: usize) -> Option { - self.inner.lock().pop() - } - fn tick(&self, current_tid: usize) -> bool { - self.inner.lock().tick(current_tid) - } - fn set_priority(&self, tid: usize, priority: u8) { - self.inner.lock().set_priority(tid, priority); - } -} - -impl StrideScheduler { - pub fn new(max_time_slice: usize) -> Self { - let inner = StrideSchedulerInner { - max_time_slice, - infos: Vec::default(), - queue: BinaryHeap::default(), - }; - StrideScheduler { - inner: Mutex::new(inner), - } - } -} - -impl StrideSchedulerInner { - fn push(&mut self, tid: Tid) { - expand(&mut self.infos, tid); - let info = &mut self.infos[tid]; - assert!(!info.present); - info.present = true; - if info.rest_slice == 0 { - info.rest_slice = self.max_time_slice; - } - self.queue.push((-info.stride, tid)); - trace!("stride push {}", tid); - } - - fn pop(&mut self) -> Option { - let ret = self.queue.pop().map(|(_, tid)| tid); - if let Some(tid) = ret { - let old_stride = self.infos[tid].stride; - self.infos[tid].pass(); - let stride = self.infos[tid].stride; - trace!("stride {} {:#x} -> {:#x}", tid, old_stride, stride); - } - trace!("stride pop {:?}", ret); - ret - } - - fn tick(&mut self, current: Tid) -> bool { - expand(&mut self.infos, current); - assert!(!self.infos[current].present); - - let rest = &mut self.infos[current].rest_slice; - if *rest > 0 { - *rest -= 1; - } else { - warn!("current process rest_slice = 0, need reschedule") - } - *rest == 0 - } - - fn set_priority(&mut self, tid: Tid, priority: u8) { - self.infos[tid].priority = priority; - trace!("stride {} priority = {}", tid, priority); - } -} diff --git a/crate/thread/src/scheduler/work_stealing.rs b/crate/thread/src/scheduler/work_stealing.rs deleted file mode 100644 index b0cac58..0000000 --- a/crate/thread/src/scheduler/work_stealing.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! Work stealing scheduler -//! -//! Each CPU has its own queue, and each CPU takes new jobs from its own queue. -//! When its queue is empty, steal jobs from other CPU's queue. - -use super::*; -use deque::{self, Stealer, Stolen, Worker}; - -pub struct WorkStealingScheduler { - /// The ready queue of each processors - workers: Vec>, - /// Stealers to all processors' queue - stealers: Vec>, -} - -impl WorkStealingScheduler { - pub fn new(core_num: usize) -> Self { - let (workers, stealers) = (0..core_num).map(|_| deque::new()).unzip(); - WorkStealingScheduler { workers, stealers } - } -} - -impl Scheduler for WorkStealingScheduler { - fn push(&self, tid: usize) { - // not random, but uniform - // no sync, because we don't need to - static mut WORKER_CPU: usize = 0; - let n = self.workers.len(); - let mut cpu = unsafe { - WORKER_CPU = WORKER_CPU + 1; - if WORKER_CPU >= n { - WORKER_CPU -= n; - } - WORKER_CPU - }; - - // potential racing, so we just check once more - if cpu >= n { - cpu -= n; - } - self.workers[cpu].push(tid); - trace!("work-stealing: cpu{} push thread {}", cpu, tid); - } - - fn pop(&self, cpu_id: usize) -> Option { - if let Some(tid) = self.workers[cpu_id].pop() { - trace!("work-stealing: cpu{} pop thread {}", cpu_id, tid); - return Some(tid); - } - let n = self.workers.len(); - for i in 1..n { - let mut other_id = cpu_id + i; - if other_id >= n { - other_id -= n; - } - loop { - match self.stealers[other_id].steal() { - Stolen::Abort => {} // retry - Stolen::Empty => break, - Stolen::Data(tid) => { - trace!( - "work-stealing: cpu{} steal thread {} from cpu{}", - cpu_id, - tid, - other_id - ); - return Some(tid); - } - } - } - } - None - } - - fn tick(&self, _current_tid: usize) -> bool { - true - } - - fn set_priority(&self, _tid: usize, _priority: u8) {} -} diff --git a/crate/thread/src/std_thread.rs b/crate/thread/src/std_thread.rs deleted file mode 100644 index 048f6d7..0000000 --- a/crate/thread/src/std_thread.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! `std::thread`-like interface -//! -//! Based on Processor. Used in kernel. -//! -//! You need to implement the following functions before use: -//! - `processor`: Get a reference of the current `Processor` -//! - `new_kernel_context`: Construct a `Context` of the new kernel thread - -use crate::processor::*; -use crate::thread_pool::*; -use alloc::boxed::Box; -use core::marker::PhantomData; -use core::time::Duration; -use log::*; - -#[linkage = "weak"] -#[no_mangle] -/// Get a reference of the current `Processor` -fn processor() -> &'static Processor { - unimplemented!("thread: Please implement and export `processor`") -} - -#[linkage = "weak"] -#[no_mangle] -/// Construct a `Context` of the new kernel thread -fn new_kernel_context(_entry: extern "C" fn(usize) -> !, _arg: usize) -> Box { - unimplemented!("thread: Please implement and export `new_kernel_context`") -} - -/// Gets a handle to the thread that invokes it. -pub fn current() -> Thread { - Thread { - tid: processor().tid(), - } -} - -/// Puts the current thread to sleep for the specified amount of time. -pub fn sleep(dur: Duration) { - let time = dur_to_ticks(dur); - trace!("sleep: {:?} ticks", time); - processor().manager().sleep(current().id(), time); - park(); - - fn dur_to_ticks(dur: Duration) -> usize { - return dur.as_secs() as usize * 100 + dur.subsec_nanos() as usize / 10_000_000; - } -} - -/// Spawns a new thread, returning a JoinHandle for it. -/// -/// `F`: Type of the function `f` -/// `T`: Type of the return value of `f` -pub fn spawn(f: F) -> JoinHandle -where - F: Send + 'static + FnOnce() -> T, - T: Send + 'static, -{ - trace!("spawn:"); - - // 注意到下面的问题: - // Processor只能从入口地址entry+参数arg创建新线程 - // 而我们现在需要让它执行一个未知类型的(闭包)函数f - - // 首先把函数本体(代码数据)置于堆空间中 - let f = Box::into_raw(Box::new(f)); - - // 定义一个静态函数作为新线程的入口点 - // 其参数是函数f在堆上的指针 - // 这样我们就把函数f传到了一个静态函数内部 - // - // 注意到它具有泛型参数,因此对每一次spawn调用, - // 由于F类型是独特的,因此都会生成一个新的kernel_thread_entry - extern "C" fn kernel_thread_entry(f: usize) -> ! - where - F: Send + 'static + FnOnce() -> T, - T: Send + 'static, - { - // 在静态函数内部: - // 根据传进来的指针,恢复f - let f = unsafe { Box::from_raw(f as *mut F) }; - // 调用f,并将其返回值也放在堆上 - let ret = Box::new(f()); - // 让Processor退出当前线程 - // 把f返回值在堆上的指针,以线程返回码的形式传递出去 - let exit_code = Box::into_raw(ret) as usize; - processor().manager().exit(current().id(), exit_code); - processor().yield_now(); - // 再也不会被调度回来了 - unreachable!() - } - - // 在Processor中创建新的线程 - let context = new_kernel_context(kernel_thread_entry::, f as usize); - let tid = processor().manager().add(context); - - // 接下来看看`JoinHandle::join()`的实现 - // 了解是如何获取f返回值的 - return JoinHandle { - thread: Thread { tid }, - mark: PhantomData, - }; -} - -/// Cooperatively gives up a time slice to the OS scheduler. -pub fn yield_now() { - trace!("yield:"); - processor().yield_now(); -} - -/// Blocks unless or until the current thread's token is made available. -pub fn park() { - trace!("park:"); - processor().manager().sleep(current().id(), 0); - processor().yield_now(); -} - -/// Blocks unless or until the current thread's token is made available. -/// Calls `f` before thread yields. Can be used to avoid racing. -pub fn park_action(f: impl FnOnce()) { - trace!("park:"); - processor().manager().sleep(current().id(), 0); - f(); - processor().yield_now(); -} - -/// A handle to a thread. -pub struct Thread { - tid: usize, -} - -impl Thread { - /// Atomically makes the handle's token available if it is not already. - pub fn unpark(&self) { - processor().manager().wakeup(self.tid); - } - /// Gets the thread's unique identifier. - pub fn id(&self) -> usize { - self.tid - } -} - -/// An owned permission to join on a thread (block on its termination). -pub struct JoinHandle { - thread: Thread, - mark: PhantomData, -} - -impl JoinHandle { - /// Extracts a handle to the underlying thread. - pub fn thread(&self) -> &Thread { - &self.thread - } - /// Waits for the associated thread to finish. - pub fn join(self) -> Result { - loop { - trace!("try to join thread {}", self.thread.tid); - if let Some(exit_code) = processor().manager().try_remove(self.thread.tid) { - // Find return value on the heap from the exit code. - return Ok(unsafe { *Box::from_raw(exit_code as *mut T) }); - } - processor().manager().wait(current().id(), self.thread.tid); - processor().yield_now(); - } - } -} diff --git a/crate/thread/src/thread_pool.rs b/crate/thread/src/thread_pool.rs deleted file mode 100644 index 10d5471..0000000 --- a/crate/thread/src/thread_pool.rs +++ /dev/null @@ -1,221 +0,0 @@ -use crate::scheduler::Scheduler; -use crate::timer::Timer; -use alloc::boxed::Box; -use alloc::vec::Vec; -use log::*; -use spin::{Mutex, MutexGuard}; - -struct Thread { - status: Status, - status_after_stop: Status, - waiter: Option, - context: Option>, -} - -pub type Tid = usize; -type ExitCode = usize; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Status { - Ready, - Running(usize), - Sleeping, - /// aka ZOMBIE. Its context was dropped. - Exited(ExitCode), -} - -#[derive(Eq, PartialEq)] -enum Event { - Wakeup(Tid), -} - -pub trait Context { - /// Switch to target context - unsafe fn switch_to(&mut self, target: &mut Context); - - /// A tid is allocated for this context - fn set_tid(&mut self, tid: Tid); -} - -pub struct ThreadPool { - threads: Vec>>, - scheduler: Box, - timer: Mutex>, -} - -impl ThreadPool { - pub fn new(scheduler: impl Scheduler, max_proc_num: usize) -> Self { - ThreadPool { - threads: new_vec_default(max_proc_num), - scheduler: Box::new(scheduler), - timer: Mutex::new(Timer::new()), - } - } - - fn alloc_tid(&self) -> (Tid, MutexGuard>) { - for (i, proc) in self.threads.iter().enumerate() { - let thread = proc.lock(); - if thread.is_none() { - return (i, thread); - } - } - panic!("Thread number exceeded"); - } - - /// Add a new thread - /// Calls action with tid and thread context - pub fn add(&self, mut context: Box) -> Tid { - let (tid, mut thread) = self.alloc_tid(); - context.set_tid(tid); - *thread = Some(Thread { - status: Status::Ready, - status_after_stop: Status::Ready, - waiter: None, - context: Some(context), - }); - self.scheduler.push(tid); - tid - } - - /// Make thread `tid` time slice -= 1. - /// Return true if time slice == 0. - /// Called by timer interrupt handler. - pub(crate) fn tick(&self, cpu_id: usize, tid: Option) -> bool { - if cpu_id == 0 { - let mut timer = self.timer.lock(); - timer.tick(); - while let Some(event) = timer.pop() { - match event { - Event::Wakeup(tid) => self.set_status(tid, Status::Ready), - } - } - } - match tid { - Some(tid) => self.scheduler.tick(tid), - None => false, - } - } - - /// Set the priority of thread `tid` - pub fn set_priority(&self, tid: Tid, priority: u8) { - self.scheduler.set_priority(tid, priority); - } - - /// Called by Processor to get a thread to run. - /// The manager first mark it `Running`, - /// then take out and return its Context. - pub(crate) fn run(&self, cpu_id: usize) -> Option<(Tid, Box)> { - self.scheduler.pop(cpu_id).map(|tid| { - let mut proc_lock = self.threads[tid].lock(); - let mut proc = proc_lock.as_mut().expect("thread not exist"); - proc.status = Status::Running(cpu_id); - (tid, proc.context.take().expect("context not exist")) - }) - } - - /// Called by Processor to finish running a thread - /// and give its context back. - pub(crate) fn stop(&self, tid: Tid, context: Box) { - let mut proc_lock = self.threads[tid].lock(); - let proc = proc_lock.as_mut().expect("thread not exist"); - proc.status = proc.status_after_stop.clone(); - proc.status_after_stop = Status::Ready; - proc.context = Some(context); - match proc.status { - Status::Ready => self.scheduler.push(tid), - Status::Exited(_) => self.exit_handler(proc), - _ => {} - } - } - - /// Called by `JoinHandle` to let thread `tid` wait for `target`. - /// The `tid` is going to sleep, and will be woke up when `target` exit. - /// (see `exit_handler()`) - pub(crate) fn wait(&self, tid: Tid, target: Tid) { - self.set_status(tid, Status::Sleeping); - let mut target_lock = self.threads[target].lock(); - let target = target_lock.as_mut().expect("thread not exist"); - target.waiter = Some(tid); - } - - /// Switch the status of a thread. - /// Insert/Remove it to/from scheduler if necessary. - fn set_status(&self, tid: Tid, status: Status) { - let mut proc_lock = self.threads[tid].lock(); - if let Some(mut proc) = proc_lock.as_mut() { - trace!("thread {} {:?} -> {:?}", tid, proc.status, status); - match (&proc.status, &status) { - (Status::Ready, Status::Ready) => return, - (Status::Ready, _) => panic!("can not remove a thread from ready queue"), - (Status::Exited(_), _) => panic!("can not set status for a exited thread"), - (Status::Sleeping, Status::Exited(_)) => self.timer.lock().stop(Event::Wakeup(tid)), - (Status::Running(_), Status::Ready) => {} // thread will be added to scheduler in stop() - (_, Status::Ready) => self.scheduler.push(tid), - _ => {} - } - match proc.status { - Status::Running(_) => proc.status_after_stop = status, - _ => proc.status = status, - } - match proc.status { - Status::Exited(_) => self.exit_handler(proc), - _ => {} - } - } - } - - /// Try to remove an exited thread `tid`. - /// Return its exit code if success. - pub fn try_remove(&self, tid: Tid) -> Option { - let mut proc_lock = self.threads[tid].lock(); - let proc = proc_lock.as_ref().expect("thread not exist"); - match proc.status { - Status::Exited(code) => { - // release the tid - *proc_lock = None; - Some(code) - } - _ => None, - } - } - - /// Sleep `tid` for `time` ticks. - /// `time` == 0 means sleep forever - pub fn sleep(&self, tid: Tid, time: usize) { - self.set_status(tid, Status::Sleeping); - if time != 0 { - self.timer.lock().start(time, Event::Wakeup(tid)); - } - } - - pub fn wakeup(&self, tid: Tid) { - let mut proc_lock = self.threads[tid].lock(); - if let Some(mut proc) = proc_lock.as_mut() { - trace!("thread {} {:?} -> {:?}", tid, proc.status, Status::Ready); - if let Status::Sleeping = proc.status { - proc.status = Status::Ready; - self.scheduler.push(tid); - } - } - } - - pub fn exit(&self, tid: Tid, code: ExitCode) { - // NOTE: if `tid` is running, status change will be deferred. - self.set_status(tid, Status::Exited(code)); - } - /// Called when a thread exit - fn exit_handler(&self, proc: &mut Thread) { - // wake up waiter - if let Some(waiter) = proc.waiter { - self.wakeup(waiter); - } - // drop its context - proc.context = None; - } -} - -fn new_vec_default(size: usize) -> Vec { - let mut vec = Vec::new(); - vec.resize_with(size, Default::default); - vec -} diff --git a/crate/thread/src/timer.rs b/crate/thread/src/timer.rs deleted file mode 100644 index 5917d72..0000000 --- a/crate/thread/src/timer.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! A simple timer - -use alloc::collections::VecDeque; - -type Time = usize; - -struct Event { - time: Time, - data: T, -} - -/// A simple timer using ordered dequeue -pub struct Timer { - tick: Time, - timers: VecDeque>, -} - -impl Timer { - /// Create a new timer. - pub fn new() -> Self { - Timer { - tick: 0, - timers: VecDeque::new(), - } - } - /// Called on each tick. - pub fn tick(&mut self) { - self.tick += 1; - } - /// Pop an expired timer after `tick`. - /// - /// This must be called after calling `tick`, - /// and should be called multiple times until return `None`. - pub fn pop(&mut self) -> Option { - match self.timers.front() { - None => return None, - Some(timer) if timer.time != self.tick => return None, - _ => {} - }; - self.timers.pop_front().map(|t| t.data) - } - /// Start a timer with given time interval - pub fn start(&mut self, time_after: Time, data: T) { - //debug!("{:?} {:?}", self.tick, time_after); - let time = self.tick + time_after; - let event = Event { time, data }; - let mut it = self.timers.iter(); - let mut i: usize = 0; - loop { - match it.next() { - None => break, - Some(e) if e.time >= time => break, - _ => {} - } - i += 1; - } - self.timers.insert(i, event); - } - /// Stop a timer - pub fn stop(&mut self, data: T) { - if let Some(i) = self.timers.iter().position(|t| t.data == data) { - self.timers.remove(i); - } - } -} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index c49497a..18ff961 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -59,13 +59,6 @@ dependencies = [ "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bit-allocator" -version = "0.1.0" -dependencies = [ - "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bit_field" version = "0.9.0" @@ -76,6 +69,14 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmap-allocator" +version = "0.1.0" +source = "git+https://github.com/rcore-os/bitmap-allocator#891867c95bc81f2376ec6eca9e349c42dc26c7fb" +dependencies = [ + "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitvec" version = "0.9.0" @@ -310,9 +311,9 @@ dependencies = [ "aarch64 2.2.2 (git+https://github.com/rcore-os/aarch64)", "apic 0.1.0 (git+https://github.com/rcore-os/apic-rs)", "bcm2837 0.1.0 (git+https://github.com/rcore-os/bcm2837)", - "bit-allocator 0.1.0", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)", "bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)", "bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader)", "buddy_system_allocator 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -330,7 +331,7 @@ dependencies = [ "rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)", "rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)", "rcore-memory 0.1.0", - "rcore-thread 0.1.0", + "rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread)", "riscv 0.5.0 (git+https://github.com/rcore-os/riscv)", "smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -367,6 +368,7 @@ dependencies = [ [[package]] name = "rcore-thread" version = "0.1.0" +source = "git+https://github.com/rcore-os/rcore-thread#470634bc15de1532ab255555ff71adf112fd52e8" dependencies = [ "deque 0.3.2 (git+https://github.com/rcore-os/deque.git?branch=no_std)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -600,6 +602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bcm2837 0.1.0 (git+https://github.com/rcore-os/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)" = "" "checksum bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)" = "" "checksum bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfadef5c4e2c2e64067b9ecc061179f12ac7ec65ba613b1f60f3972bbada1f5b" "checksum bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader)" = "" @@ -635,6 +638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" "checksum rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)" = "" "checksum rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)" = "" +"checksum rcore-thread 0.1.0 (git+https://github.com/rcore-os/rcore-thread)" = "" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 7aacfe2..5c06128 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -50,9 +50,9 @@ device_tree = { git = "https://github.com/rcore-os/device_tree-rs" } isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers" } lazy_static = { version = "1.3", features = ["spin_no_std"] } smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] } -bit-allocator = { path = "../crate/bit-allocator" } +bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator" } rcore-memory = { path = "../crate/memory" } -rcore-thread = { path = "../crate/thread" } +rcore-thread = { git = "https://github.com/rcore-os/rcore-thread" } rcore-fs = { git = "https://github.com/rcore-os/rcore-fs" } rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs" } diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs index 325b0b8..cadd738 100644 --- a/kernel/src/arch/x86_64/memory.rs +++ b/kernel/src/arch/x86_64/memory.rs @@ -1,5 +1,5 @@ use crate::consts::KERNEL_OFFSET; -use bit_allocator::BitAlloc; +use bitmap_allocator::BitAlloc; // Depends on kernel use super::{BootInfo, MemoryRegionType}; use crate::memory::{active_table, alloc_frame, init_heap, FRAME_ALLOCATOR}; diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index f48a625..a58efcd 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -3,7 +3,7 @@ pub use crate::arch::paging::*; use crate::consts::MEMORY_OFFSET; use crate::process::process_unsafe; use crate::sync::SpinNoIrqLock; -use bit_allocator::BitAlloc; +use bitmap_allocator::BitAlloc; use buddy_system_allocator::LockedHeap; use lazy_static::*; use log::*; @@ -14,15 +14,15 @@ pub type MemorySet = rcore_memory::memory_set::MemorySet; // x86_64 support up to 64G memory #[cfg(target_arch = "x86_64")] -pub type FrameAlloc = bit_allocator::BitAlloc16M; +pub type FrameAlloc = bitmap_allocator::BitAlloc16M; // RISCV has 8M memory #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] -pub type FrameAlloc = bit_allocator::BitAlloc4K; +pub type FrameAlloc = bitmap_allocator::BitAlloc4K; // Raspberry Pi 3 has 1G memory #[cfg(target_arch = "aarch64")] -pub type FrameAlloc = bit_allocator::BitAlloc1M; +pub type FrameAlloc = bitmap_allocator::BitAlloc1M; lazy_static! { pub static ref FRAME_ALLOCATOR: SpinNoIrqLock =