/*
 * 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_
