Skip to content

Commit f4fa7f2

Browse files
committed
Merge branch 'master' into use-ms-as-nonmoving
2 parents 0b9942a + 5ab62f9 commit f4fa7f2

33 files changed

+1318
-605
lines changed

.github/workflows/micro-bm.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
with:
6767
repository: mmtk/ci-perf-kit
6868
token: ${{ secrets.GITHUB_TOKEN }}
69-
ref: "0.7.4"
69+
ref: "0.7.5"
7070
path: ci-perf-kit
7171
submodules: true
7272
# Use rust-toolchain in the trunk (it doesnt matter much - if the toolchains defined in the trunk and the branch are different, we cant run anyway)

.github/workflows/perf-baseline.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
with:
4343
token: ${{ secrets.CI_ACCESS_TOKEN }}
4444
repository: mmtk/ci-perf-kit
45-
ref: "0.7.4"
45+
ref: "0.7.5"
4646
path: ci-perf-kit
4747
submodules: true
4848
# setup
@@ -94,7 +94,7 @@ jobs:
9494
with:
9595
token: ${{ secrets.CI_ACCESS_TOKEN }}
9696
repository: mmtk/ci-perf-kit
97-
ref: "0.7.4"
97+
ref: "0.7.5"
9898
path: ci-perf-kit
9999
submodules: true
100100
# setup

.github/workflows/perf-compare-ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
with:
113113
repository: mmtk/ci-perf-kit
114114
token: ${{ secrets.CI_ACCESS_TOKEN }}
115-
ref: "0.7.4"
115+
ref: "0.7.5"
116116
path: ci-perf-kit
117117
submodules: true
118118
# setup
@@ -219,7 +219,7 @@ jobs:
219219
with:
220220
repository: mmtk/ci-perf-kit
221221
token: ${{ secrets.CI_ACCESS_TOKEN }}
222-
ref: "0.7.4"
222+
ref: "0.7.5"
223223
path: ci-perf-kit
224224
submodules: true
225225
# setup

.github/workflows/perf-regression-ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
uses: actions/checkout@v2
4646
with:
4747
repository: mmtk/ci-perf-kit
48-
ref: "0.7.4"
48+
ref: "0.7.5"
4949
path: ci-perf-kit
5050
token: ${{ secrets.CI_ACCESS_TOKEN }}
5151
submodules: true
@@ -116,7 +116,7 @@ jobs:
116116
uses: actions/checkout@v2
117117
with:
118118
repository: mmtk/ci-perf-kit
119-
ref: "0.7.4"
119+
ref: "0.7.5"
120120
path: ci-perf-kit
121121
token: ${{ secrets.CI_ACCESS_TOKEN }}
122122
submodules: true
@@ -191,7 +191,7 @@ jobs:
191191
uses: actions/checkout@v2
192192
with:
193193
repository: mmtk/ci-perf-kit
194-
ref: "0.7.4"
194+
ref: "0.7.5"
195195
path: ci-perf-kit
196196
token: ${{ secrets.CI_ACCESS_TOKEN }}
197197
submodules: true

CHANGELOG.md

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
0.24.0 (2024-04-08)
2+
===
3+
4+
## What's Changed
5+
6+
### Misc
7+
* Check and fix broken links in docs by @qinsoon in https://github.com/mmtk/mmtk-core/pull/1085
8+
* Allow binding to implement GC trigger by @qinsoon in https://github.com/mmtk/mmtk-core/pull/1083
9+
* Resolve issues for unit tests on 32 bits by @qinsoon in https://github.com/mmtk/mmtk-core/pull/1095
10+
* Use SFTDenseChunkMap on 64bits when vm_space is enabled by @qinsoon in https://github.com/mmtk/mmtk-core/pull/1094
11+
* Fix warnings with the stable Rust toolchain by @wks in https://github.com/mmtk/mmtk-core/pull/1099
12+
* Use proper logging for the treadmill by @wks in https://github.com/mmtk/mmtk-core/pull/1101
13+
14+
**Full Changelog**: https://github.com/mmtk/mmtk-core/compare/v0.23.0...v0.24.0
15+
116
0.23.0 (2024-02-09)
217
===
318

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mmtk"
3-
version = "0.23.0"
3+
version = "0.24.0"
44
authors = ["The MMTk Developers <>"]
55
edition = "2021"
66
license = "MIT OR Apache-2.0"
@@ -10,7 +10,7 @@ repository = "https://github.com/mmtk/mmtk-core"
1010
readme = "README.md"
1111
categories = ["memory-management"]
1212
keywords = ["gc", "garbage", "collection", "garbage-collection", "allocation"]
13-
rust-version = "1.70.0"
13+
rust-version = "1.71.1"
1414
build = "build.rs"
1515

