From ea84bca75676ed2bc0a2520256b9056287a71084 Mon Sep 17 00:00:00 2001
From: Rolf Seuster <Rolf.Seuster@cern.ch>
Date: Mon, 12 May 2014 18:38:10 +0200
Subject: [PATCH] fix problem under valgrind (RecAlgs-00-00-13)

---
 Reconstruction/RecAlgs/cmt/requirements       |  29 +++
 Reconstruction/RecAlgs/src/JobInfo.cxx        |  60 +++++++
 Reconstruction/RecAlgs/src/JobInfo.h          |  53 ++++++
 Reconstruction/RecAlgs/src/MemoryAlg.cxx      | 124 +++++++++++++
 Reconstruction/RecAlgs/src/MemoryAlg.h        |  52 ++++++
 Reconstruction/RecAlgs/src/TimingAlg.cxx      | 165 ++++++++++++++++++
 Reconstruction/RecAlgs/src/TimingAlg.h        |  55 ++++++
 .../src/components/RecAlgs_entries.cxx        |  14 ++
 .../RecAlgs/src/components/RecAlgs_load.cxx   |   4 +
 9 files changed, 556 insertions(+)
 create mode 100755 Reconstruction/RecAlgs/cmt/requirements
 create mode 100755 Reconstruction/RecAlgs/src/JobInfo.cxx
 create mode 100755 Reconstruction/RecAlgs/src/JobInfo.h
 create mode 100755 Reconstruction/RecAlgs/src/MemoryAlg.cxx
 create mode 100755 Reconstruction/RecAlgs/src/MemoryAlg.h
 create mode 100755 Reconstruction/RecAlgs/src/TimingAlg.cxx
 create mode 100755 Reconstruction/RecAlgs/src/TimingAlg.h
 create mode 100755 Reconstruction/RecAlgs/src/components/RecAlgs_entries.cxx
 create mode 100755 Reconstruction/RecAlgs/src/components/RecAlgs_load.cxx

