#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct DefaultHugePageSizes
{
default_huge_page_size: Option<HugePageSize>,
transparent_huge_page_size: Option<HugePageSize>,
supported_huge_page_sizes: BTreeSet<HugePageSize>,
}
impl DefaultHugePageSizes
{
#[inline(always)]
pub fn default_huge_page_sizes_assuming_standard_file_system_layout() -> &'static DefaultHugePageSizes
{
static Defaults: SyncOnceCell<DefaultHugePageSizes> = SyncOnceCell::new();
let result = Defaults.get_or_try_init(||
{
let sys_path = SysPath::default();
let proc_path = ProcPath::default();
DefaultHugePageSizes::new(&sys_path, &proc_path)
});
result.expect("Could not parse suitable files in /proc and /sys to obtain page size information")
}
#[inline(always)]
pub fn new(sys_path: &SysPath, proc_path: &ProcPath) -> io::Result<Self>
{
#[inline(always)]
fn parse_and_return_if_supported(supported_huge_page_sizes: &BTreeSet<HugePageSize>, parse: impl FnOnce() -> io::Result<Option<HugePageSize>>) -> io::Result<Option<HugePageSize>>
{
let ok = if let Some(huge_page_size) = parse()?
{
if supported_huge_page_sizes.contains(&huge_page_size)
{
Some(huge_page_size)
}
else
{
None
}
}
else
{
None
};
Ok(ok)
}
let supported_huge_page_sizes = HugePageSize::supported_huge_page_sizes(sys_path);
Ok
(
Self
{
default_huge_page_size: parse_and_return_if_supported(&supported_huge_page_sizes, ||
{
let memory_information = MemoryInformation::parse_global(proc_path, false).map_err(io_error_invalid_data)?;
Ok(HugePageSize::default_huge_page_size(&memory_information))
})?,
transparent_huge_page_size: parse_and_return_if_supported(&supported_huge_page_sizes, || Ok(HugePageSize::transparent_huge_page_size(sys_path)))?,
supported_huge_page_sizes,
}
)
}
#[inline(always)]
pub fn default_huge_page_size(&self) -> Option<HugePageSize>
{
self.default_huge_page_size
}
#[inline(always)]
pub fn transparent_huge_page_size(&self) -> Option<HugePageSize>
{
self.transparent_huge_page_size
}
#[inline(always)]
pub fn is_supported_huge_page_size(&self, huge_page_size: &HugePageSize) -> bool
{
self.supported_huge_page_sizes.contains(huge_page_size)
}
#[inline(always)]
pub fn supported_huge_page_sizes(&self) -> &BTreeSet<HugePageSize>
{
&self.supported_huge_page_sizes
}
#[inline(always)]
pub fn best_fit_huge_page_size_if_any(&self, size: u64, inclusive_maximum_bytes_wasted: u64) -> Option<HugePageSize>
{
let mut best_fit = None;
for &huge_page_size in self.supported_huge_page_sizes.iter()
{
let huge_page_size_in_bytes = huge_page_size.size_in_bytes();
let bytes_wasted = size % huge_page_size_in_bytes.get();
if bytes_wasted > inclusive_maximum_bytes_wasted
{
continue
}
best_fit = Some(huge_page_size)
}
best_fit
}
#[inline(always)]
pub fn this_or_next_smaller_supported_huge_page_size(&self, huge_page_size: HugePageSize) -> Option<HugePageSize>
{
if self.is_supported(huge_page_size)
{
return Some(huge_page_size)
}
self.supported_huge_page_sizes.range(.. huge_page_size).rev().next().map(|&huge_page_size| huge_page_size)
}
#[inline(always)]
fn is_supported(&self, huge_page_size: HugePageSize) -> bool
{
self.supported_huge_page_sizes.contains(&huge_page_size)
}
}