9dfa7f694d0e87b567c30b8943567874fe221a02
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * @file rdtsc_buckets.h
25 * @brief declaration for rdtsc buckets.
29 ******************************************************************************/
37 #include "rdtsc_buckets_shared.h"
39 // unique thread id stored in thread local storage
40 extern THREAD UINT tlsThreadId
;
42 //////////////////////////////////////////////////////////////////////////
43 /// @brief BucketManager encapsulates a single instance of the buckets
44 /// functionality. There can be one or many bucket managers active
45 /// at any time. The manager owns all the threads and
46 /// bucket information that have been registered to it.
50 BucketManager(bool enableThreadViz
) : mThreadViz(enableThreadViz
)
54 uint32_t pid
= GetCurrentProcessId();
55 std::stringstream str
;
56 str
<< "threadviz." << pid
;
57 mThreadVizDir
= str
.str();
58 CreateDirectory(mThreadVizDir
.c_str(), NULL
);
62 // removes all registered thread data
67 mThreadMutex
.unlock();
70 // removes all registered buckets
75 mThreadMutex
.unlock();
78 /// Registers a new thread with the manager.
79 /// @param name - name of thread, used for labels in reports and threadviz
80 void RegisterThread(const std::string
& name
);
82 /// Registers a new bucket type with the manager. Returns a unique
83 /// id which should be used in subsequent calls to start/stop the bucket
84 /// @param desc - description of the bucket
86 UINT
RegisterBucket(const BUCKET_DESC
& desc
);
88 // dump threadviz data
92 void PrintReport(const std::string
& filename
);
95 INLINE
void StartCapture()
101 INLINE
void StopCapture()
105 // wait for all threads to pop back to root bucket
106 bool stillCapturing
= true;
107 while (stillCapturing
)
109 stillCapturing
= false;
110 for (const BUCKET_THREAD
& t
: mThreads
)
112 if (t
.pCurrent
!= &t
.root
)
114 stillCapturing
= true;
122 // @param id generated by RegisterBucket
123 INLINE
void StartBucket(UINT id
)
125 if (!mCapturing
) return;
127 SWR_ASSERT(tlsThreadId
< mThreads
.size());
129 BUCKET_THREAD
& bt
= mThreads
[tlsThreadId
];
131 // if threadviz is enabled, only need to dump start info to threads viz file
134 SWR_ASSERT(bt
.vizFile
!= nullptr);
135 if (mBuckets
[id
].enableThreadViz
)
137 VIZ_START_DATA data
{ VIZ_START
, id
, __rdtsc() };
138 Serialize(bt
.vizFile
, data
);
143 if (bt
.pCurrent
->children
.size() < mBuckets
.size())
145 bt
.pCurrent
->children
.resize(mBuckets
.size());
147 BUCKET
&child
= bt
.pCurrent
->children
[id
];
148 child
.pParent
= bt
.pCurrent
;
150 child
.start
= __rdtsc();
152 // update thread's currently executing bucket
153 bt
.pCurrent
= &child
;
159 // stop the currently executing bucket
160 INLINE
void StopBucket(UINT id
)
162 SWR_ASSERT(tlsThreadId
< mThreads
.size());
163 BUCKET_THREAD
&bt
= mThreads
[tlsThreadId
];
165 if (bt
.level
== 0) return;
169 SWR_ASSERT(bt
.vizFile
!= nullptr);
170 if (mBuckets
[id
].enableThreadViz
)
172 VIZ_STOP_DATA data
{ VIZ_STOP
, __rdtsc() };
173 Serialize(bt
.vizFile
, data
);
178 if (bt
.pCurrent
->start
== 0) return;
179 SWR_ASSERT(bt
.pCurrent
->id
== id
, "Mismatched buckets detected");
181 bt
.pCurrent
->elapsed
+= (__rdtsc() - bt
.pCurrent
->start
);
182 bt
.pCurrent
->count
++;
185 bt
.pCurrent
= bt
.pCurrent
->pParent
;
191 INLINE
void AddEvent(uint32_t id
, uint32_t count
)
193 if (!mCapturing
) return;
195 SWR_ASSERT(tlsThreadId
< mThreads
.size());
197 BUCKET_THREAD
& bt
= mThreads
[tlsThreadId
];
199 // don't record events for threadviz
202 if (bt
.pCurrent
->children
.size() < mBuckets
.size())
204 bt
.pCurrent
->children
.resize(mBuckets
.size());
206 BUCKET
&child
= bt
.pCurrent
->children
[id
];
207 child
.pParent
= bt
.pCurrent
;
209 child
.count
+= count
;
214 void PrintBucket(FILE* f
, UINT level
, uint64_t threadCycles
, uint64_t parentCycles
, const BUCKET
& bucket
);
215 void PrintThread(FILE* f
, const BUCKET_THREAD
& thread
);
217 // list of active threads that have registered with this manager
218 std::vector
<BUCKET_THREAD
> mThreads
;
220 // list of buckets registered with this manager
221 std::vector
<BUCKET_DESC
> mBuckets
;
223 // is capturing currently enabled
224 volatile bool mCapturing
{ false };
226 std::mutex mThreadMutex
;
229 bool mThreadViz
{ false };
230 std::string mThreadVizDir
;
234 // C helpers for jitter
235 void BucketManager_StartBucket(BucketManager
* pBucketMgr
, uint32_t id
);
236 void BucketManager_StopBucket(BucketManager
* pBucketMgr
, uint32_t id
);