Skip to content

Commit aef6f51

Browse files
committed
Register new threads with libgc
New thread creation is bottlenecked through `Thread::new`, so this is the ideal place to register its stack as a rootset with the collector.
1 parent d936654 commit aef6f51

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

library/std/src/sys/unix/thread.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ pub mod guard {
736736
target_os = "netbsd",
737737
target_os = "l4re"
738738
))]
739-
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
739+
pub(crate) unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
740740
let mut ret = None;
741741
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
742742
#[cfg(target_os = "freebsd")]

library/std/src/thread/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
#[cfg(all(test, not(target_os = "emscripten")))]
159159
mod tests;
160160

161+
use crate::alloc::GcAllocator;
161162
use crate::any::Any;
162163
use crate::cell::UnsafeCell;
163164
use crate::ffi::{CStr, CString};
@@ -517,6 +518,15 @@ impl Builder {
517518
imp::Thread::set_name(name);
518519
}
519520

521+
// SAFETY: Register the thread with libgc so that its stack can be scanned
522+
// for garbage collection.
523+
let stack_start = unsafe { imp::guard::get_stack_start().unwrap() };
524+
if stack_start != crate::ptr::null_mut() {
525+
unsafe {
526+
GcAllocator::register_thread(&stack_start as *const _ as *mut u8);
527+
}
528+
}
529+
520530
crate::io::set_output_capture(output_capture);
521531

522532
// SAFETY: we constructed `f` initialized.
@@ -528,6 +538,12 @@ impl Builder {
528538
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
529539
crate::sys_common::backtrace::__rust_begin_short_backtrace(f)
530540
}));
541+
542+
// SAFETY: The thread has no more work to do, so can be unregisterd.
543+
unsafe {
544+
GcAllocator::unregister_thread();
545+
}
546+
531547
// SAFETY: `their_packet` as been built just above and moved by the
532548
// closure (it is an Arc<...>) and `my_packet` will be stored in the
533549
// same `JoinInner` as this closure meaning the mutation will be
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-pass
2+
// ignore-emscripten no threads support
3+
#![feature(rustc_private)]
4+
5+
use std::alloc::GcAllocator;
6+
use std::thread;
7+
8+
pub fn main() {
9+
let res = thread::spawn(child).join().unwrap();
10+
assert!(res);
11+
}
12+
13+
fn child() -> bool {
14+
GcAllocator::thread_registered()
15+
}

0 commit comments

Comments
 (0)