Commit Graph

269 Commits

Author SHA1 Message Date
Ralf Jung
a120fb7031 rwlock: disable 'frob' test in Miri on macOS 2024-08-08 11:15:18 +02:00
bors
e485266c67 Auto merge of #128461 - matthiaskrgr:rollup-3dpp11g, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #123813 (Add `REDUNDANT_IMPORTS` lint for new redundant import detection)
 - #126697 ([RFC] mbe: consider the `_` in 2024 an expression)
 - #127159 (match lowering: Hide `Candidate` from outside the lowering algorithm)
 - #128244 (Peel off explicit (or implicit) deref before suggesting clone on move error in borrowck, remove some hacks)
 - #128431 (Add myself as VxWorks target maintainer for reference)
 - #128438 (Add special-case for [T, 0] in dropck_outlives)
 - #128457 (Fix docs for OnceLock::get_mut_or_init)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-08-01 02:26:32 +00:00
Matthias Krüger
c1f2112600
Rollup merge of #127567 - joboet:once_wait, r=Amanieu
std: implement the `once_wait` feature

Tracking issue: #127527

This additionally adds a `wait_force` method to `Once` that doesn't panic on poison.

I also took the opportunity and cleaned up up the code of the queue-based implementation a bit.
2024-08-01 00:50:10 +02:00
Juniper Tyree
83fb140ec1
Fix docs for OnceLock::get_mut_or_init 2024-07-31 22:00:38 +03:00
joboet
1d49aad844
std: fix busy-waiting in Once::wait_force, add more tests 2024-07-31 17:44:10 +02:00
joboet
cf11f499b3
std: implement the once_wait feature 2024-07-31 17:42:20 +02:00
Liigo Zhuang
918cdcc9c5
More detailed note to deprecate ONCE_INIT 2024-07-30 19:36:28 +08:00
Nicholas Nethercote
84ac80f192 Reformat use declarations.
The previous commit updated `rustfmt.toml` appropriately. This commit is
the outcome of running `x fmt --all` with the new formatting options.
2024-07-29 08:26:52 +10:00
John Arundel
a19472a93e Fix doc nits
Many tiny changes to stdlib doc comments to make them consistent (for example
"Returns foo", rather than "Return foo", per RFC1574), adding missing periods, paragraph
breaks, backticks for monospace style, and other minor nits.

https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text
2024-07-26 13:26:33 +01:00
Matthias Krüger
f62aa415c3
Rollup merge of #124881 - Sp00ph:reentrant_lock_tid, r=joboet
Use ThreadId instead of TLS-address in `ReentrantLock`

Fixes #123458

`ReentrantLock` currently uses the address of a thread local variable as an ID that's unique across all currently running threads. This can lead to uninituitive behavior as in #123458 if TLS blocks get reused. This PR changes `ReentrantLock` to instead use the `ThreadId` provided by `std` as the unique ID. `ThreadId` guarantees uniqueness across the lifetime of the whole process, so we don't need to worry about reusing IDs of terminated threads. The main appeal of this PR is thus the possibility of changing the `ReentrantLock` API to guarantee that if a thread leaks a lock guard, no other thread may ever acquire that lock again.

