1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * A mechanism for interacting with operating system-provided 9 * debugging/profiling tools such as Microsoft EWT/Windows Performance Toolkit. 10 */ 11 12 #ifndef mozilla_perfprobe_h 13 #define mozilla_perfprobe_h 14 15 #if !defined(XP_WIN) 16 #error "For the moment, perfprobe.h is defined only for Windows platforms" 17 #endif 18 19 #include "nsError.h" 20 #include "nsString.h" 21 #include "mozilla/Logging.h" 22 #include "nsTArray.h" 23 #include "nsAutoPtr.h" 24 #include <windows.h> 25 #undef GetStartupInfo //Prevent Windows from polluting global namespace 26 #include <wmistr.h> 27 #include <evntrace.h> 28 29 namespace mozilla { 30 namespace probes { 31 32 class ProbeManager; 33 34 /** 35 * A data structure supporting a trigger operation that can be used to 36 * send information to the operating system. 37 */ 38 39 class Probe 40 { 41 public: 42 NS_INLINE_DECL_REFCOUNTING(Probe) 43 44 /** 45 * Trigger the event. 46 * 47 * Note: Can be called from any thread. 48 */ 49 nsresult Trigger(); 50 51 protected: ~Probe()52 ~Probe() {}; 53 54 Probe(const nsCID& aGUID, const nsACString& aName, ProbeManager* aManager); 55 friend class ProbeManager; 56 57 protected: 58 59 /** 60 * The system GUID associated to this probe. See the documentation 61 * of |ProbeManager::Make| for more details. 62 */ 63 const GUID mGUID; 64 65 /** 66 * The name of this probe. See the documentation 67 * of |ProbeManager::Make| for more details. 68 */ 69 const nsCString mName; 70 71 /** 72 * The ProbeManager managing this probe. 73 * 74 * Note: This is a weak reference to avoid a useless cycle. 75 */ 76 class ProbeManager* mManager; 77 }; 78 79 80 /** 81 * A manager for a group of probes. 82 * 83 * You can have several managers in one application, provided that they all 84 * have distinct IDs and names. However, having more than 2 is considered a bad 85 * practice. 86 */ 87 class ProbeManager 88 { 89 public: 90 NS_INLINE_DECL_REFCOUNTING(ProbeManager) 91 92 /** 93 * Create a new probe manager. 94 * 95 * This constructor should be called from the main thread. 96 * 97 * @param aApplicationUID The unique ID of the probe. Under Windows, this 98 * unique ID must have been previously registered using an external tool. 99 * See MyCategory on http://msdn.microsoft.com/en-us/library/aa364100.aspx 100 * @param aApplicationName A name for the probe. Currently used only for 101 * logging purposes. In the future, may be attached to the data sent to the 102 * operating system. 103 * 104 * Note: If two ProbeManagers are constructed with the same uid and/or name, 105 * behavior is unspecified. 106 */ 107 ProbeManager(const nsCID& aApplicationUID, 108 const nsACString& aApplicationName); 109 110 /** 111 * Acquire a probe. 112 * 113 * Note: Only probes acquired before the call to SetReady are taken into 114 * account 115 * Note: Can be called only from the main thread. 116 * 117 * @param aEventUID The unique ID of the probe. Under Windows, this unique 118 * ID must have been previously registered using an external tool. 119 * See MyCategory on http://msdn.microsoft.com/en-us/library/aa364100.aspx 120 * @param aEventName A name for the probe. Currently used only for logging 121 * purposes. In the 122 * future, may be attached to the data sent to the operating system. 123 * @return Either |null| in case of error or a valid |Probe*|. 124 * 125 * Note: If this method is called twice with the same uid and/or name, 126 * behavior is undefined. 127 */ 128 already_AddRefed<Probe> GetProbe(const nsCID& aEventUID, 129 const nsACString& aEventName); 130 131 /** 132 * Start/stop the measuring session. 133 * 134 * This method should be called from the main thread. 135 * 136 * Note that starting an already started probe manager has no effect, 137 * nor does stopping an already stopped probe manager. 138 */ 139 nsresult StartSession(); 140 nsresult StopSession(); 141 142 /** 143 * @return true If measures are currently on, i.e. if triggering probes is any 144 * is useful. You do not have to check this before triggering a probe, unless 145 * this can avoid complex computations. 146 */ 147 bool IsActive(); 148 149 protected: 150 ~ProbeManager(); 151 152 nsresult StartSession(nsTArray<RefPtr<Probe>>& aProbes); 153 nsresult Init(const nsCID& aApplicationUID, 154 const nsACString& aApplicationName); 155 156 protected: 157 /** 158 * `true` if a session is in activity, `false` otherwise. 159 */ 160 bool mIsActive; 161 162 /** 163 * The UID of this manager. 164 * See documentation above for registration steps that you 165 * may have to take. 166 */ 167 nsCID mApplicationUID; 168 169 /** 170 * The name of the application. 171 */ 172 nsCString mApplicationName; 173 174 /** 175 * All the probes that have been created for this manager. 176 */ 177 nsTArray<RefPtr<Probe>> mAllProbes; 178 179 /** 180 * Handle used for triggering events 181 */ 182 TRACEHANDLE mSessionHandle; 183 184 /** 185 * Handle used for registration/unregistration 186 */ 187 TRACEHANDLE mRegistrationHandle; 188 189 /** 190 * `true` if initialization has been performed, `false` until then. 191 */ 192 bool mInitialized; 193 194 friend class Probe; // Needs to access |mSessionHandle| 195 friend ULONG WINAPI ControlCallback(WMIDPREQUESTCODE aRequestCode, 196 PVOID aContext, 197 ULONG* aReserved, 198 PVOID aBuffer); // Sets |mSessionHandle| 199 }; 200 201 } // namespace probes 202 } // namespace mozilla 203 204 #endif //mozilla_perfprobe_h 205