Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d6fadf5

Browse files
committedJun 28, 2024
std: add safety comments
1 parent 9dcaa15 commit d6fadf5

File tree

1 file changed

+16
-4
lines changed
  • std/src/sys/thread_local

1 file changed

+16
-4
lines changed
 

‎std/src/sys/thread_local/os.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ unsafe impl<T> Sync for Storage<T> {}
5050

5151
struct Value<T: 'static> {
5252
value: T,
53+
// INVARIANT: if this value is stored under a TLS key, `key` must be that `key`.
5354
key: Key,
5455
}
5556

@@ -73,10 +74,14 @@ impl<T: 'static> Storage<T> {
7374
// is not running) + it is coming from a trusted source (self).
7475
unsafe { &(*ptr).value }
7576
} else {
77+
// SAFETY: trivially correct.
7678
unsafe { Self::try_initialize(key, ptr, i, f) }
7779
}
7880
}
7981

82+
/// # Safety
83+
/// * `key` must be the result of calling `self.key.force()`
84+
/// * `ptr` must be the current value associated with `key`.
8085
unsafe fn try_initialize(
8186
key: Key,
8287
ptr: *mut Value<T>,
@@ -91,11 +96,16 @@ impl<T: 'static> Storage<T> {
9196
let value = Box::new(Value { value: i.and_then(Option::take).unwrap_or_else(f), key });
9297
let ptr = Box::into_raw(value);
9398

94-
let old = unsafe { get(key) as *mut Value<T> };
95-
// SAFETY: `ptr` is a correct pointer that can be destroyed by the key destructor.
96-
unsafe {
99+
// SAFETY:
100+
// * key came from a `LazyKey` and is thus correct.
101+
// * `ptr` is a correct pointer that can be destroyed by the key destructor.
102+
// * the value is stored under the key that it contains.
103+
let old = unsafe {
104+
let old = get(key) as *mut Value<T>;
97105
set(key, ptr as *mut u8);
98-
}
106+
old
107+
};
108+
99109
if !old.is_null() {
100110
// If the variable was recursively initialized, drop the old value.
101111
// SAFETY: We cannot be inside a `LocalKey::with` scope, as the
@@ -123,8 +133,10 @@ unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
123133
abort_on_dtor_unwind(|| {
124134
let ptr = unsafe { Box::from_raw(ptr as *mut Value<T>) };
125135
let key = ptr.key;
136+
// SAFETY: `key` is the TLS key `ptr` was stored under.
126137
unsafe { set(key, ptr::without_provenance_mut(1)) };
127138
drop(ptr);
139+
// SAFETY: `key` is the TLS key `ptr` was stored under.
128140
unsafe { set(key, ptr::null_mut()) };
129141
});
130142
}

0 commit comments

Comments
 (0)
Failed to load comments.