OSDN Git Service

Implement simpleperf list subcommand.
authorYabin Cui <yabinc@google.com>
Thu, 16 Apr 2015 22:26:31 +0000 (15:26 -0700)
committerYabin Cui <yabinc@google.com>
Sat, 18 Apr 2015 20:58:37 +0000 (13:58 -0700)
simpleperf is used to replace linux/tools/perf. And This CL implements
the list subcommand of it.

Change-Id: I3e6fe854e19cc370070d0fd8416d0aa6fa8f8e90

17 files changed:
simpleperf/Android.mk [new file with mode: 0644]
simpleperf/cmd_help.cpp [new file with mode: 0644]
simpleperf/cmd_list.cpp [new file with mode: 0644]
simpleperf/command.cpp [new file with mode: 0644]
simpleperf/command.h [new file with mode: 0644]
simpleperf/event_attr.cpp [new file with mode: 0644]
simpleperf/event_attr.h [new file with mode: 0644]
simpleperf/event_fd.cpp [new file with mode: 0644]
simpleperf/event_fd.h [new file with mode: 0644]
simpleperf/event_type.cpp [new file with mode: 0644]
simpleperf/event_type.h [new file with mode: 0644]
simpleperf/event_type_table.h [new file with mode: 0644]
simpleperf/generate_event_type_table.py [new file with mode: 0755]
simpleperf/main.cpp [new file with mode: 0644]
simpleperf/perf_event.h [new file with mode: 0644]
simpleperf/utils.cpp [new file with mode: 0644]
simpleperf/utils.h [new file with mode: 0644]

