Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "GeckoTaskTracer.h" |
michael@0 | 8 | #include "GeckoTaskTracerImpl.h" |
michael@0 | 9 | |
michael@0 | 10 | #include "mozilla/StaticMutex.h" |
michael@0 | 11 | #include "mozilla/ThreadLocal.h" |
michael@0 | 12 | #include "mozilla/unused.h" |
michael@0 | 13 | |
michael@0 | 14 | #include "nsClassHashtable.h" |
michael@0 | 15 | #include "nsThreadUtils.h" |
michael@0 | 16 | |
michael@0 | 17 | #include <stdarg.h> |
michael@0 | 18 | #include <stdio.h> |
michael@0 | 19 | #include <unistd.h> |
michael@0 | 20 | |
michael@0 | 21 | #if defined(__GLIBC__) |
michael@0 | 22 | // glibc doesn't implement gettid(2). |
michael@0 | 23 | #include <sys/syscall.h> |
michael@0 | 24 | static pid_t gettid() |
michael@0 | 25 | { |
michael@0 | 26 | return (pid_t) syscall(SYS_gettid); |
michael@0 | 27 | } |
michael@0 | 28 | #endif |
michael@0 | 29 | |
michael@0 | 30 | #define MAX_USER_LABEL_LEN 512 |
michael@0 | 31 | |
michael@0 | 32 | namespace mozilla { |
michael@0 | 33 | namespace tasktracer { |
michael@0 | 34 | |
michael@0 | 35 | static mozilla::ThreadLocal<TraceInfo*> sTraceInfoTLS; |
michael@0 | 36 | static StaticMutex sMutex; |
michael@0 | 37 | static nsClassHashtable<nsUint32HashKey, TraceInfo>* sTraceInfos = nullptr; |
michael@0 | 38 | |
michael@0 | 39 | namespace { |
michael@0 | 40 | |
michael@0 | 41 | static TraceInfo* |
michael@0 | 42 | AllocTraceInfo(int aTid) |
michael@0 | 43 | { |
michael@0 | 44 | StaticMutexAutoLock lock(sMutex); |
michael@0 | 45 | |
michael@0 | 46 | sTraceInfos->Put(aTid, new TraceInfo(aTid)); |
michael@0 | 47 | return sTraceInfos->Get(aTid); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | static void |
michael@0 | 51 | FreeTraceInfo(int aTid) |
michael@0 | 52 | { |
michael@0 | 53 | StaticMutexAutoLock lock(sMutex); |
michael@0 | 54 | |
michael@0 | 55 | sTraceInfos->Remove(aTid); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | static bool |
michael@0 | 59 | IsInitialized() |
michael@0 | 60 | { |
michael@0 | 61 | return sTraceInfoTLS.initialized(); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | static void |
michael@0 | 65 | SaveCurTraceInfo() |
michael@0 | 66 | { |
michael@0 | 67 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 68 | NS_ENSURE_TRUE_VOID(info); |
michael@0 | 69 | |
michael@0 | 70 | info->mSavedCurTraceSourceId = info->mCurTraceSourceId; |
michael@0 | 71 | info->mSavedCurTraceSourceType = info->mCurTraceSourceType; |
michael@0 | 72 | info->mSavedCurTaskId = info->mCurTaskId; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | static void |
michael@0 | 76 | RestoreCurTraceInfo() |
michael@0 | 77 | { |
michael@0 | 78 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 79 | NS_ENSURE_TRUE_VOID(info); |
michael@0 | 80 | |
michael@0 | 81 | info->mCurTraceSourceId = info->mSavedCurTraceSourceId; |
michael@0 | 82 | info->mCurTraceSourceType = info->mSavedCurTraceSourceType; |
michael@0 | 83 | info->mCurTaskId = info->mSavedCurTaskId; |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | static void |
michael@0 | 87 | CreateSourceEvent(SourceEventType aType) |
michael@0 | 88 | { |
michael@0 | 89 | NS_ENSURE_TRUE_VOID(IsInitialized()); |
michael@0 | 90 | |
michael@0 | 91 | // Save the currently traced source event info. |
michael@0 | 92 | SaveCurTraceInfo(); |
michael@0 | 93 | |
michael@0 | 94 | // Create a new unique task id. |
michael@0 | 95 | uint64_t newId = GenNewUniqueTaskId(); |
michael@0 | 96 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 97 | info->mCurTraceSourceId = newId; |
michael@0 | 98 | info->mCurTraceSourceType = aType; |
michael@0 | 99 | info->mCurTaskId = newId; |
michael@0 | 100 | |
michael@0 | 101 | // Log a fake dispatch and start for this source event. |
michael@0 | 102 | LogDispatch(newId, newId,newId, aType); |
michael@0 | 103 | LogBegin(newId, newId); |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | static void |
michael@0 | 107 | DestroySourceEvent() |
michael@0 | 108 | { |
michael@0 | 109 | NS_ENSURE_TRUE_VOID(IsInitialized()); |
michael@0 | 110 | |
michael@0 | 111 | // Log a fake end for this source event. |
michael@0 | 112 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 113 | LogEnd(info->mCurTraceSourceId, info->mCurTraceSourceId); |
michael@0 | 114 | |
michael@0 | 115 | // Restore the previously saved source event info. |
michael@0 | 116 | RestoreCurTraceInfo(); |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | } // namespace anonymous |
michael@0 | 120 | |
michael@0 | 121 | void |
michael@0 | 122 | InitTaskTracer() |
michael@0 | 123 | { |
michael@0 | 124 | MOZ_ASSERT(!sTraceInfos); |
michael@0 | 125 | |
michael@0 | 126 | sTraceInfos = new nsClassHashtable<nsUint32HashKey, TraceInfo>(); |
michael@0 | 127 | |
michael@0 | 128 | if (!sTraceInfoTLS.initialized()) { |
michael@0 | 129 | unused << sTraceInfoTLS.init(); |
michael@0 | 130 | } |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | void |
michael@0 | 134 | ShutdownTaskTracer() |
michael@0 | 135 | { |
michael@0 | 136 | delete sTraceInfos; |
michael@0 | 137 | sTraceInfos = nullptr; |
michael@0 | 138 | } |
michael@0 | 139 | |
michael@0 | 140 | TraceInfo* |
michael@0 | 141 | GetOrCreateTraceInfo() |
michael@0 | 142 | { |
michael@0 | 143 | NS_ENSURE_TRUE(IsInitialized(), nullptr); |
michael@0 | 144 | |
michael@0 | 145 | TraceInfo* info = sTraceInfoTLS.get(); |
michael@0 | 146 | if (!info) { |
michael@0 | 147 | info = AllocTraceInfo(gettid()); |
michael@0 | 148 | sTraceInfoTLS.set(info); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | return info; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | uint64_t |
michael@0 | 155 | GenNewUniqueTaskId() |
michael@0 | 156 | { |
michael@0 | 157 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 158 | NS_ENSURE_TRUE(info, 0); |
michael@0 | 159 | |
michael@0 | 160 | pid_t tid = gettid(); |
michael@0 | 161 | uint64_t taskid = ((uint64_t)tid << 32) | ++info->mLastUniqueTaskId; |
michael@0 | 162 | return taskid; |
michael@0 | 163 | } |
michael@0 | 164 | |
michael@0 | 165 | AutoSaveCurTraceInfo::AutoSaveCurTraceInfo() |
michael@0 | 166 | { |
michael@0 | 167 | SaveCurTraceInfo(); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | AutoSaveCurTraceInfo::~AutoSaveCurTraceInfo() |
michael@0 | 171 | { |
michael@0 | 172 | RestoreCurTraceInfo(); |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | void |
michael@0 | 176 | SetCurTraceInfo(uint64_t aSourceEventId, uint64_t aParentTaskId, |
michael@0 | 177 | SourceEventType aSourceEventType) |
michael@0 | 178 | { |
michael@0 | 179 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 180 | NS_ENSURE_TRUE_VOID(info); |
michael@0 | 181 | |
michael@0 | 182 | info->mCurTraceSourceId = aSourceEventId; |
michael@0 | 183 | info->mCurTaskId = aParentTaskId; |
michael@0 | 184 | info->mCurTraceSourceType = aSourceEventType; |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | void |
michael@0 | 188 | GetCurTraceInfo(uint64_t* aOutSourceEventId, uint64_t* aOutParentTaskId, |
michael@0 | 189 | SourceEventType* aOutSourceEventType) |
michael@0 | 190 | { |
michael@0 | 191 | TraceInfo* info = GetOrCreateTraceInfo(); |
michael@0 | 192 | NS_ENSURE_TRUE_VOID(info); |
michael@0 | 193 | |
michael@0 | 194 | *aOutSourceEventId = info->mCurTraceSourceId; |
michael@0 | 195 | *aOutParentTaskId = info->mCurTaskId; |
michael@0 | 196 | *aOutSourceEventType = info->mCurTraceSourceType; |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | void |
michael@0 | 200 | LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId, |
michael@0 | 201 | SourceEventType aSourceEventType) |
michael@0 | 202 | { |
michael@0 | 203 | NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); |
michael@0 | 204 | |
michael@0 | 205 | // Log format: |
michael@0 | 206 | // [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId] |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | void |
michael@0 | 210 | LogBegin(uint64_t aTaskId, uint64_t aSourceEventId) |
michael@0 | 211 | { |
michael@0 | 212 | NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); |
michael@0 | 213 | |
michael@0 | 214 | // Log format: |
michael@0 | 215 | // [1 taskId beginTime processId threadId] |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | void |
michael@0 | 219 | LogEnd(uint64_t aTaskId, uint64_t aSourceEventId) |
michael@0 | 220 | { |
michael@0 | 221 | NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); |
michael@0 | 222 | |
michael@0 | 223 | // Log format: |
michael@0 | 224 | // [2 taskId endTime] |
michael@0 | 225 | } |
michael@0 | 226 | |
michael@0 | 227 | void |
michael@0 | 228 | LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId, int* aVptr) |
michael@0 | 229 | { |
michael@0 | 230 | NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); |
michael@0 | 231 | |
michael@0 | 232 | // Log format: |
michael@0 | 233 | // [4 taskId address] |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | void |
michael@0 | 237 | FreeTraceInfo() |
michael@0 | 238 | { |
michael@0 | 239 | NS_ENSURE_TRUE_VOID(IsInitialized()); |
michael@0 | 240 | |
michael@0 | 241 | FreeTraceInfo(gettid()); |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | AutoSourceEvent::AutoSourceEvent(SourceEventType aType) |
michael@0 | 245 | { |
michael@0 | 246 | CreateSourceEvent(aType); |
michael@0 | 247 | } |
michael@0 | 248 | |
michael@0 | 249 | AutoSourceEvent::~AutoSourceEvent() |
michael@0 | 250 | { |
michael@0 | 251 | DestroySourceEvent(); |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | void AddLabel(const char* aFormat, ...) |
michael@0 | 255 | { |
michael@0 | 256 | NS_ENSURE_TRUE_VOID(IsInitialized()); |
michael@0 | 257 | |
michael@0 | 258 | va_list args; |
michael@0 | 259 | va_start(args, aFormat); |
michael@0 | 260 | char buffer[MAX_USER_LABEL_LEN] = {0}; |
michael@0 | 261 | vsnprintf(buffer, MAX_USER_LABEL_LEN, aFormat, args); |
michael@0 | 262 | va_end(args); |
michael@0 | 263 | |
michael@0 | 264 | // Log format: |
michael@0 | 265 | // [3 taskId "label"] |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | } // namespace tasktracer |
michael@0 | 269 | } // namespace mozilla |