Skip to main content

axalloc/
lib.rs

1//! [ArceOS](https://github.com/arceos-org/arceos) global memory allocator.
2//!
3//! It provides [`GlobalAllocator`], which implements the trait
4//! [`core::alloc::GlobalAlloc`]. A static global variable of type
5//! [`GlobalAllocator`] is defined with the `#[global_allocator]` attribute, to
6//! be registered as the standard library's default allocator.
7
8#![no_std]
9
10#[macro_use]
11extern crate log;
12extern crate alloc;
13
14use core::fmt;
15use strum::{IntoStaticStr, VariantArray};
16
17const PAGE_SIZE: usize = 0x1000;
18
19mod page;
20pub use page::GlobalPage;
21
22/// Tracking of memory usage, enabled with the `tracking` feature.
23#[cfg(feature = "tracking")]
24pub mod tracking;
25
26/// Kinds of memory usage for tracking.
27#[repr(u8)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq, VariantArray, IntoStaticStr)]
29pub enum UsageKind {
30    /// Heap allocations made by kernel Rust code.
31    RustHeap,
32    /// Virtual memory, usually used for user space.
33    VirtMem,
34    /// Page cache for file systems.
35    PageCache,
36    /// Page tables.
37    PageTable,
38    /// DMA memory.
39    Dma,
40    /// Memory used by [`GlobalPage`].
41    Global,
42}
43
44/// Statistics of memory usages.
45#[derive(Clone, Copy)]
46pub struct Usages([usize; UsageKind::VARIANTS.len()]);
47
48impl Usages {
49    const fn new() -> Self {
50        Self([0; UsageKind::VARIANTS.len()])
51    }
52
53    fn alloc(&mut self, kind: UsageKind, size: usize) {
54        self.0[kind as usize] += size;
55    }
56
57    fn dealloc(&mut self, kind: UsageKind, size: usize) {
58        self.0[kind as usize] -= size;
59    }
60
61    /// Get the memory usage for a specific kind.
62    pub fn get(&self, kind: UsageKind) -> usize {
63        self.0[kind as usize]
64    }
65}
66
67impl fmt::Debug for Usages {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        let mut d = f.debug_struct("UsageStats");
70        for &kind in UsageKind::VARIANTS {
71            d.field(kind.into(), &self.0[kind as usize]);
72        }
73        d.finish()
74    }
75}
76
77// Select implementation based on features
78// When axvisor is enabled, use axvisor_impl (axallocator features are ignored)
79#[cfg(feature = "hv")]
80mod axvisor_impl;
81#[cfg(feature = "hv")]
82use axvisor_impl as imp;
83
84// When axvisor is not enabled, use default_impl with axallocator
85#[cfg(not(feature = "hv"))]
86mod default_impl;
87#[cfg(not(feature = "hv"))]
88use default_impl as imp;
89
90// Re-export types and functions from the implementation
91pub use imp::{GlobalAllocator, global_add_memory, global_init};
92
93// Re-export DefaultByteAllocator from both implementations
94pub use imp::DefaultByteAllocator;
95
96// Re-export AddrTranslator when using hv implementation
97#[cfg(feature = "hv")]
98pub use imp::AddrTranslator;
99
100/// Returns the reference to the global allocator.
101pub fn global_allocator() -> &'static GlobalAllocator {
102    imp::global_allocator()
103}