зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1637998 - Hook up loom for concurrency testingting of wgpu r=groves
Differential Revision: https://phabricator.services.mozilla.com/D77159
This commit is contained in:
Родитель
d6f8c568eb
Коммит
e5e0a70cb4
|
@ -357,6 +357,19 @@ dependencies = [
|
|||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa160efb38ce00acbe4450d41a103fb3d2acdb17ff09a7cf38f3ac26af0738"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"log",
|
||||
"rustc_version",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-auxil"
|
||||
version = "0.3.0"
|
||||
|
@ -622,6 +635,17 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"generator",
|
||||
"scoped-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.2.3"
|
||||
|
@ -985,6 +1009,15 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.7.9"
|
||||
|
@ -1014,12 +1047,33 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.106"
|
||||
|
@ -1321,6 +1375,7 @@ dependencies = [
|
|||
"gfx-hal",
|
||||
"gfx-memory",
|
||||
"log",
|
||||
"loom",
|
||||
"parking_lot",
|
||||
"peek-poke",
|
||||
"raw-window-handle",
|
||||
|
|
|
@ -60,3 +60,6 @@ gfx-backend-vulkan = { version = "0.5" }
|
|||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "dragonfly", target_os = "freebsd"))'.dependencies]
|
||||
battery = { version = "0.7", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
loom = "0.3"
|
||||
|
|
|
@ -39,11 +39,14 @@ mod track;
|
|||
|
||||
pub use hal::pso::read_spirv;
|
||||
|
||||
use std::{
|
||||
os::raw::c_char,
|
||||
ptr,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
#[cfg(test)]
|
||||
use loom::sync::atomic;
|
||||
#[cfg(not(test))]
|
||||
use std::sync::atomic;
|
||||
|
||||
use atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use std::{os::raw::c_char, ptr};
|
||||
|
||||
type SubmissionIndex = usize;
|
||||
type Index = u32;
|
||||
|
@ -64,6 +67,27 @@ impl RefCount {
|
|||
fn load(&self) -> usize {
|
||||
unsafe { self.0.as_ref() }.load(Ordering::Acquire)
|
||||
}
|
||||
|
||||
/// This works like `std::mem::drop`, except that it returns a boolean which is true if and only
|
||||
/// if we deallocated the underlying memory, i.e. if this was the last clone of this `RefCount`
|
||||
/// to be dropped. This is useful for loom testing because it allows us to verify that we
|
||||
/// deallocated the underlying memory exactly once.
|
||||
#[cfg(test)]
|
||||
fn rich_drop_outer(self) -> bool {
|
||||
unsafe { std::mem::ManuallyDrop::new(self).rich_drop_inner() }
|
||||
}
|
||||
|
||||
/// This function exists to allow `Self::rich_drop_outer` and `Drop::drop` to share the same
|
||||
/// logic. To use this safely from outside of `Drop::drop`, the calling function must move
|
||||
/// `Self` into a `ManuallyDrop`.
|
||||
unsafe fn rich_drop_inner(&mut self) -> bool {
|
||||
if self.0.as_ref().fetch_sub(1, Ordering::Relaxed) == 1 {
|
||||
let _ = Box::from_raw(self.0.as_ptr());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RefCount {
|
||||
|
@ -76,12 +100,34 @@ impl Clone for RefCount {
|
|||
|
||||
impl Drop for RefCount {
|
||||
fn drop(&mut self) {
|
||||
if unsafe { self.0.as_ref() }.fetch_sub(1, Ordering::Relaxed) == 1 {
|
||||
let _ = unsafe { Box::from_raw(self.0.as_ptr()) };
|
||||
unsafe {
|
||||
self.rich_drop_inner();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn loom() {
|
||||
loom::model(move || {
|
||||
let bx = Box::new(AtomicUsize::new(1));
|
||||
let ref_count_main = ptr::NonNull::new(Box::into_raw(bx)).map(RefCount).unwrap();
|
||||
let ref_count_spawned = ref_count_main.clone();
|
||||
|
||||
let join_handle = loom::thread::spawn(move || {
|
||||
let _ = ref_count_spawned.clone();
|
||||
ref_count_spawned.rich_drop_outer()
|
||||
});
|
||||
|
||||
let dropped_in_main = ref_count_main.rich_drop_outer();
|
||||
let dropped_in_spawned = join_handle.join().unwrap();
|
||||
assert_ne!(
|
||||
dropped_in_main, dropped_in_spawned,
|
||||
"must drop exactly once"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LifeGuard {
|
||||
ref_count: Option<RefCount>,
|
||||
|
|
Загрузка…
Ссылка в новой задаче