blob: 7faae9c3f8b4645215ad385788499c551840d8fe [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_THREAD_STATE_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_THREAD_STATE_TRACKER_H_
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/destructible.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
namespace trace_processor {
// Responsible for filling the Thread State table by analysing sched switches,
// waking events and blocking reasons.
class ThreadStateTracker : public Destructible {
public:
explicit ThreadStateTracker(TraceStorage*);
ThreadStateTracker(const ThreadStateTracker&) = delete;
ThreadStateTracker& operator=(const ThreadStateTracker&) = delete;
~ThreadStateTracker() override;
static ThreadStateTracker* GetOrCreate(TraceProcessorContext* context) {
if (!context->thread_state_tracker) {
context->thread_state_tracker.reset(
new ThreadStateTracker(context->storage.get()));
}
return static_cast<ThreadStateTracker*>(
context->thread_state_tracker.get());
}
// Will cause addition of state and update of the previous state for next_utid
// and prev_utid.
void PushSchedSwitchEvent(int64_t event_ts,
uint32_t cpu,
UniqueTid prev_utid,
StringId prev_state,
UniqueTid next_utid);
// Will add a runnable state for utid and close the previously blocked one.
void PushWakingEvent(int64_t event_ts, UniqueTid utid, UniqueTid waker_utid);
// Will add a runnable state for utid. For a new task there are no previous
// states to close.
void PushNewTaskEvent(int64_t event_ts, UniqueTid utid, UniqueTid waker_utid);
// Updates the current blocked state for utid with blocked reason.
void PushBlockedReason(UniqueTid utid,
std::optional<bool> io_wait,
std::optional<StringId> blocked_function);
private:
void AddOpenState(int64_t ts,
UniqueTid utid,
StringId state,
std::optional<uint32_t> cpu = std::nullopt,
std::optional<UniqueTid> waker_utid = std::nullopt);
void ClosePendingState(int64_t end_ts, UniqueTid utid, bool data_loss);
bool IsRunning(StringId state);
bool IsBlocked(StringId state);
bool IsRunnable(StringId state);
bool HasPreviousRowNumbersForUtid(UniqueTid utid) {
return utid < prev_row_numbers_for_thread_.size() &&
prev_row_numbers_for_thread_[utid].has_value();
}
tables::ThreadStateTable::RowReference RowNumToRef(
tables::ThreadStateTable::RowNumber row_number) {
return row_number.ToRowReference(storage_->mutable_thread_state_table());
}
TraceStorage* const storage_;
// Strings
StringId running_string_id_;
StringId runnable_string_id_;
struct RelatedRows {
std::optional<tables::ThreadStateTable::RowNumber> last_blocked_row;
tables::ThreadStateTable::RowNumber last_row;
};
std::vector<std::optional<RelatedRows>> prev_row_numbers_for_thread_;
};
} // namespace trace_processor
} // namespace perfetto
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_THREAD_STATE_TRACKER_H_