Skip to main content

Thread

Struct Thread 

Source
pub struct Thread { /* private fields */ }
Expand description

GC Mutator.

By using this structure you can allocate, synchronize with GC and insert write barriers.

Implementations§

Source§

impl Thread

Source

pub fn safepoint_offset() -> usize

Source

pub fn mark_queue_offset() -> usize

Source

pub fn satb_buffer_offset() -> usize

Source

pub fn satb_index_offset() -> usize

Source

pub fn cm_in_progress_offset() -> usize

Source

pub fn mark_ctx_offset() -> usize

Source

pub fn mark_bitmap_offset() -> usize

Source

pub fn tlab_start_offset() -> usize

Source

pub fn tlab_top_offset() -> usize

Source

pub fn tlab_end_offset() -> usize

Source

pub fn tlab_bitmap_offset() -> usize

Source

pub unsafe fn satb_mark_queue(&self) -> &LocalSSB

Source

pub unsafe fn satb_mark_queue_mut(&mut self) -> &mut LocalSSB

Source

pub fn allocate<T: 'static + Allocation>(&mut self, value: T) -> Handle<T>

Allocates fixed sized object on the heap.

Examples found in repository?
examples/binarytrees.rs (lines 43-47)
40fn create_tree(thread: &mut Thread, depth: i64) -> Handle<TreeNode> {
41    thread.safepoint();
42    let node = if 0 < depth {
43        let mut node = thread.allocate(TreeNode {
44            item: 0,
45            left: None,
46            right: None,
47        });
48
49        thread.write_barrier(node);
50        node.left = Some(create_tree(thread, depth - 1));
51        thread.write_barrier(node);
52        node.right = Some(create_tree(thread, depth - 1));
53
54        node 
55    } else {
56        let node = TreeNode {
57            item: 0,
58            left: None,
59            right: None,
60        };
61
62        thread.allocate(node)
63    };
64    
65    node
66}
Source

pub fn allocate_varsize<T: 'static + Allocation>( &mut self, length: usize, ) -> Handle<MaybeUninit<T>>

Allocates variably sized object on the heap.

Note that length field is automatically written at Allocation::VARSIZE_OFFSETOF_CAPACITY.

Source

pub unsafe fn allocate_raw(&mut self, size: usize) -> *mut u8

Allocates raw memory, unsafe to use outside of RSGC impl itself.

§TODO

I should really update it to include all code to properly tell GC that we allocated something, right now it is done in allocate and allocate_varsize but it should be done here.

Source

pub fn write_barrier<T: Object + ?Sized>(&mut self, handle: Handle<T>)

SATB write barrier. Ensures that object processes all references correctly. Must be inserted before write to handle.

Examples found in repository?
examples/binarytrees.rs (line 49)
40fn create_tree(thread: &mut Thread, depth: i64) -> Handle<TreeNode> {
41    thread.safepoint();
42    let node = if 0 < depth {
43        let mut node = thread.allocate(TreeNode {
44            item: 0,
45            left: None,
46            right: None,
47        });
48
49        thread.write_barrier(node);
50        node.left = Some(create_tree(thread, depth - 1));
51        thread.write_barrier(node);
52        node.right = Some(create_tree(thread, depth - 1));
53
54        node 
55    } else {
56        let node = TreeNode {
57            item: 0,
58            left: None,
59            right: None,
60        };
61
62        thread.allocate(node)
63    };
64    
65    node
66}
Source

pub fn write_barrier_no_filter<T: Object + ?Sized>(&mut self, handle: Handle<T>)

Same as write_barrier but does not filter marked objects, instead they are filtered when flushing SATB buffer to collector.

Source

pub unsafe fn raw_write_barrier<const FILTER_SATB: bool>( &mut self, obj: *mut HeapObjectHeader, )

Raw implementation of write-barrier.

If SATB mode is used this code will do Yuasa deletion write barrier that captures writes to white objects. Note that this barrier is very conservative: it does not check colors of new values that are being written.

In Incremental Update mode uses Steele’s write barrier that captures black<-white writes. This barrier is very conservative as well. Note that with IU mode concurrent mark termination might take longer.

In passive mode does nothing.

Source

pub fn flush_ssb(&mut self)

Flush SSB queue. This function is called when SSB queue is full.

Writes are pushed to global SATB queue. If object is already marked it is not pushed to SATB queue.

Source

pub fn atomic_gc_state(&self) -> &AtomicI8

Source

pub unsafe fn gc_state_set(&mut self, state: i8, old_state: i8) -> i8

Source

