xpcom/build/perfprobe.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*****************************
     7  Windows implementation of probes, using xperf
     8  *****************************/
     9 #include <windows.h>
    10 #include <wmistr.h>
    11 #include <evntrace.h>
    13 #include "perfprobe.h"
    14 #include "nsAutoPtr.h"
    16 namespace mozilla {
    17 namespace probes {
    19 #if defined(MOZ_LOGGING)
    20 static PRLogModuleInfo *
    21 GetProbeLog()
    22 {
    23   static PRLogModuleInfo *sLog;
    24   if (!sLog)
    25     sLog = PR_NewLogModule("SysProbe");
    26   return sLog;
    27 }
    28 #define LOG(x)  PR_LOG(GetProbeLog(), PR_LOG_DEBUG, x)
    29 #else
    30 #define LOG(x)
    31 #endif
    33 //Utility function
    34 GUID CID_to_GUID(const nsCID &aCID)
    35 {
    36   GUID result;
    37   result.Data1 = aCID.m0;
    38   result.Data2 = aCID.m1;
    39   result.Data3 = aCID.m2;
    40   for (int i = 0; i < 8; ++i)
    41     result.Data4[i] = aCID.m3[i];
    42   return result;
    43 }
    47 // Implementation of Probe
    49 Probe::Probe(const nsCID &aGUID,
    50              const nsACString &aName,
    51              ProbeManager *aManager)
    52   : mGUID(CID_to_GUID(aGUID))
    53   , mName(aName)
    54   , mManager(aManager)
    55 {
    56 }
    58 nsresult Probe::Trigger()
    59 {
    60   if (!(mManager->mIsActive)) {
    61     //Do not trigger if there is no session
    62     return NS_OK; 
    63   }
    65   _EVENT_TRACE_HEADER event;
    66   ZeroMemory(&event, sizeof(event));
    67   event.Size = sizeof(event);
    68   event.Flags = WNODE_FLAG_TRACED_GUID ;
    69   event.Guid = (const GUID)mGUID;
    70   event.Class.Type    = 1;
    71   event.Class.Version = 0;
    72   event.Class.Level   = TRACE_LEVEL_INFORMATION;
    74   ULONG result        = TraceEvent(mManager->mSessionHandle, &event);
    76   LOG(("Probes: Triggered %s, %s, %ld",
    77        mName.Data(),
    78        result==ERROR_SUCCESS ? "success":"failure",
    79        result));
    81   nsresult rv;
    82   switch(result)
    83   {
    84     case ERROR_SUCCESS:             rv = NS_OK; break;
    85     case ERROR_INVALID_FLAG_NUMBER:
    86     case ERROR_MORE_DATA:
    87     case ERROR_INVALID_PARAMETER:   rv = NS_ERROR_INVALID_ARG; break;
    88     case ERROR_INVALID_HANDLE:      rv = NS_ERROR_FAILURE;     break;
    89     case ERROR_NOT_ENOUGH_MEMORY:
    90     case ERROR_OUTOFMEMORY:         rv = NS_ERROR_OUT_OF_MEMORY; break;
    91     default:                        rv = NS_ERROR_UNEXPECTED;
    92   }
    93   return rv;
    94 }
    97 // Implementation of ProbeManager
    99 ProbeManager::~ProbeManager()
   100 {
   101   //If the manager goes out of scope, stop the session.
   102   if (mIsActive && mRegistrationHandle) {
   103     StopSession();
   104   }
   105 }
   107 ProbeManager::ProbeManager(const nsCID &aApplicationUID,
   108                            const nsACString &aApplicationName)
   109   : mApplicationUID(aApplicationUID)
   110   , mApplicationName(aApplicationName)
   111   , mSessionHandle(0)
   112   , mRegistrationHandle(0)
   113 {
   114 #if defined(MOZ_LOGGING)
   115   char cidStr[NSID_LENGTH];
   116   aApplicationUID.ToProvidedString(cidStr);
   117   LOG(("ProbeManager::Init for application %s, %s",
   118        aApplicationName.Data(), cidStr));
   119 #endif
   120 }
   122 //Note: The Windows API is just a little bit scary there.
   123 //The only way to obtain the session handle is to
   124 //- ignore the session handle obtained from RegisterTraceGuids
   125 //- pass a callback
   126 //- in that callback, request the session handle through
   127 //      GetTraceLoggerHandle and some opaque value received by the callback
   129 ULONG WINAPI ControlCallback(
   130                              WMIDPREQUESTCODE RequestCode,
   131                              PVOID Context,
   132                              ULONG *Reserved,
   133                              PVOID Buffer
   134                              )
   135 {
   136   ProbeManager* context = (ProbeManager*)Context;
   137   switch(RequestCode)
   138   {
   139   case WMI_ENABLE_EVENTS: 
   140     {
   141       context->mIsActive = true;
   142       TRACEHANDLE sessionHandle = GetTraceLoggerHandle(Buffer);
   143       //Note: We only accept one handle
   144       if ((HANDLE)sessionHandle == INVALID_HANDLE_VALUE) {
   145         ULONG result = GetLastError();
   146         LOG(("Probes: ControlCallback failed, %ul", result));
   147         return result;
   148       } else if (context->mIsActive && context->mSessionHandle
   149                 && context->mSessionHandle != sessionHandle) {
   150         LOG(("Probes: Can only handle one context at a time, "
   151              "ignoring activation"));
   152         return ERROR_SUCCESS;
   153       } else {
   154         context->mSessionHandle = sessionHandle;
   155         LOG(("Probes: ControlCallback activated"));
   156         return ERROR_SUCCESS;
   157       }
   158     }
   160   case WMI_DISABLE_EVENTS:
   161     context->mIsActive      = false;
   162     context->mSessionHandle = 0;
   163     LOG(("Probes: ControlCallback deactivated"));
   164     return ERROR_SUCCESS;
   166   default:
   167     LOG(("Probes: ControlCallback does not know what to do with %d",
   168          RequestCode));
   169     return ERROR_INVALID_PARAMETER;
   170   }
   171 }
   173 already_AddRefed<Probe> ProbeManager::GetProbe(const nsCID &eventUID,
   174                                const nsACString &eventName)
   175 {
   176   nsRefPtr<Probe> result(new Probe(eventUID, eventName, this));
   177   mAllProbes.AppendElement(result);
   178   return result.forget();
   179 }
   181 nsresult ProbeManager::StartSession()
   182 {
   183   return StartSession(mAllProbes);
   184 }
   186 nsresult ProbeManager::StartSession(nsTArray<nsRefPtr<Probe>> &aProbes)
   187 {
   188   const size_t probesCount = aProbes.Length();
   189   _TRACE_GUID_REGISTRATION* probes = new _TRACE_GUID_REGISTRATION[probesCount];
   190   for (unsigned int i = 0; i < probesCount; ++i) {
   191     const Probe *probe = aProbes[i];
   192     const Probe *probeX = static_cast<const Probe*>(probe);
   193     probes[i].Guid = (LPCGUID)&(probeX->mGUID);
   194   }
   195   ULONG result =
   196     RegisterTraceGuids(&ControlCallback
   197                      /*RequestAddress: Sets mSessions appropriately.*/,
   198                      this
   199                      /*RequestContext: Passed to ControlCallback*/,
   200                      (LPGUID)&mApplicationUID
   201                      /*ControlGuid:    Tracing GUID
   202                       the cast comes from MSDN examples*/,
   203                      probesCount
   204                      /*GuidCount:      Number of probes*/,
   205                      probes
   206                      /*TraceGuidReg:   Probes registration*/,
   207                      nullptr
   208                      /*MofImagePath:   Must be nullptr, says MSDN*/,
   209                      nullptr
   210                      /*MofResourceName:Must be nullptr, says MSDN*/,
   211                      &mRegistrationHandle
   212                      /*RegistrationHandle: Handler.
   213                       used only for unregistration*/
   214                      );
   215   delete[] probes;
   216   if (NS_WARN_IF(result != ERROR_SUCCESS))
   217     return NS_ERROR_UNEXPECTED;
   218   return NS_OK;
   219 }
   221 nsresult ProbeManager::StopSession()
   222 {
   223   LOG(("Probes: Stopping measures"));
   224   if (mSessionHandle != 0) {
   225     ULONG result = UnregisterTraceGuids(mSessionHandle);
   226     mSessionHandle = 0;
   227     if (result != ERROR_SUCCESS) {
   228       return NS_ERROR_INVALID_ARG;
   229     }
   230   }
   231   return NS_OK;
   232 }
   235 }
   236 }

mercurial