Skip to content

Commit 77cc0f0

Browse files
committed
Auto merge of #113911 - matthiaskrgr:rollup-wk6cr7v, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #113380 (style-guide: clean up "must"/"should"/"may") - #113723 (Resurrect: rustc_llvm: Add a -Z `print-codegen-stats` option to expose LLVM statistics.) - #113780 (Support `--print KIND=PATH` command line syntax) - #113810 (Make {Rc,Arc}::allocator associated functions) - #113907 (Minor improvements to Windows TLS dtors) Failed merges: - #113392 (style-guide: Some cleanups from the fmt-rfcs repo history) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2eda937 + db4b104 commit 77cc0f0

File tree

5 files changed

+61
-32
lines changed

5 files changed

+61
-32
lines changed

alloc/src/rc.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,14 @@ impl<T> Rc<T> {
661661

662662
impl<T, A: Allocator> Rc<T, A> {
663663
/// Returns a reference to the underlying allocator.
664+
///
665+
/// Note: this is an associated function, which means that you have
666+
/// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This
667+
/// is so that there is no conflict with a method on the inner type.
664668
#[inline]
665669
#[unstable(feature = "allocator_api", issue = "32838")]
666-
pub fn allocator(&self) -> &A {
667-
&self.alloc
670+
pub fn allocator(this: &Self) -> &A {
671+
&this.alloc
668672
}
669673
/// Constructs a new `Rc` in the provided allocator.
670674
///

alloc/src/sync.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,10 +678,14 @@ impl<T> Arc<T> {
678678

679679
impl<T, A: Allocator> Arc<T, A> {
680680
/// Returns a reference to the underlying allocator.
681+
///
682+
/// Note: this is an associated function, which means that you have
683+
/// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This
684+
/// is so that there is no conflict with a method on the inner type.
681685
#[inline]
682686
#[unstable(feature = "allocator_api", issue = "32838")]
683-
pub fn allocator(&self) -> &A {
684-
&self.alloc
687+
pub fn allocator(this: &Self) -> &A {
688+
&this.alloc
685689
}
686690
/// Constructs a new `Arc<T>` in the provided allocator.
687691
///

std/src/sys/windows/thread_local_dtor.rs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,4 @@
44
#![unstable(feature = "thread_local_internals", issue = "none")]
55
#![cfg(target_thread_local)]
66

7-
// Using a per-thread list avoids the problems in synchronizing global state.
8-
#[thread_local]
9-
static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
10-
11-
// Ensure this can never be inlined because otherwise this may break in dylibs.
12-
// See #44391.
13-
#[inline(never)]
14-
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
15-
DESTRUCTORS.push((t, dtor));
16-
}
17-
18-
#[inline(never)] // See comment above
19-
/// Runs destructors. This should not be called until thread exit.
20-
pub unsafe fn run_keyless_dtors() {
21-
// Drop all the destructors.
22-
//
23-
// Note: While this is potentially an infinite loop, it *should* be
24-
// the case that this loop always terminates because we provide the
25-
// guarantee that a TLS key cannot be set after it is flagged for
26-
// destruction.
27-
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
28-
(dtor)(ptr);
29-
}
30-
// We're done so free the memory.
31-
DESTRUCTORS = Vec::new();
32-
}
7+
pub use super::thread_local_key::register_keyless_dtor as register_dtor;

std/src/sys/windows/thread_local_key.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,49 @@
11
use crate::cell::UnsafeCell;
22
use crate::ptr;
33
use crate::sync::atomic::{
4-
AtomicPtr, AtomicU32,
4+
AtomicBool, AtomicPtr, AtomicU32,
55
Ordering::{AcqRel, Acquire, Relaxed, Release},
66
};
77
use crate::sys::c;
88

99
#[cfg(test)]
1010
mod tests;
1111

12+
/// An optimization hint. The compiler is often smart enough to know if an atomic
13+
/// is never set and can remove dead code based on that fact.
14+
static HAS_DTORS: AtomicBool = AtomicBool::new(false);
15+
16+
// Using a per-thread list avoids the problems in synchronizing global state.
17+
#[thread_local]
18+
#[cfg(target_thread_local)]
19+
static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
20+
21+
// Ensure this can never be inlined because otherwise this may break in dylibs.
22+
// See #44391.
23+
#[inline(never)]
24+
#[cfg(target_thread_local)]
25+
pub unsafe fn register_keyless_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
26+
DESTRUCTORS.push((t, dtor));
27+
HAS_DTORS.store(true, Relaxed);
28+
}
29+
30+
#[inline(never)] // See comment above
31+
#[cfg(target_thread_local)]
32+
/// Runs destructors. This should not be called until thread exit.
33+
unsafe fn run_keyless_dtors() {
34+
// Drop all the destructors.
35+
//
36+
// Note: While this is potentially an infinite loop, it *should* be
37+
// the case that this loop always terminates because we provide the
38+
// guarantee that a TLS key cannot be set after it is flagged for
39+
// destruction.
40+
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
41+
(dtor)(ptr);
42+
}
43+
// We're done so free the memory.
44+
DESTRUCTORS = Vec::new();
45+
}
46+
1247
type Key = c::DWORD;
1348
type Dtor = unsafe extern "C" fn(*mut u8);
1449

@@ -156,6 +191,8 @@ static DTORS: AtomicPtr<StaticKey> = AtomicPtr::new(ptr::null_mut());
156191
/// Should only be called once per key, otherwise loops or breaks may occur in
157192
/// the linked list.
158193
unsafe fn register_dtor(key: &'static StaticKey) {
194+
// Ensure this is never run when native thread locals are available.
195+
assert_eq!(false, cfg!(target_thread_local));
159196
let this = <*const StaticKey>::cast_mut(key);
160197
// Use acquire ordering to pass along the changes done by the previously
161198
// registered keys when we store the new head with release ordering.
@@ -167,6 +204,7 @@ unsafe fn register_dtor(key: &'static StaticKey) {
167204
Err(new) => head = new,
168205
}
169206
}
207+
HAS_DTORS.store(true, Release);
170208
}
171209

172210
// -------------------------------------------------------------------------
@@ -240,10 +278,14 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::
240278

241279
#[allow(dead_code, unused_variables)]
242280
unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
281+
if !HAS_DTORS.load(Acquire) {
282+
return;
283+
}
243284
if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
285+
#[cfg(not(target_thread_local))]
244286
run_dtors();
245287
#[cfg(target_thread_local)]
246-
super::thread_local_dtor::run_keyless_dtors();
288+
run_keyless_dtors();
247289
}
248290

249291
// See comments above for what this is doing. Note that we don't need this

std/src/sys/windows/thread_local_key/tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// This file only tests the thread local key fallback.
2+
// Windows targets with native thread local support do not use this.
3+
#![cfg(not(target_thread_local))]
4+
15
use super::StaticKey;
26
use crate::ptr;
37

0 commit comments

Comments
 (0)