/*
 * Copyright (C) 2018 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_PROFILING_MEMORY_UNWINDING_H_
#define SRC_PROFILING_MEMORY_UNWINDING_H_

#include <unwindstack/Regs.h>

#include "perfetto/base/time.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "src/profiling/common/unwind_support.h"
#include "src/profiling/memory/bookkeeping.h"
#include "src/profiling/memory/unwound_messages.h"
#include "src/profiling/memory/wire_protocol.h"

namespace perfetto {
namespace profiling {

std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData(
    unwindstack::ArchEnum arch,
    void* raw_data);

bool DoUnwind(WireMessage*, UnwindingMetadata* metadata, AllocRecord* out);

// AllocRecords are expensive to construct and destruct. We have seen up to
// 10 % of total CPU of heapprofd being used to destruct them. That is why
// we re-use them to cut CPU usage significantly.
class AllocRecordArena {
 public:
  AllocRecordArena() : alloc_records_mutex_(new std::mutex()) {}

  void ReturnAllocRecord(std::unique_ptr<AllocRecord>);
  std::unique_ptr<AllocRecord> BorrowAllocRecord();

  void Enable();
  void Disable();

 private:
  std::unique_ptr<std::mutex> alloc_records_mutex_;
  std::vector<std::unique_ptr<AllocRecord>> alloc_records_;
  bool enabled_ = true;
};

class UnwindingWorker : public base::UnixSocket::EventListener {
 public:
  class Delegate {
   public:
    virtual void PostAllocRecord(UnwindingWorker*,
                                 std::unique_ptr<AllocRecord>) = 0;
    virtual void PostFreeRecord(UnwindingWorker*, std::vector<FreeRecord>) = 0;
    virtual void PostHeapNameRecord(UnwindingWorker*, HeapNameRecord rec) = 0;
    virtual void PostSocketDisconnected(UnwindingWorker*,
                                        DataSourceInstanceID,
                                        pid_t pid,
                                        SharedRingBuffer::Stats stats) = 0;
    virtual void PostDrainDone(UnwindingWorker*, DataSourceInstanceID) = 0;
    virtual ~Delegate();
  };

  struct HandoffData {
    DataSourceInstanceID data_source_instance_id;
    base::UnixSocketRaw sock;
    base::ScopedFile maps_fd;
    base::ScopedFile mem_fd;
    SharedRingBuffer shmem;
    ClientConfiguration client_config;
    bool stream_allocations;
  };

  UnwindingWorker(Delegate* delegate, base::ThreadTaskRunner thread_task_runner)
      : delegate_(delegate),
        thread_task_runner_(std::move(thread_task_runner)) {}

  ~UnwindingWorker() override;
  UnwindingWorker(UnwindingWorker&&) = default;

  // Public API safe to call from other threads.
  void PostDisconnectSocket(pid_t pid);
  void PostPurgeProcess(pid_t pid);
  void PostHandoffSocket(HandoffData);
  void PostDrainFree(DataSourceInstanceID, pid_t pid);
  void ReturnAllocRecord(std::unique_ptr<AllocRecord> record) {
    alloc_record_arena_.ReturnAllocRecord(std::move(record));
  }

  // Implementation of UnixSocket::EventListener.
  // Do not call explicitly.
  void OnDisconnect(base::UnixSocket* self) override;
  void OnNewIncomingConnection(base::UnixSocket*,
                               std::unique_ptr<base::UnixSocket>) override {
    PERFETTO_DFATAL_OR_ELOG("This should not happen.");
  }
  void OnDataAvailable(base::UnixSocket* self) override;

 public:
  // public for testing/fuzzer
  struct ClientData {
    DataSourceInstanceID data_source_instance_id;
    std::unique_ptr<base::UnixSocket> sock;
    UnwindingMetadata metadata;
    SharedRingBuffer shmem;
    ClientConfiguration client_config;
    bool stream_allocations = false;
    size_t drain_bytes = 0;
    std::vector<FreeRecord> free_records;
  };

  // public for testing/fuzzing
  static void HandleBuffer(UnwindingWorker* self,
                           AllocRecordArena* alloc_record_arena,
                           const SharedRingBuffer::Buffer& buf,
                           ClientData* client_data,
                           pid_t peer_pid,
                           Delegate* delegate);

 private:
  void HandleHandoffSocket(HandoffData data);
  void HandleDisconnectSocket(pid_t pid);
  void HandleDrainFree(DataSourceInstanceID, pid_t);
  void RemoveClientData(
      std::map<pid_t, ClientData>::iterator client_data_iterator);
  void FinishDisconnect(
      std::map<pid_t, ClientData>::iterator client_data_iterator);
  std::unique_ptr<AllocRecord> BorrowAllocRecord();

  struct ReadAndUnwindBatchResult {
    enum class Status {
      kHasMore,
      kReadSome,
      kReadNone,
    };
    size_t bytes_read = 0;
    Status status;
  };
  ReadAndUnwindBatchResult ReadAndUnwindBatch(ClientData* client_data);
  void BatchUnwindJob(pid_t);
  void DrainJob(pid_t);

  AllocRecordArena alloc_record_arena_;
  std::map<pid_t, ClientData> client_data_;
  Delegate* delegate_;

  // Task runner with a dedicated thread. Keep last. By destroying this task
  // runner first, we ensure that the UnwindingWorker is not active while the
  // rest of its state is being destroyed. Additionally this ensures that the
  // destructing thread sees a consistent view of the memory due to the
  // ThreadTaskRunner's destructor joining a thread.
  base::ThreadTaskRunner thread_task_runner_;
};

}  // namespace profiling
}  // namespace perfetto

#endif  // SRC_PROFILING_MEMORY_UNWINDING_H_