This does entail some complications:
- previously, the only way to retrieve the current thread ID would've been using `thread::current().id()` which creates a temporary `Arc` and which isn't available in TLS destructors. As part of this PR, the thread ID instead gets cached in its own thread local, as suggested [here](https://github.com/rust-lang/rust/issues/123458#issuecomment-2038207704).
- `ThreadId` is always 64-bit whereas the current implementation uses a usize-sized ID. Since this ID needs to be updated atomically, we can't simply use a single atomic variable on 32 bit platforms. Instead, we fall back to using a (sound) seqlock on 32-bit platforms, which works because only one thread at a time can write to the ID. This seqlock is technically susceptible to the ABA problem, but the attack vector to create actual unsoundness has to be very specific:
  - You would need to be able to lock+unlock the lock exactly 2^31 times (or a multiple thereof) while a thread trying to lock it sleeps
  - The sleeping thread would have to suspend after reading one half of the thread id but before reading the other half
  - The teared result from combining the halves of the thread ID would have to exactly line up with the sleeping thread's ID

The risk of this occurring seems slim enough to be acceptable to me, but correct me if I'm wrong. This also means that the size of the lock increases by 8 bytes on 32-bit platforms, but this also shouldn't be an issue.

Performance wise, I did some crude testing of the only case where this could lead to real slowdowns, which is the case of locking a `ReentrantLock` that's already locked by the current thread. On both aarch64 and x86-64, there is (expectedly) pretty much no performance hit. I didn't have any 32-bit platforms to test the seqlock performance on, so I did the next best thing and just forced the 64-bit platforms to use the seqlock implementation. There, the performance degraded by ~1-2ns/(lock+unlock) on x86-64 and ~6-8ns/(lock+unlock) on aarch64, which is measurable but seems acceptable to me seeing as 32-bit platforms should be a small minority anyways.

cc `@joboet` `@RalfJung` `@CAD97`
2024-07-18 18:10:14 +02:00
Markus Everling
fe89962237 Update ReentrantLock implementation, add CURRENT_ID thread local.
This changes `ReentrantLock` to use `ThreadId` for the thread ownership check instead of the address of a thread local. Unlike TLS blocks, `ThreadId` is guaranteed to be unique across the lifetime of the process, so if any thread ever terminates while holding a `ReentrantLockGuard`, no other thread may ever acquire that lock again.

On platforms with 64-bit atomics, this is a very simple change. On other platforms, the approach used is slightly more involved, as explained in the module comment.

This also adds a `CURRENT_ID` thread local in addition to the already existing `CURRENT`. This allows us to access the current `ThreadId` without the relatively heavy machinery used by `thread::current().id()`.
2024-07-18 14:09:25 +00:00
Jubilee Young
e32460276c std: Unsafe-wrap std::sync 2024-07-14 17:59:37 -07:00
Jubilee Young
4572ed6389 std: deny(unsafe_op_in_unsafe_fn) but allow sites
This provides a list of locations to hunt down issues in.
2024-07-14 16:44:01 -07:00
Jubilee
285d45d299
Rollup merge of #127446 - zachs18:miri-stdlib-leaks-core-alloc, r=Mark-Simulacrum
Remove memory leaks in doctests in `core`, `alloc`, and `std`

cc `@RalfJung`  https://github.com/rust-lang/rust/issues/126067 https://github.com/rust-lang/miri/issues/3670

Should be no actual *documentation* changes[^1], all added/modified lines in the doctests are hidden with `#`,

This PR splits the existing memory leaks in doctests in `core`, `alloc`, and `std` into two general categories:

1. "Non-focused" memory leaks that are incidental to the thing being documented, and/or are easy to remove, i.e. they are only there because preventing the leak would make the doctest less clear and/or concise.
    - These doctests simply have a comment like `# // Prevent leaks for Miri.` above the added line that removes the memory leak.
    - [^2]Some of these would perhaps be better as part of the public documentation part of the doctest, to clarify that a memory leak can happen if it is not otherwise mentioned explicitly in the documentation  (specifically the ones in `(A)Rc::increment_strong_count(_in)`).
2. "Focused" memory leaks that are intentional and documented, and/or are possibly fragile to remove.
    - These doctests have a `# // FIXME` comment above the line that removes the memory leak, with a note that once `-Zmiri-disable-leak-check` can be applied at test granularity, these tests should be "un-unleakified" and have `-Zmiri-disable-leak-check` enabled.
    - Some of these are possibly fragile (e.g. unleaking the result of `Vec::leak`) and thus should definitely not be made part of the documentation.

This should be all of the leaks currently in `core` and `alloc`. I only found one leak in `std`, and it was in the first category (excluding the modules `@RalfJung` mentioned in https://github.com/rust-lang/rust/issues/126067 , and reducing the number of iterations of [one test](https://github.com/rust-lang/rust/blob/master/library/std/src/sync/once_lock.rs#L49-L94) from 1000 to 10)

[^1]: assuming [^2] is not added
[^2]: backlink
2024-07-13 20:18:23 -07:00
Trevor Gross
ab56fe2053 Rename lazy_cell_consume to lazy_cell_into_inner
Name this something that is less confusable with an atomic consume API for
`{Lazy,Once}Lock`.
2024-07-11 03:16:45 -04:00
Ralf Jung
bee9120458 once_lock: make test not take as long in Miri 2024-07-07 09:19:32 +02:00
Zachary S
a10c7a4b9b Remove non-focused memory leak in std doctest for Miri. 2024-07-06 23:35:31 -05:00
Vonr
7321e79114
Replace move|| with move || in compiler/ and library/
Edit from #126631 to revert changes on ui tests
2024-06-18 23:25:08 +08:00
Jubilee Young
b8eb6ad032 std: suggest OnceLock over Once 2024-06-15 00:09:03 -07:00
Pietro Albini
be9e27e490
replace version placeholder 2024-06-11 16:52:02 +02:00
Guillaume Gomez
ee04e0f35e
Rollup merge of #125696 - workingjubilee:please-dont-say-you-are-lazy, r=Nilstrieb
Explain differences between `{Once,Lazy}{Cell,Lock}` types

The question of "which once-ish cell-ish type should I use?" has been raised multiple times, and is especially important now that we have stabilized the `LazyCell` and `LazyLock` types. The answer for the `Lazy*` types is that you would be better off using them if you want to use what is by far the most common pattern: initialize it with a single nullary function that you would call at every `get_or_init` site. For everything else there's the `Once*` types.

"For everything else" is a somewhat weak motivation, as it only describes by negation. While contrasting them is inevitable, I feel positive motivations are more understandable. For this, I now offer a distinct example that helps explain why `OnceLock` can be useful, despite `LazyLock` existing: you can do some cool stuff with it that `LazyLock` simply can't support due to its mere definition.

The pair of `std::sync::*Lock`s are usable inside a `static`, and can serve roles in async or multithreaded (or asynchronously multithreaded) programs that `*Cell`s cannot. Because of this, they received most of my attention.

Fixes #124696
Fixes #125615
2024-06-04 21:41:34 +02:00
许杰友 Jieyou Xu (Joe)
d5a04221ef
Rollup merge of #125504 - mqudsi:once_nominal, r=cuviper
Change pedantically incorrect OnceCell/OnceLock wording

While the semantic intent of a OnceCell/OnceLock is that it can only be written to once (upon init), the fact of the matter is that both these types offer a `take(&mut self) -> Option<T>` mechanism that, when successful, resets the cell to its initial state, thereby [technically allowing it to be written to again](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=415c023a6ae1ef35f371a2d3bb1aa735)

Despite the fact that this can only happen with a mutable reference (generally only used during the construction of the OnceCell/OnceLock), it would be incorrect to say that the type itself as a whole *categorically* prevents being initialized or written to more than once (since it is possible to imagine an identical type only without the `take()` method that actually fulfills that contract).

To clarify, change "that cannot be.." to "that nominally cannot.." and add a note to OnceCell about what can be done with an `&mut Self` reference.

```@rustbot``` label +A-rustdocs
2024-06-04 08:25:46 +01:00
Jubilee Young
9ed7cfc952 Add "OnceList" example to motivate OnceLock
While slightly verbose, it helps explain "why bother with OnceLock?"
This is a point of confusion that has been raised multiple times
shortly before and after the stabilization of LazyLock.
2024-06-02 22:53:41 -07:00
Jubilee Young
2d0ebca979 Move first OnceLock example to LazyLock
This example is spiritually an example of LazyLock, as it computes a
variable at runtime but accepts no inputs into that process.
It is also slightly simpler and thus easier to understand.
Change it to an even-more concise version and move it to LazyLock.

The example now editorializes slightly more. This may be unnecessary,
but it can be educational for the reader.
2024-06-02 22:53:41 -07:00
Jubilee Young
fdb96f2123 Differ LazyLock vs. OnceLock in std::sync overview 2024-06-02 22:53:41 -07:00
Trevor Spiteri
402a649e75 update tracking issue for lazy_cell_consume 2024-05-28 11:02:03 +02:00
Mahmoud Al-Qudsi
65dffc1990 Change pedantically incorrect OnceCell/OnceLock wording
While the semantic intent of a OnceCell/OnceLock is that it can only be written
to once (upon init), the fact of the matter is that both these types offer a
`take(&mut self) -> Option<T>` mechanism that, when successful, resets the cell
to its initial state, thereby technically allowing it to be written to again.

Despite the fact that this can only happen with a mutable reference (generally
only used during the construction of the OnceCell/OnceLock), it would be
incorrect to say that the type itself as a whole categorically prevents being
initialized or written to more than once (since it is possible to imagine an
identical type only without the `take()` method that actually fulfills that
contract).

To clarify, change "that cannot be.." to "that nominally cannot.." and add a
note to OnceCell about what can be done with an `&mut Self` reference.
2024-05-24 12:15:06 -05:00
Ralf Jung
df437a2af4 remove an unused type from the reentrant lock tests 2024-04-22 19:36:21 +02:00
Matthias Krüger
3bcf402322
Rollup merge of #114788 - tisonkun:get_mut_or_init, r=dtolnay
impl get_mut_or_init and get_mut_or_try_init for OnceCell and OnceLock

See also https://github.com/rust-lang/rust/issues/74465#issuecomment-1676522051

I'm trying to understand the process for such proposal. And I'll appreciate it if anyone can guide me the next step for consensus or adding tests.
2024-04-06 13:00:04 +02:00
tison
95e195f41e
impl get_mut_or_init and get_mut_or_try_init for OnceCell and OnceLock
See also https://github.com/rust-lang/rust/issues/74465#issuecomment-1676522051

Signed-off-by: tison <wander4096@gmail.com>
2024-03-27 16:16:08 +08:00
Trevor Gross
0cd57725f9 Update RwLock deadlock example to not use shadowing
Tweak variable names in the deadlock example to remove any potential
confusion that the behavior is somehow shadowing-related.
2024-03-26 21:40:31 -04:00
MultisampledNight
e853b50a72
docs(sync): normalize dot in fn summaries 2024-03-22 23:04:20 +01:00
Jacob Pratt
43ad753adb
Rollup merge of #122729 - m-ou-se:relax, r=Amanieu
Relax SeqCst ordering in standard library.

Every single SeqCst in the standard library is unnecessary. In all cases, Relaxed or Release+Acquire was sufficient.

As I [wrote](https://marabos.nl/atomics/memory-ordering.html#common-misconceptions) in my book on atomics:

> [..] when reading code, SeqCst basically tells the reader: "this operation depends on the total order of every single SeqCst operation in the program," which is an incredibly far-reaching claim. The same code would likely be easier to review and verify if it used weaker memory ordering instead, if possible. For example, Release effectively tells the reader: "this relates to an acquire operation on the same variable," which involves far fewer considerations when forming an understanding of the code.
>
> It is advisable to see SeqCst as a warning sign. Seeing it in the wild often means that either something complicated is going on, or simply that the author did not take the time to analyze their memory ordering related assumptions, both of which are reasons for extra scrutiny.

r? ````@Amanieu```` ````@joboet````
2024-03-20 20:29:44 -04:00
Mara Bos
34621757ea SeqCst->Relaxed in condvar test.
Relaxed is enough here. Synchronization is done by the mutex.
2024-03-20 15:38:09 +01:00
Mark Rousskov
4fb89c5056 branch 1.78: replace-version-placeholder 2024-03-19 19:27:24 -04:00
Matthias Krüger
dff680d359
Rollup merge of #122386 - joboet:move_pal_once, r=jhpratt
Move `Once` implementations to `sys`

Part of https://github.com/rust-lang/rust/issues/117276.
2024-03-13 06:41:24 +01:00
joboet
22a5267c83
std: move Once implementations to sys 2024-03-12 15:41:06 +01:00
Nadrieril
9962a01e9f Use min_exhaustive_patterns in core & std 2024-03-12 08:20:46 +01:00
Matthias Krüger
90ca049320
Rollup merge of #121736 - HTGAzureX1212:HTGAzureX1212/remove-mutex-unlock, r=jhpratt
Remove `Mutex::unlock` Function

As of the completion of the FCP in https://github.com/rust-lang/rust/issues/81872#issuecomment-1474104525, it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes #81872.
2024-03-01 17:51:30 +01:00
Ibraheem Ahmed
7c9fa952c3
fix typos
Co-authored-by: Ralf Jung <post@ralfj.de>
2024-02-29 01:33:02 -05:00
Ibraheem Ahmed
9c6a0766be
document potential memory leak in unbounded channel 2024-02-29 00:56:31 -05:00
Matthias Krüger
332b9be7a1
Rollup merge of #110543 - joboet:reentrant_lock, r=m-ou-se
Make `ReentrantLock` public

Implements the ACP rust-lang/libs-team#193.

``@rustbot`` label +T-libs-api +S-waiting-on-ACP
2024-02-29 00:16:58 +01:00
HTGAzureX1212.
a9907b1fdf remove Mutex::unlock 2024-02-28 20:26:19 +08:00
Ibraheem Ahmed
580b003edd
fix race between block initialization and receiver disconnection 2024-02-26 13:53:35 -05:00
bors
a2f3c0cf88 Auto merge of #117107 - zachs18:mapped-mutex-guard, r=Amanieu
Implement `MappedMutexGuard`, `MappedRwLockReadGuard`, and `MappedRwLockWriteGuard`.

ACP: https://github.com/rust-lang/libs-team/issues/260
Tracking issue: https://github.com/rust-lang/rust/issues/117108

<details> <summary> (Outdated) </summary>

`MutexState`/`RwLockState` structs

~~Having `sys::(Mutex|RwLock)` and `poison::Flag` as separate fields in the `Mutex`/`RwLock` would require `MappedMutexGuard`/`MappedRwLockWriteGuard` to hold an additional pointer, so I combined the two fields into a `MutexState`/`RwLockState` struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former `.inner` or `.poison` fields (now `.state.inner` and `.state.poison`).~~ If this is not desired, then `MappedMutexGuard`/`MappedRwLockWriteGuard` can instead hold separate pointers to the two fields.

</details>

The doc-comments are mostly copied from the existing `*Guard` doc-comments, with some parts from `lock_api::Mapped*Guard`'s doc-comments.

Unresolved question: Are more tests needed?
2024-02-25 05:59:54 +00:00
Pavel Grigorenko
ff187a92d8
library: use addr_of! 2024-02-24 16:02:17 +03:00
zachs18
8aaa04b5c5
Apply suggestions from code review
Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
2024-02-23 20:18:04 -06:00
bors
8f359beca4 Auto merge of #119536 - Jules-Bertholet:const-barrier, r=dtolnay
Make `Barrier::new()` const

I guess this was just missed in #97791?

`@rustbot` label T-libs-api -T-libs
2024-02-23 20:54:02 +00:00
joboet
2aa8a1d45c
std: make ReentrantLock public 2024-02-23 20:43:27 +01:00
Peter Jaszkowiak
4913ab8f77
Stabilize LazyCell and LazyLock (lazy_cell) 2024-02-20 20:55:13 -07:00