blob: 9e01a641fd0a5e1293a2beccde40419d198a83fd [file] [log] [blame]
Adithya Srinivasanb9f62d62020-06-18 11:28:12 -07001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "GpuMemTracer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "tracing/GpuMemTracer.h"
22
23#include <gpumem/GpuMem.h>
24#include <perfetto/trace/android/gpu_mem_event.pbzero.h>
25#include <unistd.h>
26#include <utils/Timers.h>
27
28#include <algorithm>
29#include <thread>
30
31PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::GpuMemTracer::GpuMemDataSource);
32
33namespace android {
34
35std::mutex GpuMemTracer::sTraceMutex;
36std::condition_variable GpuMemTracer::sCondition;
37bool GpuMemTracer::sTraceStarted;
38
39void GpuMemTracer::initialize(std::shared_ptr<GpuMem> gpuMem) {
40 if (!gpuMem->isInitialized()) {
41 ALOGE("Cannot initialize GpuMemTracer before GpuMem");
42 return;
43 }
44 mGpuMem = gpuMem;
45 perfetto::TracingInitArgs args;
46 args.backends = perfetto::kSystemBackend;
Adithya Srinivasanb9f62d62020-06-18 11:28:12 -070047 perfetto::Tracing::Initialize(args);
48 registerDataSource();
49 std::thread tracerThread(&GpuMemTracer::threadLoop, this);
50 pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread");
51 tracerThread.detach();
52}
53
54void GpuMemTracer::registerDataSource() {
55 perfetto::DataSourceDescriptor dsd;
56 dsd.set_name(kGpuMemDataSource);
57 GpuMemDataSource::Register(dsd);
58}
59
60void GpuMemTracer::threadLoop() {
61 while (true) {
62 {
63 std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
64 while (!sTraceStarted) {
65 sCondition.wait(lock);
66 }
67 }
68 traceInitialCounters();
69 {
70 std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex);
71 sTraceStarted = false;
72 }
73 }
74}
75
76void GpuMemTracer::traceInitialCounters() {
77 if (!mGpuMem->isInitialized()) {
78 // This should never happen.
79 ALOGE("Cannot trace without GpuMem initialization");
80 return;
81 }
82 mGpuMem->traceGpuMemTotals([](uint32_t gpuId, uint32_t pid, uint64_t size) {
83 GpuMemDataSource::Trace([&](GpuMemDataSource::TraceContext ctx) {
84 auto packet = ctx.NewTracePacket();
85 packet->set_timestamp(systemTime());
86 auto* event = packet->set_gpu_mem_total_event();
87 event->set_gpu_id(gpuId);
88 event->set_pid(pid);
89 event->set_size(size);
90 });
91 });
92 // Flush the TraceContext. The last packet in the above loop will go
93 // missing without this flush.
94 GpuMemDataSource::Trace([](GpuMemDataSource::TraceContext ctx) { ctx.Flush(); });
95}
96
97} // namespace android