1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/GeckoTaskTracer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,269 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "GeckoTaskTracer.h" 1.11 +#include "GeckoTaskTracerImpl.h" 1.12 + 1.13 +#include "mozilla/StaticMutex.h" 1.14 +#include "mozilla/ThreadLocal.h" 1.15 +#include "mozilla/unused.h" 1.16 + 1.17 +#include "nsClassHashtable.h" 1.18 +#include "nsThreadUtils.h" 1.19 + 1.20 +#include <stdarg.h> 1.21 +#include <stdio.h> 1.22 +#include <unistd.h> 1.23 + 1.24 +#if defined(__GLIBC__) 1.25 +// glibc doesn't implement gettid(2). 1.26 +#include <sys/syscall.h> 1.27 +static pid_t gettid() 1.28 +{ 1.29 + return (pid_t) syscall(SYS_gettid); 1.30 +} 1.31 +#endif 1.32 + 1.33 +#define MAX_USER_LABEL_LEN 512 1.34 + 1.35 +namespace mozilla { 1.36 +namespace tasktracer { 1.37 + 1.38 +static mozilla::ThreadLocal<TraceInfo*> sTraceInfoTLS; 1.39 +static StaticMutex sMutex; 1.40 +static nsClassHashtable<nsUint32HashKey, TraceInfo>* sTraceInfos = nullptr; 1.41 + 1.42 +namespace { 1.43 + 1.44 +static TraceInfo* 1.45 +AllocTraceInfo(int aTid) 1.46 +{ 1.47 + StaticMutexAutoLock lock(sMutex); 1.48 + 1.49 + sTraceInfos->Put(aTid, new TraceInfo(aTid)); 1.50 + return sTraceInfos->Get(aTid); 1.51 +} 1.52 + 1.53 +static void 1.54 +FreeTraceInfo(int aTid) 1.55 +{ 1.56 + StaticMutexAutoLock lock(sMutex); 1.57 + 1.58 + sTraceInfos->Remove(aTid); 1.59 +} 1.60 + 1.61 +static bool 1.62 +IsInitialized() 1.63 +{ 1.64 + return sTraceInfoTLS.initialized(); 1.65 +} 1.66 + 1.67 +static void 1.68 +SaveCurTraceInfo() 1.69 +{ 1.70 + TraceInfo* info = GetOrCreateTraceInfo(); 1.71 + NS_ENSURE_TRUE_VOID(info); 1.72 + 1.73 + info->mSavedCurTraceSourceId = info->mCurTraceSourceId; 1.74 + info->mSavedCurTraceSourceType = info->mCurTraceSourceType; 1.75 + info->mSavedCurTaskId = info->mCurTaskId; 1.76 +} 1.77 + 1.78 +static void 1.79 +RestoreCurTraceInfo() 1.80 +{ 1.81 + TraceInfo* info = GetOrCreateTraceInfo(); 1.82 + NS_ENSURE_TRUE_VOID(info); 1.83 + 1.84 + info->mCurTraceSourceId = info->mSavedCurTraceSourceId; 1.85 + info->mCurTraceSourceType = info->mSavedCurTraceSourceType; 1.86 + info->mCurTaskId = info->mSavedCurTaskId; 1.87 +} 1.88 + 1.89 +static void 1.90 +CreateSourceEvent(SourceEventType aType) 1.91 +{ 1.92 + NS_ENSURE_TRUE_VOID(IsInitialized()); 1.93 + 1.94 + // Save the currently traced source event info. 1.95 + SaveCurTraceInfo(); 1.96 + 1.97 + // Create a new unique task id. 1.98 + uint64_t newId = GenNewUniqueTaskId(); 1.99 + TraceInfo* info = GetOrCreateTraceInfo(); 1.100 + info->mCurTraceSourceId = newId; 1.101 + info->mCurTraceSourceType = aType; 1.102 + info->mCurTaskId = newId; 1.103 + 1.104 + // Log a fake dispatch and start for this source event. 1.105 + LogDispatch(newId, newId,newId, aType); 1.106 + LogBegin(newId, newId); 1.107 +} 1.108 + 1.109 +static void 1.110 +DestroySourceEvent() 1.111 +{ 1.112 + NS_ENSURE_TRUE_VOID(IsInitialized()); 1.113 + 1.114 + // Log a fake end for this source event. 1.115 + TraceInfo* info = GetOrCreateTraceInfo(); 1.116 + LogEnd(info->mCurTraceSourceId, info->mCurTraceSourceId); 1.117 + 1.118 + // Restore the previously saved source event info. 1.119 + RestoreCurTraceInfo(); 1.120 +} 1.121 + 1.122 +} // namespace anonymous 1.123 + 1.124 +void 1.125 +InitTaskTracer() 1.126 +{ 1.127 + MOZ_ASSERT(!sTraceInfos); 1.128 + 1.129 + sTraceInfos = new nsClassHashtable<nsUint32HashKey, TraceInfo>(); 1.130 + 1.131 + if (!sTraceInfoTLS.initialized()) { 1.132 + unused << sTraceInfoTLS.init(); 1.133 + } 1.134 +} 1.135 + 1.136 +void 1.137 +ShutdownTaskTracer() 1.138 +{ 1.139 + delete sTraceInfos; 1.140 + sTraceInfos = nullptr; 1.141 +} 1.142 + 1.143 +TraceInfo* 1.144 +GetOrCreateTraceInfo() 1.145 +{ 1.146 + NS_ENSURE_TRUE(IsInitialized(), nullptr); 1.147 + 1.148 + TraceInfo* info = sTraceInfoTLS.get(); 1.149 + if (!info) { 1.150 + info = AllocTraceInfo(gettid()); 1.151 + sTraceInfoTLS.set(info); 1.152 + } 1.153 + 1.154 + return info; 1.155 +} 1.156 + 1.157 +uint64_t 1.158 +GenNewUniqueTaskId() 1.159 +{ 1.160 + TraceInfo* info = GetOrCreateTraceInfo(); 1.161 + NS_ENSURE_TRUE(info, 0); 1.162 + 1.163 + pid_t tid = gettid(); 1.164 + uint64_t taskid = ((uint64_t)tid << 32) | ++info->mLastUniqueTaskId; 1.165 + return taskid; 1.166 +} 1.167 + 1.168 +AutoSaveCurTraceInfo::AutoSaveCurTraceInfo() 1.169 +{ 1.170 + SaveCurTraceInfo(); 1.171 +} 1.172 + 1.173 +AutoSaveCurTraceInfo::~AutoSaveCurTraceInfo() 1.174 +{ 1.175 + RestoreCurTraceInfo(); 1.176 +} 1.177 + 1.178 +void 1.179 +SetCurTraceInfo(uint64_t aSourceEventId, uint64_t aParentTaskId, 1.180 + SourceEventType aSourceEventType) 1.181 +{ 1.182 + TraceInfo* info = GetOrCreateTraceInfo(); 1.183 + NS_ENSURE_TRUE_VOID(info); 1.184 + 1.185 + info->mCurTraceSourceId = aSourceEventId; 1.186 + info->mCurTaskId = aParentTaskId; 1.187 + info->mCurTraceSourceType = aSourceEventType; 1.188 +} 1.189 + 1.190 +void 1.191 +GetCurTraceInfo(uint64_t* aOutSourceEventId, uint64_t* aOutParentTaskId, 1.192 + SourceEventType* aOutSourceEventType) 1.193 +{ 1.194 + TraceInfo* info = GetOrCreateTraceInfo(); 1.195 + NS_ENSURE_TRUE_VOID(info); 1.196 + 1.197 + *aOutSourceEventId = info->mCurTraceSourceId; 1.198 + *aOutParentTaskId = info->mCurTaskId; 1.199 + *aOutSourceEventType = info->mCurTraceSourceType; 1.200 +} 1.201 + 1.202 +void 1.203 +LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId, 1.204 + SourceEventType aSourceEventType) 1.205 +{ 1.206 + NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); 1.207 + 1.208 + // Log format: 1.209 + // [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId] 1.210 +} 1.211 + 1.212 +void 1.213 +LogBegin(uint64_t aTaskId, uint64_t aSourceEventId) 1.214 +{ 1.215 + NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); 1.216 + 1.217 + // Log format: 1.218 + // [1 taskId beginTime processId threadId] 1.219 +} 1.220 + 1.221 +void 1.222 +LogEnd(uint64_t aTaskId, uint64_t aSourceEventId) 1.223 +{ 1.224 + NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); 1.225 + 1.226 + // Log format: 1.227 + // [2 taskId endTime] 1.228 +} 1.229 + 1.230 +void 1.231 +LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId, int* aVptr) 1.232 +{ 1.233 + NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId); 1.234 + 1.235 + // Log format: 1.236 + // [4 taskId address] 1.237 +} 1.238 + 1.239 +void 1.240 +FreeTraceInfo() 1.241 +{ 1.242 + NS_ENSURE_TRUE_VOID(IsInitialized()); 1.243 + 1.244 + FreeTraceInfo(gettid()); 1.245 +} 1.246 + 1.247 +AutoSourceEvent::AutoSourceEvent(SourceEventType aType) 1.248 +{ 1.249 + CreateSourceEvent(aType); 1.250 +} 1.251 + 1.252 +AutoSourceEvent::~AutoSourceEvent() 1.253 +{ 1.254 + DestroySourceEvent(); 1.255 +} 1.256 + 1.257 +void AddLabel(const char* aFormat, ...) 1.258 +{ 1.259 + NS_ENSURE_TRUE_VOID(IsInitialized()); 1.260 + 1.261 + va_list args; 1.262 + va_start(args, aFormat); 1.263 + char buffer[MAX_USER_LABEL_LEN] = {0}; 1.264 + vsnprintf(buffer, MAX_USER_LABEL_LEN, aFormat, args); 1.265 + va_end(args); 1.266 + 1.267 + // Log format: 1.268 + // [3 taskId "label"] 1.269 +} 1.270 + 1.271 +} // namespace tasktracer 1.272 +} // namespace mozilla