Commit cf885171 authored by danakj's avatar danakj Committed by Commit Bot

viz: Make SharedBitmap tracing consistent and more clear

Make SharedBitmap return an UnguessableToken as the shared bitmap-based
tracing id, if the SharedBitmap is in fact backed by shared memory for
cross-process use. This means ClientSharedBitmapManager always does
and ServerSharedBitmapManager returns null if the bitmap was allocated
inside the ServerSharedBitmapManager.

In ServerSharedBitmapManager memory dumps, if a bitmap is shared memory
backed, it dumps the |mapped_id()| which is the UnguessableToken.
Otherwise, it dumps the SharedBitmapGUID from the SharedBitmapId.

In ResourceProvider, if the SharedBitmap has an UnguessableToken for
its shared memory backing, it dumps that, else uses the SharedBitmapID
to make a GUID.

In ResourcePool, the same thing is done as ResourceProvider.

Thus, all child-process bitmaps will be dumped via the shared memory
mapped_id() which is an UnguessableToken. And all service-process
bitmaps are dumped via the SharedBitmapGUID.

R=ericrk@chromium.org

Bug: 730660
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: Id4b1c20350a139d36df13743d012756181937c6e
Reviewed-on: https://chromium-review.googlesource.com/935428
Commit-Queue: danakj <danakj@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541275}
parent c0b5b756
...@@ -570,11 +570,11 @@ void ResourcePool::PoolResource::OnMemoryDump( ...@@ -570,11 +570,11 @@ void ResourcePool::PoolResource::OnMemoryDump(
base::UnguessableToken shm_guid; base::UnguessableToken shm_guid;
base::trace_event::MemoryAllocatorDumpGuid backing_guid; base::trace_event::MemoryAllocatorDumpGuid backing_guid;
if (shared_bitmap_) { if (shared_bitmap_) {
// Software resources are in shared memory but are kept closed to avoid // If the SharedBitmap was allocated for cross-process use, then it has this
// holding an fd open. So there is no SharedMemoryHandle to get a guid // |shm_guid|, else we fallback to the SharedBitmapGUID.
// from. shm_guid = shared_bitmap_->GetCrossProcessGUID();
DCHECK(!shared_bitmap_->GetSharedMemoryHandle().IsValid()); if (shm_guid.is_empty())
backing_guid = viz::GetSharedBitmapGUIDForTracing(shared_bitmap_->id()); backing_guid = viz::GetSharedBitmapGUIDForTracing(shared_bitmap_->id());
} else if (gpu_backing_) { } else if (gpu_backing_) {
// We prefer the SharedMemoryGuid() if it exists, if the resource is backed // We prefer the SharedMemoryGuid() if it exists, if the resource is backed
// by shared memory. // by shared memory.
......
...@@ -207,7 +207,7 @@ bool ResourceProvider::OnMemoryDump( ...@@ -207,7 +207,7 @@ bool ResourceProvider::OnMemoryDump(
backing_memory_allocated = !!resource.gl_id; backing_memory_allocated = !!resource.gl_id;
break; break;
case viz::ResourceType::kBitmap: case viz::ResourceType::kBitmap:
backing_memory_allocated = resource.has_shared_bitmap_id; backing_memory_allocated = !!resource.shared_bitmap;
break; break;
} }
...@@ -236,10 +236,16 @@ bool ResourceProvider::OnMemoryDump( ...@@ -236,10 +236,16 @@ bool ResourceProvider::OnMemoryDump(
base::UnguessableToken shared_memory_guid; base::UnguessableToken shared_memory_guid;
switch (resource.type) { switch (resource.type) {
case viz::ResourceType::kGpuMemoryBuffer: case viz::ResourceType::kGpuMemoryBuffer:
guid = // GpuMemoryBuffers may be backed by shared memory, and in that case we
resource.gpu_memory_buffer->GetGUIDForTracing(tracing_process_id); // use the guid from there to attribute for the global shared memory
// dumps. Otherwise, they may be backed by native structures, and we
// fall back to that with GetGUIDForTracing.
shared_memory_guid = shared_memory_guid =
resource.gpu_memory_buffer->GetHandle().handle.GetGUID(); resource.gpu_memory_buffer->GetHandle().handle.GetGUID();
if (shared_memory_guid.is_empty()) {
guid =
resource.gpu_memory_buffer->GetGUIDForTracing(tracing_process_id);
}
break; break;
case viz::ResourceType::kTexture: case viz::ResourceType::kTexture:
DCHECK(resource.gl_id); DCHECK(resource.gl_id);
...@@ -249,24 +255,28 @@ bool ResourceProvider::OnMemoryDump( ...@@ -249,24 +255,28 @@ bool ResourceProvider::OnMemoryDump(
resource.gl_id); resource.gl_id);
break; break;
case viz::ResourceType::kBitmap: case viz::ResourceType::kBitmap:
DCHECK(resource.has_shared_bitmap_id); // If the resource comes from out of process, it will have this id,
guid = viz::GetSharedBitmapGUIDForTracing(resource.shared_bitmap_id); // which we prefer. Otherwise, we fall back to the SharedBitmapGUID
if (resource.shared_bitmap) { // which can be generated for in-process bitmaps.
shared_memory_guid = shared_memory_guid = resource.shared_bitmap->GetCrossProcessGUID();
resource.shared_bitmap->GetSharedMemoryHandle().GetGUID(); if (shared_memory_guid.is_empty())
} guid = viz::GetSharedBitmapGUIDForTracing(resource.shared_bitmap_id);
break; break;
} }
DCHECK(!guid.empty()); DCHECK(!shared_memory_guid.is_empty() || !guid.empty());
const int kImportance = 2; const int kImportanceForInteral = 2;
const int kImportanceForExternal = 1;
int importance = resource.origin == viz::internal::Resource::INTERNAL
? kImportanceForInteral
: kImportanceForExternal;
if (!shared_memory_guid.is_empty()) { if (!shared_memory_guid.is_empty()) {
pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
kImportance); importance);
} else { } else {
pmd->CreateSharedGlobalAllocatorDump(guid); pmd->CreateSharedGlobalAllocatorDump(guid);
pmd->AddOwnershipEdge(dump->guid(), guid, kImportance); pmd->AddOwnershipEdge(dump->guid(), guid, importance);
} }
} }
......
...@@ -32,7 +32,8 @@ class ClientSharedBitmap : public SharedBitmap { ...@@ -32,7 +32,8 @@ class ClientSharedBitmap : public SharedBitmap {
id, id,
sequence_number), sequence_number),
shared_bitmap_allocation_notifier_( shared_bitmap_allocation_notifier_(
std::move(shared_bitmap_allocation_notifier)) {} std::move(shared_bitmap_allocation_notifier)),
tracing_id_(shared_memory->mapped_id()) {}
ClientSharedBitmap( ClientSharedBitmap(
scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr>
...@@ -51,17 +52,16 @@ class ClientSharedBitmap : public SharedBitmap { ...@@ -51,17 +52,16 @@ class ClientSharedBitmap : public SharedBitmap {
(*shared_bitmap_allocation_notifier_)->DidDeleteSharedBitmap(id()); (*shared_bitmap_allocation_notifier_)->DidDeleteSharedBitmap(id());
} }
// SharedBitmap: // SharedBitmap implementation.
base::SharedMemoryHandle GetSharedMemoryHandle() const override { base::UnguessableToken GetCrossProcessGUID() const override {
if (!shared_memory_holder_) return tracing_id_;
return base::SharedMemoryHandle();
return shared_memory_holder_->handle();
} }
private: private:
scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr>
shared_bitmap_allocation_notifier_; shared_bitmap_allocation_notifier_;
std::unique_ptr<base::SharedMemory> shared_memory_holder_; std::unique_ptr<base::SharedMemory> shared_memory_holder_;
base::UnguessableToken tracing_id_;
}; };
// Collect extra information for debugging bitmap creation failures. // Collect extra information for debugging bitmap creation failures.
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
namespace base { namespace base {
class SharedMemoryHandle; class UnguessableToken;
} }
namespace viz { namespace viz {
...@@ -40,16 +40,15 @@ class VIZ_COMMON_EXPORT SharedBitmap { ...@@ -40,16 +40,15 @@ class VIZ_COMMON_EXPORT SharedBitmap {
virtual ~SharedBitmap(); virtual ~SharedBitmap();
uint8_t* pixels() { return pixels_; } uint8_t* pixels() { return pixels_; }
const SharedBitmapId& id() { return id_; } const SharedBitmapId& id() { return id_; }
// The sequence number that ClientSharedBitmapManager assigned to this // The sequence number that ClientSharedBitmapManager assigned to this
// SharedBitmap. // SharedBitmap.
uint32_t sequence_number() const { return sequence_number_; } uint32_t sequence_number() const { return sequence_number_; }
// Returns the shared memory's handle when the back end is base::SharedMemory. // Returns the GUID for tracing when the SharedBitmap supports cross-process
// Otherwise, this returns an invalid handle. // use via shared memory. Otherwise, this returns empty.
virtual base::SharedMemoryHandle GetSharedMemoryHandle() const = 0; virtual base::UnguessableToken GetCrossProcessGUID() const = 0;
// Returns true if the size is valid and false otherwise. // Returns true if the size is valid and false otherwise.
static bool SizeInBytes(const gfx::Size& size, size_t* size_in_bytes); static bool SizeInBytes(const gfx::Size& size, size_t* size_in_bytes);
......
...@@ -22,7 +22,9 @@ namespace viz { ...@@ -22,7 +22,9 @@ namespace viz {
class BitmapData : public base::RefCountedThreadSafe<BitmapData> { class BitmapData : public base::RefCountedThreadSafe<BitmapData> {
public: public:
explicit BitmapData(size_t buffer_size) : buffer_size(buffer_size) {} explicit BitmapData(size_t buffer_size) : buffer_size(buffer_size) {}
// For shm allocated and shared from a client out-of-process.
std::unique_ptr<base::SharedMemory> memory; std::unique_ptr<base::SharedMemory> memory;
// For memory allocated by the ServerSharedBitmapManager for in-process.
std::unique_ptr<uint8_t[]> pixels; std::unique_ptr<uint8_t[]> pixels;
size_t buffer_size; size_t buffer_size;
...@@ -49,11 +51,13 @@ class ServerSharedBitmap : public SharedBitmap { ...@@ -49,11 +51,13 @@ class ServerSharedBitmap : public SharedBitmap {
manager_->FreeSharedMemoryFromMap(id()); manager_->FreeSharedMemoryFromMap(id());
} }
// SharedBitmap: // SharedBitmap implementation.
base::SharedMemoryHandle GetSharedMemoryHandle() const override { base::UnguessableToken GetCrossProcessGUID() const override {
if (!bitmap_data_->memory) if (!bitmap_data_->memory) {
return base::SharedMemoryHandle(); // Locally allocated for in-process use.
return bitmap_data_->memory->handle(); return {};
}
return bitmap_data_->memory->mapped_id();
} }
private: private:
...@@ -151,7 +155,8 @@ bool ServerSharedBitmapManager::ChildAllocatedSharedBitmapForTest( ...@@ -151,7 +155,8 @@ bool ServerSharedBitmapManager::ChildAllocatedSharedBitmapForTest(
const SharedBitmapId& id) { const SharedBitmapId& id) {
auto data = base::MakeRefCounted<BitmapData>(buffer_size); auto data = base::MakeRefCounted<BitmapData>(buffer_size);
data->memory = std::make_unique<base::SharedMemory>(memory_handle, false); data->memory = std::make_unique<base::SharedMemory>(memory_handle, false);
data->memory->Map(data->buffer_size); if (!data->memory->Map(data->buffer_size))
return false;
data->memory->Close(); data->memory->Close();
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
...@@ -172,30 +177,32 @@ bool ServerSharedBitmapManager::OnMemoryDump( ...@@ -172,30 +177,32 @@ bool ServerSharedBitmapManager::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd) { base::trace_event::ProcessMemoryDump* pmd) {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
for (const auto& bitmap : handle_map_) { for (const auto& pair : handle_map_) {
const SharedBitmapId& id = pair.first;
BitmapData* data = pair.second.get();
std::string dump_str = base::StringPrintf(
"sharedbitmap/%s", base::HexEncode(id.name, sizeof(id.name)).c_str());
base::trace_event::MemoryAllocatorDump* dump = base::trace_event::MemoryAllocatorDump* dump =
pmd->CreateAllocatorDump(base::StringPrintf( pmd->CreateAllocatorDump(dump_str);
"sharedbitmap/%s",
base::HexEncode(bitmap.first.name, sizeof(bitmap.first.name))
.c_str()));
if (!dump) if (!dump)
return false; return false;
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes, base::trace_event::MemoryAllocatorDump::kUnitsBytes,
bitmap.second->buffer_size); data->buffer_size);
if (bitmap.second->memory) { if (data->memory) {
base::UnguessableToken shared_memory_guid = // Resources from a client have shared memory, and we use the guid from
bitmap.second->memory->mapped_id(); // that.
if (!shared_memory_guid.is_empty()) { base::UnguessableToken shared_memory_guid = data->memory->mapped_id();
pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, DCHECK(!shared_memory_guid.is_empty());
0 /* importance*/); pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
} 0 /* importance*/);
} else { } else {
// Generate a global GUID used to share this allocation with renderer // Otherwise, resources were allocated locally for in-process use, and
// processes. // there is no shared memory. Instead make up a GUID for them.
auto guid = GetSharedBitmapGUIDForTracing(bitmap.first); auto guid = GetSharedBitmapGUIDForTracing(id);
pmd->CreateSharedGlobalAllocatorDump(guid); pmd->CreateSharedGlobalAllocatorDump(guid);
pmd->AddOwnershipEdge(dump->guid(), guid); pmd->AddOwnershipEdge(dump->guid(), guid);
} }
......
...@@ -160,13 +160,14 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) { ...@@ -160,13 +160,14 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) {
size_t size_in_bytes; size_t size_in_bytes;
EXPECT_TRUE(SharedBitmap::SizeInBytes(bitmap_size, &size_in_bytes)); EXPECT_TRUE(SharedBitmap::SizeInBytes(bitmap_size, &size_in_bytes));
std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory()); std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory());
auto shared_memory_guid = bitmap->handle().GetGUID();
bitmap->CreateAndMapAnonymous(size_in_bytes); bitmap->CreateAndMapAnonymous(size_in_bytes);
memset(bitmap->memory(), 0xff, size_in_bytes); memset(bitmap->memory(), 0xff, size_in_bytes);
SharedBitmapId id = SharedBitmap::GenerateId(); base::UnguessableToken shared_memory_guid = bitmap->handle().GetGUID();
EXPECT_FALSE(shared_memory_guid.is_empty());
SharedBitmapAllocationNotifierImpl notifier(manager()); SharedBitmapAllocationNotifierImpl notifier(manager());
SharedBitmapId id = SharedBitmap::GenerateId();
base::SharedMemoryHandle handle = bitmap->handle().Duplicate(); base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle( mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, size_in_bytes, handle, size_in_bytes,
...@@ -175,8 +176,7 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) { ...@@ -175,8 +176,7 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) {
std::unique_ptr<SharedBitmap> shared_bitmap; std::unique_ptr<SharedBitmap> shared_bitmap;
shared_bitmap = manager()->GetSharedBitmapFromId(gfx::Size(1, 1), id); shared_bitmap = manager()->GetSharedBitmapFromId(gfx::Size(1, 1), id);
EXPECT_EQ(shared_bitmap->GetSharedMemoryHandle().GetGUID(), EXPECT_EQ(shared_bitmap->GetCrossProcessGUID(), shared_memory_guid);
shared_memory_guid);
notifier.DidDeleteSharedBitmap(id); notifier.DidDeleteSharedBitmap(id);
} }
......
...@@ -27,8 +27,8 @@ class OwnedSharedBitmap : public SharedBitmap { ...@@ -27,8 +27,8 @@ class OwnedSharedBitmap : public SharedBitmap {
~OwnedSharedBitmap() override = default; ~OwnedSharedBitmap() override = default;
// SharedBitmap: // SharedBitmap:
base::SharedMemoryHandle GetSharedMemoryHandle() const override { base::UnguessableToken GetCrossProcessGUID() const override {
return shared_memory_->handle(); return shared_memory_->mapped_id();
} }
private: private:
...@@ -37,13 +37,19 @@ class OwnedSharedBitmap : public SharedBitmap { ...@@ -37,13 +37,19 @@ class OwnedSharedBitmap : public SharedBitmap {
class UnownedSharedBitmap : public SharedBitmap { class UnownedSharedBitmap : public SharedBitmap {
public: public:
UnownedSharedBitmap(uint8_t* pixels, const SharedBitmapId& id) UnownedSharedBitmap(uint8_t* pixels,
: SharedBitmap(pixels, id, g_next_sequence_number++) {} const SharedBitmapId& id,
const base::UnguessableToken& tracing_id)
: SharedBitmap(pixels, id, g_next_sequence_number++),
tracing_id_(tracing_id) {}
// SharedBitmap: // SharedBitmap:
base::SharedMemoryHandle GetSharedMemoryHandle() const override { base::UnguessableToken GetCrossProcessGUID() const override {
return base::SharedMemoryHandle(); return tracing_id_;
} }
private:
base::UnguessableToken tracing_id_;
}; };
} // namespace } // namespace
...@@ -69,7 +75,8 @@ std::unique_ptr<SharedBitmap> TestSharedBitmapManager::GetSharedBitmapFromId( ...@@ -69,7 +75,8 @@ std::unique_ptr<SharedBitmap> TestSharedBitmapManager::GetSharedBitmapFromId(
if (bitmap_map_.find(id) == bitmap_map_.end()) if (bitmap_map_.find(id) == bitmap_map_.end())
return nullptr; return nullptr;
uint8_t* pixels = static_cast<uint8_t*>(bitmap_map_[id]->memory()); uint8_t* pixels = static_cast<uint8_t*>(bitmap_map_[id]->memory());
return std::make_unique<UnownedSharedBitmap>(pixels, id); const base::UnguessableToken& tracing_id = bitmap_map_[id]->mapped_id();
return std::make_unique<UnownedSharedBitmap>(pixels, id, tracing_id);
} }
bool TestSharedBitmapManager::ChildAllocatedSharedBitmap( bool TestSharedBitmapManager::ChildAllocatedSharedBitmap(
......
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