Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:20

0001 // -*- C++ -*-
0002 //
0003 // Package:     PerfTools/AllocMonitor
0004 // Class  :     AllocMonitorRegistry
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Christopher Jones
0010 //         Created:  Mon, 21 Aug 2023 15:42:48 GMT
0011 //
0012 
0013 // system include files
0014 #include <dlfcn.h>  // dlsym
0015 
0016 // user include files
0017 #include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h"
0018 #include "FWCore/Utilities/interface/Exception.h"
0019 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0020 
0021 //
0022 // constants, enums and typedefs
0023 //
0024 extern "C" {
0025 void alloc_monitor_start();
0026 void alloc_monitor_stop();
0027 }
0028 
0029 namespace {
0030   bool& threadRunning() {
0031     static thread_local bool s_running = true;
0032     return s_running;
0033   }
0034 }  // namespace
0035 
0036 using namespace cms::perftools;
0037 
0038 //
0039 // static data member definitions
0040 //
0041 
0042 //
0043 // constructors and destructor
0044 //
0045 AllocMonitorRegistry::AllocMonitorRegistry() {
0046   threadRunning() = true;
0047   //Cannot start here because statics can cause memory to be allocated in the atexit registration
0048   // done behind the scenes. If the allocation happens, AllocMonitorRegistry::instance will be called
0049   // recursively before the static has finished and we well deadlock
0050 }
0051 
0052 AllocMonitorRegistry::~AllocMonitorRegistry() {
0053   void* stop = dlsym(RTLD_DEFAULT, "alloc_monitor_stop");
0054   if (stop != nullptr) {
0055     auto s = reinterpret_cast<decltype(&::alloc_monitor_stop)>(stop);
0056     s();
0057   }
0058   threadRunning() = false;
0059   monitors_.clear();
0060 }
0061 
0062 //
0063 // member functions
0064 //
0065 bool AllocMonitorRegistry::necessaryLibraryWasPreloaded() {
0066   return dlsym(RTLD_DEFAULT, "alloc_monitor_start") != nullptr;
0067 }
0068 
0069 void AllocMonitorRegistry::start() {
0070   if (monitors_.empty()) {
0071     void* start = dlsym(RTLD_DEFAULT, "alloc_monitor_start");
0072     if (start == nullptr) {
0073       throw cms::Exception("NoAllocMonitorPreload")
0074           << "The libPerfToolsAllocMonitorPreload.so was not LD_PRELOADed into the job";
0075     }
0076     auto s = reinterpret_cast<decltype(&::alloc_monitor_start)>(start);
0077     s();
0078   }
0079 }
0080 
0081 bool& AllocMonitorRegistry::isRunning() { return threadRunning(); }
0082 
0083 void AllocMonitorRegistry::deregisterMonitor(AllocMonitorBase* iMonitor) {
0084   for (auto it = monitors_.begin(); monitors_.end() != it; ++it) {
0085     if (it->get() == iMonitor) {
0086       [[maybe_unused]] Guard g = makeGuard();
0087       monitors_.erase(it);
0088       break;
0089     }
0090   }
0091 }
0092 
0093 //
0094 // const member functions
0095 //
0096 void AllocMonitorRegistry::allocCalled_(size_t iRequested, size_t iActual) {
0097   for (auto& m : monitors_) {
0098     m->allocCalled(iRequested, iActual);
0099   }
0100 }
0101 void AllocMonitorRegistry::deallocCalled_(size_t iActual) {
0102   for (auto& m : monitors_) {
0103     m->deallocCalled(iActual);
0104   }
0105 }
0106 
0107 //
0108 // static member functions
0109 //
0110 AllocMonitorRegistry& AllocMonitorRegistry::instance() {
0111   //The thread unsafe methods are marked as unsafe
0112   CMS_SA_ALLOW static AllocMonitorRegistry s_registry;
0113   return s_registry;
0114 }