blob: c9bfa57a30b2864ce40705e575f23638ca2c9dc6 [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;
47 // TODO(b/160016498): Find a better way to wait for traced
48 // Sleep for 30 seconds to make sure the data source is registered only
49 // after traced starts.
50 sleep(30);
51 perfetto::Tracing::Initialize(args);
52 registerDataSource();
53 std::thread tracerThread(&GpuMemTracer::threadLoop, this);
54 pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread");
55 tracerThread.detach();
56}
57
58void GpuMemTracer::registerDataSource() {
59 perfetto::DataSourceDescriptor dsd;
60 dsd.set_name(kGpuMemDataSource);
61 GpuMemDataSource::Register(dsd);
62}
63
64void GpuMemTracer::threadLoop() {
65 while (true) {
66 {
67 std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
68 while (!sTraceStarted) {
69 sCondition.wait(lock);
70 }
71 }
72 traceInitialCounters();
73 {
74 std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex);
75 sTraceStarted = false;
76 }
77 }
78}
79
80void GpuMemTracer::traceInitialCounters() {
81 if (!mGpuMem->isInitialized()) {
82 // This should never happen.
83 ALOGE("Cannot trace without GpuMem initialization");
84 return;
85 }
86 mGpuMem->traceGpuMemTotals([](uint32_t gpuId, uint32_t pid, uint64_t size) {
87 GpuMemDataSource::Trace([&](GpuMemDataSource::TraceContext ctx) {
88 auto packet = ctx.NewTracePacket();
89 packet->set_timestamp(systemTime());
90 auto* event = packet->set_gpu_mem_total_event();
91 event->set_gpu_id(gpuId);
92 event->set_pid(pid);
93 event->set_size(size);
94 });
95 });
96 // Flush the TraceContext. The last packet in the above loop will go
97 // missing without this flush.
98 GpuMemDataSource::Trace([](GpuMemDataSource::TraceContext ctx) { ctx.Flush(); });
99}
100
101} // namespace android