Skip to content

Commit 97fa666

Browse files
authored
Build MMTk on macOS (#719)
This PR allows mmtk-core to build on macOS (x86_64). This PR finishes a task in #206. This PR does not guarantee that MMTk works properly on macOS. It only makes sure that we can build and run our unit tests on macOS. This should be a good first step for any following work on macOS. Changes: * Use `malloc_size` instead of `malloc_usable_size` on macOS * Use `MAP_FIXED` instead of `MAP_FIXED_NOREPLACE` on macOS * Remove warnings when building `scheduler::affinity` on macOS * Make a few tests only run on linux (related with thread affinity and mmap) * Test our pre-code-review test on `macos-12` and `x86_64-apple-darwin`
1 parent 46cabaa commit 97fa666

File tree

10 files changed

+41
-13
lines changed

10 files changed

+41
-13
lines changed

.github/scripts/ci-setup-i686-unknown-linux-gnu.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ sudo apt-get install build-essential gcc-multilib -y
77
sudo dpkg --add-architecture i386
88
sudo apt-get update
99
sudo apt-get install zlib1g-dev:i386
10+
sudo apt-get install libc6-dev-i386
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
set -xe

.github/workflows/pre-review-ci.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
target:
2929
- { os: ubuntu-18.04, triple: x86_64-unknown-linux-gnu }
3030
- { os: ubuntu-18.04, triple: i686-unknown-linux-gnu }
31+
- { os: macos-12, triple: x86_64-apple-darwin }
3132
rust: ${{ fromJson(needs.setup-test-matrix.outputs.rust )}}
3233

3334
name: ${{ matrix.target.triple }} / ${{ matrix.rust }}
@@ -53,10 +54,7 @@ jobs:
5354

5455
# Test
5556
- name: Test
56-
run: |
57-
sudo apt-get update
58-
sudo apt-get install libc6-dev-i386
59-
./.github/scripts/ci-test.sh
57+
run: ./.github/scripts/ci-test.sh
6058

6159
# Style checks
6260
- name: Style checks

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ mmtk-macros = { version = "0.16.0", path = "macros/" }
2525
libc = "0.2"
2626
jemalloc-sys = { version = "0.3.2", features = ["disable_initial_exec_tls"], optional = true }
2727
mimalloc-sys = { version = "0.1.6", optional = true }
28-
hoard-sys = { version = "0.1.2", optional = true }
2928
lazy_static = "1.1"
3029
log = { version = "0.4", features = ["max_level_trace", "release_max_level_off"] }
3130
crossbeam = "0.8.1"
@@ -131,7 +130,6 @@ malloc_counted_size = []
131130
# this does not replace the global Rust allocator, but provides these libraries for GC implementation
132131
malloc_mimalloc = ["mimalloc-sys"]
133132
malloc_jemalloc = ["jemalloc-sys"]
134-
malloc_hoard = ["hoard-sys"]
135133
# Use the native mimalloc allocator for malloc. This is not tested by me (Yi) yet, and it is only used to make sure that some code
136134
# is not compiled in default builds.
137135
malloc_native_mimalloc = []

src/scheduler/affinity.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use super::worker::ThreadId;
22
use crate::util::options::AffinityKind;
33
#[cfg(target_os = "linux")]
44
use libc::{cpu_set_t, sched_getaffinity, sched_setaffinity, CPU_COUNT, CPU_SET, CPU_ZERO};
5-
use std::mem::MaybeUninit;
65

76
/// Represents the ID of a logical CPU on a system.
87
pub type CoreId = u16;
@@ -12,6 +11,7 @@ pub type CoreId = u16;
1211
#[cfg(target_os = "linux")]
1312
/// Return the total number of cores allocated to the program.
1413
pub fn get_total_num_cpus() -> u16 {
14+
use std::mem::MaybeUninit;
1515
unsafe {
1616
let mut cs = MaybeUninit::zeroed().assume_init();
1717
CPU_ZERO(&mut cs);
@@ -45,6 +45,7 @@ impl AffinityKind {
4545
#[cfg(target_os = "linux")]
4646
/// Bind the current thread to the specified core.
4747
fn bind_current_thread_to_core(cpu: CoreId) {
48+
use std::mem::MaybeUninit;
4849
unsafe {
4950
let mut cs = MaybeUninit::zeroed().assume_init();
5051
CPU_ZERO(&mut cs);
@@ -55,6 +56,6 @@ fn bind_current_thread_to_core(cpu: CoreId) {
5556

5657
#[cfg(not(target_os = "linux"))]
5758
/// Bind the current thread to the specified core.
58-
fn bind_current_thread_to_core(cpu: CoreId) {
59+
fn bind_current_thread_to_core(_cpu: CoreId) {
5960
unimplemented!()
6061
}

src/util/malloc/library.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,12 @@ mod libc_malloc {
7474
// Posix
7575
pub use libc::posix_memalign;
7676
// GNU
77+
#[cfg(target_os = "linux")]
7778
pub use libc::malloc_usable_size;
79+
#[cfg(target_os = "macos")]
80+
extern "C" {
81+
pub fn malloc_size(ptr: *const libc::c_void) -> usize;
82+
}
83+
#[cfg(target_os = "macos")]
84+
pub use self::malloc_size as malloc_usable_size;
7885
}

src/util/memory.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,20 @@ pub unsafe fn dzmmap(start: Address, size: usize) -> Result<()> {
3939
ret
4040
}
4141

42+
#[cfg(target_os = "linux")]
43+
// MAP_FIXED_NOREPLACE returns EEXIST if already mapped
44+
const MMAP_FLAGS: libc::c_int = libc::MAP_ANON | libc::MAP_PRIVATE | libc::MAP_FIXED_NOREPLACE;
45+
#[cfg(target_os = "macos")]
46+
// MAP_FIXED is used instead of MAP_FIXED_NOREPLACE (which is not available on macOS). We are at the risk of overwriting pre-existing mappings.
47+
const MMAP_FLAGS: libc::c_int = libc::MAP_ANON | libc::MAP_PRIVATE | libc::MAP_FIXED;
48+
4249
/// Demand-zero mmap (no replace):
4350
/// This function mmaps the memory and guarantees to zero all mapped memory.
4451
/// This function will not overwrite existing memory mapping, and it will result Err if there is an existing mapping.
4552
#[allow(clippy::let_and_return)] // Zeroing is not neceesary for some OS/s
4653
pub fn dzmmap_noreplace(start: Address, size: usize) -> Result<()> {
4754
let prot = PROT_READ | PROT_WRITE | PROT_EXEC;
48-
let flags = libc::MAP_ANON | libc::MAP_PRIVATE | libc::MAP_FIXED_NOREPLACE;
55+
let flags = MMAP_FLAGS;
4956
let ret = mmap_fixed(start, size, prot, flags);
5057
// We do not need to explicitly zero for Linux (memory is guaranteed to be zeroed)
5158
#[cfg(not(target_os = "linux"))]
@@ -61,8 +68,7 @@ pub fn dzmmap_noreplace(start: Address, size: usize) -> Result<()> {
6168
/// We can use this to reserve the address range, and then later overwrites the mapping with dzmmap().
6269
pub fn mmap_noreserve(start: Address, size: usize) -> Result<()> {
6370
let prot = PROT_NONE;
64-
let flags =
65-
libc::MAP_ANON | libc::MAP_PRIVATE | libc::MAP_FIXED_NOREPLACE | libc::MAP_NORESERVE;
71+
let flags = MMAP_FLAGS | libc::MAP_NORESERVE;
6672
mmap_fixed(start, size, prot, flags)
6773
}
6874

@@ -119,10 +125,10 @@ pub fn handle_mmap_error<VM: VMBinding>(error: Error, tls: VMThread) -> ! {
119125
/// Checks if the memory has already been mapped. If not, we panic.
120126
// Note that the checking has a side effect that it will map the memory if it was unmapped. So we panic if it was unmapped.
121127
// Be very careful about using this function.
128+
#[cfg(target_os = "linux")]
122129
pub fn panic_if_unmapped(start: Address, size: usize) {
123130
let prot = PROT_READ | PROT_WRITE;
124-
// MAP_FIXED_NOREPLACE returns EEXIST if already mapped
125-
let flags = libc::MAP_ANON | libc::MAP_PRIVATE | libc::MAP_FIXED_NOREPLACE;
131+
let flags = MMAP_FLAGS;
126132
match mmap_fixed(start, size, prot, flags) {
127133
Ok(_) => panic!("{} of size {} is not mapped", start, size),
128134
Err(e) => {
@@ -135,6 +141,13 @@ pub fn panic_if_unmapped(start: Address, size: usize) {
135141
}
136142
}
137143

144+
#[cfg(not(target_os = "linux"))]
145+
pub fn panic_if_unmapped(_start: Address, _size: usize) {
146+
// This is only used for assertions, so MMTk will still run even if we never panic.
147+
// TODO: We need a proper implementation for this. As we do not have MAP_FIXED_NOREPLACE, we cannot use the same implementation as Linux.
148+
// Possibly we can use posix_mem_offset for both OS/s.
149+
}
150+
138151
pub fn munprotect(start: Address, size: usize) -> Result<()> {
139152
wrap_libc_call(
140153
&|| unsafe { libc::mprotect(start.to_mut_ptr(), size, PROT_READ | PROT_WRITE | PROT_EXEC) },
@@ -232,6 +245,7 @@ mod tests {
232245
})
233246
}
234247

248+
#[cfg(target_os = "linux")]
235249
#[test]
236250
fn test_mmap_noreplace() {
237251
serial_test(|| {
@@ -269,6 +283,7 @@ mod tests {
269283
})
270284
}
271285

286+
#[cfg(target_os = "linux")]
272287
#[test]
273288
#[should_panic]
274289
fn test_check_is_mmapped_for_unmapped() {
@@ -300,6 +315,7 @@ mod tests {
300315
})
301316
}
302317

318+
#[cfg(target_os = "linux")]
303319
#[test]
304320
#[should_panic]
305321
fn test_check_is_mmapped_for_unmapped_next_to_mapped() {

src/util/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,7 @@ mod tests {
890890
})
891891
}
892892

893+
#[cfg(target_os = "linux")]
893894
#[test]
894895
fn test_thread_affinity_single_core() {
895896
serial_test(|| {
@@ -910,6 +911,7 @@ mod tests {
910911
})
911912
}
912913

914+
#[cfg(target_os = "linux")]
913915
#[test]
914916
fn test_thread_affinity_generate_core_list() {
915917
serial_test(|| {

src/util/raw_memory_freelist.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,10 @@ mod tests {
258258
Ok(guard) => guard,
259259
Err(poisoned) => poisoned.into_inner(),
260260
};
261+
#[cfg(target_os = "linux")]
261262
let start = unsafe { Address::from_usize(0x8000_0000) };
263+
#[cfg(target_os = "macos")]
264+
let start = unsafe { Address::from_usize(0x2400_0000_0000) };
262265
let extent = BYTES_IN_PAGE;
263266
let pages_per_block = RawMemoryFreeList::default_block_size(list_size as _, 1);
264267
assert_eq!(pages_per_block, 1);

vmbindings/dummyvm/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// There are also helpers for creating fixtures in `fixture/mod.rs`.
77
mod issue139;
88
mod handle_mmap_oom;
9+
#[cfg(target_os = "linux")]
910
mod handle_mmap_conflict;
1011
mod allocate_align_offset;
1112
mod allocate_without_initialize_collection;

0 commit comments

Comments
 (0)