diff --git a/simpleperf/Android.mk b/simpleperf/Android.mk
new file mode 100644 (file)
index 0000000..22bfd77
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2015 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+simpleperf_src_files := \
+  cmd_help.cpp \
+  cmd_list.cpp \
+  command.cpp \
+  event_attr.cpp \
+  event_fd.cpp \
+  event_type.cpp \
+  main.cpp \
+  utils.cpp \
+
+simpleperf_cppflags := -std=c++11 -Wall -Wextra -Werror -Wunused
+
+include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_CPPFLAGS := $(simpleperf_cppflags)
+LOCAL_SRC_FILES := $(simpleperf_src_files)
+LOCAL_STATIC_LIBRARIES := libbase libcutils liblog
+LOCAL_MODULE := simpleperf
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_CPPFLAGS := $(simpleperf_cppflags)
+LOCAL_SRC_FILES := $(simpleperf_src_files)
+LOCAL_STATIC_LIBRARIES := libbase libcutils liblog
+LOCAL_LDLIBS := -lrt
+LOCAL_MODULE := simpleperf
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_EXECUTABLE)
+endif
diff --git a/simpleperf/cmd_help.cpp b/simpleperf/cmd_help.cpp
new file mode 100644 (file)
index 0000000..bf08dba
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+
+#include "command.h"
+
+class HelpCommand : public Command {
+ public:
+  HelpCommand()
+      : Command("help", "print help information for simpleperf",
+                "Usage: simpleperf help [subcommand]\n"
+                "    Without subcommand, print short help string for every subcommand.\n"
+                "    With subcommand, print long help string for the subcommand.\n\n") {
+  }
+
+  bool Run(const std::vector<std::string>& args) override;
+
+ private:
+  void PrintShortHelp();
+  void PrintLongHelpForOneCommand(const Command& cmd);
+};
+
+bool HelpCommand::Run(const std::vector<std::string>& args) {
+  if (args.empty()) {
+    PrintShortHelp();
+  } else {
+    Command* cmd = Command::FindCommandByName(args[0]);
+    if (cmd == nullptr) {
+      LOG(ERROR) << "malformed command line: can't find help string for unknown command " << args[0];
+      LOG(ERROR) << "try using \"--help\"";
+      return false;
+    } else {
+      PrintLongHelpForOneCommand(*cmd);
+    }
+  }
+  return true;
+}
+
+void HelpCommand::PrintShortHelp() {
+  printf("Usage: simpleperf [--help] subcommand [args_for_subcommand]\n\n");
+  for (auto& command : Command::GetAllCommands()) {
+    printf("%-20s%s\n", command->Name().c_str(), command->ShortHelpString().c_str());
+  }
+}
+
+void HelpCommand::PrintLongHelpForOneCommand(const Command& command) {
+  printf("%s\n", command.LongHelpString().c_str());
+}
+
+HelpCommand help_command;
diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp
new file mode 100644 (file)
index 0000000..dd35c29
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+
+#include "command.h"
+#include "event_type.h"
+#include "perf_event.h"
+
+class ListCommand : public Command {
+ public:
+  ListCommand()
+      : Command("list", "list all available perf events",
+                "Usage: simpleperf list\n"
+                "    List all available perf events on this machine.\n") {
+  }
+
+  bool Run(const std::vector<std::string>& args) override;
+
+ private:
+  void PrintEventTypesOfType(uint32_t type, const char* type_name,
+                             const std::vector<const EventType>& event_types);
+};
+
+bool ListCommand::Run(const std::vector<std::string>& args) {
+  if (!args.empty()) {
+    LOG(ERROR) << "malformed command line: list subcommand needs no argument";
+    LOG(ERROR) << "try using \"help list\"";
+    return false;
+  }
+  auto& event_types = EventTypeFactory::GetAllEventTypes();
+
+  PrintEventTypesOfType(PERF_TYPE_HARDWARE, "hardware events", event_types);
+  PrintEventTypesOfType(PERF_TYPE_SOFTWARE, "software events", event_types);
+  PrintEventTypesOfType(PERF_TYPE_HW_CACHE, "hw-cache events", event_types);
+  return true;
+}
+
+void ListCommand::PrintEventTypesOfType(uint32_t type, const char* type_name,
+                                        const std::vector<const EventType>& event_types) {
+  printf("List of %s:\n", type_name);
+  for (auto& event_type : event_types) {
+    if (event_type.type == type && event_type.IsSupportedByKernel()) {
+      printf("  %s\n", event_type.name);
+    }
+  }
+  printf("\n");
+}
+
+ListCommand list_command;
diff --git a/simpleperf/command.cpp b/simpleperf/command.cpp
new file mode 100644 (file)
index 0000000..d26576a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "command.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+static std::vector<Command*>& Commands() {
+  // commands is used in the constructor of Command. Defining it as a static
+  // variable in a function makes sure it is initialized before use.
+  static std::vector<Command*> commands;
+  return commands;
+}
+
+Command* Command::FindCommandByName(const std::string& cmd_name) {
+  for (auto command : Commands()) {
+    if (command->Name() == cmd_name) {
+      return command;
+    }
+  }
+  return nullptr;
+}
+
+static bool CompareCommandByName(Command* cmd1, Command* cmd2) {
+  return cmd1->Name() < cmd2->Name();
+}
+
+const std::vector<Command*>& Command::GetAllCommands() {
+  std::sort(Commands().begin(), Commands().end(), CompareCommandByName);
+  return Commands();
+}
+
+void Command::RegisterCommand(Command* cmd) {
+  Commands().push_back(cmd);
+}
diff --git a/simpleperf/command.h b/simpleperf/command.h
new file mode 100644 (file)
index 0000000..a2e1923
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_COMMAND_H_
+#define SIMPLE_PERF_COMMAND_H_
+
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+class Command {
+ public:
+  Command(const std::string& name, const std::string& short_help_string,
+          const std::string& long_help_string)
+      : name_(name), short_help_string_(short_help_string), long_help_string_(long_help_string) {
+    RegisterCommand(this);
+  }
+
+  virtual ~Command() {
+  }
+
+  const std::string& Name() const {
+    return name_;
+  }
+
+  const std::string& ShortHelpString() const {
+    return short_help_string_;
+  }
+
+  const std::string LongHelpString() const {
+    return long_help_string_;
+  }
+
+  virtual bool Run(const std::vector<std::string>& args) = 0;
+
+  static Command* FindCommandByName(const std::string& cmd_name);
+  static const std::vector<Command*>& GetAllCommands();
+
+ private:
+  const std::string name_;
+  const std::string short_help_string_;
+  const std::string long_help_string_;
+
+  static void RegisterCommand(Command* cmd);
+
+  DISALLOW_COPY_AND_ASSIGN(Command);
+};
+
+#endif  // SIMPLE_PERF_COMMAND_H_
diff --git a/simpleperf/event_attr.cpp b/simpleperf/event_attr.cpp
new file mode 100644 (file)
index 0000000..a1ee3d9
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "event_attr.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string>
+#include <unordered_map>
+
+#include <base/logging.h>
+
+#include "event_type.h"
+#include "utils.h"
+
+static std::string SampleTypeToString(uint64_t sample_type) {
+  std::unordered_map<int, std::string> map = {
+      {PERF_SAMPLE_IP, "ip"},
+      {PERF_SAMPLE_TID, "tid"},
+      {PERF_SAMPLE_TIME, "time"},
+      {PERF_SAMPLE_ADDR, "addr"},
+      {PERF_SAMPLE_READ, "read"},
+      {PERF_SAMPLE_CALLCHAIN, "callchain"},
+      {PERF_SAMPLE_ID, "id"},
+      {PERF_SAMPLE_CPU, "cpu"},
+      {PERF_SAMPLE_PERIOD, "period"},
+      {PERF_SAMPLE_STREAM_ID, "stream_id"},
+      {PERF_SAMPLE_RAW, "raw"},
+  };
+
+  std::string result;
+  for (auto p : map) {
+    if (sample_type & p.first) {
+      sample_type &= ~p.first;
+      if (!result.empty()) {
+        result += ", ";
+      }
+      result += p.second;
+    }
+  }
+  if (sample_type != 0) {
+    LOG(DEBUG) << "unknown sample_type bits: " << std::hex << sample_type;
+  }
+
+  return result;
+}
+
+EventAttr EventAttr::CreateDefaultAttrToMonitorEvent(const EventType& event_type) {
+  perf_event_attr attr;
+  memset(&attr, 0, sizeof(attr));
+  attr.size = sizeof(perf_event_attr);
+  attr.type = event_type.type;
+  attr.config = event_type.config;
+  attr.mmap = 1;
+  attr.comm = 1;
+  attr.read_format =
+      PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID;
+  attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_PERIOD;
+  return EventAttr(attr);
+}
+
+void EventAttr::Dump(size_t indent) const {
+  std::string event_name = "unknown";
+  const EventType* event_type = EventTypeFactory::FindEventTypeByConfig(attr_.type, attr_.config);
+  if (event_type != nullptr) {
+    event_name = event_type->name;
+  }
+
+  PrintIndented(indent, "event_attr_: for event %s\n", event_name.c_str());
+
+  PrintIndented(indent + 2, "type %u, size %u, config %llu\n", attr_.type, attr_.size, attr_.config);
+
+  if (attr_.freq != 0) {
+    PrintIndented(indent + 2, "sample_freq %llu\n", attr_.sample_freq);
+  } else {
+    PrintIndented(indent + 2, "sample_period %llu\n", attr_.sample_period);
+  }
+
+  PrintIndented(indent + 2, "sample_type (0x%llx) %s\n", attr_.sample_type,
+                SampleTypeToString(attr_.sample_type).c_str());
+
+  PrintIndented(indent + 2, "read_format (0x%llx)\n", attr_.read_format);
+
+  PrintIndented(indent + 2, "disabled %llu, inherit %llu, pinned %llu, exclusive %llu\n",
+                attr_.disabled, attr_.inherit, attr_.pinned, attr_.exclusive);
+
+  PrintIndented(indent + 2, "exclude_user %llu, exclude_kernel %llu, exclude_hv %llu\n",
+                attr_.exclude_user, attr_.exclude_kernel, attr_.exclude_hv);
+
+  PrintIndented(indent + 2, "exclude_idle %llu, mmap %llu, comm %llu, freq %llu\n",
+                attr_.exclude_idle, attr_.mmap, attr_.comm, attr_.freq);
+
+  PrintIndented(indent + 2, "inherit_stat %llu, enable_on_exec %llu, task %llu\n",
+                attr_.inherit_stat, attr_.enable_on_exec, attr_.task);
+
+  PrintIndented(indent + 2, "watermark %llu, precise_ip %llu, mmap_data %llu\n", attr_.watermark,
+                attr_.precise_ip, attr_.mmap_data);
+
+  PrintIndented(indent + 2, "sample_id_all %llu, exclude_host %llu, exclude_guest %llu\n",
+                attr_.sample_id_all, attr_.exclude_host, attr_.exclude_guest);
+}
diff --git a/simpleperf/event_attr.h b/simpleperf/event_attr.h
new file mode 100644 (file)
index 0000000..30052f1
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_EVENT_ATTR_H_
+#define SIMPLE_PERF_EVENT_ATTR_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "perf_event.h"
+
+struct EventType;
+
+// EventAttr manages perf_event_attr, which provides detailed configuration information when
+// opening a perf_event_file. The configuration information tells the kernel how to count and
+// record events.
+class EventAttr {
+ public:
+  static EventAttr CreateDefaultAttrToMonitorEvent(const EventType& event_type);
+
+  EventAttr(const perf_event_attr& attr) : attr_(attr) {
+  }
+
+  perf_event_attr Attr() const {
+    return attr_;
+  }
+
+  uint64_t SampleType() const {
+    return attr_.sample_type;
+  }
+
+  void EnableOnExec() {
+    attr_.enable_on_exec = 1;
+  }
+
+  void SetSampleFreq(uint64_t freq) {
+    attr_.freq = 1;
+    attr_.sample_freq = freq;
+  }
+
+  void SetSamplePeriod(uint64_t period) {
+    attr_.freq = 0;
+    attr_.sample_period = period;
+  }
+
+  void SetSampleAll() {
+    attr_.sample_id_all = 1;
+  }
+
+  void Dump(size_t indent = 0) const;
+
+ private:
+  perf_event_attr attr_;
+};
+
+#endif  // SIMPLE_PERF_EVENT_ATTR_H_
diff --git a/simpleperf/event_fd.cpp b/simpleperf/event_fd.cpp
new file mode 100644 (file)
index 0000000..7c4ea44
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "event_fd.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <memory>
+
+#include <base/logging.h>
+#include <base/stringprintf.h>
+
+#include "event_type.h"
+#include "event_attr.h"
+#include "perf_event.h"
+#include "utils.h"
+
+static int perf_event_open(perf_event_attr* attr, pid_t pid, int cpu, int group_fd,
+                           unsigned long flags) {
+  return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+std::unique_ptr<EventFd> EventFd::OpenEventFileForProcess(const EventAttr& attr, pid_t pid) {
+  return OpenEventFile(attr, pid, -1);
+}
+
+std::unique_ptr<EventFd> EventFd::OpenEventFileForCpu(const EventAttr& attr, int cpu) {
+  return OpenEventFile(attr, -1, cpu);
+}
+
+std::unique_ptr<EventFd> EventFd::OpenEventFile(const EventAttr& attr, pid_t pid, int cpu) {
+  perf_event_attr perf_attr = attr.Attr();
+  std::string event_name = "unknown event";
+  const EventType* event_type =
+      EventTypeFactory::FindEventTypeByConfig(perf_attr.type, perf_attr.config);
+  if (event_type != nullptr) {
+    event_name = event_type->name;
+  }
+  int perf_event_fd = perf_event_open(&perf_attr, pid, cpu, -1, 0);
+  if (perf_event_fd == -1) {
+    // It depends whether the perf_event_file configuration is supported by the kernel and the
+    // machine. So fail to open the file is not an error.
+    PLOG(DEBUG) << "open perf_event_file (event " << event_name << ", pid " << pid << ", cpu "
+                << cpu << ") failed";
+    return nullptr;
+  }
+  if (fcntl(perf_event_fd, F_SETFD, FD_CLOEXEC) == -1) {
+    PLOG(ERROR) << "fcntl(FD_CLOEXEC) for perf_event_file (event " << event_name << ", pid " << pid
+                << ", cpu " << cpu << ") failed";
+    return nullptr;
+  }
+  return std::unique_ptr<EventFd>(new EventFd(perf_event_fd, event_name, pid, cpu));
+}
+
+EventFd::~EventFd() {
+  close(perf_event_fd_);
+}
+
+std::string EventFd::Name() const {
+  return android::base::StringPrintf("perf_event_file(event %s, pid %d, cpu %d)",
+                                     event_name_.c_str(), pid_, cpu_);
+}
+
+bool EventFd::EnableEvent() {
+  int result = ioctl(perf_event_fd_, PERF_EVENT_IOC_ENABLE, 0);
+  if (result < 0) {
+    PLOG(ERROR) << "ioctl(enable) " << Name() << " failed";
+    return false;
+  }
+  return true;
+}
+
+bool EventFd::DisableEvent() {
+  int result = ioctl(perf_event_fd_, PERF_EVENT_IOC_DISABLE, 0);
+  if (result < 0) {
+    PLOG(ERROR) << "ioctl(disable) " << Name() << " failed";
+    return false;
+  }
+  return true;
+}
diff --git a/simpleperf/event_fd.h b/simpleperf/event_fd.h
new file mode 100644 (file)
index 0000000..96286fb
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_EVENT_FD_H_
+#define SIMPLE_PERF_EVENT_FD_H_
+
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+
+class EventAttr;
+
+// EventFd represents an opened perf_event_file.
+class EventFd {
+ public:
+  static std::unique_ptr<EventFd> OpenEventFileForProcess(const EventAttr& attr, pid_t pid);
+  static std::unique_ptr<EventFd> OpenEventFileForCpu(const EventAttr& attr, int cpu);
+  static std::unique_ptr<EventFd> OpenEventFile(const EventAttr& attr, pid_t pid, int cpu);
+
+  ~EventFd();
+
+  // Give information about this perf_event_file, like (event_name, pid, cpu).
+  std::string Name() const;
+
+  // It tells the kernel to start counting and recording events specified by this file.
+  bool EnableEvent();
+
+  // It tells the kernel to stop counting and recording events specified by this file.
+  bool DisableEvent();
+
+ private:
+  EventFd(int perf_event_fd, const std::string& event_name, pid_t pid, int cpu)
+      : perf_event_fd_(perf_event_fd), event_name_(event_name), pid_(pid), cpu_(cpu) {
+  }
+
+  int perf_event_fd_;
+  const std::string event_name_;
+  pid_t pid_;
+  int cpu_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventFd);
+};
+
+#endif  // SIMPLE_PERF_EVENT_FD_H_
diff --git a/simpleperf/event_type.cpp b/simpleperf/event_type.cpp
new file mode 100644 (file)
index 0000000..01d7457
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "event_type.h"
+
+#include <unistd.h>
+#include <string>
+#include <vector>
+#include "event_attr.h"
+#include "event_fd.h"
+
+#define EVENT_TYPE_TABLE_ENTRY(name, type, config) \
+  { name, type, config }                           \
+  ,
+
+static std::vector<const EventType> event_type_array = {
+#include "event_type_table.h"
+};
+
+static bool IsEventTypeSupportedByKernel(const EventType& event_type) {
+  auto event_fd = EventFd::OpenEventFileForProcess(
+      EventAttr::CreateDefaultAttrToMonitorEvent(event_type), getpid());
+  return event_fd != nullptr;
+}
+
+bool EventType::IsSupportedByKernel() const {
+  return IsEventTypeSupportedByKernel(*this);
+}
+
+const std::vector<const EventType>& EventTypeFactory::GetAllEventTypes() {
+  return event_type_array;
+}
+
+const EventType* EventTypeFactory::FindEventTypeByName(const std::string& name) {
+  for (auto& event_type : event_type_array) {
+    if (event_type.name == name) {
+      return &event_type;
+    }
+  }
+  return nullptr;
+}
+
+const EventType* EventTypeFactory::FindEventTypeByConfig(uint32_t type, uint64_t config) {
+  for (auto& event_type : event_type_array) {
+    if (event_type.type == type && event_type.config == config) {
+      return &event_type;
+    }
+  }
+  return nullptr;
+}
diff --git a/simpleperf/event_type.h b/simpleperf/event_type.h
new file mode 100644 (file)
index 0000000..e2f21d5
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_EVENT_H_
+#define SIMPLE_PERF_EVENT_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+// EventType represents one type of event, like cpu_cycle_event, cache_misses_event.
+// The user knows one event type by its name, and the kernel knows one event type by its
+// (type, config) pair. EventType connects the two representations, and tells the user if
+// the event type is supported by the kernel.
+
+struct EventType {
+  bool IsSupportedByKernel() const;
+
+  const char* name;
+  uint32_t type;
+  uint64_t config;
+};
+
+class EventTypeFactory {
+ public:
+  static const std::vector<const EventType>& GetAllEventTypes();
+  static const EventType* FindEventTypeByName(const std::string& name);
+  static const EventType* FindEventTypeByConfig(uint32_t type, uint64_t config);
+};
+
+#endif  // SIMPLE_PERF_EVENT_H_
diff --git a/simpleperf/event_type_table.h b/simpleperf/event_type_table.h
new file mode 100644 (file)
index 0000000..895cc85
--- /dev/null
@@ -0,0 +1,65 @@
+// This file is auto-generated by generate-event_table.py.
+
+{"cpu-cycles", PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES},
+{"instructions", PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS},
+{"cache-references", PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES},
+{"cache-misses", PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES},
+{"branch-instructions", PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS},
+{"branch-misses", PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES},
+{"bus-cycles", PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES},
+{"stalled-cycles-frontend", PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND},
+{"stalled-cycles-backend", PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND},
+
+{"cpu-clock", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK},
+{"task-clock", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK},
+{"page-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS},
+{"context-switches", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES},
+{"cpu-migrations", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS},
+{"minor-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN},
+{"major-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ},
+{"alignment-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS},
+{"emulation-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS},
+
+{"L1-dcache-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-dcache-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"L1-dcache-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-dcache-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"L1-dcache-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-dcache-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"L1-icache-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-icache-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"L1-icache-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-icache-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"L1-icache-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"L1-icache-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"LLC-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"LLC-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"LLC-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"LLC-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"LLC-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"LLC-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"dTLB-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"dTLB-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"dTLB-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"dTLB-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"dTLB-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"dTLB-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"iTLB-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"iTLB-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"iTLB-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"iTLB-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"iTLB-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"iTLB-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"branch-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"branch-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"branch-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"branch-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"branch-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"branch-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"node-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"node-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"node-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"node-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+{"node-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
+{"node-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
+
diff --git a/simpleperf/generate_event_type_table.py b/simpleperf/generate_event_type_table.py
new file mode 100755 (executable)
index 0000000..b3fb897
--- /dev/null
@@ -0,0 +1,119 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2015 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.
+#
+
+
+def gen_event_type_entry_str(event_type_name, event_type, event_config):
+    """
+    return string like:
+    {"cpu-cycles", PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES},
+    """
+    return '{"%s", %s, %s},\n' % (event_type_name, event_type, event_config)
+
+
+def gen_hardware_events():
+    hardware_configs = ["cpu-cycles",
+                        "instructions",
+                        "cache-references",
+                        "cache-misses",
+                        "branch-instructions",
+                        "branch-misses",
+                        "bus-cycles",
+                        "stalled-cycles-frontend",
+                        "stalled-cycles-backend",
+                        ]
+    generated_str = ""
+    for config in hardware_configs:
+        event_type_name = config
+        event_config = "PERF_COUNT_HW_" + config.replace('-', '_').upper()
+
+        generated_str += gen_event_type_entry_str(
+            event_type_name, "PERF_TYPE_HARDWARE", event_config)
+
+    return generated_str
+
+
+def gen_software_events():
+    software_configs = ["cpu-clock",
+                        "task-clock",
+                        "page-faults",
+                        "context-switches",
+                        "cpu-migrations",
+                        ["minor-faults", "PERF_COUNT_SW_PAGE_FAULTS_MIN"],
+                        ["major-faults", "PERF_COUNT_SW_PAGE_FAULTS_MAJ"],
+                        "alignment-faults",
+                        "emulation-faults",
+                        ]
+    generated_str = ""
+    for config in software_configs:
+        if type(config) is list:
+            event_type_name = config[0]
+            event_config = config[1]
+        else:
+            event_type_name = config
+            event_config = "PERF_COUNT_SW_" + config.replace('-', '_').upper()
+
+        generated_str += gen_event_type_entry_str(
+            event_type_name, "PERF_TYPE_SOFTWARE", event_config)
+
+    return generated_str
+
+
+def gen_hw_cache_events():
+    hw_cache_types = [["L1-dcache", "PERF_COUNT_HW_CACHE_L1D"],
+                      ["L1-icache", "PERF_COUNT_HW_CACHE_L1I"],
+                      ["LLC", "PERF_COUNT_HW_CACHE_LL"],
+                      ["dTLB", "PERF_COUNT_HW_CACHE_DTLB"],
+                      ["iTLB", "PERF_COUNT_HW_CACHE_ITLB"],
+                      ["branch", "PERF_COUNT_HW_CACHE_BPU"],
+                      ["node", "PERF_COUNT_HW_CACHE_NODE"],
+                      ]
+    hw_cache_ops = [["loades", "load", "PERF_COUNT_HW_CACHE_OP_READ"],
+                    ["stores", "store", "PERF_COUNT_HW_CACHE_OP_WRITE"],
+                    ["prefetches", "prefetch",
+                     "PERF_COUNT_HW_CACHE_OP_PREFETCH"],
+                    ]
+    hw_cache_op_results = [["accesses", "PERF_COUNT_HW_CACHE_RESULT_ACCESS"],
+                           ["misses", "PERF_COUNT_HW_CACHE_RESULT_MISS"],
+                           ]
+    generated_str = ""
+    for (type_name, type_config) in hw_cache_types:
+        for (op_name_access, op_name_miss, op_config) in hw_cache_ops:
+            for (result_name, result_config) in hw_cache_op_results:
+                if result_name == "accesses":
+                    event_type_name = type_name + '-' + op_name_access
+                else:
+                    event_type_name = type_name + '-' + \
+                        op_name_miss + '-' + result_name
+                event_config = "((%s) | (%s << 8) | (%s << 16))" % (
+                    type_config, op_config, result_config)
+                generated_str += gen_event_type_entry_str(
+                    event_type_name, "PERF_TYPE_HW_CACHE", event_config)
+
+    return generated_str
+
+
+def gen_events():
+    generated_str = "// This file is auto-generated by generate-event_table.py.\n\n"
+    generated_str += gen_hardware_events() + '\n'
+    generated_str += gen_software_events() + '\n'
+    generated_str += gen_hw_cache_events() + '\n'
+    return generated_str
+
+generated_str = gen_events()
+fh = open('event_type_table.h', 'w')
+fh.write(generated_str)
+fh.close()
diff --git a/simpleperf/main.cpp b/simpleperf/main.cpp
new file mode 100644 (file)
index 0000000..017e495
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+
+#include "command.h"
+
+int main(int argc, char** argv) {
+  InitLogging(argv, android::base::StderrLogger);
+  std::vector<std::string> args;
+
+  if (argc == 1 || (argc == 2 && strcmp(argv[1], "--help") == 0)) {
+    args.push_back("help");
+  } else {
+    for (int i = 1; i < argc; ++i) {
+      args.push_back(argv[i]);
+    }
+  }
+
+  Command* command = Command::FindCommandByName(args[0]);
+  if (command == nullptr) {
+    LOG(ERROR) << "malformed command line: unknown command " << args[0];
+    return 1;
+  }
+  args.erase(args.begin());
+  bool result = command->Run(args);
+  if (result == true) {
+    LOG(DEBUG) << "run command " << args[0] << " successfully";
+  } else {
+    LOG(DEBUG) << "run command " << args[0] << "unsuccessfully";
+  }
+  return result ? 0 : 1;
+}
diff --git a/simpleperf/perf_event.h b/simpleperf/perf_event.h
new file mode 100644 (file)
index 0000000..a91eb6b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_PERF_EVENT_H_
+#define SIMPLE_PERF_PERF_EVENT_H_
+
+#include <linux/perf_event.h>
+
+#endif  // SIMPLE_PERF_PERF_EVENT_H_
diff --git a/simpleperf/utils.cpp b/simpleperf/utils.cpp
new file mode 100644 (file)
index 0000000..2b02bb1
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "utils.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+void PrintIndented(size_t indent, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  printf("%*s", static_cast<int>(indent), "");
+  vprintf(fmt, ap);
+  va_end(ap);
+}
diff --git a/simpleperf/utils.h b/simpleperf/utils.h
new file mode 100644 (file)
index 0000000..dcbe74d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 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 SIMPLE_PERF_UTILS_H_
+#define SIMPLE_PERF_UTILS_H_
+
+#include <stddef.h>
+
+void PrintIndented(size_t indent, const char* fmt, ...);
+
+#endif  // SIMPLE_PERF_UTILS_H_