blob: 218256b9dc466dee7c3e71cc0eef7f86714ce289 [file] [log] [blame]
/*
* Copyright (C) 2019 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_SYSCALLS_SYSCALL_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_
#include <limits>
#include <tuple>
#include "perfetto/ext/base/string_view.h"
#include "src/kernel_utils/syscall_table.h"
#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_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 {
class SyscallTracker : public Destructible {
public:
SyscallTracker(const SyscallTracker&) = delete;
SyscallTracker& operator=(const SyscallTracker&) = delete;
~SyscallTracker() override;
static SyscallTracker* GetOrCreate(TraceProcessorContext* context) {
if (!context->syscall_tracker) {
context->syscall_tracker.reset(new SyscallTracker(context));
}
return static_cast<SyscallTracker*>(context->syscall_tracker.get());
}
void SetArchitecture(Architecture architecture);
void Enter(int64_t ts,
UniqueTid utid,
uint32_t syscall_num,
EventTracker::SetArgsCallback args_callback =
EventTracker::SetArgsCallback()) {
StringId name = SyscallNumberToStringId(syscall_num);
if (name.is_null())
return;
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */, name,
args_callback);
if (name == sys_write_string_id_) {
if (utid >= in_sys_write_.size())
in_sys_write_.Resize(utid + 1);
in_sys_write_.Set(utid);
}
}
void Exit(int64_t ts,
UniqueTid utid,
uint32_t syscall_num,
EventTracker::SetArgsCallback args_callback =
EventTracker::SetArgsCallback()) {
StringId name = SyscallNumberToStringId(syscall_num);
if (name.is_null())
return;
if (name == sys_write_string_id_) {
if (utid >= in_sys_write_.size())
in_sys_write_.Resize(utid + 1);
// Either seeing an exit event without the corresponding entry at the
// start of the trace, or the slice was closed by
// MaybeTruncateOngoingWriteSlice.
if (!in_sys_write_.IsSet(utid))
return;
in_sys_write_.Clear(utid);
}
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */, name,
args_callback);
}
// Resolves slice nesting issues when the sys_write is for an atrace slice on
// android. See callsite for details.
void MaybeTruncateOngoingWriteSlice(int64_t ts, UniqueTid utid) {
if (utid >= in_sys_write_.size())
in_sys_write_.Resize(utid + 1);
if (!in_sys_write_.IsSet(utid))
return;
in_sys_write_.Clear(utid);
context_->storage->IncrementStats(stats::truncated_sys_write_duration);
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */,
sys_write_string_id_);
}
private:
explicit SyscallTracker(TraceProcessorContext*);
TraceProcessorContext* const context_;
inline StringId SyscallNumberToStringId(uint32_t syscall_num) {
if (syscall_num > kMaxSyscalls)
return kNullStringId;
return arch_syscall_to_string_id_[syscall_num];
}
// This is table from platform specific syscall number directly to
// the relevant StringId (this avoids having to always do two conversions).
std::array<StringId, kMaxSyscalls> arch_syscall_to_string_id_{};
StringId sys_write_string_id_ = std::numeric_limits<StringId>::max();
// UniqueTids currently in a sys_write syscall.
BitVector in_sys_write_;
};
} // namespace trace_processor
} // namespace perfetto
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_