use crate::policy::space::Space;
use crate::util::address::Address;
use crate::util::OpaquePointer;
use crate::vm::ActivePlan;
use std::sync::atomic::{AtomicUsize, Ordering};
use super::layout::map::Map;
use crate::util::heap::layout::heap_layout::VMMap;
use crate::vm::VMBinding;
pub trait PageResource<VM: VMBinding>: 'static {
fn get_new_pages(
&self,
reserved_pages: usize,
required_pages: usize,
zeroed: bool,
tls: OpaquePointer,
) -> Address {
self.alloc_pages(reserved_pages, required_pages, zeroed, tls)
}
fn reserve_pages(&self, pages: usize) -> usize {
let adj_pages = self.adjust_for_metadata(pages);
self.common()
.reserved
.fetch_add(adj_pages, Ordering::Relaxed);
adj_pages
}
fn clear_request(&self, reserved_pages: usize) {
self.common()
.reserved
.fetch_sub(reserved_pages, Ordering::Relaxed);
}
fn update_zeroing_approach(&self, _nontemporal: bool, concurrent: bool) {
debug_assert!(!concurrent || self.common().contiguous);
unimplemented!()
}
fn skip_concurrent_zeroing(&self) {
unimplemented!()
}
fn trigger_concurrent_zeroing(&self) {
unimplemented!()
}
fn concurrent_zeroing(&self) {
panic!("This PageResource does not implement concurrent zeroing")
}
fn alloc_pages(
&self,
reserved_pages: usize,
required_pages: usize,
zeroed: bool,
tls: OpaquePointer,
) -> Address;
fn adjust_for_metadata(&self, pages: usize) -> usize;
fn commit_pages(&self, reserved_pages: usize, actual_pages: usize, tls: OpaquePointer) {
let delta = actual_pages - reserved_pages;
self.common().reserved.fetch_add(delta, Ordering::Relaxed);
self.common()
.committed
.fetch_add(actual_pages, Ordering::Relaxed);
if unsafe { VM::VMActivePlan::is_mutator(tls) } {
self.vm_map()
.add_to_cumulative_committed_pages(actual_pages);
}
}
fn reserved_pages(&self) -> usize {
self.common().reserved.load(Ordering::Relaxed)
}
fn committed_pages(&self) -> usize {
self.common().committed.load(Ordering::Relaxed)
}
fn bind_space(&mut self, space: &'static dyn Space<VM>) {
self.common_mut().space = Some(space);
}
fn common(&self) -> &CommonPageResource<VM>;
fn common_mut(&mut self) -> &mut CommonPageResource<VM>;
fn vm_map(&self) -> &'static VMMap {
self.common().space.unwrap().common().vm_map()
}
}
pub struct CommonPageResource<VM: VMBinding> {
reserved: AtomicUsize,
committed: AtomicUsize,
pub contiguous: bool,
pub growable: bool,
pub space: Option<&'static dyn Space<VM>>,
}
impl<VM: VMBinding> CommonPageResource<VM> {
pub fn new(contiguous: bool, growable: bool) -> CommonPageResource<VM> {
CommonPageResource {
reserved: AtomicUsize::new(0),
committed: AtomicUsize::new(0),
contiguous,
growable,
space: None,
}
}
pub fn reserve(&self, pages: usize) {
self.reserved.fetch_add(pages, Ordering::Relaxed);
}
pub fn release_reserved(&self, pages: usize) {
self.reserved.fetch_sub(pages, Ordering::Relaxed);
}
pub fn get_reserved(&self) -> usize {
self.reserved.load(Ordering::Relaxed)
}
pub fn reset_reserved(&self) {
self.reserved.store(0, Ordering::Relaxed);
}
pub fn commit(&self, pages: usize) {
self.committed.fetch_add(pages, Ordering::Relaxed);
}
pub fn release_committed(&self, pages: usize) {
self.committed.fetch_sub(pages, Ordering::Relaxed);
}
pub fn get_committed(&self) -> usize {
self.committed.load(Ordering::Relaxed)
}
pub fn reset_committed(&self) {
self.committed.store(0, Ordering::Relaxed);
}
}