swr: [rasterizer] Add SWR_ASSUME / SWR_ASSUME_ASSERT macros
[mesa.git] / src / gallium / drivers / swr / rasterizer / common / rdtsc_buckets.cpp
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.cpp
24 *
25 * @brief implementation of rdtsc buckets.
26 *
27 * Notes:
28 *
29 ******************************************************************************/
30 #include "rdtsc_buckets.h"
31 #include <inttypes.h>
32
33 THREAD UINT tlsThreadId = 0;
34
35 void BucketManager::RegisterThread(const std::string& name)
36 {
37 // lazy evaluate threadviz knob
38 if (!mThreadViz && KNOB_BUCKETS_ENABLE_THREADVIZ)
39 {
40 uint32_t pid = GetCurrentProcessId();
41 std::stringstream str;
42 str << "threadviz." << pid;
43 mThreadVizDir = str.str();
44 CreateDirectory(mThreadVizDir.c_str(), NULL);
45
46 mThreadViz = true;
47 }
48
49 BUCKET_THREAD newThread;
50 newThread.name = name;
51 newThread.root.children.reserve(mBuckets.size());
52 newThread.root.id = 0;
53 newThread.root.pParent = nullptr;
54 newThread.pCurrent = &newThread.root;
55
56 mThreadMutex.lock();
57
58 // assign unique thread id for this thread
59 size_t id = mThreads.size();
60 newThread.id = (UINT)id;
61 tlsThreadId = (UINT)id;
62
63 // open threadviz file if enabled
64 if (mThreadViz)
65 {
66 std::stringstream ss;
67 ss << mThreadVizDir << "\\threadviz_thread." << newThread.id << ".dat";
68 newThread.vizFile = fopen(ss.str().c_str(), "wb");
69 }
70
71 // store new thread
72 mThreads.push_back(newThread);
73
74 mThreadMutex.unlock();
75 }
76
77 UINT BucketManager::RegisterBucket(const BUCKET_DESC& desc)
78 {
79 mThreadMutex.lock();
80 size_t id = mBuckets.size();
81 mBuckets.push_back(desc);
82 mThreadMutex.unlock();
83 return (UINT)id;
84 }
85
86 void BucketManager::PrintBucket(FILE* f, UINT level, uint64_t threadCycles, uint64_t parentCycles, const BUCKET& bucket)
87 {
88 const char *arrows[] = {
89 "",
90 "|-> ",
91 " |-> ",
92 " |-> ",
93 " |-> ",
94 " |-> ",
95 " |-> ",
96 " |-> ",
97 " |-> ",
98 };
99
100 // compute percent of total cycles used by this bucket
101 float percentTotal = (float)((double)bucket.elapsed / (double)threadCycles * 100.0);
102
103 // compute percent of parent cycles used by this bucket
104 float percentParent = (float)((double)bucket.elapsed / (double)parentCycles * 100.0);
105
106 // compute average cycle count per invocation
107 uint64_t CPE = bucket.elapsed / bucket.count;
108
109 BUCKET_DESC &desc = mBuckets[bucket.id];
110
111 // construct hierarchy visualization
112 char hier[80];
113 strcpy(hier, arrows[level]);
114 strcat(hier, desc.name.c_str());
115
116 // print out
117 fprintf(f, "%6.2f %6.2f %-10" PRIu64 " %-10" PRIu64 " %-10u %-10lu %-10u %s\n",
118 percentTotal,
119 percentParent,
120 bucket.elapsed,
121 CPE,
122 bucket.count,
123 (unsigned long)0,
124 (uint32_t)0,
125 hier
126 );
127
128 // dump all children of this bucket
129 for (const BUCKET& child : bucket.children)
130 {
131 if (child.count)
132 {
133 PrintBucket(f, level + 1, threadCycles, bucket.elapsed, child);
134 }
135 }
136 }
137
138 void BucketManager::PrintThread(FILE* f, const BUCKET_THREAD& thread)
139 {
140 // print header
141 fprintf(f, "\nThread %u (%s)\n", thread.id, thread.name.c_str());
142 fprintf(f, " %%Tot %%Par Cycles CPE NumEvent CPE2 NumEvent2 Bucket\n");
143
144 // compute thread level total cycle counts across all buckets from root
145 const BUCKET& root = thread.root;
146 uint64_t totalCycles = 0;
147 for (const BUCKET& child : root.children)
148 {
149 totalCycles += child.elapsed;
150 }
151
152 for (const BUCKET& child : root.children)
153 {
154 if (child.count)
155 {
156 PrintBucket(f, 0, totalCycles, totalCycles, child);
157 }
158 }
159 }
160
161 void BucketManager::DumpThreadViz()
162 {
163 // ensure all thread data is flushed
164 mThreadMutex.lock();
165 for (auto& thread : mThreads)
166 {
167 fflush(thread.vizFile);
168 fclose(thread.vizFile);
169 }
170 mThreadMutex.unlock();
171
172 // dump bucket descriptions
173 std::stringstream ss;
174 ss << mThreadVizDir << "\\threadviz_buckets.dat";
175
176 FILE* f = fopen(ss.str().c_str(), "wb");
177 for (auto& bucket : mBuckets)
178 {
179 Serialize(f, bucket);
180 }
181 fclose(f);
182 }
183
184 void BucketManager::PrintReport(const std::string& filename)
185 {
186 if (mThreadViz)
187 {
188 DumpThreadViz();
189 }
190 else
191 {
192 FILE* f = fopen(filename.c_str(), "w");
193
194 mThreadMutex.lock();
195 for (const BUCKET_THREAD& thread : mThreads)
196 {
197 PrintThread(f, thread);
198 fprintf(f, "\n");
199 }
200 mThreadMutex.unlock();
201
202 fclose(f);
203 }
204 }
205
206 void BucketManager_StartBucket(BucketManager* pBucketMgr, uint32_t id)
207 {
208 pBucketMgr->StartBucket(id);
209 }
210
211 void BucketManager_StopBucket(BucketManager* pBucketMgr, uint32_t id)
212 {
213 pBucketMgr->StopBucket(id);
214 }