Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h
4574 views
/****************************************************************************1* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* @file rdtsc_buckets.h23*24* @brief declaration for rdtsc buckets.25*26* Notes:27*28******************************************************************************/29#pragma once3031#include "os.h"32#include <vector>33#include <mutex>34#include <sstream>3536#include "rdtsc_buckets_shared.h"373839// unique thread id stored in thread local storage40extern THREAD UINT tlsThreadId;4142//////////////////////////////////////////////////////////////////////////43/// @brief BucketManager encapsulates a single instance of the buckets44/// functionality. There can be one or many bucket managers active45/// at any time. The manager owns all the threads and46/// bucket information that have been registered to it.47class BucketManager48{49public:5051uint32_t mCurrentFrame;52std::vector<uint32_t> mBucketMap;53bool mBucketsInitialized;54std::string mBucketMgrName;555657BucketManager(std::string name) : mCurrentFrame(0), mBucketsInitialized(false), mBucketMgrName(name)58{59mBucketMap.clear();60}61~BucketManager();6263// removes all registered thread data64void ClearThreads()65{66mThreadMutex.lock();67mThreads.clear();68mThreadMutex.unlock();69}7071// removes all registered buckets72void ClearBuckets()73{74mThreadMutex.lock();75mBuckets.clear();76mThreadMutex.unlock();77}7879/// Registers a new thread with the manager.80/// @param name - name of thread, used for labels in reports and threadviz81void RegisterThread(const std::string& name);8283/// Registers a new bucket type with the manager. Returns a unique84/// id which should be used in subsequent calls to start/stop the bucket85/// @param desc - description of the bucket86/// @return unique id87UINT RegisterBucket(const BUCKET_DESC& desc);8889// print report90void PrintReport(const std::string& filename);919293// start capturing94void StartCapture();9596// stop capturing97INLINE void StopCapture()98{99mCapturing = false;100101// wait for all threads to pop back to root bucket102bool stillCapturing = true;103while (stillCapturing)104{105stillCapturing = false;106for (const BUCKET_THREAD& t : mThreads)107{108if (t.level > 0)109{110stillCapturing = true;111continue;112}113}114}115116mDoneCapturing = true;117printf("Capture Stopped\n");118}119120// start a bucket121// @param id generated by RegisterBucket122INLINE void StartBucket(UINT id)123{124if (!mCapturing)125return;126127SWR_ASSERT(tlsThreadId < mThreads.size());128129BUCKET_THREAD& bt = mThreads[tlsThreadId];130131uint64_t tsc = __rdtsc();132133{134if (bt.pCurrent->children.size() < mBuckets.size())135{136bt.pCurrent->children.resize(mBuckets.size());137}138BUCKET& child = bt.pCurrent->children[id];139child.pParent = bt.pCurrent;140child.id = id;141child.start = tsc;142143// update thread's currently executing bucket144bt.pCurrent = &child;145}146147148bt.level++;149}150151// stop the currently executing bucket152INLINE void StopBucket(UINT id)153{154SWR_ASSERT(tlsThreadId < mThreads.size());155BUCKET_THREAD& bt = mThreads[tlsThreadId];156157if (bt.level == 0)158{159return;160}161162uint64_t tsc = __rdtsc();163164{165if (bt.pCurrent->start == 0)166return;167SWR_ASSERT(bt.pCurrent->id == id, "Mismatched buckets detected");168169bt.pCurrent->elapsed += (tsc - bt.pCurrent->start);170bt.pCurrent->count++;171172// pop to parent173bt.pCurrent = bt.pCurrent->pParent;174}175176bt.level--;177}178179INLINE void AddEvent(uint32_t id, uint32_t count)180{181if (!mCapturing)182return;183184SWR_ASSERT(tlsThreadId < mThreads.size());185186BUCKET_THREAD& bt = mThreads[tlsThreadId];187188// don't record events for threadviz189{190if (bt.pCurrent->children.size() < mBuckets.size())191{192bt.pCurrent->children.resize(mBuckets.size());193}194BUCKET& child = bt.pCurrent->children[id];195child.pParent = bt.pCurrent;196child.id = id;197child.count += count;198}199}200201private:202void PrintBucket(203FILE* f, UINT level, uint64_t threadCycles, uint64_t parentCycles, const BUCKET& bucket);204void PrintThread(FILE* f, const BUCKET_THREAD& thread);205206// list of active threads that have registered with this manager207std::vector<BUCKET_THREAD> mThreads;208209// list of buckets registered with this manager210std::vector<BUCKET_DESC> mBuckets;211212// is capturing currently enabled213volatile bool mCapturing{false};214215// has capturing completed216volatile bool mDoneCapturing{false};217218std::mutex mThreadMutex;219220std::string mThreadVizDir;221222};223224// C helpers for jitter225void BucketManager_StartBucket(BucketManager* pBucketMgr, uint32_t id);226void BucketManager_StopBucket(BucketManager* pBucketMgr, uint32_t id);227228229