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:
Dzmitry Malyshau 2020-05-28 03:38:21 +00:00
Родитель d6f8c568eb
Коммит e5e0a70cb4
3 изменённых файлов: 111 добавлений и 7 удалений

55
gfx/wgpu/Cargo.lock сгенерированный
Просмотреть файл

@ -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>,