CMS 3D CMS Logo

IgProfPerf.cc

Go to the documentation of this file.
00001 #include "IgTools/IgProf/src/IgProf.h"
00002 #include "IgTools/IgProf/src/IgProfTrace.h"
00003 #include "IgTools/IgHook/interface/IgHook.h"
00004 #include "IgTools/IgHook/interface/IgHookTrace.h"
00005 #include <cstdlib>
00006 #include <cstring>
00007 #include <signal.h>
00008 #include <sys/time.h>
00009 
00010 #ifdef __APPLE__
00011 typedef sig_t sighandler_t;
00012 #endif
00013 
00014 // -------------------------------------------------------------------
00015 // Traps for this profiler module
00016 IGPROF_LIBHOOK(3, int, dopthread_sigmask, _main,
00017                (int how, sigset_t *newmask, sigset_t *oldmask),
00018                (how, newmask, oldmask),
00019                "pthread_sigmask", 0, 0)
00020 IGPROF_LIBHOOK(3, int, dosigaction, _main,
00021                (int signum, const struct sigaction *act, struct sigaction *oact),
00022                (signum, act, oact),
00023                "sigaction", 0, 0)
00024 
00025 // Data for this profiler module
00026 static IgProfTrace::CounterDef  s_ct_ticks      = { "PERF_TICKS", IgProfTrace::TICK, -1 };
00027 static bool                     s_initialized   = false;
00028 static int                      s_signal        = SIGPROF;
00029 static int                      s_itimer        = ITIMER_PROF;
00030 static int                      s_moduleid      = -1;
00031 
00037 static void
00038 profileSignalHandler(int /* nsig */, siginfo_t * /* info */, void * /* ctx */)
00039 {
00040   if (! IgProf::enabled(false))
00041     return;
00042 
00043   IgProfTrace *buf = IgProf::buffer(s_moduleid);
00044   if (! buf)
00045     return;
00046 
00047   void                  *addresses [IgProfTrace::MAX_DEPTH];
00048   int                   depth = IgHookTrace::stacktrace(addresses, IgProfTrace::MAX_DEPTH);
00049   IgProfTrace::Record   entry = { IgProfTrace::COUNT, &s_ct_ticks, 1, 1, 0 };
00050 
00051   // Drop two bottom frames, three top ones (stacktrace, me, signal frame).
00052   buf->push(addresses+3, depth-4, &entry, 1);
00053 }
00054 
00058 static void
00059 enableTimer(void)
00060 {
00061   itimerval interval = { { 0, 10000 }, { 0, 10000 } };
00062   setitimer(s_itimer, &interval, 0);
00063 }
00064 
00066 static void
00067 enableSignalHandler(void)
00068 {
00069   sigset_t profset;
00070   sigemptyset(&profset);
00071   sigaddset(&profset, s_signal);
00072   if (IgProf::isMultiThreaded())
00073     pthread_sigmask(SIG_UNBLOCK, &profset, 0);
00074   else
00075     sigprocmask(SIG_UNBLOCK, &profset, 0);
00076 
00077   struct sigaction sa;
00078   sigemptyset(&sa.sa_mask);
00079   sa.sa_handler = (sighandler_t) &profileSignalHandler;
00080   sa.sa_flags = SA_RESTART | SA_SIGINFO;
00081   sigaction(s_signal, &sa, 0);
00082 }
00083 
00085 static void
00086 threadInit(void)
00087 {
00088   // Enable profiling in this thread.
00089   enableSignalHandler();
00090   enableTimer();
00091 }
00092 
00093 // -------------------------------------------------------------------
00095 static void
00096 initialize(void)
00097 {
00098   if (s_initialized) return;
00099   s_initialized = true;
00100 
00101   const char    *options = IgProf::options();
00102   bool          enable = false;
00103 
00104   while (options && *options)
00105   {
00106     while (*options == ' ' || *options == ',')
00107       ++options;
00108 
00109     if (! strncmp(options, "perf", 4))
00110     {
00111       enable = true;
00112       options += 4;
00113       while (*options)
00114       {
00115         if (! strncmp(options, ":real", 5))
00116         {
00117           s_signal = SIGALRM;
00118           s_itimer = ITIMER_REAL;
00119           options += 5;
00120         }
00121         else if (! strncmp(options, ":user", 5))
00122         {
00123           s_signal = SIGVTALRM;
00124           s_itimer = ITIMER_VIRTUAL;
00125           options += 5;
00126         }
00127         else if (! strncmp(options, ":process", 7))
00128         {
00129           s_signal = SIGPROF;
00130           s_itimer = ITIMER_PROF;
00131           options += 7;
00132         }
00133         else
00134           break;
00135       }
00136     }
00137     else
00138       options++;
00139 
00140     while (*options && *options != ',' && *options != ' ')
00141       options++;
00142   }
00143 
00144   if (! enable)
00145     return;
00146 
00147   if (! IgProf::initialize(&s_moduleid, &threadInit, true))
00148     return;
00149 
00150   IgProf::disable(true);
00151   if (s_itimer == ITIMER_REAL)
00152     IgProf::debug("Perf: measuring real time\n");
00153   else if (s_itimer == ITIMER_VIRTUAL)
00154     IgProf::debug("Perf: profiling user time\n");
00155   else if (s_itimer == ITIMER_PROF)
00156     IgProf::debug("Perf: profiling process time\n");
00157 
00158   // Enable profiler.
00159   IgHook::hook(dopthread_sigmask_hook_main.raw);
00160   IgHook::hook(dosigaction_hook_main.raw);
00161   IgProf::debug("Performance profiler enabled\n");
00162 
00163   enableSignalHandler();
00164   enableTimer();
00165   IgProf::enable(true);
00166 }
00167 
00168 // -------------------------------------------------------------------
00169 // Trap fiddling with thread signal masks
00170 static int
00171 dopthread_sigmask(IgHook::SafeData<igprof_dopthread_sigmask_t> &hook,
00172                   int how, sigset_t *newmask,  sigset_t *oldmask)
00173 {
00174   if (newmask
00175       && (how == SIG_BLOCK || how == SIG_SETMASK)
00176       && sigismember(newmask, s_signal))
00177   {
00178     IgProf::debug("pthread_sigmask(): prevented profiling signal"
00179                   " %d from being blocked in thread 0x%lx\n",
00180                   s_signal, (unsigned long) pthread_self());
00181     sigdelset(newmask, s_signal);
00182   }
00183 
00184   return hook.chain(how, newmask, oldmask);
00185 }
00186 
00187 // Trap fiddling with the profiling signal.
00188 static int
00189 dosigaction(IgHook::SafeData<igprof_dosigaction_t> &hook,
00190             int signum, const struct sigaction *act, struct sigaction *oact)
00191 {
00192   struct sigaction sa;
00193   if (signum == s_signal
00194       && act
00195       && act->sa_handler != (sighandler_t) &profileSignalHandler)
00196   {
00197     IgProf::debug("sigaction(): prevented profiling signal"
00198                   " %d from being overridden in thread 0x%lx\n",
00199                   s_signal, (unsigned long) pthread_self());
00200     sigemptyset(&sa.sa_mask);
00201     sa.sa_handler = (sighandler_t) &profileSignalHandler;
00202     sa.sa_flags = SA_RESTART | SA_SIGINFO;
00203     act = &sa;
00204   }
00205 
00206   return hook.chain(signum, act, oact);
00207 }
00208 
00209 // -------------------------------------------------------------------
00210 static bool autoboot = (initialize(), true);

Generated on Tue Jun 9 17:38:08 2009 for CMSSW by  doxygen 1.5.4