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.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/. */
7 #include "GeckoTaskTracer.h"
8 #include "GeckoTaskTracerImpl.h"
10 #include "mozilla/StaticMutex.h"
11 #include "mozilla/ThreadLocal.h"
12 #include "mozilla/unused.h"
14 #include "nsClassHashtable.h"
15 #include "nsThreadUtils.h"
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <unistd.h>
21 #if defined(__GLIBC__)
22 // glibc doesn't implement gettid(2).
23 #include <sys/syscall.h>
24 static pid_t gettid()
25 {
26 return (pid_t) syscall(SYS_gettid);
27 }
28 #endif
30 #define MAX_USER_LABEL_LEN 512
32 namespace mozilla {
33 namespace tasktracer {
35 static mozilla::ThreadLocal<TraceInfo*> sTraceInfoTLS;
36 static StaticMutex sMutex;
37 static nsClassHashtable<nsUint32HashKey, TraceInfo>* sTraceInfos = nullptr;
39 namespace {
41 static TraceInfo*
42 AllocTraceInfo(int aTid)
43 {
44 StaticMutexAutoLock lock(sMutex);
46 sTraceInfos->Put(aTid, new TraceInfo(aTid));
47 return sTraceInfos->Get(aTid);
48 }
50 static void
51 FreeTraceInfo(int aTid)
52 {
53 StaticMutexAutoLock lock(sMutex);
55 sTraceInfos->Remove(aTid);
56 }
58 static bool
59 IsInitialized()
60 {
61 return sTraceInfoTLS.initialized();
62 }
64 static void
65 SaveCurTraceInfo()
66 {
67 TraceInfo* info = GetOrCreateTraceInfo();
68 NS_ENSURE_TRUE_VOID(info);
70 info->mSavedCurTraceSourceId = info->mCurTraceSourceId;
71 info->mSavedCurTraceSourceType = info->mCurTraceSourceType;
72 info->mSavedCurTaskId = info->mCurTaskId;
73 }
75 static void
76 RestoreCurTraceInfo()
77 {
78 TraceInfo* info = GetOrCreateTraceInfo();
79 NS_ENSURE_TRUE_VOID(info);
81 info->mCurTraceSourceId = info->mSavedCurTraceSourceId;
82 info->mCurTraceSourceType = info->mSavedCurTraceSourceType;
83 info->mCurTaskId = info->mSavedCurTaskId;
84 }
86 static void
87 CreateSourceEvent(SourceEventType aType)
88 {
89 NS_ENSURE_TRUE_VOID(IsInitialized());
91 // Save the currently traced source event info.
92 SaveCurTraceInfo();
94 // Create a new unique task id.
95 uint64_t newId = GenNewUniqueTaskId();
96 TraceInfo* info = GetOrCreateTraceInfo();
97 info->mCurTraceSourceId = newId;
98 info->mCurTraceSourceType = aType;
99 info->mCurTaskId = newId;
101 // Log a fake dispatch and start for this source event.
102 LogDispatch(newId, newId,newId, aType);
103 LogBegin(newId, newId);
104 }
106 static void
107 DestroySourceEvent()
108 {
109 NS_ENSURE_TRUE_VOID(IsInitialized());
111 // Log a fake end for this source event.
112 TraceInfo* info = GetOrCreateTraceInfo();
113 LogEnd(info->mCurTraceSourceId, info->mCurTraceSourceId);
115 // Restore the previously saved source event info.
116 RestoreCurTraceInfo();
117 }
119 } // namespace anonymous
121 void
122 InitTaskTracer()
123 {
124 MOZ_ASSERT(!sTraceInfos);
126 sTraceInfos = new nsClassHashtable<nsUint32HashKey, TraceInfo>();
128 if (!sTraceInfoTLS.initialized()) {
129 unused << sTraceInfoTLS.init();
130 }
131 }
133 void
134 ShutdownTaskTracer()
135 {
136 delete sTraceInfos;
137 sTraceInfos = nullptr;
138 }
140 TraceInfo*
141 GetOrCreateTraceInfo()
142 {
143 NS_ENSURE_TRUE(IsInitialized(), nullptr);
145 TraceInfo* info = sTraceInfoTLS.get();
146 if (!info) {
147 info = AllocTraceInfo(gettid());
148 sTraceInfoTLS.set(info);
149 }
151 return info;
152 }
154 uint64_t
155 GenNewUniqueTaskId()
156 {
157 TraceInfo* info = GetOrCreateTraceInfo();
158 NS_ENSURE_TRUE(info, 0);
160 pid_t tid = gettid();
161 uint64_t taskid = ((uint64_t)tid << 32) | ++info->mLastUniqueTaskId;
162 return taskid;
163 }
165 AutoSaveCurTraceInfo::AutoSaveCurTraceInfo()
166 {
167 SaveCurTraceInfo();
168 }
170 AutoSaveCurTraceInfo::~AutoSaveCurTraceInfo()
171 {
172 RestoreCurTraceInfo();
173 }
175 void
176 SetCurTraceInfo(uint64_t aSourceEventId, uint64_t aParentTaskId,
177 SourceEventType aSourceEventType)
178 {
179 TraceInfo* info = GetOrCreateTraceInfo();
180 NS_ENSURE_TRUE_VOID(info);
182 info->mCurTraceSourceId = aSourceEventId;
183 info->mCurTaskId = aParentTaskId;
184 info->mCurTraceSourceType = aSourceEventType;
185 }
187 void
188 GetCurTraceInfo(uint64_t* aOutSourceEventId, uint64_t* aOutParentTaskId,
189 SourceEventType* aOutSourceEventType)
190 {
191 TraceInfo* info = GetOrCreateTraceInfo();
192 NS_ENSURE_TRUE_VOID(info);
194 *aOutSourceEventId = info->mCurTraceSourceId;
195 *aOutParentTaskId = info->mCurTaskId;
196 *aOutSourceEventType = info->mCurTraceSourceType;
197 }
199 void
200 LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
201 SourceEventType aSourceEventType)
202 {
203 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
205 // Log format:
206 // [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId]
207 }
209 void
210 LogBegin(uint64_t aTaskId, uint64_t aSourceEventId)
211 {
212 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
214 // Log format:
215 // [1 taskId beginTime processId threadId]
216 }
218 void
219 LogEnd(uint64_t aTaskId, uint64_t aSourceEventId)
220 {
221 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
223 // Log format:
224 // [2 taskId endTime]
225 }
227 void
228 LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId, int* aVptr)
229 {
230 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
232 // Log format:
233 // [4 taskId address]
234 }
236 void
237 FreeTraceInfo()
238 {
239 NS_ENSURE_TRUE_VOID(IsInitialized());
241 FreeTraceInfo(gettid());
242 }
244 AutoSourceEvent::AutoSourceEvent(SourceEventType aType)
245 {
246 CreateSourceEvent(aType);
247 }
249 AutoSourceEvent::~AutoSourceEvent()
250 {
251 DestroySourceEvent();
252 }
254 void AddLabel(const char* aFormat, ...)
255 {
256 NS_ENSURE_TRUE_VOID(IsInitialized());
258 va_list args;
259 va_start(args, aFormat);
260 char buffer[MAX_USER_LABEL_LEN] = {0};
261 vsnprintf(buffer, MAX_USER_LABEL_LEN, aFormat, args);
262 va_end(args);
264 // Log format:
265 // [3 taskId "label"]
266 }
268 } // namespace tasktracer
269 } // namespace mozilla