I'm working on a hobby operating system and one of the things I'm doing is having allocators in userspace be defaulted to being only single-threaded, and I discovered today with some testing on the playground that the Global allocator type has the Send and Sync autotraits applied, regardless of if the global allocator is Send or Sync (in the example below, it is neither). The expectation is the std::thread::spawn would error as the Box bound to foo should not impl Send, thus preventing the move, as the actual underlying allocator (Foo) isn't Send.
#![feature(thread_local)]
struct Foo(*mut ());
unsafe impl core::alloc::GlobalAlloc for Foo {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { /* IRRELEVANT */ std::alloc::System.alloc(layout) }
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { /* IRRELEVANT */ std::alloc::System.dealloc(ptr, layout) }
}
#[thread_local]
#[global_allocator]
static FOO: Foo = Foo(core::ptr::null_mut());
fn main() {
let foo = Box::new(0u32);
let _ = std::thread::spawn(move || println!("{}", foo)).join();
}
playground link
I'm working on a hobby operating system and one of the things I'm doing is having allocators in userspace be defaulted to being only single-threaded, and I discovered today with some testing on the playground that the
Globalallocator type has theSendandSyncautotraits applied, regardless of if the global allocator isSendorSync(in the example below, it is neither). The expectation is thestd::thread::spawnwould error as theBoxbound tofooshould not implSend, thus preventing the move, as the actual underlying allocator (Foo) isn'tSend.playground link