1 /* 2 * Copyright (C) 2019 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 #include "src/trace_processor/clock_tracker.h" 18 19 #include <algorithm> 20 21 #include "perfetto/base/logging.h" 22 #include "src/trace_processor/trace_processor_context.h" 23 #include "src/trace_processor/trace_storage.h" 24 25 namespace perfetto { 26 namespace trace_processor { 27 28 ClockTracker::ClockTracker(TraceProcessorContext* ctx) : context_(ctx) {} 29 ClockTracker::~ClockTracker() = default; 30 31 void ClockTracker::SyncClocks(ClockDomain domain, 32 int64_t clock_time_ns, 33 int64_t trace_time_ns) { 34 ClockSnapshotVector& snapshots = clocks_[domain]; 35 if (!snapshots.empty()) { 36 // The trace clock (typically CLOCK_BOOTTIME) must be monotonic. 37 if (trace_time_ns <= snapshots.back().trace_time_ns) { 38 PERFETTO_ELOG("Trace time in clock snapshot is moving backwards"); 39 context_->storage->IncrementStats(stats::clock_snapshot_not_monotonic); 40 return; 41 } 42 if (clock_time_ns <= snapshots.back().clock_time_ns) { 43 if (domain == ClockDomain::kMonotonic) { 44 PERFETTO_ELOG("CLOCK_MONOTONIC in clock snapshot is moving backwards"); 45 context_->storage->IncrementStats(stats::clock_snapshot_not_monotonic); 46 return; 47 } 48 // This can happen in other clocks, for instance CLOCK_REALTIME if 49 // adjusting the timezone or during daylight saving. In this case the most 50 // reasonable thing we can do is obliterating all the past snapshots. 51 while (!snapshots.empty() && 52 snapshots.back().clock_time_ns >= clock_time_ns) { 53 snapshots.pop_back(); 54 } 55 } 56 } 57 snapshots.emplace_back(ClockSnapshot{clock_time_ns, trace_time_ns}); 58 } 59 60 base::Optional<int64_t> ClockTracker::ToTraceTime(ClockDomain domain, 61 int64_t clock_time_ns) { 62 ClockSnapshotVector& snapshots = clocks_[domain]; 63 if (snapshots.empty()) { 64 context_->storage->IncrementStats(stats::clock_sync_failure); 65 return base::nullopt; 66 } 67 static auto comparator = [](int64_t lhs, const ClockSnapshot& rhs) { 68 return lhs < rhs.clock_time_ns; 69 }; 70 auto it = std::upper_bound(snapshots.begin(), snapshots.end(), clock_time_ns, 71 comparator); 72 if (it != snapshots.begin()) 73 it--; 74 return it->trace_time_ns + (clock_time_ns - it->clock_time_ns); 75 } 76 77 } // namespace trace_processor 78 } // namespace perfetto 79