Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7895c88
feat: add Windows platform support
sepcnt Nov 26, 2025
b11ef21
fix: use constants, CI placeholder, detailed comment and better
sepcnt Nov 27, 2025
1ad2f65
Merge branch 'master' into feat-windows-support
sepcnt Dec 4, 2025
e7e5f74
Add OS abstraction
qinsoon Dec 31, 2025
7cfd2b3
Implement OS interface for Windows
qinsoon Jan 1, 2026
0cba681
Able to build on Windows
qinsoon Jan 4, 2026
cda7b72
Test passed on Windows
qinsoon Jan 4, 2026
3bdf295
Build and pass tests on Linux
qinsoon Jan 5, 2026
88ccd39
Refactor MmapStrategy to builder style
qinsoon Jan 6, 2026
582b885
Get macOS to work
qinsoon Jan 6, 2026
c09128d
Add CPU affinity methods into Process
qinsoon Jan 6, 2026
1be26c3
Tidy up for Linux
qinsoon Jan 7, 2026
f781f9a
Tidy up for macOS
qinsoon Jan 7, 2026
86baa5b
Tidy up for Windows
qinsoon Jan 7, 2026
a36639c
Fix for 32 bits linux
qinsoon Jan 7, 2026
04ea5aa
Restructure os imp
qinsoon Jan 7, 2026
72d98ea
Introduce trait OS. Rename set/zero to memset/zero.
qinsoon Jan 8, 2026
4ab4f52
Revert windows-related changes.
qinsoon Feb 10, 2026
ab892b0
Merge branch 'master' into os-interface
qinsoon Feb 10, 2026
b638bad
Fix macos build
qinsoon Feb 10, 2026
67c5789
Put set/zero back to crate::util::memory. Other minor changes to address
qinsoon Feb 11, 2026
dd24170
Remove MmapStrategy::SIDE_METADATA (unused). Minor fix to unprotect
qinsoon Feb 11, 2026
474d60a
Further remove some changes due to windows support
qinsoon Feb 11, 2026
9853346
Fix style check
qinsoon Feb 11, 2026
4390600
Minor fix. Change mprotect/munprotect to set_memory_access.
qinsoon Feb 12, 2026
8e44495
Add Process/ThreadIDType for OSProcess
qinsoon Feb 12, 2026
46b0818
Add doc for process/thread id type
qinsoon Feb 12, 2026
70cba51
Extract some methods from linux/android to linux_common
qinsoon Feb 13, 2026
8b1bf8a
Add back comments for align_alloc
qinsoon Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions benches/mock_bench/mmapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ pub use criterion::Criterion;
use mmtk::{
memory_manager, mmap_anno_test,
util::{
constants::BYTES_IN_PAGE, memory::MmapStrategy, test_private::MMAPPER,
test_util::fixtures::*, Address,
constants::BYTES_IN_PAGE, os::*, test_private::MMAPPER, test_util::fixtures::*, Address,
},
};

