diff --git a/usr/init/src/dynrep/allocator.rs b/usr/init/src/dynrep/allocator.rs index 7220b168..f316d3cf 100644 --- a/usr/init/src/dynrep/allocator.rs +++ b/usr/init/src/dynrep/allocator.rs @@ -1,5 +1,8 @@ use core::slice::from_raw_parts_mut; use x86::bits64::paging::LARGE_PAGE_SIZE; +use lazy_static::lazy_static; +use core::sync::atomic::AtomicU8; +use core::sync::atomic::Ordering; use log::info; use core::{ @@ -10,47 +13,55 @@ use core::{ pub const BASE: u64 = 0x0510_0000_0000; pub const MAX_FRAMES: u64 = 600; +lazy_static!{ + static ref NODE_ID: AtomicU8 = AtomicU8::new(1); +} + #[derive(Clone, Copy)] pub struct MyAllocator; -impl Default for MyAllocator { - fn default() -> Self { +impl MyAllocator { + fn allocate_pages(node_id: u8) { let mut allocated = 0; + let node_offset = (node_id - 1) as u64 * LARGE_PAGE_SIZE as u64 * MAX_FRAMES; while allocated < MAX_FRAMES { // Allocate a large page of physical memory // Note that even if you allocate a base page, behind the scenes a large page is allocated // because DCM (and thus DiNOS) only allocates at large page granularity // 1 is the client machine id we want to allocate from - let (frame_id, paddr) = vibrio::syscalls::PhysicalMemory::allocate_large_page(1) + let (frame_id, paddr) = vibrio::syscalls::PhysicalMemory::allocate_large_page(node_id as usize) .expect("Failed to get physical memory large page"); info!("large frame id={:?}, paddr={:?}", frame_id, paddr); // Map allocated physical memory into user space so we can actually access it. unsafe { - vibrio::syscalls::VSpace::map_frame(frame_id, BASE + (allocated * LARGE_PAGE_SIZE as u64)).expect("Failed to map base page"); + vibrio::syscalls::VSpace::map_frame(frame_id, BASE + node_offset + (allocated * LARGE_PAGE_SIZE as u64)).expect("Failed to map base page"); } allocated += 1; } - info!("# Allocated {} frames", allocated); - MyAllocator{} + info!("# Allocated {} frames on {}", allocated, node_id); } } unsafe impl Allocator for MyAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { + let node_id = NODE_ID.fetch_add(1, Ordering::SeqCst); + let node_offset = (node_id - 1) as u64 * LARGE_PAGE_SIZE as u64 * MAX_FRAMES; + MyAllocator::allocate_pages(node_id); info!("# Allocating {:?}", layout); if layout.size() > LARGE_PAGE_SIZE * MAX_FRAMES as usize { return Err(AllocError); } - let slice = unsafe {from_raw_parts_mut(BASE as *mut u8, layout.size()) }; - // DO we need to zero the memory for mapping to work? + let slice = unsafe {from_raw_parts_mut((BASE + node_offset) as *mut u8, layout.size()) }; Ok(NonNull::from(slice)) } unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { info!("# Deallocating {:?}", layout); - vibrio::syscalls::VSpace::unmap(ptr.as_ptr() as u64, layout.size() as u64) - .expect("Failed to unmap base page"); + for i in 0..MAX_FRAMES { + vibrio::syscalls::VSpace::unmap((BASE + (i * LARGE_PAGE_SIZE as u64)) as u64, LARGE_PAGE_SIZE as u64) + .expect("Failed to unmap base page"); + } } } diff --git a/usr/init/src/dynrep/mod.rs b/usr/init/src/dynrep/mod.rs index 75fc3b80..899c3114 100644 --- a/usr/init/src/dynrep/mod.rs +++ b/usr/init/src/dynrep/mod.rs @@ -21,7 +21,7 @@ struct HashTable { impl Default for HashTable { fn default() -> Self { - let allocator = MyAllocator::default(); + let allocator = MyAllocator{}; let map = HashMap::::with_capacity_in(NUM_ENTRIES as usize, allocator); HashTable { map } } @@ -60,27 +60,35 @@ impl Dispatch for HashTable { } } -pub fn userspace_dynrep_test() { - let replicas = NonZeroUsize::new(1).unwrap(); - let nrht = NodeReplicated::::new(replicas, |_| { 0 }).unwrap(); - let ttkn = nrht.register(0).unwrap(); - - let mut ops = 0; - let batch_size = 64; +fn run_bench(core_id : usize, replica: Arc>) { + let ttkn = replica.register(core_id).unwrap(); let mut random_key :u64 = 0; + let batch_size = 64; + let duration = 5; - let start = Instant::now(); - while start.elapsed().as_secs() < 1 { - for i in 0..batch_size { - unsafe { rdrand64(&mut random_key) }; - random_key = random_key % NUM_ENTRIES; - let _ = nrht.execute(OpRd::Get(random_key), ttkn).unwrap(); - ops += 1; - } + let mut iterations = 0; + while iterations <= duration { + let mut ops = 0; + let start = Instant::now(); + while start.elapsed().as_secs() < 1 { + for i in 0..batch_size { + unsafe { rdrand64(&mut random_key) }; + random_key = random_key % NUM_ENTRIES; + let _ = replica.execute(OpRd::Get(random_key), ttkn).unwrap(); + ops += 1; + } + } + info!( + "dynhash,{}", ops + ); + iterations += 1; } - info!( - "dynhash,{}", ops - ); +} +pub fn userspace_dynrep_test() { + let replicas = NonZeroUsize::new(1).unwrap(); + let nrht = Arc::new(NodeReplicated::::new(replicas, |_| { 0 }).unwrap()); + let core_id = 0; + run_bench(core_id, nrht.clone()); info!("dynrep_test OK"); }