summaryrefslogtreecommitdiffstats
path: root/tools/profiler/tasktracer/GeckoTaskTracerImpl.h
blob: 2b44a0f9045dc6683e42e188ac389b245ffcda92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GECKO_TASK_TRACER_IMPL_H
#define GECKO_TASK_TRACER_IMPL_H

#include "GeckoTaskTracer.h"

#include "mozilla/Mutex.h"
#include "nsTArray.h"

namespace mozilla {
namespace tasktracer {

struct LogRecDispatch {
  uint32_t mType;
  uint32_t mSourceEventType;
  uint64_t mTaskId;
  uint64_t mTime;
  uint64_t mSourceEventId;
  uint64_t mParentTaskId;
};

struct LogRecBegin {
  uint32_t mType;
  uint64_t mTaskId;
  uint64_t mTime;
  uint32_t mPid;
  uint32_t mTid;
};

struct LogRecEnd {
  uint32_t mType;
  uint64_t mTaskId;
  uint64_t mTime;
};

struct LogRecVPtr {
  uint32_t mType;
  uint64_t mTaskId;
  uintptr_t mVPtr;
};

struct LogRecLabel {
  uint32_t mType;
  uint32_t mStrIdx;
  uint64_t mTaskId;
  uint64_t mTime;
};

union TraceInfoLogType {
  uint32_t mType;
  LogRecDispatch mDispatch;
  LogRecBegin mBegin;
  LogRecEnd mEnd;
  LogRecVPtr mVPtr;
  LogRecLabel mLabel;
};

struct TraceInfoLogNode {
  TraceInfoLogType mLog;
  TraceInfoLogNode* mNext;
};

struct TraceInfo {
  explicit TraceInfo(uint32_t aThreadId)
      : mCurTraceSourceId(0),
        mCurTaskId(0),
        mCurTraceSourceType(Unknown),
        mThreadId(aThreadId),
        mLastUniqueTaskId(0),
        mObsolete(false),
        mLogsMutex("TraceInfoMutex"),
        mLogsHead(nullptr),
        mLogsTail(nullptr),
        mLogsSize(0) {
    MOZ_COUNT_CTOR(TraceInfo);
  }

  ~TraceInfo() {
    MOZ_COUNT_DTOR(TraceInfo);
    while (mLogsHead) {
      auto node = mLogsHead;
      mLogsHead = node->mNext;
      delete node;
    }
  }

  TraceInfoLogType* AppendLog();

  uint64_t mCurTraceSourceId;
  uint64_t mCurTaskId;
  SourceEventType mCurTraceSourceType;
  uint32_t mThreadId;
  uint32_t mLastUniqueTaskId;
  mozilla::Atomic<bool> mObsolete;

  // This mutex protects the following log
  mozilla::Mutex mLogsMutex;
  TraceInfoLogNode* mLogsHead;
  TraceInfoLogNode* mLogsTail;
  int mLogsSize;
  nsTArray<nsCString> mStrs;
};

class TraceInfoHolder {
 public:
  TraceInfoHolder() : mInfo(nullptr) {}
  explicit TraceInfoHolder(TraceInfo* aInfo) : mInfo(aInfo) {
    aInfo->mLogsMutex.AssertNotCurrentThreadOwns();  // in case of recursive
    aInfo->mLogsMutex.Lock();
    MOZ_ASSERT(aInfo);
  }
  TraceInfoHolder(const TraceInfoHolder& aOther) = delete;
  TraceInfoHolder(TraceInfoHolder&& aOther) : mInfo(aOther.mInfo) {
    if (!!aOther) {
      aOther->mLogsMutex.AssertCurrentThreadOwns();
    }
    aOther.mInfo = nullptr;
  }
  ~TraceInfoHolder() {
    if (mInfo) mInfo->mLogsMutex.Unlock();
  }
  explicit operator bool() const { return !!mInfo; }
  TraceInfo* operator->() { return mInfo; }
  bool operator==(TraceInfo* aOther) const { return mInfo == aOther; }
  bool operator==(const TraceInfoHolder& aOther) const {
    return mInfo == aOther.mInfo;
  }
  void Reset() {
    if (mInfo) {
      mInfo->mLogsMutex.Unlock();
      mInfo = nullptr;
    }
  }

 private:
  TraceInfo* mInfo;
};

// Return the TraceInfo of current thread, allocate a new one if not exit.
TraceInfoHolder GetOrCreateTraceInfo();

uint64_t GenNewUniqueTaskId();

void SetCurTraceInfo(uint64_t aSourceEventId, uint64_t aParentTaskId,
                     SourceEventType aSourceEventType);

/**
 * Logging functions of different trace actions.
 */
enum ActionType {
  ACTION_DISPATCH = 0,
  ACTION_BEGIN,
  ACTION_END,
  ACTION_ADD_LABEL,
  ACTION_GET_VTABLE
};

void LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId,
                 uint64_t aSourceEventId, SourceEventType aSourceEventType);

void LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId,
                 uint64_t aSourceEventId, SourceEventType aSourceEventType,
                 int aDelayTimeMs);

void LogBegin(uint64_t aTaskId, uint64_t aSourceEventId);

void LogEnd(uint64_t aTaskId, uint64_t aSourceEventId);

void LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId,
                        uintptr_t* aVptr);

}  // namespace tasktracer
}  // namespace mozilla

#endif