Simplify manual ptr arithmetic in slice::Iter with ptr_sub
The old code was introduced in #61885, which predates the ptr_sub method and underlying intrinsic. The codegen test still passes.
r? `@scottmcm`
Leak amplification for peek_mut() to ensure BinaryHeap's invariant is always met
In the libs-api team's discussion around #104210, some of the team had hesitations around exposing malformed BinaryHeaps of an element type whose Ord and Drop impls are trusted, and which does not contain interior mutability.
For example in the context of this kind of code:
```rust
use std::collections::BinaryHeap;
use std::ops::Range;
use std::slice;
fn main() {
let slice = &mut ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let cut_points = BinaryHeap::from(vec![4, 2, 7]);
println!("{:?}", chop(slice, cut_points));
}
// This is a souped up slice::split_at_mut to split in arbitrary many places.
//
// usize's Ord impl is trusted, so 1 single bounds check guarantees all those
// output slices are non-overlapping and in-bounds
fn chop<T>(slice: &mut [T], mut cut_points: BinaryHeap<usize>) -> Vec<&mut [T]> {
let mut vec = Vec::with_capacity(cut_points.len() + 1);
let max = match cut_points.pop() {
Some(max) => max,
None => {
vec.push(slice);
return vec;
}
};
assert!(max <= slice.len());
let len = slice.len();
let ptr: *mut T = slice.as_mut_ptr();
let get_unchecked_mut = unsafe {
|range: Range<usize>| &mut *slice::from_raw_parts_mut(ptr.add(range.start), range.len())
};
vec.push(get_unchecked_mut(max..len));
let mut end = max;
while let Some(start) = cut_points.pop() {
vec.push(get_unchecked_mut(start..end));
end = start;
}
vec.push(get_unchecked_mut(0..end));
vec
}
```
```console
[['7', '8', '9'], ['4', '5', '6'], ['2', '3'], ['0', '1']]
```
In the current BinaryHeap API, `peek_mut()` is the only thing that makes the above function unsound.
```rust
let slice = &mut ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let mut cut_points = BinaryHeap::from(vec![4, 2, 7]);
{
let mut max = cut_points.peek_mut().unwrap();
*max = 0;
std::mem::forget(max);
}
println!("{:?}", chop(slice, cut_points));
```
```console
[['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], [], ['2', '3'], ['0', '1']]
```
Or worse:
```rust
let slice = &mut ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let mut cut_points = BinaryHeap::from(vec![100, 100]);
{
let mut max = cut_points.peek_mut().unwrap();
*max = 0;
std::mem::forget(max);
}
println!("{:?}", chop(slice, cut_points));
```
```console
[['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], [], ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u{1}', '\0', '?', '翾', '?', '翾', '\0', '\0', '?', '翾', '?', '翾', '?', '啿', '?', '啿', '?', '啿', '?', '啿', '?', '啿', '?', '翾', '\0', '\0', '', '啿', '\u{5}', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\u{8}', '\0', '`@',` '\0', '\u{1}', '\0', '?', '翾', '?', '翾', '?', '翾', '
thread 'main' panicked at 'index out of bounds: the len is 33 but the index is 33', library/core/src/unicode/unicode_data.rs:319:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
---
This PR makes `peek_mut()` use leak amplification (https://doc.rust-lang.org/1.66.0/nomicon/leaking.html#drain) to preserve the heap's invariant even in the situation that `PeekMut` gets leaked.
I'll also follow up in the tracking issue of unstable `drain_sorted()` (#59278) and `retain()` (#71503).
Fix the stability attributes for `std::os::fd`.
As `@bjorn3` pointed out [here], I used the wrong stability attribute in #98368 when making `std::os::fd` public. I set it to Rust 1.63, which was when io-safety was stabilized, but it should be Rust 1.66, which was when `std::os::fd` was stabilized.
[here]: https://github.com/rust-lang/rust/pull/98368#discussion_r1063721420
As @bjorn3 pointed out [here], I used the wrong stability attribute in #98368
when making `std::os::fd` public. I set it to Rust 1.63, which was when
io-safety was stabilized, but it should be Rust 1.66, which was when
`std::os::fd` was stabilized.
[here]: https://github.com/rust-lang/rust/pull/98368#discussion_r1063721420
Remove various double spaces in the libraries.
I was just pretty bothered by this when reading the source for a function, and was suggested to check if this happened elsewhere.
Stop probing for statx unless necessary
As is the current toy program:
fn main() -> std::io::Result<()> {
use std::fs;
let metadata = fs::metadata("foo.txt")?;
assert!(!metadata.is_dir());
Ok(())
}
... observed under strace will issue:
[snip]
statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address) statx(AT_FDCWD, "foo.txt", AT_STATX_SYNC_AS_STAT, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=0, ...}) = 0
While statx is not necessarily always present, checking for it can be delayed to the first error condition. Said condition may very well never happen, in which case the check got avoided altogether.
Note this is still suboptimal as there still will be programs issuing it, but bulk of the problem is removed.
Tested by forbidding the syscall for the binary and observing it correctly falls back to newfstatat.
While here tidy up the commentary, in particular by denoting some problems with the current approach.
mv binary_heap.rs binary_heap/mod.rs
I confess this request is somewhat selfish, as it's made in order to ease synchronisation with my [copse](https://crates.io/crates/copse) crate (see eggyal/copse#6 for explanation). I wholly understand that such grounds may be insufficient to justify merging this request—but no harm in asking, right?
reword Option::as_ref and Option::map examples
The description for the examples of `Option::as_ref` and `Option::map` imply that the example is only doing type conversion, when it is actually finding the length of a string.
Changes the wording to imply that some operation is being run on the value contained in the `Option`
closes#104476
[LSDA] Take ttype_index into account when taking unwind action
If `cs_action != 0`, we should check the `ttype_index` field in action record. If `ttype_index == 0`, a clean up action is taken; otherwise catch action is taken.
This can fix unwind failure on AIX which uses LLVM's libunwind by default. IIUC, rust's LSDA is borrowed from c++ and I'm assuming itanium-cxx-abi https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf should be followed, so the fix follows what libcxxabi does. See ec48682ce9/libcxxabi/src/cxa_personality.cpp (L152) for use of `ttype_index`.
- Fixes https://github.com/rust-lang/rust/issues/91628.
- Fixes https://github.com/emscripten-core/emscripten/issues/15722.
See discussion in both issues.
The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid.
Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway.
Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++.
r? @alexcrichton
Two locations check whether this build-time environment variable is
defined. Allowing it to be explicitly disabled with a "0" value is
useful, especially for integrating with external build systems.
Stabilize `::{core,std}::pin::pin!`
As discussed [over here](https://github.com/rust-lang/rust/issues/93178#issuecomment-1295843548), it looks like a decent time to stabilize the `pin!` macro.
### Public API
```rust
// in module `core::pin`
/// API: `fn pin<T>($value: T) -> Pin<&'local mut T>`
pub macro pin($value:expr $(,)?) {
…
}
```
- Tracking issue: #93178
(now all this needs is an FCP by the proper team?)
doc: rewrite doc for signed int::{carrying_add,borrowing_sub}
Reword the documentation for bigint helper methods, signed `int::{carrying_add,borrowing_sub}` (#85532).
This change is a follow-up to #101889, which was for the unsigned methods.
std tests: use __OsLocalKeyInner from realstd
This is basically the same as https://github.com/rust-lang/rust/pull/100201, but for __OsLocalKeyInner:
Some std tests are failing in Miri on Windows because [this static](a377893da2/library/std/src/sys/windows/thread_local_key.rs (L234-L239)) is getting duplicated, and Miri does not handle that properly -- Miri does not support this magic `.CRT$XLB` linker section, but instead just looks up this particular hard-coded static in the standard library. This PR lets the test suite use the std static instead of having its own copy.
Fixes https://github.com/rust-lang/miri/issues/2754
r? `@thomcc`
As is the current toy program:
fn main() -> std::io::Result<()> {
use std::fs;
let metadata = fs::metadata("foo.txt")?;
assert!(!metadata.is_dir());
Ok(())
}
... observed under strace will issue:
[snip]
statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address)
statx(AT_FDCWD, "foo.txt", AT_STATX_SYNC_AS_STAT, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=0, ...}) = 0
While statx is not necessarily always present, checking for it can be
delayed to the first error condition. Said condition may very well never
happen, in which case the check got avoided altogether.
Note this is still suboptimal as there still will be programs issuing
it, but bulk of the problem is removed.
Tested by forbidding the syscall for the binary and observing it
correctly falls back to newfstatat.
While here tidy up the commentary, in particular by denoting some
problems with the current approach.
specialize impl of `ToString` on `bool`
Fixes#106611
Specialize `bool`s `ToString` impl by copying it from `Display`. This is a significant optimization as we avoid lots of dynamic dispatch. AFAIK, this doesn't require a API Change Proposal as this doesn't regress existing code and can be undone without regressing code.
The `std::os::unix` module is stubbed out when building docs for these
target platforms. The introduction of Linux-specific extension traits
caused `std::os::net` to depend on sub-modules of `std::os::unix`,
which broke rustdoc for the `wasm32-unknown-unknown` target.
Adding an additional `#[cfg]` guard solves that rustdoc failure by
not declaring `linux_ext` on targets with a stubbed `std::os::unix`.
Document that `Vec::from_raw_parts[_in]` must be given a pointer from the correct allocator.
Currently, the documentation of `Vec::from_raw_parts` and `Vec::from_raw_parts_in` says nothing about what allocator the pointer must come from. This PR adds that missing information explicitly.
Don't derive Debug for `OnceWith` & `RepeatWith`
Closures don't impl Debug, so the derived impl is kinda useless. The behavior of not debug-printing closures is consistent with the rest of the iterator adapters/sources.
Loosen the bound on the Debug implementation of Weak.
Both `rc::Weak<T>` and `sync::Weak<T>` currently require `T: Debug` in their own `Debug` implementations, but they don't currently use it; they only ever print a fixed string.
A general implementation of Debug for Weak that actually attempts to upgrade and rely on the contents is unlikely in the future because it may have unbounded recursion in the presence of reference cycles, which Weak is commonly used in. (This was the justification for why the current implementation [was implemented the way it is](f0976e2cf3)).
When I brought it up [on the forum](https://internals.rust-lang.org/t/could-the-bound-on-weak-debug-be-relaxed/15504), it was suggested that, even if an implementation is specialized in the future that relies on the data stored within the Weak, it would likely rely on specialization anyway, and could therefore easily specialize on the Debug bound as well.
Update `rand` in the stdlib tests, and remove the `getrandom` feature from it.
The main goal is actually removing `getrandom`, so that eventually we can allow running the stdlib test suite on tier3 targets which don't have `getrandom` support. Currently those targets can only run the subset of stdlib tests that exist in uitests, and (generally speaking), we prefer not to test libstd functionality in uitests, which came up recently in https://github.com/rust-lang/rust/pull/104095 and https://github.com/rust-lang/rust/pull/104185. Additionally, the fact that we can't update `rand`/`getrandom` means we're stuck with the old set of tier3 targets, so can't test new ones.
~~Anyway, I haven't checked that this actually does allow use on tier3 targets (I think it does not, as some work is needed in stdlib submodules) but it moves us slightly closer to this, and seems to allow at least finally updating our `rand` dep, which definitely improves the status quo.~~ Checked and works now.
For the most part, our tests and benchmarks are fine using hard-coded seeds. A couple tests seem to fail with this (stuff manipulating the environment expecting no collisions, for example), or become pointless (all inputs to a function become equivalent). In these cases I've done a (gross) dance (ab)using `RandomState` and `Location::caller()` for some extra "entropy".
Trying to share that code seems *way* more painful than it's worth given that the duplication is a 7-line function, even if the lines are quite gross. (Keeping in mind that sharing it would require adding `rand` as a non-dev dep to std, and exposing a type from it publicly, all of which sounds truly awful, even if done behind a perma-unstable feature).
See also some previous attempts:
- https://github.com/rust-lang/rust/pull/86963 (in particular https://github.com/rust-lang/rust/pull/86963#issuecomment-885438936 which explains why this is non-trivial)
- https://github.com/rust-lang/rust/pull/89131
- https://github.com/rust-lang/rust/pull/96626#issuecomment-1114562857 (I tried in that PR at the same time, but settled for just removing the usage of `thread_rng()` from the benchmarks, since that was the main goal).
- https://github.com/rust-lang/rust/pull/104185
- Probably more. It's very tempting of a thing to "just update".
r? `@Mark-Simulacrum`
Improve include macro documentation
As outlined in #106118, the `include!` macro is a SEO problem when it comes to the Rust documentation. Beginners may see it as a replacement to `include` syntax in other languages. I feel like this documentation should quite explicitly link to the modules' documentation.
The primary goal of this PR is to address that issue by adding a warning to the documentation. While I was here, I also added some other parts. This included a `Uses` section and some (intra doc) links to other relevant topics.
I hope this can help beginners to Rust more quickly understand some multi-file project intricacies.
# References
- Syntax for the warning: 58accc6da3/tracing/src/lib.rs (L55)
Fix a few clippy lints in libtest
- Remove unnecessary references and dereferences
- Use `.contains` instead of `a <= x && x <= b`
- Use `mem::take` instead of `mem::replace` where possible
cc https://github.com/rust-lang/rust/pull/106394 :)
Suggest `impl Fn*` and `impl Future` in `-> _` return suggestions
Follow-up to #106172, only the last commit is relevant. Can rebase once that PR is landed for easier review.
Suggests `impl Future` and `impl Fn{,Mut,Once}` in `-> _` return suggestions.
r? `@estebank`
default OOM handler: use non-unwinding panic, to match std handler
The OOM handler in std will by default abort. This adjusts the default in liballoc to do the same, using the `can_unwind` flag on the panic info to indicate a non-unwinding panic.
In practice this probably makes little difference since the liballoc default will only come into play in no-std situations where people write a custom panic handler, which most likely will not implement unwinding. But still, this seems more consistent.
Cc `@rust-lang/wg-allocators,` https://github.com/rust-lang/rust/issues/66741
- Remove unnecessary references and dereferences
- Use `.contains` instead of `a <= x && x <= b`
- Use `mem::take` instead of `mem::replace` where possible
`Split*::as_str` refactor
I've made this patch almost a year ago, so the rename and the behavior change are in one commit, sorry 😅
This fixes#84974, as it's required to make other changes work.
This PR
- Renames `as_str` method of string `Split*` iterators to `remainder` (it seems like the `as_str` name was confusing to users)
- Makes `remainder` return `Option<&str>`, to distinguish between "the iterator is exhausted" and "the tail is empty", this was [required on the tracking issue](https://github.com/rust-lang/rust/issues/77998#issuecomment-832696619)
r? `@m-ou-se`
Add notes and examples about non-intuitive `PathBuf::set_extension` behavior
Basically, passing the empty string will actually remove the extension instead of setting it to the empty string. This might change what is considered to be an extension. Additionally, passing an extension that contains dots will make the path only consider the last part of it to be the new extension.
Context is no longer Sync so this doesn't work.
error[E0277]: `*mut ()` cannot be shared between threads safely
--> library/core/tests/task.rs:24:21
|
24 | static CONTEXT: Context<'static> = Context::from_waker(&WAKER);
| ^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
|
= help: within `Context<'static>`, the trait `Sync` is not implemented for `*mut ()`
= note: required because it appears within the type `PhantomData<*mut ()>`
= note: required because it appears within the type `Context<'static>`
= note: shared static variables must have a type that implements `Sync`
Revert "Implement allow-by-default `multiple_supertrait_upcastable` lint"
This is a clean revert of #105484.
I confirmed that reverting that PR fixes the regression reported in #106247. ~~I can't say I understand what this code is doing, but maybe it can be re-landed with a different implementation.~~ **Edit:** https://github.com/rust-lang/rust/issues/106247#issuecomment-1367174384 has an explanation of why #105484 ends up surfacing spurious `where_clause_object_safety` errors. The implementation of `where_clause_object_safety` assumes we only check whether a trait is object safe when somebody actually uses that trait with `dyn`. However the implementation of `multiple_supertrait_upcastable` added in the problematic PR involves checking *every* trait for whether it is object-safe.
FYI `@nbdd0121` `@compiler-errors`
Unify id-based thread parking implementations
Multiple platforms currently use thread-id-based parking implementations (NetBSD and SGX[^1]). Even though the strategy does not differ, these are duplicated for each platform, as the id is encoded into an atomic thread variable in different ways for each platform.
Since `park` is only called by one thread, it is possible to move the thread id into a separate field. By ensuring that the field is only written to once, before any other threads access it, these accesses can be unsynchronized, removing any restrictions on the size and niches of the thread id.
This PR also renames the internal `thread_parker` modules to `thread_parking`, as that name now better reflects their contents. I hope this does not add too much reviewing noise.
r? `@m-ou-se`
`@rustbot` label +T-libs
[^1]: SOLID supports this as well, I will switch it over in a follow-up PR.
Basically, passing the empty string will actually remove the extension
instead of setting it to the empty string. This might change what is
considered to be an extension. Additionally, passing an extension that
contains dots will make the path only consider the last part of it to be
the new extension.
Add #[inline] markers to once_cell methods
Added inline markers to all simple methods under the `once_cell` feature. Relates to #74465 and #105587
This should not block #105587
`IN6ADDR_ANY_INIT` and `IN6ADDR_LOOPBACK_INIT` documentation.
Added documentation for IPv6 Addresses `IN6ADDR_ANY_INIT` also known as `in6addr_any` and `IN6ADDR_LOOPBACK_INIT` also known as `in6addr_loopback` similar to `INADDR_ANY` for IPv4 Addresses.
Replace libstd, libcore, liballoc terminology in docs
Fixes#103551. I changed line comments containing the outdated terms as well.
It would be great if someone with more experience could weigh in on whether these changes introduce ambiguity as suggested in https://github.com/rust-lang/rust/issues/103551#issuecomment-1291225315.
doc: clearer and more correct Iterator::scan
The `Iterator::scan` documentation seemed a little misleading to my newcomer
eyes, and this tries to address that.
* I found “similar to `fold`” unhelpful because (a) the similarity is only that
they maintain state between iterations, and (b) the _dissimilarity_ is no less
important: one returns a final value and the other an iterator. So this
replaces that with “which, like `fold`, holds internal state, but unlike
`fold`, produces a new iterator.
* I found “the return value from the closure, an `Option`, is yielded by the
iterator” to be downright incorrect, because “yielded by the iterator” means
“returned by the `next` method wrapped in `Some`”, so this implied that `scan`
would convert an input iterator of `T` to an output iterator of `Option<T>`.
So this replaces “yielded by the iterator” with “returned by the `next`
method” and elaborates: “Thus the closure can return `Some(value)` to yield
`value`, or `None` to end the iteration.”
* This also changes the example to illustrate the latter point by returning
`None` to terminate the iteration early based on `state`.
Catch panics/unwinding in destruction of TLS values
`destroy_value` is/can be called from C code (libc). Unwinding from Rust to C code is undefined behavior, which is why unwinding is caught here.
This problem caused an infinite loop inside the unwinding code when running `src/test/ui/threads-sendsync/issue-24313.rs` on a tier 3 target (QNX/Neutrino) on aarch64.
See also https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Infinite.20unwinding.20bug.
kmc-solid: Fix memory ordering in thread operations
Fixes two memory ordering issues in the thread state machine (`ThreadInner::lifecycle`) of the [`*-kmc-solid_*`](https://doc.rust-lang.org/nightly/rustc/platform-support/kmc-solid.html) Tier 3 targets.
1. When detaching a thread that is still running (i.e., the owner updates `lifecycle` first, and the child updates it next), the first update did not synchronize-with the second update, resulting in a data race between the first update and the deallocation of `ThreadInner` by the child thread.
2. When joining on a thread, the joiner has to pass its own task ID to the joinee in order to be woken up later, but in doing so, it did not synchronize-with the read operation, creating possible sequences of execution where the joinee wakes up an incorrect or non-existent task.
Both issue are theoretical and most likely have never manifested in practice because of the stronger guarantees provided by the Arm memory model (particularly due to its barrier-based definition). Compiler optimizations could have subverted this, but the inspection of compiled code did not reveal such optimizations taking place.
Bump master bootstrap compiler
This PR bumps the bootstrap compiler to the beta created earlier this week, cherry-picks the stabilization version number updates, and updates the `cfg(bootstrap)`s.
r? `@Mark-Simulacrum`
adjust message on non-unwinding panic
"thread panicked while panicking" is just plain wrong in case this is a non-unwinding panic, such as
- a panic out of a `nounwind` function
- the sanity checks we have in `mem::uninitialized` and `mem::zeroed`
- the optional debug assertion in various unsafe std library functions
Clarify `catch_unwind` docs about panic hooks
Makes it clear from `catch_unwind` docs that the panic hook will be called before the panic is caught.
Fixes#105432
Make sentinel value configurable in `library/std/src/sys_common/thread_local_key.rs`
This is an excerpt of a changeset for the QNX/Neutrino OS. To make the patch for QNX smaller and easier to review, I've extracted this change (which is OS independent). I would be surprised if no other OS is also affected.
All this patch does is to define a `const` for a sentinel value instead of using it directly at several places.
There are OSs that always return the lowest free value. The algorithm in `lazy_init` always avoids keys with the sentinel value.
In affected OSs, this means that each call to `lazy_init` will always request two keys from the OS and returns/frees the first one (with sentinel value) immediately afterwards.
By making the sentinel value configurable, affected OSs can use a different value than zero to prevent this performance issue.
On QNX/Neutrino, it is planned to use a different sentinel value:
```rust
// Define a sentinel value that is unlikely to be returned
// as a TLS key (but it may be returned).
#[cfg(not(target_os = "nto"))]
const KEY_SENTVAL: usize = 0;
// On QNX/Neutrino, 0 is always returned when currently not in use.
// Using 0 would mean to always create two keys and remote the first
// one (with value of 0) immediately afterwards.
#[cfg(target_os = "nto")]
const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
```
It seems like no other OS defines `PTHREAD_KEYS_MAX` in Rusts libc, but `limits.h` on unix systems does.
available_parallelism: Gracefully handle zero value cfs_period_us
There seem to be some scenarios where the cgroup cpu quota field `cpu.cfs_period_us` can contain `0`. This field is used to determine the "amount" of parallelism suggested by the function `std:🧵:available_parallelism`
A zero value of this field cause a panic when `available_parallelism()` is invoked. This issue was detected by the call from binaries built by `cargo test`. I really don't feel like `0` is a good value for `cpu.cfs_period_us`, but I also don't think applications should panic if this value is seen.
This panic started happening with rust 1.64.0.
This case is gracefully handled by other projects which read this information: [num_cpus](e437b9d908/src/linux.rs (L207-L210)), [ninja](https://github.com/ninja-build/ninja/pull/2174/files), [dotnet](c4341d45ac/src/coreclr/pal/src/misc/cgroup.cpp (L481-L483))
Before this change, running `cargo test` in environments configured as described above would trigger this panic:
```
$ RUST_BACKTRACE=1 cargo test
Finished test [unoptimized + debuginfo] target(s) in 3.55s
Running unittests src/main.rs (target/debug/deps/x-9a42e145aca2934d)
thread 'main' panicked at 'attempt to divide by zero', library/std/src/sys/unix/thread.rs:546:70
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::panic
3: std::sys::unix:🧵:cgroups::quota
4: std::sys::unix:🧵:available_parallelism
5: std:🧵:available_parallelism
6: test::helpers::concurrency::get_concurrency
7: test::console::run_tests_console
8: test::test_main
9: test::test_main_static
10: x::main
at ./src/main.rs:1:1
11: core::ops::function::FnOnce::call_once
at /tmp/rust-1.64-1.64.0-1/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: test failed, to rerun pass '--bin x'
```
I've tested this change in an environment which has the bad (questionable?) setup and rebuilding the test executable against a fixed std library fixes the panic.
Move `ReentrantMutex` to `std::sync`
If I understand #84187 correctly, `sys_common` should not contain platform-independent code, even if it is private.