• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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