From 2113ae2d856a208350ccbafdc19e8dda322515b8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 19 Nov 2020 16:50:06 +0000 Subject: [PATCH] Make drv hash modulo memo table thread-safe Let's get one step closer to the daemon not needing to fork. --- src/libexpr/primops.cc | 7 ++++--- src/libstore/derivations.cc | 27 +++++++++++++++------------ src/libstore/derivations.hh | 3 ++- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 236433ef1..41f06c219 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1132,9 +1132,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * However, we don't bother doing this for floating CA derivations because their "hash modulo" is indeterminate until built. */ - if (drv.type() != DerivationType::CAFloating) - drvHashes.insert_or_assign(drvPath, - hashDerivationModulo(*state.store, Derivation(drv), false)); + if (drv.type() != DerivationType::CAFloating) { + auto h = hashDerivationModulo(*state.store, Derivation(drv), false); + drvHashes.lock()->insert_or_assign(drvPath, h); + } state.mkAttrs(v, 1 + drv.outputs.size()); mkString(*state.allocAttr(v, state.sDrvPath), drvPathS, {"=" + drvPathS}); diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 106ec5daa..231ca26c2 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -451,7 +451,7 @@ DerivationType BasicDerivation::type() const } -DrvHashes drvHashes; +Sync drvHashes; /* pathDerivationModulo and hashDerivationModulo are mutually recursive */ @@ -459,19 +459,22 @@ DrvHashes drvHashes; /* Look up the derivation by value and memoize the `hashDerivationModulo` call. */ -static const DrvHashModulo & pathDerivationModulo(Store & store, const StorePath & drvPath) +static const DrvHashModulo pathDerivationModulo(Store & store, const StorePath & drvPath) { - auto h = drvHashes.find(drvPath); - if (h == drvHashes.end()) { - // Cache it - h = drvHashes.insert_or_assign( - drvPath, - hashDerivationModulo( - store, - store.readInvalidDerivation(drvPath), - false)).first; + { + auto hashes = drvHashes.lock(); + auto h = hashes->find(drvPath); + if (h != hashes->end()) { + return h->second; + } } - return h->second; + auto h = hashDerivationModulo( + store, + store.readInvalidDerivation(drvPath), + false); + // Cache it + drvHashes.lock()->insert_or_assign(drvPath, h); + return h; } /* See the header for interface details. These are the implementation details. diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index f9ba935e6..b966d6d90 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -210,7 +210,8 @@ DrvHashModulo hashDerivationModulo(Store & store, const Derivation & drv, bool m /* Memoisation of hashDerivationModulo(). */ typedef std::map DrvHashes; -extern DrvHashes drvHashes; // FIXME: global, not thread-safe +// FIXME: global, though at least thread-safe. +extern Sync drvHashes; /* Memoisation of `readDerivation(..).resove()`. */ typedef std::map<