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