xpcom/build/perfprobe.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial