418: Hotfix deadlocks on resource cleanup r=kvark a=LaylConway

This resolves resource cleanup causing deadlocks with `maintain`, because of `Device::pending` being locked in reverse order.

I'm calling this a "hotfix" because I don't think this is a scaleable approach to resolve how the issue happened in the first place, but it alleviates current deadlocking isssues.

I'm not quite sure how `Token` works, so I don't know if I used that right here.

This fixes #417

Co-authored-by: Layl <2385329-layl@users.noreply.gitlab.com>
This commit is contained in:
bors[bot]
2019-12-31 06:07:35 +00:00
committed by GitHub

View File

@@ -941,12 +941,19 @@ impl<F: IdentityFilter<BufferId>> Global<F> {
pub fn buffer_destroy<B: GfxBackend>(&self, buffer_id: BufferId) {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let (buffer_guard, _) = hub.buffers.read(&mut token);
let buffer = &buffer_guard[buffer_id];
device_guard[buffer.device_id.value].pending.lock().destroy(
// Deadlock hotfix, pending doesn't have a token
let (device_id, ref_count) = {
let (buffer_guard, _) = hub.buffers.read(&mut token);
let buffer = &buffer_guard[buffer_id];
(buffer.device_id.value, buffer.life_guard.ref_count.clone())
};
let (device_guard, _) = hub.devices.read(&mut token);
device_guard[device_id].pending.lock().destroy(
ResourceId::Buffer(buffer_id),
buffer.life_guard.ref_count.clone(),
ref_count,
);
}
}
@@ -984,15 +991,21 @@ impl<F: IdentityFilter<TextureId>> Global<F> {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let (texture_guard, _) = hub.textures.read(&mut token);
let texture = &texture_guard[texture_id];
device_guard[texture.device_id.value]
// Deadlock hotfix, pending doesn't have a token
let (device_id, ref_count) = {
let (texture_guard, _) = hub.textures.read(&mut token);
let texture = &texture_guard[texture_id];
(texture.device_id.value, texture.life_guard.ref_count.clone())
};
let (device_guard, _) = hub.devices.read(&mut token);
device_guard[device_id]
.pending
.lock()
.destroy(
ResourceId::Texture(texture_id),
texture.life_guard.ref_count.clone(),
ref_count,
);
}
}
@@ -1092,21 +1105,29 @@ impl<F: IdentityFilter<TextureViewId>> Global<F> {
pub fn texture_view_destroy<B: GfxBackend>(&self, texture_view_id: TextureViewId) {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let (texture_guard, mut token) = hub.textures.read(&mut token);
let (texture_view_guard, _) = hub.texture_views.read(&mut token);
let view = &texture_view_guard[texture_view_id];
let device_id = match view.inner {
resource::TextureViewInner::Native { ref source_id, .. } => {
texture_guard[source_id.value].device_id.value
}
resource::TextureViewInner::SwapChain { .. } => {
panic!("Can't destroy a swap chain image")
}
// Deadlock hotfix, pending doesn't have a token
let (device_id, ref_count) = {
let (texture_guard, mut token) = hub.textures.read(&mut token);
let (texture_view_guard, _) = hub.texture_views.read(&mut token);
let view = &texture_view_guard[texture_view_id];
let device_id = match view.inner {
resource::TextureViewInner::Native { ref source_id, .. } => {
texture_guard[source_id.value].device_id.value
}
resource::TextureViewInner::SwapChain { .. } => {
panic!("Can't destroy a swap chain image")
}
};
(device_id, view.life_guard.ref_count.clone())
};
let (device_guard, _) = hub.devices.read(&mut token);
device_guard[device_id].pending.lock().destroy(
ResourceId::TextureView(texture_view_id),
view.life_guard.ref_count.clone(),
ref_count,
);
}
}
@@ -1165,15 +1186,22 @@ impl<F: IdentityFilter<SamplerId>> Global<F> {
pub fn sampler_destroy<B: GfxBackend>(&self, sampler_id: SamplerId) {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let (sampler_guard, _) = hub.samplers.read(&mut token);
let sampler = &sampler_guard[sampler_id];
device_guard[sampler.device_id.value]
// Deadlock hotfix, pending doesn't have a token
let (device_id, ref_count) = {
let (sampler_guard, _) = hub.samplers.read(&mut token);
let sampler = &sampler_guard[sampler_id];
(sampler.device_id.value, sampler.life_guard.ref_count.clone())
};
let (device_guard, _) = hub.devices.read(&mut token);
device_guard[device_id]
.pending
.lock()
.destroy(
ResourceId::Sampler(sampler_id),
sampler.life_guard.ref_count.clone(),
ref_count,
);
}
}
@@ -1468,15 +1496,22 @@ impl<F: IdentityFilter<BindGroupId>> Global<F> {
pub fn bind_group_destroy<B: GfxBackend>(&self, bind_group_id: BindGroupId) {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let (bind_group_guard, _) = hub.bind_groups.read(&mut token);
let bind_group = &bind_group_guard[bind_group_id];
device_guard[bind_group.device_id.value]
// Deadlock hotfix, pending doesn't have a token
let (device_id, ref_count) = {
let (bind_group_guard, _) = hub.bind_groups.read(&mut token);
let bind_group = &bind_group_guard[bind_group_id];
(bind_group.device_id.value, bind_group.life_guard.ref_count.clone())
};
let (device_guard, _) = hub.devices.read(&mut token);
device_guard[device_id]
.pending
.lock()
.destroy(
ResourceId::BindGroup(bind_group_id),
bind_group.life_guard.ref_count.clone(),
ref_count,
);
}
}