1616
[lib]
@@ -38,7 +38,7 @@ log = { version = "0.4", features = ["max_level_trace", "release_max_level_off"]
3838
memoffset = "0.9"
3939
mimalloc-sys = { version = "0.1.6", optional = true }
4040
# MMTk macros - we have to specify a version here in order to publish the crate, even though we use the dependency from a local path.
41-
mmtk-macros = { version="0.23.0", path = "macros/" }
41+
mmtk-macros = { version="0.24.0", path = "macros/" }
4242
num_cpus = "1.8"
4343
num-traits = "0.2"
4444
pfm = { version = "0.1.1", optional = true }

docs/header/mmtk.h

-3
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ extern void mmtk_scan_region();
7878
// Request MMTk to trigger a GC. Note that this may not actually trigger a GC
7979
extern void mmtk_handle_user_collection_request(void* tls);
8080

81-
// Run the main loop for the GC controller thread. Does not return
82-
extern void mmtk_start_control_collector(void* tls, void* worker);
83-
8481
// Run the main loop for a GC worker. Does not return
8582
extern void mmtk_start_worker(void* tls, void* worker);
8683

macros/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "mmtk-macros"
33
# the macro crate uses the same version as mmtk-core
4-
version = "0.23.0"
4+
version = "0.24.0"
55
edition = "2021"
66
license = "MIT OR Apache-2.0"
77
description = "MMTk macros provides procedural macros used by mmtk-core."

rust-toolchain

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.71.1
1+
1.77.0

src/global_state.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
22
use std::sync::Mutex;
3+
use std::time::Instant;
4+
5+
use atomic_refcell::AtomicRefCell;
36

47
/// This stores some global states for an MMTK instance.
58
/// Some MMTK components like plans and allocators may keep an reference to the struct, and can access it.
@@ -15,6 +18,8 @@ pub struct GlobalState {
1518
pub(crate) initialized: AtomicBool,
1619
/// The current GC status.
1720
pub(crate) gc_status: Mutex<GcStatus>,
21+
/// When did the last GC start? Only accessed by the last parked worker.
22+
pub(crate) gc_start_time: AtomicRefCell<Option<Instant>>,
1823
/// Is the current GC an emergency collection? Emergency means we may run out of memory soon, and we should
1924
/// attempt to collect as much as we can.
2025
pub(crate) emergency_collection: AtomicBool,
@@ -195,6 +200,7 @@ impl Default for GlobalState {
195200
Self {
196201
initialized: AtomicBool::new(false),
197202
gc_status: Mutex::new(GcStatus::NotInGC),
203+
gc_start_time: AtomicRefCell::new(None),
198204
stacks_prepared: AtomicBool::new(false),
199205
emergency_collection: AtomicBool::new(false),
200206
user_triggered_collection: AtomicBool::new(false),

src/memory_manager.rs

+8-41
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::mmtk::MMTK;
1616
use crate::plan::AllocationSemantics;
1717
use crate::plan::{Mutator, MutatorContext};
1818
use crate::scheduler::WorkBucketStage;
19-
use crate::scheduler::{GCController, GCWork, GCWorker};
19+
use crate::scheduler::{GCWork, GCWorker};
2020
use crate::util::alloc::allocators::AllocatorSelector;
2121
use crate::util::constants::{LOG_BYTES_IN_PAGE, MIN_OBJECT_SIZE};
2222
use crate::util::heap::layout::vm_layout::vm_layout;
@@ -25,7 +25,7 @@ use crate::util::{Address, ObjectReference};
2525
use crate::vm::edge_shape::MemorySlice;
2626
use crate::vm::ReferenceGlue;
2727
use crate::vm::VMBinding;
28-
use std::sync::atomic::Ordering;
28+
2929
/// Initialize an MMTk instance. A VM should call this method after creating an [`crate::MMTK`]
3030
/// instance but before using any of the methods provided in MMTk (except `process()` and `process_bulk()`).
3131
///
@@ -438,6 +438,7 @@ pub fn free_with_size<VM: VMBinding>(mmtk: &MMTK<VM>, addr: Address, old_size: u
438438
/// Get the current active malloc'd bytes. Here MMTk only accounts for bytes that are done through those 'counted malloc' functions.
439439
#[cfg(feature = "malloc_counted_size")]
440440
pub fn get_malloc_bytes<VM: VMBinding>(mmtk: &MMTK<VM>) -> usize {
441+
use std::sync::atomic::Ordering;
441442
mmtk.state.malloc_bytes.load(Ordering::SeqCst)
442443
}
443444

@@ -460,53 +461,18 @@ pub fn gc_poll<VM: VMBinding>(mmtk: &MMTK<VM>, tls: VMMutatorThread) {
460461
}
461462
}
462463

463-
/// Run the main loop for the GC controller thread. This method does not return.
464-
///
465-
/// Arguments:
466-
/// * `tls`: The thread that will be used as the GC controller.
467-
/// * `gc_controller`: The execution context of the GC controller threa.
468-
/// It is the `GCController` passed to `Collection::spawn_gc_thread`.
469-
/// * `mmtk`: A reference to an MMTk instance.
470-
pub fn start_control_collector<VM: VMBinding>(
471-
_mmtk: &'static MMTK<VM>,
472-
tls: VMWorkerThread,
473-
gc_controller: &mut GCController<VM>,
474-
) {
475-
gc_controller.run(tls);
476-
}
477-
478-
/// Run the main loop of a GC worker. This method does not return.
479-
///
480-
/// Arguments:
481-
/// * `tls`: The thread that will be used as the GC worker.
482-
/// * `worker`: The execution context of the GC worker thread.
483-
/// It is the `GCWorker` passed to `Collection::spawn_gc_thread`.
484-
/// * `mmtk`: A reference to an MMTk instance.
464+
/// Wrapper for [`crate::scheduler::GCWorker::run`].
485465
pub fn start_worker<VM: VMBinding>(
486466
mmtk: &'static MMTK<VM>,
487467
tls: VMWorkerThread,
488-
worker: &mut GCWorker<VM>,
468+
worker: Box<GCWorker<VM>>,
489469
) {
490470
worker.run(tls, mmtk);
491471
}
492472

493-
/// Initialize the scheduler and GC workers that are required for doing garbage collections.
494-
/// This is a mandatory call for a VM during its boot process once its thread system
495-
/// is ready. This should only be called once. This call will invoke Collection::spawn_gc_thread()
496-
/// to create GC threads.
497-
///
498-
/// Arguments:
499-
/// * `mmtk`: A reference to an MMTk instance.
500-
/// * `tls`: The thread that wants to enable the collection. This value will be passed back to the VM in
501-
/// Collection::spawn_gc_thread() so that the VM knows the context.
473+
/// Wrapper for [`crate::mmtk::MMTK::initialize_collection`].
502474
pub fn initialize_collection<VM: VMBinding>(mmtk: &'static MMTK<VM>, tls: VMThread) {
503-
assert!(
504-
!mmtk.state.is_initialized(),
505-
"MMTk collection has been initialized (was initialize_collection() already called before?)"
506-
);
507-
mmtk.scheduler.spawn_gc_threads(mmtk, tls);
508-
mmtk.state.initialized.store(true, Ordering::SeqCst);
509-
probe!(mmtk, collection_initialized);
475+
mmtk.initialize_collection(tls);
510476
}
511477

512478
/// Process MMTk run-time options. Returns true if the option is processed successfully.
@@ -554,6 +520,7 @@ pub fn free_bytes<VM: VMBinding>(mmtk: &MMTK<VM>) -> usize {
554520
/// to call this method is at the end of a GC (e.g. when the runtime is about to resume threads).
555521
#[cfg(feature = "count_live_bytes_in_gc")]
556522
pub fn live_bytes_in_last_gc<VM: VMBinding>(mmtk: &MMTK<VM>) -> usize {
523+
use std::sync::atomic::Ordering;
557524
mmtk.state.live_bytes_in_last_gc.load(Ordering::SeqCst)
558525
}
559526

src/mmtk.rs

+90-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl<VM: VMBinding> MMTK<VM> {
148148

149149
let state = Arc::new(GlobalState::default());
150150

151-
let gc_requester = Arc::new(GCRequester::new());
151+
let gc_requester = Arc::new(GCRequester::new(scheduler.clone()));
152152

153153
let gc_trigger = Arc::new(GCTrigger::new(
154154
options.clone(),
@@ -220,6 +220,93 @@ impl<VM: VMBinding> MMTK<VM> {
220220
}
221221
}
222222

223+
/// Initialize the GC worker threads that are required for doing garbage collections.
224+
/// This is a mandatory call for a VM during its boot process once its thread system
225+
/// is ready.
226+
///
227+
/// Internally, this function will invoke [`Collection::spawn_gc_thread()`] to spawn GC worker
228+
/// threads.
229+
///
230+
/// # Arguments
231+
///
232+
/// * `tls`: The thread that wants to enable the collection. This value will be passed back
233+
/// to the VM in [`Collection::spawn_gc_thread()`] so that the VM knows the context.
234+
///
235+
/// [`Collection::spawn_gc_thread()`]: crate::vm::Collection::spawn_gc_thread()
236+
pub fn initialize_collection(&'static self, tls: VMThread) {
237+
assert!(
238+
!self.state.is_initialized(),
239+
"MMTk collection has been initialized (was initialize_collection() already called before?)"
240+
);
241+
self.scheduler.spawn_gc_threads(self, tls);
242+
self.state.initialized.store(true, Ordering::SeqCst);
243+
probe!(mmtk, collection_initialized);
244+
}
245+
246+
/// Prepare an MMTk instance for calling the `fork()` system call.
247+
///
248+
/// The `fork()` system call is available on Linux and some UNIX variants, and may be emulated
249+
/// on other platforms by libraries such as Cygwin. The properties of the `fork()` system call
250+
/// requires the users to do some preparation before calling it.
251+
///
252+
/// - **Multi-threading**: If `fork()` is called when the process has multiple threads, it
253+
/// will only duplicate the current thread into the child process, and the child process can
254+
/// only call async-signal-safe functions, notably `exec()`. For VMs that that use
255+
/// multi-process concurrency, it is imperative that when calling `fork()`, only one thread may
256+
/// exist in the process.
257+
///
258+
/// - **File descriptors**: The child process inherits copies of the parent's set of open
259+
/// file descriptors. This may or may not be desired depending on use cases.
260+
///
261+
/// This function helps VMs that use `fork()` for multi-process concurrency. It instructs all
262+
/// GC threads to save their contexts and return from their entry-point functions. Currently,
263+
/// such threads only include GC workers, and the entry point is
264+
/// [`crate::memory_manager::start_worker`]. A subsequent call to `MMTK::after_fork()` will
265+
/// re-spawn the threads using their saved contexts. The VM must not allocate objects in the
266+
/// MMTk heap before calling `MMTK::after_fork()`.
267+
///
268+
/// TODO: Currently, the MMTk core does not keep any files open for a long time. In the
269+
/// future, this function and the `after_fork` function may be used for handling open file
270+
/// descriptors across invocations of `fork()`. One possible use case is logging GC activities
271+
/// and statistics to files, such as performing heap dumps across multiple GCs.
272+
///
273+
/// If a VM intends to execute another program by calling `fork()` and immediately calling
274+
/// `exec`, it may skip this function because the state of the MMTk instance will be irrelevant
275+
/// in that case.
276+
///
277+
/// # Caution!
278+
///
279+
/// This function sends an asynchronous message to GC threads and returns immediately, but it
280+
/// is only safe for the VM to call `fork()` after the underlying **native threads** of the GC
281+
/// threads have exited. After calling this function, the VM should wait for their underlying
282+
/// native threads to exit in VM-specific manner before calling `fork()`.
283+
pub fn prepare_to_fork(&'static self) {
284+
assert!(
285+
self.state.is_initialized(),
286+
"MMTk collection has not been initialized, yet (was initialize_collection() called before?)"
287+
);
288+
probe!(mmtk, prepare_to_fork);
289+
self.scheduler.stop_gc_threads_for_forking();
290+
}
291+
292+
/// Call this function after the VM called the `fork()` system call.
293+
///
294+
/// This function will re-spawn MMTk threads from saved contexts.
295+
///
296+
/// # Arguments
297+
///
298+
/// * `tls`: The thread that wants to respawn MMTk threads after forking. This value will be
299+
/// passed back to the VM in `Collection::spawn_gc_thread()` so that the VM knows the
300+
/// context.
301+
pub fn after_fork(&'static self, tls: VMThread) {
302+
assert!(
303+
self.state.is_initialized(),
304+
"MMTk collection has not been initialized, yet (was initialize_collection() called before?)"
305+
);
306+
probe!(mmtk, after_fork);
307+
self.scheduler.respawn_gc_threads_after_forking(tls);
308+
}
309+
223310
/// Generic hook to allow benchmarks to be harnessed. MMTk will trigger a GC
224311
/// to clear any residual garbage and start collecting statistics for the benchmark.
225312
/// This is usually called by the benchmark harness as its last step before the actual benchmark.
@@ -349,6 +436,8 @@ impl<VM: VMBinding> MMTK<VM> {
349436
self.state
350437
.internal_triggered_collection
351438
.store(true, Ordering::Relaxed);
439+
// TODO: The current `GCRequester::request()` is probably incorrect for internally triggered GC.
440+
// Consider removing functions related to "internal triggered collection".
352441
self.gc_requester.request();
353442
}
354443

0 commit comments

Comments
 (0)