diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index a4223e62..96e9244d 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -61,7 +61,7 @@ impl Drop for Client { } thread_local! { - pub(crate) static CLIENT: std::cell::Cell<*const Client> = const { std::cell::Cell::new(ptr::null()) }; + pub(crate) static CLIENT: Cell<*const Client> = const { Cell::new(ptr::null()) }; } unsafe fn with_client T>(data: *const u8, f: F) -> T { diff --git a/src/clientmem.rs b/src/clientmem.rs index 993b0eed..685b67ae 100644 --- a/src/clientmem.rs +++ b/src/clientmem.rs @@ -88,12 +88,12 @@ impl ClientMemOffset { } let mref = MemRef { mem: &*self.mem, - outer: MEM, + outer: MEM.get(), }; - MEM = &mref; + MEM.set(&mref); compiler_fence(Ordering::SeqCst); let res = f(&*self.data); - MEM = mref.outer; + MEM.set(mref.outer); compiler_fence(Ordering::SeqCst); match self.mem.failed.get() { true => Err(ClientMemError::Sigbus), @@ -116,8 +116,9 @@ struct MemRef { outer: *const MemRef, } -#[thread_local] -static mut MEM: *const MemRef = ptr::null(); +thread_local! { + static MEM: Cell<*const MemRef> = const { Cell::new(ptr::null()) }; +} unsafe fn kill() -> ! { c::signal(c::SIGBUS, c::SIG_DFL); @@ -127,7 +128,7 @@ unsafe fn kill() -> ! { unsafe extern "C" fn sigbus(sig: i32, info: &c::siginfo_t, _ucontext: *mut c::c_void) { assert_eq!(sig, c::SIGBUS); - let mut memr_ptr = MEM; + let mut memr_ptr = MEM.get(); while !memr_ptr.is_null() { let memr = &*memr_ptr; let mem = &*memr.mem; diff --git a/src/gfx_apis/gl/egl/context.rs b/src/gfx_apis/gl/egl/context.rs index 094308a2..c72ea95f 100644 --- a/src/gfx_apis/gl/egl/context.rs +++ b/src/gfx_apis/gl/egl/context.rs @@ -15,7 +15,7 @@ use { }, }, ahash::AHashMap, - std::rc::Rc, + std::{cell::Cell, rc::Rc}, }; #[derive(Debug, Clone)] @@ -36,8 +36,9 @@ impl Drop for EglContext { } } -#[thread_local] -static mut CURRENT: EGLContext = EGLContext::none(); +thread_local! { + static CURRENT: Cell = const { Cell::new(EGLContext::none()) }; +} impl EglContext { pub fn reset_status(&self) -> Option { @@ -63,7 +64,7 @@ impl EglContext { f: F, ) -> Result { unsafe { - if CURRENT == self.ctx { + if CURRENT.get() == self.ctx { return f(); } self.with_current_slow(f) @@ -84,15 +85,15 @@ impl EglContext { { return Err(RenderError::MakeCurrent); } - let prev = CURRENT; - CURRENT = self.ctx; + let prev = CURRENT.get(); + CURRENT.set(self.ctx); let res = f(); if (self.dpy.egl.eglMakeCurrent)(self.dpy.dpy, EGLSurface::none(), EGLSurface::none(), prev) == EGL_FALSE { panic!("Could not restore EGLContext"); } - CURRENT = prev; + CURRENT.set(prev); res } } diff --git a/src/it/test_config.rs b/src/it/test_config.rs index 0a3428c5..e98dc8a7 100644 --- a/src/it/test_config.rs +++ b/src/it/test_config.rs @@ -27,26 +27,25 @@ pub static TEST_CONFIG_ENTRY: ConfigEntry = ConfigEntry { handle_msg, }; -#[thread_local] -static mut CONFIG: *const TestConfig = ptr::null(); +thread_local! { + static CONFIG: Cell<*const TestConfig> = const { Cell::new(ptr::null()) }; +} pub fn with_test_config(f: F) -> T where F: FnOnce(Rc) -> T, { - unsafe { - let tc = Rc::new(TestConfig { - srv: Cell::new(None), - responses: Default::default(), - invoked_shortcuts: Default::default(), - graphics_initialized: Cell::new(false), - }); - let old = CONFIG; - CONFIG = tc.deref(); - let res = f(tc.clone()); - CONFIG = old; - res - } + let tc = Rc::new(TestConfig { + srv: Cell::new(None), + responses: Default::default(), + invoked_shortcuts: Default::default(), + graphics_initialized: Cell::new(false), + }); + let old = CONFIG.get(); + CONFIG.set(tc.deref()); + let res = f(tc.clone()); + CONFIG.set(old); + res } unsafe extern "C" fn init( @@ -56,7 +55,7 @@ unsafe extern "C" fn init( _msg: *const u8, _size: usize, ) -> *const u8 { - let tc = CONFIG; + let tc = CONFIG.get(); assert!(tc.is_not_null()); Rc::increment_strong_count(tc); { diff --git a/src/it/test_logger.rs b/src/it/test_logger.rs index d07ef06e..d8bde2c5 100644 --- a/src/it/test_logger.rs +++ b/src/it/test_logger.rs @@ -13,8 +13,9 @@ use { static LEVEL: AtomicUsize = AtomicUsize::new(Level::Info as usize); -#[thread_local] -static FILE: CloneCell>> = CloneCell::new(None); +thread_local! { + static FILE: CloneCell>> = CloneCell::new(None); +} pub fn install() { log::set_logger(&Logger).unwrap(); @@ -27,11 +28,11 @@ pub fn set_level(level: Level) { } pub fn set_file(file: Rc) { - FILE.set(Some(file)); + FILE.with(|f| f.set(Some(file))); } pub fn unset_file() { - FILE.set(None); + FILE.with(|f| f.set(None)); } struct Logger; @@ -65,7 +66,7 @@ impl Log for Logger { record.args(), ) }; - let mut fd = match FILE.get() { + let mut fd = match FILE.with(|f| f.get()) { Some(f) => f.borrow(), _ => Fd::new(2), }; diff --git a/src/leaks.rs b/src/leaks.rs index 97072151..10ae0af5 100644 --- a/src/leaks.rs +++ b/src/leaks.rs @@ -52,27 +52,27 @@ mod leaks { std::{ alloc::{GlobalAlloc, Layout}, any, + cell::Cell, marker::PhantomData, mem, ptr, }, uapi::c, }; - #[thread_local] - static mut MAP: *mut AHashMap = ptr::null_mut(); - - #[thread_local] - static mut ID: u64 = 0; + thread_local! { + static MAP: Cell<*mut AHashMap> = const { Cell::new(ptr::null_mut()) }; + static ID: Cell = const { Cell::new(0) }; + } pub fn init() { unsafe { if INITIALIZED { return; } - MAP = Box::into_raw(Box::new(AHashMap::new())); - ALLOCATIONS = Box::into_raw(Box::new(AHashMap::new())); - IN_ALLOCATOR = 0; - INITIALIZED = true; + MAP.set(Box::into_raw(Box::new(AHashMap::new()))); + ALLOCATIONS.set(Box::into_raw(Box::new(AHashMap::new()))); + IN_ALLOCATOR.set(0); + INITIALIZED.set(true); } } @@ -151,7 +151,7 @@ mod leaks { pub fn log_leaked() { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut map: AHashMap> = AHashMap::new(); for (id, obj) in MAP.deref_mut().drain() { map.entry(obj.client).or_default().push((id, obj)); @@ -176,7 +176,7 @@ mod leaks { } } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); } } // @@ -210,8 +210,8 @@ mod leaks { fn default() -> Self { Self { id: unsafe { - let id = ID; - ID += 1; + let id = ID.get(); + ID.set(id + 1); id }, _phantom: Default::default(), @@ -227,7 +227,7 @@ mod leaks { tv_nsec: 0, }; uapi::clock_gettime(c::CLOCK_REALTIME, &mut time).unwrap(); - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); MAP.deref_mut().insert( self.id, Tracked { @@ -237,7 +237,7 @@ mod leaks { time: (time.tv_sec as i64, time.tv_nsec as u32), }, ); - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); } } } @@ -262,20 +262,17 @@ mod leaks { pub backtrace: Backtrace, } - #[thread_local] - static mut ALLOCATIONS: *mut AHashMap<*mut u8, Allocation> = ptr::null_mut(); - - #[thread_local] - static mut IN_ALLOCATOR: u32 = 1; - - #[thread_local] - static mut INITIALIZED: bool = false; + thread_local! { + static ALLOCATIONS: Cell<*mut AHashMap<*mut u8, Allocation>> = const { Cell::new(ptr::null_mut()) }; + static IN_ALLOCATOR: Cell = const { Cell::new(1) }; + static INITIALIZED: Cell = const { Cell::new(false) }; + } unsafe impl GlobalAlloc for TracingAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { let res = c::calloc(layout.size(), 1) as *mut u8; - if IN_ALLOCATOR == 0 { - IN_ALLOCATOR = 1; + if IN_ALLOCATOR.get() == 0 { + IN_ALLOCATOR.set(1); ALLOCATIONS.deref_mut().insert( res, Allocation { @@ -301,7 +298,7 @@ mod leaks { fn find_allocations_pointing_to(addr: *mut u8) -> Vec<(Allocation, usize)> { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut res = vec![]; for allocation in ALLOCATIONS.deref().values() { let num = allocation.len / mem::size_of::(); @@ -313,14 +310,14 @@ mod leaks { } } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); res } } fn find_allocation_containing(addr: usize) -> Option { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut res = None; for allocation in ALLOCATIONS.deref().values() { let aaddr = allocation.addr as usize; @@ -329,7 +326,7 @@ mod leaks { break; } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); res } } diff --git a/src/logger.rs b/src/logger.rs index 32b4666c..274604a2 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -4,9 +4,11 @@ use { bstr::{BStr, BString, ByteSlice}, log::{Level, Log, Metadata, Record}, std::{ + cell::Cell, fs::DirBuilder, io::Write, os::unix::{ffi::OsStringExt, fs::DirBuilderExt}, + ptr, sync::{ atomic::{AtomicU32, Ordering::Relaxed}, Arc, @@ -16,8 +18,9 @@ use { uapi::{c, format_ustr, Errno, Fd, OwnedFd}, }; -#[thread_local] -static mut BUFFER: Vec = Vec::new(); +thread_local! { + static BUFFER: Cell<*mut Vec> = const { Cell::new(ptr::null_mut()) }; +} pub struct Logger { level: AtomicU32, @@ -141,7 +144,12 @@ impl Log for LogWrapper { if record.level() as u32 > self.logger.level.load(Relaxed) { return; } - let buffer = unsafe { &mut BUFFER }; + let mut buffer = BUFFER.get(); + if buffer.is_null() { + buffer = Box::into_raw(Box::default()); + BUFFER.set(buffer); + } + let buffer = unsafe { &mut *buffer }; buffer.clear(); let now = SystemTime::now(); let _ = if let Some(mp) = record.module_path() { diff --git a/src/main.rs b/src/main.rs index f8c1b45c..097432d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ #![feature( c_variadic, // https://github.com/rust-lang/rust/issues/44930 - thread_local, // https://github.com/rust-lang/rust/issues/29594 )] #![allow( clippy::len_zero, diff --git a/src/rect/region.rs b/src/rect/region.rs index 98c46257..f004c1af 100644 --- a/src/rect/region.rs +++ b/src/rect/region.rs @@ -4,18 +4,17 @@ use { region::{extents, rects_to_bands, subtract, union}, RectRaw, }, - once_cell::unsync::Lazy, smallvec::SmallVec, std::{mem, ops::Deref, rc::Rc}, }; -#[thread_local] -static EMPTY: Lazy> = Lazy::new(|| { - Rc::new(Region { - rects: Default::default(), - extents: Default::default(), - }) -}); +thread_local! { + static EMPTY: Rc = + Rc::new(Region { + rects: Default::default(), + extents: Default::default(), + }); +} impl Region { pub fn new(rect: Rect) -> Rc { @@ -28,7 +27,7 @@ impl Region { } pub fn empty() -> Rc { - EMPTY.clone() + EMPTY.with(|e| e.clone()) } pub fn from_rects(rects: &[Rect]) -> Rc {