pub unsafe fn set_last_sp(&mut self, sp: *mut u8)

Source

pub unsafe fn state_save_and_set(&mut self, state: i8) -> i8

Source

pub fn stack_start(&self) -> *mut u8

Source

pub fn last_sp(&self) -> *mut u8

Source

pub unsafe fn safepoint_page(&self) -> *mut u8

Returns pointer to safepoint page. When JITing your code you can directly inline safepoint poll into your code.

Source

pub const fn is_conditional_safepoint() -> bool

Returns true if safepoints are conditional in this build of RSGC.

Source

pub fn safepoint(&mut self)

Reads from polling page. If safepoint is disabled nothing happens but when safepoint is enabled this triggers page fault (SIGSEGV/SIGBUS on Linux/macOS/BSD) and goes into signal to suspend thread.

§Note

Enable conditional-safepoint feature when running in LLDB/GDB, otherwise safepoint events will be treatened as segfault by debuggers.

Examples found in repository?
examples/binarytrees.rs (line 41)
40fn create_tree(thread: &mut Thread, depth: i64) -> Handle<TreeNode> {
41    thread.safepoint();
42    let node = if 0 < depth {
43        let mut node = thread.allocate(TreeNode {
44            item: 0,
45            left: None,
46            right: None,
47        });
48
49        thread.write_barrier(node);
50        node.left = Some(create_tree(thread, depth - 1));
51        thread.write_barrier(node);
52        node.right = Some(create_tree(thread, depth - 1));
53
54        node 
55    } else {
56        let node = TreeNode {
57            item: 0,
58            left: None,
59            right: None,
60        };
61
62        thread.allocate(node)
63    };
64    
65    node
66}
Source

pub fn is_registered(&self) -> bool

Returns true if thread is registered in a GC.

Source

pub fn current() -> &'static mut Thread

Returns current thread.

Examples found in repository?
examples/binarytrees.rs (line 91)
68fn bench_parallel() {
69
70    let mut n = 0;
71    if let Some(arg) = std::env::args().skip(1).next() {
72        if let Ok(x) = arg.parse::<usize>() {
73            n = x;
74        }
75    }
76
77    let min_depth = 4;
78    let max_depth = if n < (min_depth + 2) {
79        min_depth + 2
80    } else {
81        n 
82    };
83
84    let start = std::time::Instant::now();
85    let stretch_depth = max_depth + 1;
86
87    {
88        println!(
89            "stretch tree of depth {}\t check: {}",
90            stretch_depth,
91            create_tree(Thread::current(), stretch_depth as _)
92                .as_ref()
93                .check_tree()
94        );
95    }
96
97    let long_lasting_tree = create_tree(Thread::current(), max_depth as _);
98    use parking_lot::Mutex;
99    let results = Arc::new(
100        (0..(max_depth - min_depth) / 2 + 1)
101            .map(|_| Mutex::new(String::new()))
102            .collect::<Vec<_>>(),
103    );
104    rsgc::thread::scoped::scoped(|scope| {
105        let mut d = min_depth;
106
107        while d <= max_depth {
108            let depth = d;
109            let cloned = results.clone();
110            scope.spawn(move || {
111                let thread = Thread::current();
112                let iterations = 1 << (max_depth - depth + min_depth);
113                let mut check = 0;
114                for _ in 1..=iterations {
115                    let tree_node = create_tree(thread, depth as _);
116                    check += tree_node.as_ref().check_tree();
117                }
118
119                *cloned[(depth - min_depth) / 2].lock() = format!(
120                    "{}\t trees of depth {}\t check: {}",
121                    iterations, depth, check
122                );
123            });
124
125            d += 2;
126        }
127    });
128    for result in results.iter() {
129        println!("{}", *result.lock());
130    }
131    println!(
132        "long lived tree of depth {}\t check: {}",
133        max_depth,
134        long_lasting_tree.as_ref().check_tree()
135    );
136
137    println!(
138        "time: {}ms",
139        start.elapsed().as_millis()
140    );
141}
Source

pub unsafe fn get_registers(&self) -> (*mut u8, usize)

Returns registers for current thread. This is used by GC to trace current registers.

§Safety

Can return invalid pointer or null. Must be used only by GC and only when roots are traced.

Should not be used outside of RSGC.

Auto Trait Implementations§

§

impl !RefUnwindSafe for Thread

§

impl !Send for Thread

§

impl !Sync for Thread

§

impl !UnwindSafe for Thread

§

impl Freeze for Thread

§

impl Unpin for Thread

§

impl UnsafeUnpin for Thread

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V