mirror of
https://github.com/rust-lang/cargo.git
synced 2026-03-03 19:09:16 +00:00
fix: Fix parallel locking when -Zfine-grain-locking is enabled
This commit replaces a `Mutex` with an `RwLock` lock to avoid holding a mutex guard while waiting on a file lock. Instead we hold a read guard which allows multiple threads to access the `HashMap` inside of `LockManager`.
This commit is contained in:
parent
21ac09614f
commit
31d3b42857
@ -10,19 +10,19 @@ use std::{
|
||||
collections::HashMap,
|
||||
fmt::{Display, Formatter},
|
||||
path::PathBuf,
|
||||
sync::Mutex,
|
||||
sync::RwLock,
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
/// A struct to store the lock handles for build units during compilation.
|
||||
pub struct LockManager {
|
||||
locks: Mutex<HashMap<LockKey, FileLock>>,
|
||||
locks: RwLock<HashMap<LockKey, FileLock>>,
|
||||
}
|
||||
|
||||
impl LockManager {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
locks: Mutex::new(HashMap::new()),
|
||||
locks: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ impl LockManager {
|
||||
let key = LockKey::from_unit(build_runner, unit);
|
||||
tracing::Span::current().record("key", key.0.to_str());
|
||||
|
||||
let mut locks = self.locks.lock().unwrap();
|
||||
let mut locks = self.locks.write().unwrap();
|
||||
if let Some(lock) = locks.get_mut(&key) {
|
||||
lock.file().lock_shared()?;
|
||||
} else {
|
||||
@ -60,8 +60,8 @@ impl LockManager {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub fn lock(&self, key: &LockKey) -> CargoResult<()> {
|
||||
let mut locks = self.locks.lock().unwrap();
|
||||
if let Some(lock) = locks.get_mut(&key) {
|
||||
let locks = self.locks.read().unwrap();
|
||||
if let Some(lock) = locks.get(&key) {
|
||||
lock.file().lock()?;
|
||||
} else {
|
||||
bail!("lock was not found in lock manager: {key}");
|
||||
@ -73,8 +73,8 @@ impl LockManager {
|
||||
/// Upgrades an existing exclusive lock into a shared lock.
|
||||
#[instrument(skip(self))]
|
||||
pub fn downgrade_to_shared(&self, key: &LockKey) -> CargoResult<()> {
|
||||
let mut locks = self.locks.lock().unwrap();
|
||||
let Some(lock) = locks.get_mut(key) else {
|
||||
let locks = self.locks.read().unwrap();
|
||||
let Some(lock) = locks.get(key) else {
|
||||
bail!("lock was not found in lock manager: {key}");
|
||||
};
|
||||
lock.file().lock_shared()?;
|
||||
@ -83,8 +83,8 @@ impl LockManager {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub fn unlock(&self, key: &LockKey) -> CargoResult<()> {
|
||||
let mut locks = self.locks.lock().unwrap();
|
||||
if let Some(lock) = locks.get_mut(key) {
|
||||
let locks = self.locks.read().unwrap();
|
||||
if let Some(lock) = locks.get(key) {
|
||||
lock.file().unlock()?;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user