forked from mmtk/mmtk-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgc_requester.rs
42 lines (37 loc) · 1.58 KB
/
gc_requester.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use crate::scheduler::GCWorkScheduler;
use crate::vm::VMBinding;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
/// This data structure lets mutators trigger GC.
pub struct GCRequester<VM: VMBinding> {
/// Set by mutators to trigger GC. It is atomic so that mutators can check if GC has already
/// been requested efficiently in `poll` without acquiring any mutex.
request_flag: AtomicBool,
scheduler: Arc<GCWorkScheduler<VM>>,
}
impl<VM: VMBinding> GCRequester<VM> {
pub fn new(scheduler: Arc<GCWorkScheduler<VM>>) -> Self {
GCRequester {
request_flag: AtomicBool::new(false),
scheduler,
}
}
/// Request a GC. Called by mutators when polling (during allocation) and when handling user
/// GC requests (e.g. `System.gc();` in Java).
pub fn request(&self) {
if self.request_flag.load(Ordering::Relaxed) {
return;
}
if !self.request_flag.swap(true, Ordering::Relaxed) {
// `GCWorkScheduler::request_schedule_collection` needs to hold a mutex to communicate
// with GC workers, which is expensive for functions like `poll`. We use the atomic
// flag `request_flag` to elide the need to acquire the mutex in subsequent calls.
self.scheduler.request_schedule_collection();
}
}
/// Clear the "GC requested" flag so that mutators can trigger the next GC.
/// Called by a GC worker when all mutators have come to a stop.
pub fn clear_request(&self) {
self.request_flag.store(false, Ordering::Relaxed);
}
}