1 /* 2 * Copyright 2022 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 #pragma once 18 19 #include <bpf/BpfMap.h> 20 #include <stats_pull_atom_callback.h> 21 #include <utils/Mutex.h> 22 #include <utils/String16.h> 23 #include <utils/Vector.h> 24 25 #include <condition_variable> 26 #include <cstdint> 27 #include <functional> 28 #include <thread> 29 30 #include "gpuwork/gpu_work.h" 31 32 namespace android { 33 namespace gpuwork { 34 35 class GpuWork { 36 public: 37 using Uid = uint32_t; 38 39 GpuWork() = default; 40 ~GpuWork(); 41 42 void initialize(); 43 44 // Dumps the GPU work information. 45 void dump(const Vector<String16>& args, std::string* result); 46 47 private: 48 // Attaches tracepoint |tracepoint_group|/|tracepoint_name| to BPF program at path 49 // |program_path|. The tracepoint is also enabled. 50 static bool attachTracepoint(const char* program_path, const char* tracepoint_group, 51 const char* tracepoint_name); 52 53 // Native atom puller callback registered in statsd. 54 static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, 55 AStatsEventList* data, 56 void* cookie); 57 58 AStatsManager_PullAtomCallbackReturn pullWorkAtoms(AStatsEventList* data); 59 60 // Periodically calls |clearMapIfNeeded| to clear the |mGpuWorkMap| map, if 61 // needed. 62 // 63 // Thread safety analysis is skipped because we need to use 64 // |std::unique_lock|, which is not currently supported by thread safety 65 // analysis. 66 void periodicallyClearMap() NO_THREAD_SAFETY_ANALYSIS; 67 68 // Checks whether the |mGpuWorkMap| map is nearly full and, if so, clears 69 // it. 70 void clearMapIfNeeded() REQUIRES(mMutex); 71 72 // Clears the |mGpuWorkMap| map. 73 void clearMap() REQUIRES(mMutex); 74 75 // Waits for required permissions to become set. This seems to be needed 76 // because platform service permissions might not be set when a service 77 // first starts. See b/214085769. 78 void waitForPermissions(); 79 80 // Indicates whether our eBPF components have been initialized. 81 std::atomic<bool> mInitialized = false; 82 83 // A thread that periodically checks whether |mGpuWorkMap| is nearly full 84 // and, if so, clears it. 85 std::thread mMapClearerThread; 86 87 // Mutex for |mGpuWorkMap| and a few other fields. 88 std::mutex mMutex; 89 90 // BPF map for per-UID GPU work. 91 bpf::BpfMap<GpuIdUid, UidTrackingInfo> mGpuWorkMap GUARDED_BY(mMutex); 92 93 // BPF map containing a single element for global data. 94 bpf::BpfMap<uint32_t, GlobalData> mGpuWorkGlobalDataMap GUARDED_BY(mMutex); 95 96 // When true, we are being destructed, so |mMapClearerThread| should stop. 97 bool mIsTerminating GUARDED_BY(mMutex); 98 99 // A condition variable for |mIsTerminating|. 100 std::condition_variable mIsTerminatingConditionVariable GUARDED_BY(mMutex); 101 102 // 30 second timeout for trying to attach a BPF program to a tracepoint. 103 static constexpr int kGpuWaitTimeoutSeconds = 30; 104 105 // The wait duration for the map clearer thread; the thread checks the map 106 // every ~1 hour. 107 static constexpr uint32_t kMapClearerWaitDurationSeconds = 60 * 60; 108 109 // Whether our |pullAtomCallback| function is registered. 110 bool mStatsdRegistered GUARDED_BY(mMutex) = false; 111 112 // The number of randomly chosen (i.e. sampled) UIDs to log stats for. 113 static constexpr size_t kNumSampledUids = 10; 114 115 // A "large" number of GPUs. If we observe more GPUs than this limit then 116 // we reduce the amount of stats we log. 117 static constexpr size_t kNumGpusSoftLimit = 4; 118 119 // A "very large" number of GPUs. If we observe more GPUs than this limit 120 // then we don't log any stats. 121 static constexpr size_t kNumGpusHardLimit = 32; 122 123 // The minimum GPU time needed to actually log stats for a UID. 124 static constexpr uint64_t kMinGpuTimeNanoseconds = 30U * 1000000000U; // 30 seconds. 125 126 // The previous time point at which |mGpuWorkMap| was cleared. 127 std::chrono::steady_clock::time_point mPreviousMapClearTimePoint GUARDED_BY(mMutex); 128 129 // Permission to register a statsd puller. 130 static constexpr char16_t kPermissionRegisterStatsPullAtom[] = 131 u"android.permission.REGISTER_STATS_PULL_ATOM"; 132 133 // Time limit for waiting for permissions. 134 static constexpr int kPermissionsWaitTimeoutSeconds = 30; 135 }; 136 137 } // namespace gpuwork 138 } // namespace android 139