swr: [rasterizer core] Frontend dependency work
[mesa.git] / src / gallium / drivers / swr / rasterizer / common / rdtsc_buckets.h
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 *
23 * @file rdtsc_buckets.h
24 *
25 * @brief declaration for rdtsc buckets.
26 *
27 * Notes:
28 *
29 ******************************************************************************/
30 #pragma once
31
32 #include "os.h"
33 #include <vector>
34 #include <mutex>
35 #include <sstream>
36
37 #include "rdtsc_buckets_shared.h"
38
39
40 // unique thread id stored in thread local storage
41 extern THREAD UINT tlsThreadId;
42
43 //////////////////////////////////////////////////////////////////////////
44 /// @brief BucketManager encapsulates a single instance of the buckets
45 /// functionality. There can be one or many bucket managers active
46 /// at any time. The manager owns all the threads and
47 /// bucket information that have been registered to it.
48 class BucketManager
49 {
50 public:
51 BucketManager() { }
52 ~BucketManager();
53
54 // removes all registered thread data
55 void ClearThreads()
56 {
57 mThreadMutex.lock();
58 mThreads.clear();
59 mThreadMutex.unlock();
60 }
61
62 // removes all registered buckets
63 void ClearBuckets()
64 {
65 mThreadMutex.lock();
66 mBuckets.clear();
67 mThreadMutex.unlock();
68 }
69
70 /// Registers a new thread with the manager.
71 /// @param name - name of thread, used for labels in reports and threadviz
72 void RegisterThread(const std::string& name);
73
74 /// Registers a new bucket type with the manager. Returns a unique
75 /// id which should be used in subsequent calls to start/stop the bucket
76 /// @param desc - description of the bucket
77 /// @return unique id
78 UINT RegisterBucket(const BUCKET_DESC& desc);
79
80 // print report
81 void PrintReport(const std::string& filename);
82
83
84 // start capturing
85 void StartCapture();
86
87 // stop capturing
88 INLINE void StopCapture()
89 {
90 mCapturing = false;
91
92 // wait for all threads to pop back to root bucket
93 bool stillCapturing = true;
94 while (stillCapturing)
95 {
96 stillCapturing = false;
97 for (const BUCKET_THREAD& t : mThreads)
98 {
99 if (t.level > 0)
100 {
101 stillCapturing = true;
102 continue;
103 }
104 }
105 }
106
107 mDoneCapturing = true;
108 printf("Capture Stopped\n");
109 }
110
111 // start a bucket
112 // @param id generated by RegisterBucket
113 INLINE void StartBucket(UINT id)
114 {
115 if (!mCapturing) return;
116
117 SWR_ASSERT(tlsThreadId < mThreads.size());
118
119 BUCKET_THREAD& bt = mThreads[tlsThreadId];
120
121 uint64_t tsc = __rdtsc();
122
123 {
124 if (bt.pCurrent->children.size() < mBuckets.size())
125 {
126 bt.pCurrent->children.resize(mBuckets.size());
127 }
128 BUCKET &child = bt.pCurrent->children[id];
129 child.pParent = bt.pCurrent;
130 child.id = id;
131 child.start = tsc;
132
133 // update thread's currently executing bucket
134 bt.pCurrent = &child;
135 }
136
137
138 bt.level++;
139 }
140
141 // stop the currently executing bucket
142 INLINE void StopBucket(UINT id)
143 {
144 SWR_ASSERT(tlsThreadId < mThreads.size());
145 BUCKET_THREAD &bt = mThreads[tlsThreadId];
146
147 if (bt.level == 0)
148 {
149 return;
150 }
151
152 uint64_t tsc = __rdtsc();
153
154 {
155 if (bt.pCurrent->start == 0) return;
156 SWR_ASSERT(bt.pCurrent->id == id, "Mismatched buckets detected");
157
158 bt.pCurrent->elapsed += (tsc - bt.pCurrent->start);
159 bt.pCurrent->count++;
160
161 // pop to parent
162 bt.pCurrent = bt.pCurrent->pParent;
163 }
164
165 bt.level--;
166 }
167
168 INLINE void AddEvent(uint32_t id, uint32_t count)
169 {
170 if (!mCapturing) return;
171
172 SWR_ASSERT(tlsThreadId < mThreads.size());
173
174 BUCKET_THREAD& bt = mThreads[tlsThreadId];
175
176 // don't record events for threadviz
177 {
178 if (bt.pCurrent->children.size() < mBuckets.size())
179 {
180 bt.pCurrent->children.resize(mBuckets.size());
181 }
182 BUCKET &child = bt.pCurrent->children[id];
183 child.pParent = bt.pCurrent;
184 child.id = id;
185 child.count += count;
186 }
187 }
188
189 private:
190 void PrintBucket(FILE* f, UINT level, uint64_t threadCycles, uint64_t parentCycles, const BUCKET& bucket);
191 void PrintThread(FILE* f, const BUCKET_THREAD& thread);
192
193 // list of active threads that have registered with this manager
194 std::vector<BUCKET_THREAD> mThreads;
195
196 // list of buckets registered with this manager
197 std::vector<BUCKET_DESC> mBuckets;
198
199 // is capturing currently enabled
200 volatile bool mCapturing{ false };
201
202 // has capturing completed
203 volatile bool mDoneCapturing{ false };
204
205 std::mutex mThreadMutex;
206
207 std::string mThreadVizDir;
208
209 };
210
211
212 // C helpers for jitter
213 void BucketManager_StartBucket(BucketManager* pBucketMgr, uint32_t id);
214 void BucketManager_StopBucket(BucketManager* pBucketMgr, uint32_t id);