diff --git a/Reconstruction/RecAlgs/cmt/requirements b/Reconstruction/RecAlgs/cmt/requirements
new file mode 100755
index 00000000000..1446e752c35
--- /dev/null
+++ b/Reconstruction/RecAlgs/cmt/requirements
@@ -0,0 +1,29 @@
+package RecAlgs
+
+author Rolf Seuster <seuster AT cern.ch>
+
+public
+
+use AtlasPolicy		AtlasPolicy-*
+
+private
+use StoreGate		StoreGate-*		Control
+use RecEvent		RecEvent-*		Reconstruction
+use AthenaBaseComps	AthenaBaseComps-*	Control
+use GaudiInterface	GaudiInterface-*	External
+use AtlasROOT		AtlasROOT-*		External
+end_private
+
+#apply_pattern declare_joboptions files="*.py"
+#apply_pattern declare_python_modules files="*.py"
+
+private
+library RecAlgs *.cxx components/*.cxx
+apply_pattern component_library
+
+end_private
+
+#private
+#macro cppdebugflags '$(cppdebugflags_s)'
+#macro_remove componentshr_linkopts "-Wl,-s"
+#end_private
diff --git a/Reconstruction/RecAlgs/src/JobInfo.cxx b/Reconstruction/RecAlgs/src/JobInfo.cxx
new file mode 100755
index 00000000000..3aa1ad898fa
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/JobInfo.cxx
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "JobInfo.h"
+
+#include "Cintex/Cintex.h"
+#include "Api.h"
+#include "G__ci.h"
+#include "Class.h"
+
+//================ Constructor =================================================
+
+namespace G__functionscope {
+  extern int sm_tagdefining;
+}
+
+JobInfo::JobInfo(const std::string& name, ISvcLocator* pSvcLocator)
+  :
+  AthAlgorithm(name,pSvcLocator),
+  m_events(0),
+  m_last_entries(0),
+  m_max_entries(G__functionscope::sm_tagdefining),
+  m_no_warnings(true),
+  m_printFATAL(false)
+{
+  declareProperty("PrintFATAL", m_printFATAL,"flag to decide if a FATAL should be printed - protection for Tier0");
+}
+
+StatusCode JobInfo::execute()
+{
+  int nc=Cint::G__ClassInfo::GetNumClasses();
+  if ( m_events < 2 || nc != m_last_entries )
+    {
+      ATH_MSG_INFO("root's CINTDictionaryArray G__struct : " << nc << " entries are in use");
+      ATH_MSG_INFO(" probably around " << m_max_entries << " entries are available (unreliable - use with care !");
+      if ( m_no_warnings and nc > 0.9 * m_max_entries )
+	{
+	  ATH_MSG_WARNING("CINTDictionary : over 90% filled !!");
+	  m_no_warnings=false;
+	}
+      // will be printed at most twice (m_last_entries will be equal to nc)
+      if ( nc >= m_max_entries )
+	{
+	  if ( m_printFATAL )
+	    ATH_MSG_FATAL("root's CINTDictionaryArray G__struct : too many entries !! You might experience strange crashes !!");
+	  else
+	    ATH_MSG_WARNING("root's CINTDictionaryArray G__struct : too many entries !! You might experience strange crashes !!");
+	}
+	
+	if(msgLvl(MSG::DEBUG))
+	  for ( int i=m_last_entries; i < nc; ++i )
+	    ATH_MSG_DEBUG("class " << i << " " << Cint::G__ClassInfo(i).Fullname() );
+	m_last_entries=nc;
+    }
+  ++m_events;
+  
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/RecAlgs/src/JobInfo.h b/Reconstruction/RecAlgs/src/JobInfo.h
new file mode 100755
index 00000000000..17a3c13292a
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/JobInfo.h
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RECALGS_JOBINFO_H
+#define RECALGS_JOBINFO_H
+
+// Gaudi includes
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include <string>
+
+/** @class JobInfo
+    
+
+@author Rolf Seuster <seuster AT cern.ch>
+*/
+
+class ISvcLocator;
+
+class JobInfo : public AthAlgorithm
+{
+ public:
+  
+  /** Standard Athena-Algorithm Constructor */
+  JobInfo(const std::string& name, ISvcLocator* pSvcLocator);
+  
+  /** Default Destructor */
+  ~JobInfo() {};
+  
+  /** standard Athena-Algorithm method */
+  StatusCode          initialize()
+  { return StatusCode::SUCCESS; };
+  /** standard Athena-Algorithm method */
+  StatusCode          execute();
+  /** standard Athena-Algorithm method */
+  StatusCode          finalize()
+  { return StatusCode::SUCCESS; };
+
+ private:
+  
+  int m_events;
+  
+  int m_last_entries;
+  
+  int m_max_entries;
+  
+  bool m_no_warnings;
+  
+  bool m_printFATAL;
+};
+
+#endif 
diff --git a/Reconstruction/RecAlgs/src/MemoryAlg.cxx b/Reconstruction/RecAlgs/src/MemoryAlg.cxx
new file mode 100755
index 00000000000..c2bc9c24272
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/MemoryAlg.cxx
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "MemoryAlg.h"
+#include "RecEvent/RecoTimingObj.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include <malloc.h>
+#include <stdint.h>
+
+//================ Constructor =================================================
+
+MemoryAlg::MemoryAlg(const std::string& name, ISvcLocator* pSvcLocator)
+  :
+  AthAlgorithm(name,pSvcLocator),
+  m_memoryObjOutputName("unspecified"),
+  m_usetcmalloc(true)
+{
+  //  template for property declaration
+  declareProperty("MemoryObjOutputName", m_memoryObjOutputName, "storegate key of output object");
+}
+
+//================ Initialisation =================================================
+
+StatusCode MemoryAlg::initialize()
+{
+  ATH_MSG_DEBUG( "initialize(); will write out RecoTimingObj with key " << m_memoryObjOutputName);
+  char *ch = getenv("USETCMALLOC");
+  if ( ch && strncmp(ch,"0",1) == 0 )
+    m_usetcmalloc=false;
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode MemoryAlg::execute()
+{
+  float f0(0);
+  float f1(0);
+  RecoTimingObj *t(0);
+  if(evtStore()->contains<RecoTimingObj>(m_memoryObjOutputName))
+    {
+      ATH_MSG_DEBUG("reading existing object ");
+      evtStore()->retrieve(t,m_memoryObjOutputName).ignore();
+      if ( t->size() )
+	f0=(*t)[0];
+      if ( t->size() > 0 )
+	f1=(*t)[1];
+      ATH_MSG_DEBUG("got f0 / f1 " << f0 << " / " << f1);
+    }
+  else
+    {
+      ATH_MSG_DEBUG("creating new object ");
+      t=new RecoTimingObj(false);
+      evtStore()->record(t,m_memoryObjOutputName).ignore();
+    }
+  int a(-1);
+  FILE *proc = fopen("/proc/self/statm","r");
+  if (proc)
+    fscanf(proc, "%d", &a);
+  fclose(proc);
+  float f=float(a) - f0;
+  t->push_back(f);
+  ATH_MSG_DEBUG("Memory and delta memory for this event now is: " << f << " (" << f0 << ")" );
+  
+  uintptr_t mem(0);
+  
+  char buffer[2048] = {0};
+  int out_pipe[2];
+  int saved_stderr;
+  saved_stderr = dup (STDERR_FILENO);
+  pipe (out_pipe);
+  dup2 (out_pipe[1], STDERR_FILENO);
+  close (out_pipe[1]);
+  malloc_stats ();
+  // when running under valgrind malloc_stats is a no-op, so reading from the pipe will stall
+  fprintf(stderr,"\n");
+  read (out_pipe[0], buffer, 2047);
+  // close (STDERR_FILENO);
+  dup2 (saved_stderr, STDERR_FILENO);
+  close (out_pipe[0]);
+  close (saved_stderr);
+  
+  ATH_MSG_DEBUG("ROLF " << buffer);  
+  
+  unsigned int start(0);
+  while ( start < strlen(buffer) )
+    {
+      int pos(0);
+      uintptr_t memtmp(0);
+      int ret;
+      if ( m_usetcmalloc )
+	{
+#if __WORDSIZE == 64
+	  ret = sscanf(&buffer[start], "MALLOC:   %lu Bytes in use by application%n", &memtmp, &pos);
+#else
+	  ret = sscanf(&buffer[start], "MALLOC:   %u Bytes in use by application%n", &memtmp, &pos);
+#endif
+	  if ( pos )
+	    mem=memtmp;
+	}
+      else
+	{
+#if __WORDSIZE == 64
+	  ret = sscanf(&buffer[start], "in use bytes     = %lu%n", &memtmp, &pos);
+#else
+	  ret = sscanf(&buffer[start], "in use bytes     = %u%n", &memtmp, &pos);
+#endif
+	  if ( pos )
+	    mem=memtmp;
+	}
+      ATH_MSG_VERBOSE("ROLF rr " << start << " " << ret << " " << memtmp << " " << mem << " len: " << strlen(buffer) << " pos : " << pos );  
+      while (buffer[start] != '\n' && start<strlen(buffer))
+	start += 1;
+      start += 1;
+    }
+  
+  
+  t->push_back(float(mem)/1024 - f1);
+  
+  /* Success */
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/RecAlgs/src/MemoryAlg.h b/Reconstruction/RecAlgs/src/MemoryAlg.h
new file mode 100755
index 00000000000..f9734b87e26
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/MemoryAlg.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RECALGS_MEMORYALG_H
+#define RECALGS_MEMORYALG_H
+
+// Gaudi includes
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include <string>
+#include <malloc.h>
+
+/** @class MemoryAlg
+    
+Several of the memory algs can be scheduled.
+# Each one saves memory consumption (VMem, VMemPeak, RSS, RSSPeak)
+Each one saves memory consumption (VMem, RSS, mallinfo)
+to the vector.
+
+@author Rolf Seuster <seuster AT cern.ch>
+*/
+
+class MemoryAlg : public AthAlgorithm
+{
+ public:
+  
+  /** Standard Athena-Algorithm Constructor */
+  MemoryAlg(const std::string& name, ISvcLocator* pSvcLocator);
+  
+  /** Default Destructor */
+  ~MemoryAlg() {};
+  
+  /** standard Athena-Algorithm method */
+  StatusCode          initialize();
+  /** standard Athena-Algorithm method */
+  StatusCode          execute();
+  /** standard Athena-Algorithm method */
+  StatusCode          finalize()
+  { return StatusCode::SUCCESS; };
+  
+ private:
+  
+  /** member variables for algorithm properties: */
+  std::string  m_memoryObjOutputName;
+
+  struct mallinfo mi;
+
+  bool m_usetcmalloc;
+  };
+
+#endif 
diff --git a/Reconstruction/RecAlgs/src/TimingAlg.cxx b/Reconstruction/RecAlgs/src/TimingAlg.cxx
new file mode 100755
index 00000000000..ea6daa3f811
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/TimingAlg.cxx
@@ -0,0 +1,165 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TimingAlg.h"
+#include "RecEvent/RecoTimingObj.h"
+#include "StoreGate/StoreGateSvc.h"
+
+unsigned int TimingAlg::m_CPUID=0;
+
+//================ Constructor =================================================
+
+TimingAlg::TimingAlg(const std::string& name, ISvcLocator* pSvcLocator)
+  :
+  AthAlgorithm(name,pSvcLocator),
+  m_timingObjOutputName("unspecified"),
+  m_determineCPUID(true)
+{
+  //  template for property declaration
+  declareProperty("TimingObjOutputName", m_timingObjOutputName, "storegate key of output object");
+  declareProperty("DetermineCPUID", m_determineCPUID,"flag to decide if CPUID should be determined");
+}
+
+//================ Initialisation =================================================
+
+StatusCode TimingAlg::initialize()
+{
+  ATH_MSG_DEBUG( "initialize(); will write out RecoTimingObj with key " << m_timingObjOutputName);
+  
+  // retrieve the StoreGate Service (delete if not needed)
+  if (!evtStore().retrieve().isSuccess()) {
+    ATH_MSG_ERROR("Could not retrieve StoreGateSvc!");
+    return StatusCode::FAILURE;
+  }
+  
+  if ( m_determineCPUID && ! m_CPUID )
+    {
+      std::string vendor("none");
+      std::string stepping("none");
+      std::string cpuFamily("none");
+      std::string model("none");
+      
+      FILE* file;
+      unsigned int numProcessors(0);
+      char line[1024];
+      
+      file = fopen("/proc/cpuinfo", "r");
+      numProcessors = 0;
+      while(fgets(line, 1024, file) != NULL){
+	if (strncmp(line, "processor",   9) == 0) numProcessors++;
+	if (strncmp(line, "vendor_id",   9) == 0) vendor=line;
+	if (strncmp(line, "stepping",    8) == 0) stepping=line;
+	if (strncmp(line, "cpu family", 10) == 0) cpuFamily=line;
+	if (strncmp(line, "model\t"   ,  6) == 0) model=line;
+      }
+      fclose(file);
+      
+      size_t found=vendor.find(':');
+      if (found!=std::string::npos)
+	vendor.erase(0,found+2);
+      
+      vendor.erase(vendor.size()-1);
+      stepping.erase(stepping.size()-1);
+      cpuFamily.erase(cpuFamily.size()-1);
+      model.erase(model.size()-1);
+      
+      ATH_MSG_INFO( "number of CPUs found: " << numProcessors << " of type " << vendor << " "
+		    << cpuFamily << " " << model << " " << stepping );
+      
+      //compress all strings/numbers into 2 uints
+      m_CPUID_a = 0xFFFFFFFF;
+      if ( vendor.length() == 12 )
+	{
+	  m_CPUID_a =
+	    0x01000000 * vendor[0] +
+	    0x00010000 * vendor[1] +
+	    0x00000100 * vendor[10] +
+	    0x00000001 * vendor[11]; 
+	  
+	  ATH_MSG_DEBUG( "CPU : vendor " << vendor[0] << vendor[1] << " * " << vendor[10] << vendor[11] );
+	}
+      
+      m_CPUID_b = 0;
+      int s(0);
+      s=0xFF;
+      if (stepping.compare("none") != 0)
+	sscanf(stepping.c_str(),"stepping\t: %d",&s);
+      ATH_MSG_VERBOSE( "stepping  : " << s );
+      if ( s > 255 )
+	s = 255;
+      m_CPUID_b += 0x00000100 * s;
+      
+      s=0xFF;
+      if (cpuFamily.compare("none") != 0)
+	sscanf(cpuFamily.c_str(),"cpu family\t: %d",&s);
+      ATH_MSG_VERBOSE( "cpuFamily : " << s );
+      if ( s > 255 )
+	s = 255;
+      m_CPUID_b += 0x01000000 * s;
+      
+      s=0xFF;
+      if (model.compare("none") != 0)
+	sscanf(model.c_str(),"model\t: %d",&s);
+      ATH_MSG_VERBOSE( "model     : " << s );
+      if ( s > 255 )
+	s = 255;
+      m_CPUID_b += 0x00010000 * s;
+      
+      s = numProcessors;
+      if ( s > 255 )
+	s = 255;
+      m_CPUID_b += s;
+      
+      ATH_MSG_VERBOSE( "CPU : compresses to " << std::hex << m_CPUID_a << " " << m_CPUID_b << std::dec );
+      
+      m_CPUID=1;
+    }
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TimingAlg::execute()
+{
+  float f0(0);
+  RecoTimingObj *t(0);
+  if(evtStore()->contains<RecoTimingObj>(m_timingObjOutputName))
+    {
+      ATH_MSG_DEBUG("reading existing object ");
+      evtStore()->retrieve(t,m_timingObjOutputName).ignore();
+      if ( t->size() )
+	f0=(*t)[0];
+      ATH_MSG_DEBUG("got f0 " << f0 );
+      m_CPUID=0;
+    }
+  else
+    {
+      ATH_MSG_DEBUG("creating new object ");
+      t=new RecoTimingObj();
+      evtStore()->record(t,m_timingObjOutputName).ignore();
+    }
+  
+  getrusage(RUSAGE_SELF, &r);
+  float f=float(r.ru_utime.tv_sec+r.ru_stime.tv_sec) + float(r.ru_utime.tv_usec+r.ru_stime.tv_usec)/1000000-f0;
+  t->push_back(f);
+  ATH_MSG_DEBUG(" CPU time for this event until now is: " << f);
+  if ( m_determineCPUID && m_CPUID )
+    {
+      union mytypes_t
+      {
+	unsigned int ui;
+	float f;
+      } mytypes;
+      // mytypes.ui=m_CPUID;     t->push_back(mytypes.f);
+      
+      mytypes.ui=0xF0F0F0F0;   t->push_back(mytypes.f);
+      mytypes.ui=m_CPUID_a;    t->push_back(mytypes.f);
+      mytypes.ui=m_CPUID_b;    t->push_back(mytypes.f);
+      mytypes.ui=0x0F0F0F0F;   t->push_back(mytypes.f);
+      
+      // don't write out again
+      m_CPUID=0;
+      m_determineCPUID=false;
+    }
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/RecAlgs/src/TimingAlg.h b/Reconstruction/RecAlgs/src/TimingAlg.h
new file mode 100755
index 00000000000..65d94d63e15
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/TimingAlg.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RECALGS_TIMINGALG_H
+#define RECALGS_TIMINGALG_H
+
+// Gaudi includes
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include <string>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+/** @class TimingAlg
+    
+Several of the timing algs can be scheduled.
+Each one adds the sum of user and system time 
+from a getrusage call to the vector.
+
+@author Rolf Seuster <seuster AT cern.ch>
+*/
+
+class TimingAlg : public AthAlgorithm
+{
+ public:
+  
+  /** Standard Athena-Algorithm Constructor */
+  TimingAlg(const std::string& name, ISvcLocator* pSvcLocator);
+  
+  /** Default Destructor */
+  ~TimingAlg() {};
+  
+  /** standard Athena-Algorithm method */
+  StatusCode          initialize();
+  /** standard Athena-Algorithm method */
+  StatusCode          execute();
+  /** standard Athena-Algorithm method */
+  StatusCode          finalize()
+  { return StatusCode::SUCCESS; };
+  
+ private:
+  
+  /** member variables for algorithm properties: */
+  std::string  m_timingObjOutputName;
+  
+  bool m_determineCPUID;
+  struct rusage r;
+  
+  static unsigned int m_CPUID;
+  unsigned int m_CPUID_a;
+  unsigned int m_CPUID_b;
+};
+
+#endif 
diff --git a/Reconstruction/RecAlgs/src/components/RecAlgs_entries.cxx b/Reconstruction/RecAlgs/src/components/RecAlgs_entries.cxx
new file mode 100755
index 00000000000..0a0d6a6caf0
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/components/RecAlgs_entries.cxx
@@ -0,0 +1,14 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+#include "../TimingAlg.h"
+#include "../MemoryAlg.h"
+#include "../JobInfo.h"
+
+DECLARE_ALGORITHM_FACTORY( TimingAlg )
+DECLARE_ALGORITHM_FACTORY( MemoryAlg )
+DECLARE_ALGORITHM_FACTORY( JobInfo )
+
+DECLARE_FACTORY_ENTRIES( RecAlgs ) {
+  DECLARE_ALGORITHM( TimingAlg );
+  DECLARE_ALGORITHM( MemoryAlg );
+  DECLARE_ALGORITHM( JobInfo );
+}   
diff --git a/Reconstruction/RecAlgs/src/components/RecAlgs_load.cxx b/Reconstruction/RecAlgs/src/components/RecAlgs_load.cxx
new file mode 100755
index 00000000000..36c0d478e78
--- /dev/null
+++ b/Reconstruction/RecAlgs/src/components/RecAlgs_load.cxx
@@ -0,0 +1,4 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( RecAlgs )
+
-- 
GitLab