Commit d65e44ba authored by Benoît Lizé's avatar Benoît Lizé Committed by Commit Bot

cc: Add mutex annotations to SoftwareImageDecodeCache.

Add mutex annotations to replace load-bearing comments in
SoftwareImageDecodeCache. This requires adding the proper annotation to
Lock::AssertAcquired(), which is also done in this CL. As a consequence, this CL
does a few things:

In SoftwareImageDecodeCache:
- Convert comments to annotations
- Make a member const instead of annotating it
- Change a test-only method to make compile-time checks pass
- Fix "git cl lint" warnings (include what you use)

In Lock:
- Add a mutex annotation to Lock::AssertAcquired()

Bug: 1013082, 831825, 983348
Change-Id: If779a0f6453a2060ed3e7dedf7ad7f6823ebac68
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1939749
Commit-Queue: Benoit L <lizeb@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720164}
parent 4e5d6562
...@@ -26,8 +26,8 @@ class LOCKABLE BASE_EXPORT Lock { ...@@ -26,8 +26,8 @@ class LOCKABLE BASE_EXPORT Lock {
~Lock() {} ~Lock() {}
// TODO(lukasza): https://crbug.com/831825: Add EXCLUSIVE_LOCK_FUNCTION // TODO(lukasza): https://crbug.com/831825: Add EXCLUSIVE_LOCK_FUNCTION
// annotation to Acquire method and similar annotations to Release, Try and // annotation to Acquire method and similar annotations to Release and Try
// AssertAcquired methods (here and in the #else branch). // methods (here and in the #else branch).
void Acquire() { lock_.Lock(); } void Acquire() { lock_.Lock(); }
void Release() { lock_.Unlock(); } void Release() { lock_.Unlock(); }
...@@ -38,7 +38,7 @@ class LOCKABLE BASE_EXPORT Lock { ...@@ -38,7 +38,7 @@ class LOCKABLE BASE_EXPORT Lock {
bool Try() { return lock_.Try(); } bool Try() { return lock_.Try(); }
// Null implementation if not debug. // Null implementation if not debug.
void AssertAcquired() const {} void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK() {}
#else #else
Lock(); Lock();
~Lock(); ~Lock();
...@@ -63,7 +63,7 @@ class LOCKABLE BASE_EXPORT Lock { ...@@ -63,7 +63,7 @@ class LOCKABLE BASE_EXPORT Lock {
return rv; return rv;
} }
void AssertAcquired() const; void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK();
#endif // DCHECK_IS_ON() #endif // DCHECK_IS_ON()
// Whether Lock mitigates priority inversion when used from different thread // Whether Lock mitigates priority inversion when used from different thread
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include <stdint.h> #include <stdint.h>
#include <algorithm>
#include <string>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/format_macros.h" #include "base/format_macros.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
...@@ -267,7 +271,6 @@ void SoftwareImageDecodeCache::AddBudgetForImage(const CacheKey& key, ...@@ -267,7 +271,6 @@ void SoftwareImageDecodeCache::AddBudgetForImage(const CacheKey& key,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::AddBudgetForImage", "key", "SoftwareImageDecodeCache::AddBudgetForImage", "key",
key.ToString()); key.ToString());
lock_.AssertAcquired();
DCHECK(!entry->is_budgeted); DCHECK(!entry->is_budgeted);
DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes()); DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes());
...@@ -280,7 +283,6 @@ void SoftwareImageDecodeCache::RemoveBudgetForImage(const CacheKey& key, ...@@ -280,7 +283,6 @@ void SoftwareImageDecodeCache::RemoveBudgetForImage(const CacheKey& key,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::RemoveBudgetForImage", "key", "SoftwareImageDecodeCache::RemoveBudgetForImage", "key",
key.ToString()); key.ToString());
lock_.AssertAcquired();
DCHECK(entry->is_budgeted); DCHECK(entry->is_budgeted);
locked_images_budget_.SubtractUsage(key.locked_bytes()); locked_images_budget_.SubtractUsage(key.locked_bytes());
...@@ -297,7 +299,6 @@ void SoftwareImageDecodeCache::UnrefImage(const DrawImage& image) { ...@@ -297,7 +299,6 @@ void SoftwareImageDecodeCache::UnrefImage(const DrawImage& image) {
} }
void SoftwareImageDecodeCache::UnrefImage(const CacheKey& key) { void SoftwareImageDecodeCache::UnrefImage(const CacheKey& key) {
lock_.AssertAcquired();
auto decoded_image_it = decoded_images_.Peek(key); auto decoded_image_it = decoded_images_.Peek(key);
DCHECK(decoded_image_it != decoded_images_.end()); DCHECK(decoded_image_it != decoded_images_.end());
auto* entry = decoded_image_it->second.get(); auto* entry = decoded_image_it->second.get();
...@@ -340,7 +341,6 @@ SoftwareImageDecodeCache::DecodeImageIfNecessary(const CacheKey& key, ...@@ -340,7 +341,6 @@ SoftwareImageDecodeCache::DecodeImageIfNecessary(const CacheKey& key,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::DecodeImageIfNecessary", "key", "SoftwareImageDecodeCache::DecodeImageIfNecessary", "key",
key.ToString()); key.ToString());
lock_.AssertAcquired();
DCHECK_GT(entry->ref_count, 0); DCHECK_GT(entry->ref_count, 0);
if (key.target_size().IsEmpty()) if (key.target_size().IsEmpty())
...@@ -550,7 +550,6 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal( ...@@ -550,7 +550,6 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal(
"SoftwareImageDecodeCache::GetDecodedImageForDrawInternal", "SoftwareImageDecodeCache::GetDecodedImageForDrawInternal",
"key", key.ToString()); "key", key.ToString());
lock_.AssertAcquired();
auto decoded_it = decoded_images_.Get(key); auto decoded_it = decoded_images_.Get(key);
CacheEntry* cache_entry = nullptr; CacheEntry* cache_entry = nullptr;
if (decoded_it == decoded_images_.end()) if (decoded_it == decoded_images_.end())
...@@ -695,13 +694,17 @@ void SoftwareImageDecodeCache::OnMemoryPressure( ...@@ -695,13 +694,17 @@ void SoftwareImageDecodeCache::OnMemoryPressure(
SoftwareImageDecodeCache::CacheEntry* SoftwareImageDecodeCache::AddCacheEntry( SoftwareImageDecodeCache::CacheEntry* SoftwareImageDecodeCache::AddCacheEntry(
const CacheKey& key) { const CacheKey& key) {
lock_.AssertAcquired();
frame_key_to_image_keys_[key.frame_key()].push_back(key); frame_key_to_image_keys_[key.frame_key()].push_back(key);
auto it = decoded_images_.Put(key, std::make_unique<CacheEntry>()); auto it = decoded_images_.Put(key, std::make_unique<CacheEntry>());
it->second.get()->mark_cached(); it->second.get()->mark_cached();
return it->second.get(); return it->second.get();
} }
size_t SoftwareImageDecodeCache::GetNumCacheEntriesForTesting() {
base::AutoLock lock(lock_);
return decoded_images_.size();
}
// MemoryBudget ---------------------------------------------------------------- // MemoryBudget ----------------------------------------------------------------
SoftwareImageDecodeCache::MemoryBudget::MemoryBudget(size_t limit_bytes) SoftwareImageDecodeCache::MemoryBudget::MemoryBudget(size_t limit_bytes)
: limit_bytes_(limit_bytes), current_usage_bytes_(0u) {} : limit_bytes_(limit_bytes), current_usage_bytes_(0u) {}
......
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "base/containers/mru_cache.h" #include "base/containers/mru_cache.h"
#include "base/memory/memory_pressure_listener.h" #include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/numerics/safe_math.h" #include "base/numerics/safe_math.h"
#include "base/thread_annotations.h"
#include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/memory_dump_provider.h"
#include "cc/cc_export.h" #include "cc/cc_export.h"
#include "cc/paint/draw_image.h" #include "cc/paint/draw_image.h"
...@@ -72,7 +74,7 @@ class CC_EXPORT SoftwareImageDecodeCache ...@@ -72,7 +74,7 @@ class CC_EXPORT SoftwareImageDecodeCache
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override; base::trace_event::ProcessMemoryDump* pmd) override;
size_t GetNumCacheEntriesForTesting() const { return decoded_images_.size(); } size_t GetNumCacheEntriesForTesting();
private: private:
using CacheEntry = Utils::CacheEntry; using CacheEntry = Utils::CacheEntry;
...@@ -98,69 +100,67 @@ class CC_EXPORT SoftwareImageDecodeCache ...@@ -98,69 +100,67 @@ class CC_EXPORT SoftwareImageDecodeCache
using ImageMRUCache = base:: using ImageMRUCache = base::
HashingMRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>; HashingMRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>;
// Actually decode the image. Note that this function can (and should) be
// called with no lock acquired, since it can do a lot of work. Note that it
// can also return nullptr to indicate the decode failed.
std::unique_ptr<CacheEntry> DecodeImageInternal(const CacheKey& key,
const DrawImage& draw_image);
// Get the decoded draw image for the given key and paint_image. Note that // Get the decoded draw image for the given key and paint_image. Note that
// this function has to be called with no lock acquired, since it will acquire
// its own locks and might call DecodeImageInternal above. Note that
// when used internally, we still require that DrawWithImageFinished() is // when used internally, we still require that DrawWithImageFinished() is
// called afterwards. // called afterwards.
DecodedDrawImage GetDecodedImageForDrawInternal( DecodedDrawImage GetDecodedImageForDrawInternal(const CacheKey& key,
const CacheKey& key, const PaintImage& paint_image)
const PaintImage& paint_image); EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Removes unlocked decoded images until the number of decoded images is // Removes unlocked decoded images until the number of decoded images is
// reduced within the given limit. // reduced within the given limit.
void ReduceCacheUsageUntilWithinLimit(size_t limit); void ReduceCacheUsageUntilWithinLimit(size_t limit)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void OnMemoryPressure( void OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel level)
base::MemoryPressureListener::MemoryPressureLevel level); LOCKS_EXCLUDED(lock_);
// Helper method to get the different tasks. Note that this should be used as // Helper method to get the different tasks. Note that this should be used as
// if it was public (ie, all of the locks need to be properly acquired). // if it was public (ie, all of the locks need to be properly acquired).
TaskResult GetTaskForImageAndRefInternal(const DrawImage& image, TaskResult GetTaskForImageAndRefInternal(const DrawImage& image,
const TracingInfo& tracing_info, const TracingInfo& tracing_info,
DecodeTaskType type); DecodeTaskType type)
LOCKS_EXCLUDED(lock_);
CacheEntry* AddCacheEntry(const CacheKey& key); CacheEntry* AddCacheEntry(const CacheKey& key)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
TaskProcessingResult DecodeImageIfNecessary(const CacheKey& key, TaskProcessingResult DecodeImageIfNecessary(const CacheKey& key,
const PaintImage& paint_image, const PaintImage& paint_image,
CacheEntry* cache_entry); CacheEntry* cache_entry)
void AddBudgetForImage(const CacheKey& key, CacheEntry* entry); EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RemoveBudgetForImage(const CacheKey& key, CacheEntry* entry); void AddBudgetForImage(const CacheKey& key, CacheEntry* entry)
base::Optional<CacheKey> FindCachedCandidate(const CacheKey& key); EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RemoveBudgetForImage(const CacheKey& key, CacheEntry* entry)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
base::Optional<CacheKey> FindCachedCandidate(const CacheKey& key)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void UnrefImage(const CacheKey& key); void UnrefImage(const CacheKey& key) EXCLUSIVE_LOCKS_REQUIRED(lock_);
// The members below this comment can only be accessed if the lock is held to
// ensure that they are safe to access on multiple threads.
// The exception is accessing |locked_images_budget_.total_limit_bytes()|,
// which is const and thread safe.
base::Lock lock_; base::Lock lock_;
// Decoded images and ref counts (predecode path). // Decoded images and ref counts (predecode path).
ImageMRUCache decoded_images_; ImageMRUCache decoded_images_ GUARDED_BY(lock_);
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_
GUARDED_BY(lock_);
// A map of PaintImage::FrameKey to the ImageKeys for cached decodes of this // A map of PaintImage::FrameKey to the ImageKeys for cached decodes of this
// PaintImage. // PaintImage.
std::unordered_map<PaintImage::FrameKey, std::unordered_map<PaintImage::FrameKey,
std::vector<CacheKey>, std::vector<CacheKey>,
PaintImage::FrameKeyHash> PaintImage::FrameKeyHash>
frame_key_to_image_keys_; frame_key_to_image_keys_ GUARDED_BY(lock_);
// Should be GUARDED_BY(lock_), except that accessing
// |locked_images_budget_.total_limit_bytes()| is fine without the lock, as
// it is const and thread safe.
MemoryBudget locked_images_budget_; MemoryBudget locked_images_budget_;
const SkColorType color_type_; const SkColorType color_type_;
const PaintImage::GeneratorClientId generator_client_id_; const PaintImage::GeneratorClientId generator_client_id_;
size_t max_items_in_cache_; const size_t max_items_in_cache_;
}; };
} // namespace cc } // namespace cc
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment