Ask from binding if GC is disabled#1075
Conversation
|
If the VM needs to disable GC to implement critical sections where GC activities such as moving object may affect the correctness of the program (usuallly due to native programs accessing buffers in heap objects), the easiest way is simply telling the current thread not to yield. Of course this approach only works for STW GC. p.s. It is always better to pin objects for this purpose instead of relying on disabling GC. The mechanism introduced in this PR (i.e. letting mmtk-core ask the binding whether it should trigger GC) is still not sound for implementing critical sections. For example,
The problem is that one mutator is still active after another mutator triggered GC and a GC thread responded. |
|
I don't think this PR is trying to introduce something that can be used for implementing critical section. It is trying to replace the current |
@qinsoon is correct.
For critical sections, Julia has the notion of GC state. Essentially, if Mutator2 enters a critical section, Mutator1 should wait (when it's waiting for the world to stop) until Mutator2 leaves the critical section. |
|
Currently, If As long as mmtk-core doesn't need to enforce any sychronization between mutators, this PR should be OK. Specifically,
And the synchronization is left to the VM. The VM can duplicate the current behavior by adding an atomic boolean variable in the binding. And it is also up to the VM to define the semantics of disabling GC. For CRuby, the semantics of
But since CRuby uses global VM lock, the execution within one Ractor should be sequentially consistent by definition (because it is sequential). |
I'm a bit confused. Are you referring to
We can ask the Julia folks why they have it, but the semantics as far as I understand is that you may continue allocating (beyond any heap limit) and it will not trigger GC. Essentially disabling any GC pooling that may happen, including the case when the user asks for a GC.
I'll try to improve the documentation to include (1). For (2), it means that bindings for VMs that do not have such "feature" don't need to change anything. Again, if we're talking about |
…when_heap_is_full which are now redundant
Both. Ruby currently uses both // The threading system is ready. Initialize collection.
mmtk_initialize_collection(th);
// Bind the main thread.
rb_mmtk_bind_mutator(th);
// Temporarily disable GC.
mmtk_disable_collection();
// After lots of initialization, in another function
if (rb_mmtk_enabled_p()) {
// Now that the VM says it's time to enable GC, we enable GC for MMTk, too.
mmtk_enable_collection();
}Given that the only thing |
|
Is this PR ready for review? I would prefer @wks to review this. I will remove myself from the reviewer list. |
|
Here is a PR for the Ruby binding: mmtk/mmtk-ruby#52 |
|
binding-refs |
|
The merge check somehow failed, which is strange. It seems observing extended tests from previous runs (not the most recent runs). [2024-02-01 01:57:33.902814] wait.DEBUG: Check "extended-tests-ruby (release)" has the following status "completed" and conclusion "failure"
[2024-02-01 01:57:33.902824] wait.DEBUG: Check (extended-tests-ruby (release)) failed, marking resolve and failure
[2024-02-01 01:57:33.902834] wait.DEBUG: Check "extended-tests-ruby (debug)" has the following status "completed" and conclusion "cancelled"
[2024-02-01 01:57:33.902843] wait.DEBUG: Check (extended-tests-ruby (debug)) failed, marking resolve and failure
[2024-02-01 01:57:33.902853] wait.DEBUG: Check "extended-tests-jikesrvm" has the following status "completed" and conclusion "failure"
[2024-02-01 01:57:33.902862] wait.DEBUG: Check (extended-tests-jikesrvm) failed, marking resolve and failure
[2024-02-01 01:57:33.902871] wait.DEBUG: Check "extended-tests-julia" has the following status "completed" and conclusion "failure"
[2024-02-01 01:57:33.902881] wait.DEBUG: Check (extended-tests-julia) failed, marking resolve and failureThose tests passed in the most recent run. |
|
@wks I've just re-requested a review in case you have further comments. |
Did you observe this? If so, it sounds like a bug. Without |
src/vm/tests/mock_tests/mock_test_allocate_with_re_enable_collection.rs
Outdated
Show resolved
Hide resolved
src/vm/tests/mock_tests/mock_test_allocate_with_re_enable_collection.rs
Outdated
Show resolved
Hide resolved
Co-authored-by: Kunshan Wang <[email protected]>
No. This is purely hypothetical. I see that // Is a GC allowed here? If we should poll but are not allowed to poll, we will panic.
// initialize_collection() has to be called so we know GC is initialized.
let allow_gc = should_poll && self.common().global_state.is_initialized();And this: if should_poll && self.get_gc_trigger().poll(false, Some(self.as_space())) {
debug!("Collection required");
assert!(allow_gc, "GC is not allowed here: collection is not initialized (did you call initialize_collection()?).");
// ...
VM::VMCollection::block_for_gc(VMMutatorThread(tls)); // We have checked that this is mutator
unsafe { Address::zero() }So if It looks like the actual contract of |
|
The "Merge Check" failed for the reason of "Status checks failed". That's strange. |
I think the first attempt to run Julia tests failed, which caused the merge check fail. When we reran the failed tests (Julia tests), the merge check did not get a rerun and its status won't change. |
Upstream PR: mmtk/mmtk-core#1075 --------- Co-authored-by: Eduardo Souza <[email protected]> Co-authored-by: mmtkgc-bot <[email protected]>
Upstream PR: mmtk/mmtk-core#1075 Julia PR: mmtk/julia#35 --------- Co-authored-by: mmtkgc-bot <[email protected]>
Upstream PR: mmtk/mmtk-core#1075 Julia PR: mmtk/julia#35 --------- Co-authored-by: mmtkgc-bot <[email protected]> (cherry picked from commit eac7e88) # Conflicts: # mmtk/Cargo.lock # mmtk/Cargo.toml # mmtk/api/mmtk.h # mmtk/src/api.rs # mmtk/src/collection.rs
Upstream PR: mmtk/mmtk-core#1075 Julia PR: mmtk/julia#35 --------- Co-authored-by: mmtkgc-bot <[email protected]> (cherry picked from commit eac7e88) # Conflicts: # mmtk/Cargo.lock # mmtk/Cargo.toml # mmtk/src/collection.rs
MMTk currently supports disabling GC (a.k.a. allowing the heap to grow above its limit) via two api functions:
disable_collectionandenable_collection.This PR replaces this strategy since currently, MMTk relies on the binding ensuring thread safety when calling those functions. In this refactoring, MMTk asks if GC is disabled in
VM::VMCollection::is_collection_disabled()function, and expects any thread safety logic to be implemented in the VM itself, and not necessarily depend on MMTk.