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 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_ 19 20 #include <limits> 21 #include <tuple> 22 23 #include "perfetto/ext/base/string_view.h" 24 #include "src/kernel_utils/syscall_table.h" 25 #include "src/trace_processor/containers/bit_vector.h" 26 #include "src/trace_processor/importers/common/event_tracker.h" 27 #include "src/trace_processor/importers/common/slice_tracker.h" 28 #include "src/trace_processor/importers/common/track_tracker.h" 29 #include "src/trace_processor/storage/trace_storage.h" 30 #include "src/trace_processor/types/destructible.h" 31 #include "src/trace_processor/types/trace_processor_context.h" 32 33 namespace perfetto { 34 namespace trace_processor { 35 36 class SyscallTracker : public Destructible { 37 public: 38 SyscallTracker(const SyscallTracker&) = delete; 39 SyscallTracker& operator=(const SyscallTracker&) = delete; 40 ~SyscallTracker() override; GetOrCreate(TraceProcessorContext * context)41 static SyscallTracker* GetOrCreate(TraceProcessorContext* context) { 42 if (!context->syscall_tracker) { 43 context->syscall_tracker.reset(new SyscallTracker(context)); 44 } 45 return static_cast<SyscallTracker*>(context->syscall_tracker.get()); 46 } 47 48 void SetArchitecture(Architecture architecture); 49 50 void Enter(int64_t ts, 51 UniqueTid utid, 52 uint32_t syscall_num, 53 EventTracker::SetArgsCallback args_callback = 54 EventTracker::SetArgsCallback()) { 55 StringId name = SyscallNumberToStringId(syscall_num); 56 if (name.is_null()) 57 return; 58 59 TrackId track_id = context_->track_tracker->InternThreadTrack(utid); 60 context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */, name, 61 args_callback); 62 63 if (name == sys_write_string_id_) { 64 if (utid >= in_sys_write_.size()) 65 in_sys_write_.Resize(utid + 1); 66 67 in_sys_write_.Set(utid); 68 } 69 } 70 71 void Exit(int64_t ts, 72 UniqueTid utid, 73 uint32_t syscall_num, 74 EventTracker::SetArgsCallback args_callback = 75 EventTracker::SetArgsCallback()) { 76 StringId name = SyscallNumberToStringId(syscall_num); 77 if (name.is_null()) 78 return; 79 80 if (name == sys_write_string_id_) { 81 if (utid >= in_sys_write_.size()) 82 in_sys_write_.Resize(utid + 1); 83 // Either seeing an exit event without the corresponding entry at the 84 // start of the trace, or the slice was closed by 85 // MaybeTruncateOngoingWriteSlice. 86 if (!in_sys_write_.IsSet(utid)) 87 return; 88 in_sys_write_.Clear(utid); 89 } 90 91 TrackId track_id = context_->track_tracker->InternThreadTrack(utid); 92 context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */, name, 93 args_callback); 94 } 95 96 // Resolves slice nesting issues when the sys_write is for an atrace slice on 97 // android. See callsite for details. MaybeTruncateOngoingWriteSlice(int64_t ts,UniqueTid utid)98 void MaybeTruncateOngoingWriteSlice(int64_t ts, UniqueTid utid) { 99 if (utid >= in_sys_write_.size()) 100 in_sys_write_.Resize(utid + 1); 101 102 if (!in_sys_write_.IsSet(utid)) 103 return; 104 in_sys_write_.Clear(utid); 105 context_->storage->IncrementStats(stats::truncated_sys_write_duration); 106 107 TrackId track_id = context_->track_tracker->InternThreadTrack(utid); 108 context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */, 109 sys_write_string_id_); 110 } 111 112 private: 113 explicit SyscallTracker(TraceProcessorContext*); 114 115 TraceProcessorContext* const context_; 116 SyscallNumberToStringId(uint32_t syscall_num)117 inline StringId SyscallNumberToStringId(uint32_t syscall_num) { 118 if (syscall_num > kMaxSyscalls) 119 return kNullStringId; 120 return arch_syscall_to_string_id_[syscall_num]; 121 } 122 123 // This is table from platform specific syscall number directly to 124 // the relevant StringId (this avoids having to always do two conversions). 125 std::array<StringId, kMaxSyscalls> arch_syscall_to_string_id_{}; 126 StringId sys_write_string_id_ = std::numeric_limits<StringId>::max(); 127 // UniqueTids currently in a sys_write syscall. 128 BitVector in_sys_write_; 129 }; 130 131 } // namespace trace_processor 132 } // namespace perfetto 133 134 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_ 135