Expand Down Expand Up @@ -76,10 +75,17 @@ pub fn bench(c: &mut Criterion) {
c.bench_function("ensure_mapped_regular", |b| {
let start = regular.align_down(BYTES_IN_PAGE);
assert!(start.is_mapped());
let strategy = MmapStrategy::new(false, mmtk::util::memory::MmapProtection::ReadWrite);
let anno = mmap_anno_test!();
b.iter(|| {
MMAPPER.ensure_mapped(start, 1, strategy, anno).unwrap();
MMAPPER
.ensure_mapped(
start,
1,
HugePageSupport::No,
MmapProtection::ReadWrite,
anno,
)
.unwrap();
})
});
}
3 changes: 2 additions & 1 deletion src/plan/generational/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::plan::PlanTraceObject;
use crate::plan::VectorObjectQueue;
use crate::policy::gc_work::TraceKind;
use crate::scheduler::{gc_work::*, GCWork, GCWorker, WorkBucketStage};
use crate::util::os::*;
use crate::util::ObjectReference;
use crate::vm::slot::{MemorySlice, Slot};
use crate::vm::*;
Expand Down Expand Up @@ -117,7 +118,7 @@ impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessModBuf<E> {
!gen.is_object_in_nursery(*obj),
"{} was logged but is not mature. Dumping process memory maps:\n{}",
*obj,
crate::util::memory::get_process_memory_maps(),
OS::get_process_memory_maps().unwrap(),
);
<E::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<E::VM, u8>(
*obj,
Expand Down
14 changes: 5 additions & 9 deletions src/policy/copyspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ use crate::util::heap::{MonotonePageResource, PageResource};
use crate::util::metadata::{extract_side_metadata, MetadataSpec};
use crate::util::object_enum::ObjectEnumerator;
use crate::util::object_forwarding;
use crate::util::os::*;
use crate::util::{copy::*, object_enum};
use crate::util::{Address, ObjectReference};
use crate::vm::*;
use libc::{mprotect, PROT_EXEC, PROT_NONE, PROT_READ, PROT_WRITE};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

Expand Down Expand Up @@ -293,8 +293,8 @@ impl<VM: VMBinding> CopySpace<VM> {
}
let start = self.common().start;
let extent = self.common().extent;
unsafe {
mprotect(start.to_mut_ptr(), extent, PROT_NONE);
if let Err(e) = OS::set_memory_access(start, extent, MmapProtection::NoAccess) {
panic!("Failed to protect memory: {:?}", e);
}
trace!("Protect {:x} {:x}", start, start + extent);
}
Expand All @@ -308,12 +308,8 @@ impl<VM: VMBinding> CopySpace<VM> {
}
let start = self.common().start;
let extent = self.common().extent;
unsafe {
mprotect(
start.to_mut_ptr(),
extent,
PROT_READ | PROT_WRITE | PROT_EXEC,
);
if let Err(e) = OS::set_memory_access(start, extent, self.common().mmap_protection()) {
panic!("Failed to unprotect memory: {:?}", e);
}
trace!("Unprotect {:x} {:x}", start, start + extent);
}
Expand Down
2 changes: 1 addition & 1 deletion src/policy/largeobjectspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {
FreeListPageResource::new_contiguous(common.start, common.extent, vm_map)
};
pr.protect_memory_on_release = if protect_memory_on_release {
Some(common.mmap_strategy().prot)
Some(common.mmap_protection())
} else {
None
};
Expand Down
14 changes: 7 additions & 7 deletions src/policy/lockfreeimmortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ use crate::util::heap::gc_trigger::GCTrigger;
use crate::util::heap::layout::vm_layout::vm_layout;
use crate::util::heap::PageResource;
use crate::util::heap::VMRequest;
use crate::util::memory::MmapAnnotation;
use crate::util::memory::MmapStrategy;
use crate::util::metadata::side_metadata::SideMetadataContext;
use crate::util::metadata::side_metadata::SideMetadataSanity;
use crate::util::object_enum::ObjectEnumerator;
use crate::util::opaque_pointer::*;
use crate::util::os::*;
use crate::util::ObjectReference;
use crate::vm::VMBinding;

Expand Down Expand Up @@ -255,11 +254,12 @@ impl<VM: VMBinding> LockFreeImmortalSpace<VM> {
};

// Eagerly memory map the entire heap (also zero all the memory)
let strategy = MmapStrategy::new(
*args.options.transparent_hugepages,
crate::util::memory::MmapProtection::ReadWrite,
);
crate::util::memory::dzmmap_noreplace(
let strategy = MmapStrategy::default()
Comment thread
wks marked this conversation as resolved.
.transparent_hugepages(*args.options.transparent_hugepages)
.prot(crate::util::os::MmapProtection::ReadWrite)
.replace(false)
.reserve(true);
crate::util::os::OS::dzmmap(
start,
aligned_total_bytes,
strategy,
Expand Down
32 changes: 15 additions & 17 deletions src/policy/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::util::heap::layout::Mmapper;
use crate::util::heap::layout::VMMap;
use crate::util::heap::space_descriptor::SpaceDescriptor;
use crate::util::heap::HeapMeta;
use crate::util::memory::{self, HugePageSupport, MmapProtection, MmapStrategy};
use crate::util::os::*;
use crate::vm::VMBinding;

use std::marker::PhantomData;
Expand Down Expand Up @@ -191,8 +191,13 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
.ensure_mapped(
res.start,
res.pages,
self.common().mmap_strategy(),
&memory::MmapAnnotation::Space {
if *self.common().options.transparent_hugepages {
HugePageSupport::TransparentHugePages
} else {
HugePageSupport::No
},
self.common().mmap_protection(),
&MmapAnnotation::Space {
name: self.get_name(),
},
)
Expand All @@ -202,7 +207,7 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
self.get_name(),
))
{
memory::handle_mmap_error::<VM>(mmap_error, tls, res.start, bytes);
OS::handle_mmap_error::<VM>(mmap_error, tls, res.start, bytes);
}
};
let grow_space = || {
Expand All @@ -227,7 +232,7 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {

// TODO: Concurrent zeroing
if self.common().zeroed {
memory::zero(res.start, bytes);
crate::util::memory::zero(res.start, bytes);
}

// Some assertions
Expand Down Expand Up @@ -755,18 +760,11 @@ impl<VM: VMBinding> CommonSpace<VM> {
self.vm_map
}

pub fn mmap_strategy(&self) -> MmapStrategy {
MmapStrategy {
huge_page: if *self.options.transparent_hugepages {
HugePageSupport::TransparentHugePages
} else {
HugePageSupport::No
},
prot: if self.permission_exec || cfg!(feature = "exec_permission_on_all_spaces") {
MmapProtection::ReadWriteExec
} else {
MmapProtection::ReadWrite
},
pub fn mmap_protection(&self) -> MmapProtection {
if self.permission_exec || cfg!(feature = "exec_permission_on_all_spaces") {
MmapProtection::ReadWriteExec
} else {
MmapProtection::ReadWrite
}
}

Expand Down
68 changes: 3 additions & 65 deletions src/scheduler/affinity.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
use super::worker::ThreadId;
use crate::util::options::AffinityKind;
#[cfg(target_os = "linux")]
use libc::{cpu_set_t, sched_getaffinity, sched_setaffinity, CPU_COUNT, CPU_SET, CPU_ZERO};

/// Represents the ID of a logical CPU on a system.
pub type CoreId = u16;

// XXX: Maybe in the future we can use a library such as https://github.com/Elzair/core_affinity_rs
// to have an OS agnostic way of setting thread affinity.
#[cfg(target_os = "linux")]
/// Return the total number of cores allocated to the program.
pub fn get_total_num_cpus() -> u16 {
use std::mem::MaybeUninit;
unsafe {
let mut cs = MaybeUninit::zeroed().assume_init();
CPU_ZERO(&mut cs);
sched_getaffinity(0, std::mem::size_of::<cpu_set_t>(), &mut cs);
CPU_COUNT(&cs) as u16
}
}

#[cfg(not(target_os = "linux"))]
/// Return the total number of cores allocated to the program.
pub fn get_total_num_cpus() -> u16 {
unimplemented!()
}
use crate::util::os::*;

impl AffinityKind {
/// Resolve affinity of GC thread. Has a side-effect of calling into the kernel to set the
Expand All @@ -36,51 +12,13 @@ impl AffinityKind {
AffinityKind::AllInSet(cpuset) => {
// Bind the current thread to all the cores in the set
debug!("Set affinity for thread {} to cpuset {:?}", thread, cpuset);
bind_current_thread_to_cpuset(cpuset.as_slice());
OS::bind_current_thread_to_cpuset(cpuset.as_slice());
}
AffinityKind::RoundRobin(cpuset) => {
let cpu = cpuset[thread % cpuset.len()];
debug!("Set affinity for thread {} to core {}", thread, cpu);
bind_current_thread_to_core(cpu);
OS::bind_current_thread_to_core(cpu);
}
}
}
}

#[cfg(target_os = "linux")]
/// Bind the current thread to the specified core.
fn bind_current_thread_to_core(cpu: CoreId) {
use std::mem::MaybeUninit;
unsafe {
let mut cs = MaybeUninit::zeroed().assume_init();
CPU_ZERO(&mut cs);
CPU_SET(cpu as usize, &mut cs);
sched_setaffinity(0, std::mem::size_of::<cpu_set_t>(), &cs);
}
}

#[cfg(not(target_os = "linux"))]
/// Bind the current thread to the specified core.
fn bind_current_thread_to_core(_cpu: CoreId) {
unimplemented!()
}

#[cfg(any(target_os = "linux", target_os = "android"))]
/// Bind the current thread to the specified core.
fn bind_current_thread_to_cpuset(cpuset: &[CoreId]) {
use std::mem::MaybeUninit;
unsafe {
let mut cs = MaybeUninit::zeroed().assume_init();
CPU_ZERO(&mut cs);
for cpu in cpuset {
CPU_SET(*cpu as usize, &mut cs);
}
sched_setaffinity(0, std::mem::size_of::<cpu_set_t>(), &cs);
}
}

#[cfg(not(any(target_os = "linux", target_os = "android")))]
/// Bind the current thread to the specified core.
fn bind_current_thread_to_cpuset(_cpuset: &[CoreId]) {
unimplemented!()
}
3 changes: 1 addition & 2 deletions src/util/alloc/free_list_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::sync::Arc;

use super::allocator::AllocatorContext;
use crate::policy::marksweepspace::native_ms::*;
use crate::util::alloc::allocator;
use crate::util::alloc::Allocator;
Expand All @@ -10,8 +11,6 @@ use crate::util::Address;
use crate::util::VMThread;
use crate::vm::VMBinding;

use super::allocator::AllocatorContext;

/// A MiMalloc free list allocator
#[repr(C)]
pub struct FreeListAllocator<VM: VMBinding> {
Expand Down
12 changes: 8 additions & 4 deletions src/util/heap/freelistpageresource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::util::heap::layout::vm_layout::*;
use crate::util::heap::layout::CreateFreeListResult;
use crate::util::heap::pageresource::CommonPageResource;
use crate::util::heap::space_descriptor::SpaceDescriptor;
use crate::util::memory;
use crate::util::opaque_pointer::*;
use crate::util::os::*;
use crate::util::raw_memory_freelist::RawMemoryFreeList;
use crate::vm::*;
use std::marker::PhantomData;
Expand All @@ -27,7 +27,7 @@ pub struct FreeListPageResource<VM: VMBinding> {
sync: Mutex<FreeListPageResourceSync>,
_p: PhantomData<VM>,
/// Protect memory on release, and unprotect on re-allocate.
pub(crate) protect_memory_on_release: Option<memory::MmapProtection>,
pub(crate) protect_memory_on_release: Option<MmapProtection>,
}

unsafe impl<VM: VMBinding> Send for FreeListPageResource<VM> {}
Expand Down Expand Up @@ -219,7 +219,11 @@ impl<VM: VMBinding> FreeListPageResource<VM> {
// > (e.g., read versus read/write protection) exceeding the
// > allowed maximum.
assert!(self.protect_memory_on_release.is_some());
if let Err(e) = memory::mprotect(start, conversions::pages_to_bytes(pages)) {
if let Err(e) = OS::set_memory_access(
start,
conversions::pages_to_bytes(pages),
MmapProtection::NoAccess,
) {
panic!(
"Failed at protecting memory (starting at {}): {:?}",
start, e
Expand All @@ -230,7 +234,7 @@ impl<VM: VMBinding> FreeListPageResource<VM> {
/// Unprotect the memory
fn munprotect(&self, start: Address, pages: usize) {
assert!(self.protect_memory_on_release.is_some());
if let Err(e) = memory::munprotect(
if let Err(e) = OS::set_memory_access(
start,
conversions::pages_to_bytes(pages),
self.protect_memory_on_release.unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion src/util/heap/layout/map64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::util::freelist::FreeList;
use crate::util::heap::layout::heap_parameters::*;
use crate::util::heap::layout::vm_layout::*;
use crate::util::heap::space_descriptor::SpaceDescriptor;
use crate::util::memory::MmapStrategy;
use crate::util::os::*;
use crate::util::raw_memory_freelist::RawMemoryFreeList;
use crate::util::Address;
use std::cell::UnsafeCell;
Expand Down
Loading
Loading