1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  */
    
  7. 
    
  8. #ifndef incl_HPHP_UTIL_HARDWARE_COUNTER_H_
    
  9. #define incl_HPHP_UTIL_HARDWARE_COUNTER_H_
    
  10. 
    
  11. #include "thread-local.h"
    
  12. 
    
  13. #include <cstdint>
    
  14. #include <memory>
    
  15. #include <vector>
    
  16. 
    
  17. namespace HPHP {
    
  18. ///////////////////////////////////////////////////////////////////////////////
    
  19. 
    
  20. #ifndef NO_HARDWARE_COUNTERS
    
  21. 
    
  22. class InstructionCounter;
    
  23. class LoadCounter;
    
  24. class StoreCounter;
    
  25. 
    
  26. struct PerfTable {
    
  27.   const char* name;
    
  28.   uint32_t type;
    
  29.   uint64_t config;
    
  30. };
    
  31. 
    
  32. class HardwareCounterImpl;
    
  33. 
    
  34. class HardwareCounter {
    
  35. public:
    
  36.   HardwareCounter();
    
  37.   ~HardwareCounter();
    
  38. 
    
  39.   static void Reset();
    
  40.   static int64_t GetInstructionCount();
    
  41.   static int64_t GetLoadCount();
    
  42.   static int64_t GetStoreCount();
    
  43.   static bool SetPerfEvents(std::string events);
    
  44.   static void IncInstructionCount(int64_t amount);
    
  45.   static void IncLoadCount(int64_t amount);
    
  46.   static void IncStoreCount(int64_t amount);
    
  47. 
    
  48.   typedef void (*PerfEventCallback)(const std::string&, int64_t, void*);
    
  49.   static void GetPerfEvents(PerfEventCallback f, void* data);
    
  50.   static void ClearPerfEvents();
    
  51.   static void Init(bool enable, const std::string& events, bool subProc);
    
  52.   static DECLARE_THREAD_LOCAL_NO_CHECK(HardwareCounter, s_counter);
    
  53.   bool m_countersSet{false};
    
  54. private:
    
  55.   void reset();
    
  56.   int64_t getInstructionCount();
    
  57.   int64_t getLoadCount();
    
  58.   int64_t getStoreCount();
    
  59.   bool eventExists(const char* event);
    
  60.   bool addPerfEvent(const char* event);
    
  61.   bool setPerfEvents(std::string events);
    
  62.   void getPerfEvents(PerfEventCallback f, void* data);
    
  63.   void clearPerfEvents();
    
  64. 
    
  65.   std::unique_ptr<InstructionCounter> m_instructionCounter;
    
  66.   std::unique_ptr<LoadCounter> m_loadCounter;
    
  67.   std::unique_ptr<StoreCounter> m_storeCounter;
    
  68.   std::vector<std::unique_ptr<HardwareCounterImpl>> m_counters;
    
  69. };
    
  70. 
    
  71. #else // NO_HARDWARE_COUNTERS
    
  72. 
    
  73. /* Stub implementation for platforms without hardware counters (non-linux)
    
  74.  * This mock class pretends to track performance events, but just returns
    
  75.  * static values, so it doesn't even need to worry about thread safety
    
  76.  * for the one static instance of itself.
    
  77.  */
    
  78. class HardwareCounter {
    
  79. public:
    
  80.   HardwareCounter() : m_countersSet(false) { }
    
  81.   ~HardwareCounter() { }
    
  82. 
    
  83.   static void Reset() { }
    
  84.   static int64_t GetInstructionCount() { return 0; }
    
  85.   static int64_t GetLoadCount() { return 0; }
    
  86.   static int64_t GetStoreCount() { return 0; }
    
  87.   static bool SetPerfEvents(folly::StringPiece events) { return false; }
    
  88.   static void IncInstructionCount(int64_t amount) {}
    
  89.   static void IncLoadCount(int64_t amount) {}
    
  90.   static void IncStoreCount(int64_t amount) {}
    
  91.   typedef void (*PerfEventCallback)(const std::string&, int64_t, void*);
    
  92.   static void GetPerfEvents(PerfEventCallback f, void* data) { }
    
  93.   static void ClearPerfEvents() { }
    
  94.   static void Init(bool enable, const std::string& events, bool subProc) {}
    
  95. 
    
  96.   // Normally exposed by DECLARE_THREAD_LOCAL_NO_CHECK
    
  97.   void getCheck() { }
    
  98.   void destroy() { }
    
  99.   static HardwareCounter s_counter;
    
  100.   bool m_countersSet;
    
  101. };
    
  102. 
    
  103. #endif // NO_HARDWARE_COUNTERS
    
  104. 
    
  105. ///////////////////////////////////////////////////////////////////////////////
    
  106. }
    
  107. 
    
  108. #endif