xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/thread_state_tracker.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 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 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_THREAD_STATE_TRACKER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_THREAD_STATE_TRACKER_H_
19 
20 #include "src/trace_processor/storage/trace_storage.h"
21 #include "src/trace_processor/types/destructible.h"
22 #include "src/trace_processor/types/trace_processor_context.h"
23 
24 namespace perfetto {
25 namespace trace_processor {
26 
27 // Responsible for filling the Thread State table by analysing sched switches,
28 // waking events and blocking reasons.
29 class ThreadStateTracker : public Destructible {
30  public:
31   explicit ThreadStateTracker(TraceProcessorContext*);
32   ThreadStateTracker(const ThreadStateTracker&) = delete;
33   ThreadStateTracker& operator=(const ThreadStateTracker&) = delete;
34   ~ThreadStateTracker() override;
GetOrCreate(TraceProcessorContext * context)35   static ThreadStateTracker* GetOrCreate(TraceProcessorContext* context) {
36     if (!context->thread_state_tracker) {
37       context->thread_state_tracker.reset(new ThreadStateTracker(context));
38     }
39     return static_cast<ThreadStateTracker*>(
40         context->thread_state_tracker.get());
41   }
42 
43   // Will cause addition of state and update of the previous state for next_utid
44   // and prev_utid.
45   void PushSchedSwitchEvent(int64_t event_ts,
46                             uint32_t cpu,
47                             UniqueTid prev_utid,
48                             StringId prev_state,
49                             UniqueTid next_utid);
50 
51   // Will add a runnable state for utid and close the previously blocked one.
52   void PushWakingEvent(int64_t event_ts,
53                        UniqueTid utid,
54                        UniqueTid waker_utid,
55                        std::optional<uint16_t> common_flags = std::nullopt);
56 
57   // Will add a runnable state for utid. For a new task there are no previous
58   // states to close.
59   void PushNewTaskEvent(int64_t event_ts, UniqueTid utid, UniqueTid waker_utid);
60 
61   // Updates the current blocked state for utid with blocked reason.
62   void PushBlockedReason(UniqueTid utid,
63                          std::optional<bool> io_wait,
64                          std::optional<StringId> blocked_function);
65 
66  private:
67   void AddOpenState(int64_t ts,
68                     UniqueTid utid,
69                     StringId state,
70                     std::optional<uint16_t> cpu = std::nullopt,
71                     std::optional<UniqueTid> waker_utid = std::nullopt,
72                     std::optional<uint16_t> common_flags = std::nullopt);
73   void ClosePendingState(int64_t end_ts, UniqueTid utid, bool data_loss);
74 
75   uint32_t CommonFlagsToIrqContext(uint32_t common_flags);
76 
77   bool IsRunning(StringId state);
78   bool IsBlocked(StringId state);
79   bool IsRunnable(StringId state);
80 
HasPreviousRowNumbersForUtid(UniqueTid utid)81   bool HasPreviousRowNumbersForUtid(UniqueTid utid) {
82     return utid < prev_row_numbers_for_thread_.size() &&
83            prev_row_numbers_for_thread_[utid].has_value();
84   }
85 
RowNumToRef(tables::ThreadStateTable::RowNumber row_number)86   tables::ThreadStateTable::RowReference RowNumToRef(
87       tables::ThreadStateTable::RowNumber row_number) {
88     return row_number.ToRowReference(storage_->mutable_thread_state_table());
89   }
90 
91   TraceStorage* const storage_;
92   TraceProcessorContext* const context_;
93 
94   // Strings
95   StringId running_string_id_;
96   StringId runnable_string_id_;
97 
98   struct RelatedRows {
99     std::optional<tables::ThreadStateTable::RowNumber> last_blocked_row;
100     tables::ThreadStateTable::RowNumber last_row;
101   };
102 
103   std::vector<std::optional<RelatedRows>> prev_row_numbers_for_thread_;
104 };
105 }  // namespace trace_processor
106 }  // namespace perfetto
107 
108 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_THREAD_STATE_TRACKER_H_
109