use std:🧵:scope instead of scoped_threadpool

as it's easier to deal with TSAN false positives in the former API

as surfaced in PR 280 the current supression rules don't handle newer versions of the
scoped_threadpool crate

trying to update the supression rules related to scoped_threadpool in PR #282 revealed that the
supression rules are masking (hiding) real data races:
https://github.com/japaric/heapless/pull/282#issuecomment-1113173358

std:🧵:scope requires less supression rules and does not mask real data races -- for instance,
the data race in the linked issue comment is not masked when using std:🧵:scope

tradeoffs:
- pro: one less dev dependency
- pro: supressions file is simpler
- cons: std:🧵:scope is only available on recent nightlies
This commit is contained in:
Jorge Aparicio 2022-04-29 14:53:01 +02:00
parent 9fb9cd7045
commit 477c53b25d
3 changed files with 18 additions and 26 deletions

View File

@ -27,9 +27,6 @@ mpmc_large = []
# This flag has no version guarantee, the `defmt` dependency can be updated in a patch release
defmt-impl = ["defmt"]
[target.'cfg(not(target_os = "none"))'.dev-dependencies]
scoped_threadpool = "0.1.8"
[target.thumbv6m-none-eabi.dependencies]
atomic-polyfill = { version = "0.1.2", optional = true }

View File

@ -1,7 +1,2 @@
# false positives in thread::spawn (?)
race:*dealloc
race:*drop_slow*
race:__call_tls_dtors
# false positives in scoped_threadpool (?)
race:*drop*
race:std::panic::catch_unwind
race:std::thread::scope

View File

@ -1,3 +1,4 @@
#![feature(scoped_threads)]
#![deny(rust_2018_compatibility)]
#![deny(rust_2018_idioms)]
#![deny(warnings)]
@ -5,7 +6,6 @@
use std::{sync::mpsc, thread};
use heapless::{mpmc::Q64, spsc};
use scoped_threadpool::Pool;
#[test]
fn once() {
@ -59,12 +59,12 @@ fn scoped() {
{
let (mut p, mut c) = rb.split();
Pool::new(2).scoped(move |scope| {
scope.execute(move || {
thread::scope(move |scope| {
scope.spawn(move || {
p.enqueue(1).unwrap();
});
scope.execute(move || {
scope.spawn(move || {
c.dequeue().unwrap();
});
});
@ -83,8 +83,8 @@ fn contention() {
{
let (mut p, mut c) = rb.split();
Pool::new(2).scoped(move |scope| {
scope.execute(move || {
thread::scope(move |scope| {
scope.spawn(move || {
let mut sum: u32 = 0;
for i in 0..(2 * N) {
@ -95,7 +95,7 @@ fn contention() {
println!("producer: {}", sum);
});
scope.execute(move || {
scope.spawn(move || {
let mut sum: u32 = 0;
for _ in 0..(2 * N) {
@ -126,9 +126,9 @@ fn mpmc_contention() {
static Q: Q64<u32> = Q64::new();
let (s, r) = mpsc::channel();
Pool::new(2).scoped(|scope| {
thread::scope(|scope| {
let s1 = s.clone();
scope.execute(move || {
scope.spawn(move || {
let mut sum: u32 = 0;
for i in 0..(16 * N) {
@ -141,7 +141,7 @@ fn mpmc_contention() {
});
let s2 = s.clone();
scope.execute(move || {
scope.spawn(move || {
let mut sum: u32 = 0;
for _ in 0..(16 * N) {
@ -178,14 +178,14 @@ fn unchecked() {
{
let (mut p, mut c) = rb.split();
Pool::new(2).scoped(move |scope| {
scope.execute(move || {
thread::scope(move |scope| {
scope.spawn(move || {
for _ in 0..N / 2 - 1 {
p.enqueue(2).unwrap();
}
});
scope.execute(move || {
scope.spawn(move || {
let mut sum: usize = 0;
for _ in 0..N / 2 - 1 {
@ -246,8 +246,8 @@ fn pool() {
A::grow(unsafe { &mut M });
Pool::new(2).scoped(move |scope| {
scope.execute(move || {
thread::pool(move |scope| {
scope.spawn(move || {
for _ in 0..N / 4 {
let a = A::alloc().unwrap();
let b = A::alloc().unwrap();
@ -257,7 +257,7 @@ fn pool() {
}
});
scope.execute(move || {
scope.spawn(move || {
for _ in 0..N / 2 {
let a = A::alloc().unwrap();
let a = a.init([2; 8]);