mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-10 12:53:42 +08:00
Initial commit
Change-Id: I4bf1707bd3dfeadf2c17b0a7daff372b1925ebbd
This commit is contained in:
54
runtime/utilities/api_intercept.h
Normal file
54
runtime/utilities/api_intercept.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/utilities/perf_profiler.h"
|
||||
#include "runtime/os_interface/debug_settings_manager.h"
|
||||
|
||||
#define API_ENTER(retValPointer) \
|
||||
DebugSettingsApiEnterWrapper<DebugManager.debugLoggingAvailable()> ApiWrapperForSingleCall(__FUNCTION__, retValPointer)
|
||||
#define SYSTEM_ENTER()
|
||||
#define SYSTEM_LEAVE(id)
|
||||
#define WAIT_ENTER()
|
||||
#define WAIT_LEAVE()
|
||||
|
||||
#if OCL_RUNTIME_PROFILING == 1
|
||||
#undef API_ENTER
|
||||
#undef SYSTEM_ENTER
|
||||
#undef SYSTEM_LEAVE
|
||||
#undef WAIT_ENTER
|
||||
#undef WAIT_LEAVE
|
||||
|
||||
#define API_ENTER(x) \
|
||||
PerfProfilerApiWrapper globalPerfProfilersWrapperInstanceForSingleApiFunction(__FUNCTION__)
|
||||
|
||||
#define SYSTEM_ENTER() \
|
||||
PerfProfiler::create(); \
|
||||
gPerfProfiler->SystemEnter();
|
||||
|
||||
#define SYSTEM_LEAVE(id) \
|
||||
gPerfProfiler->SystemLeave(id);
|
||||
#define WAIT_ENTER() \
|
||||
SYSTEM_ENTER()
|
||||
#define WAIT_LEAVE() \
|
||||
SYSTEM_LEAVE(0)
|
||||
#endif
|
96
runtime/utilities/arrayref.h
Normal file
96
runtime/utilities/arrayref.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
template <typename DataType>
|
||||
class ArrayRef {
|
||||
public:
|
||||
template <typename IteratorType>
|
||||
ArrayRef(IteratorType b, IteratorType e)
|
||||
: b(&*b), e(&*(e - 1) + 1) {
|
||||
}
|
||||
|
||||
template <typename IteratorType>
|
||||
ArrayRef(IteratorType b, size_t s)
|
||||
: ArrayRef(b, b + s) {
|
||||
}
|
||||
|
||||
template <typename SequentialContainerType>
|
||||
ArrayRef(SequentialContainerType &ctr)
|
||||
: b(&*ctr.begin()), e(&*(ctr.end() - 1) + 1) {
|
||||
}
|
||||
|
||||
template <size_t Size>
|
||||
ArrayRef(DataType (&array)[Size])
|
||||
: b(&array[0]), e(&array[Size]) {
|
||||
}
|
||||
|
||||
ArrayRef()
|
||||
: b(0), e(0) {
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return e - b;
|
||||
}
|
||||
|
||||
DataType &operator[](std::size_t idx) {
|
||||
return b[idx];
|
||||
}
|
||||
|
||||
const DataType &operator[](std::size_t idx) const {
|
||||
return b[idx];
|
||||
}
|
||||
|
||||
DataType *begin() {
|
||||
return b;
|
||||
}
|
||||
|
||||
const DataType *begin() const {
|
||||
return b;
|
||||
}
|
||||
|
||||
DataType *end() {
|
||||
return e;
|
||||
}
|
||||
|
||||
const DataType *end() const {
|
||||
return e;
|
||||
}
|
||||
|
||||
void swap(ArrayRef &rhs) {
|
||||
std::swap(b, rhs.b);
|
||||
std::swap(e, rhs.e);
|
||||
}
|
||||
|
||||
operator ArrayRef<const DataType>() {
|
||||
return ArrayRef<const DataType>(b, e);
|
||||
}
|
||||
|
||||
private:
|
||||
DataType *b;
|
||||
DataType *e;
|
||||
};
|
208
runtime/utilities/cpu_info.h
Normal file
208
runtime/utilities/cpu_info.h
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#define BIT(x) (1ull << (x))
|
||||
|
||||
namespace OCLRT {
|
||||
struct CpuInfo {
|
||||
static const uint64_t featureNone = 0x000000000ULL;
|
||||
static const uint64_t featureGenericIA32 = 0x000000001ULL;
|
||||
static const uint64_t featureFpu = 0x000000002ULL;
|
||||
static const uint64_t featureCmov = 0x000000004ULL;
|
||||
static const uint64_t featureMmx = 0x000000008ULL;
|
||||
static const uint64_t featureFxsave = 0x000000010ULL;
|
||||
static const uint64_t featureSse = 0x000000020ULL;
|
||||
static const uint64_t featureSsE2 = 0x000000040ULL;
|
||||
static const uint64_t featureSsE3 = 0x000000080ULL;
|
||||
static const uint64_t featureSssE3 = 0x000000100ULL;
|
||||
static const uint64_t featureSsE41 = 0x000000200ULL;
|
||||
static const uint64_t featureSsE42 = 0x000000400ULL;
|
||||
static const uint64_t featureMovbe = 0x000000800ULL;
|
||||
static const uint64_t featurePopcnt = 0x000001000ULL;
|
||||
static const uint64_t featurePclmulqdq = 0x000002000ULL;
|
||||
static const uint64_t featureAes = 0x000004000ULL;
|
||||
static const uint64_t featureF16C = 0x000008000ULL;
|
||||
static const uint64_t featureAvx = 0x000010000ULL;
|
||||
static const uint64_t featureRdrnd = 0x000020000ULL;
|
||||
static const uint64_t featureFma = 0x000040000ULL;
|
||||
static const uint64_t featureBmi = 0x000080000ULL;
|
||||
static const uint64_t featureLzcnt = 0x000100000ULL;
|
||||
static const uint64_t featureHle = 0x000200000ULL;
|
||||
static const uint64_t featureRtm = 0x000400000ULL;
|
||||
static const uint64_t featureAvX2 = 0x000800000ULL;
|
||||
static const uint64_t featureKncni = 0x004000000ULL;
|
||||
static const uint64_t featureAvX512F = 0x008000000ULL;
|
||||
static const uint64_t featureAdx = 0x010000000ULL;
|
||||
static const uint64_t featureRdseed = 0x020000000ULL;
|
||||
static const uint64_t featureAvX512Er = 0x100000000ULL;
|
||||
static const uint64_t featureAvX512Pf = 0x200000000ULL;
|
||||
static const uint64_t featureAvX512Cd = 0x400000000ULL;
|
||||
static const uint64_t featureSha = 0x800000000ULL;
|
||||
static const uint64_t featureMpx = 0x1000000000ULL;
|
||||
|
||||
CpuInfo() : features(featureNone) {
|
||||
}
|
||||
|
||||
void cpuid(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId) const;
|
||||
|
||||
void cpuidex(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId,
|
||||
uint32_t subfunctionId) const;
|
||||
|
||||
void detect() const {
|
||||
uint32_t cpuInfo[4];
|
||||
|
||||
cpuid(cpuInfo, 0u);
|
||||
auto numFunctionIds = cpuInfo[0];
|
||||
|
||||
if (numFunctionIds >= 1u) {
|
||||
cpuid(cpuInfo, 1u);
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(0) ? featureFpu : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(15) ? featureCmov : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(23) ? featureMmx : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(24) ? featureFxsave : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(25) ? featureSse : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[3] & BIT(26) ? featureSsE2 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(0) ? featureSsE3 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(1) ? featurePclmulqdq : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(9) ? featureSssE3 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(12) ? featureFma : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(19) ? featureSsE41 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(20) ? featureSsE42 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(22) ? featureMovbe : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(23) ? featurePopcnt : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(25) ? featureAes : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(28) ? featureAvx : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(29) ? featureF16C : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(30) ? featureRdrnd : featureNone;
|
||||
}
|
||||
}
|
||||
|
||||
if (numFunctionIds >= 7u) {
|
||||
cpuid(cpuInfo, 7u);
|
||||
{
|
||||
auto mask = BIT(5) | BIT(3) | BIT(8);
|
||||
features |= (cpuInfo[1] & mask) == mask ? featureAvX2 : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
auto mask = BIT(3) | BIT(8);
|
||||
features |= (cpuInfo[1] & mask) == mask ? featureBmi : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[1] & BIT(4) ? featureHle : featureNone;
|
||||
}
|
||||
|
||||
{
|
||||
features |= cpuInfo[1] & BIT(11) ? featureRtm : featureNone;
|
||||
}
|
||||
}
|
||||
|
||||
cpuid(cpuInfo, 0x80000000);
|
||||
auto maxExtendedId = cpuInfo[0];
|
||||
if (maxExtendedId >= 0x80000001) {
|
||||
cpuid(cpuInfo, 0x80000001);
|
||||
{
|
||||
features |= cpuInfo[2] & BIT(5) ? featureLzcnt : featureNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isFeatureSupported(uint64_t feature) const {
|
||||
if (features == featureNone) {
|
||||
detect();
|
||||
}
|
||||
|
||||
return (features & feature) == feature;
|
||||
}
|
||||
|
||||
static const CpuInfo &getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void (*cpuidexFunc)(int *, int, int);
|
||||
|
||||
protected:
|
||||
mutable uint64_t features;
|
||||
static const CpuInfo instance;
|
||||
};
|
||||
|
||||
} // namespace OCLRT
|
99
runtime/utilities/debug_file_reader.cpp
Normal file
99
runtime/utilities/debug_file_reader.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/debug_file_reader.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
SettingsFileReader::SettingsFileReader(const char *filePath) {
|
||||
std::ifstream settingsFile;
|
||||
|
||||
if (filePath == nullptr)
|
||||
settingsFile.open(settingsFileName);
|
||||
else
|
||||
settingsFile.open(filePath);
|
||||
|
||||
if (settingsFile.is_open()) {
|
||||
|
||||
stringstream ss;
|
||||
string key;
|
||||
int32_t value;
|
||||
char temp;
|
||||
|
||||
while (!settingsFile.eof()) {
|
||||
string tempString;
|
||||
string tempStringValue;
|
||||
getline(settingsFile, tempString);
|
||||
|
||||
ss << tempString;
|
||||
ss >> key;
|
||||
ss >> temp;
|
||||
ss >> value;
|
||||
if (!ss.fail()) {
|
||||
settingValueMap.insert(pair<string, int32_t>(key, value));
|
||||
} else {
|
||||
stringstream ss2;
|
||||
ss2 << tempString;
|
||||
ss2 >> key;
|
||||
ss2 >> temp;
|
||||
ss2 >> tempStringValue;
|
||||
if (!ss2.fail())
|
||||
settingStringMap.insert(pair<string, string>(key, tempStringValue));
|
||||
}
|
||||
|
||||
ss.clear();
|
||||
key.clear();
|
||||
}
|
||||
|
||||
settingsFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
SettingsFileReader::~SettingsFileReader() {
|
||||
settingValueMap.clear();
|
||||
settingStringMap.clear();
|
||||
}
|
||||
|
||||
int32_t SettingsFileReader::getSetting(const char *settingName, int32_t defaultValue) {
|
||||
int32_t value = defaultValue;
|
||||
map<string, int32_t>::iterator it = settingValueMap.find(string(settingName));
|
||||
if (it != settingValueMap.end())
|
||||
value = it->second;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool SettingsFileReader::getSetting(const char *settingName, bool defaultValue) {
|
||||
return getSetting(settingName, static_cast<int32_t>(defaultValue)) ? true : false;
|
||||
}
|
||||
|
||||
std::string SettingsFileReader::getSetting(const char *settingName, const std::string &value) {
|
||||
std::string returnValue = value;
|
||||
map<string, string>::iterator it = settingStringMap.find(string(settingName));
|
||||
if (it != settingStringMap.end())
|
||||
returnValue = it->second;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
};
|
47
runtime/utilities/debug_file_reader.h
Normal file
47
runtime/utilities/debug_file_reader.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "runtime/utilities/debug_settings_reader.h"
|
||||
#include <stdint.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class SettingsFileReader : public SettingsReader {
|
||||
public:
|
||||
SettingsFileReader(const char *filePath = nullptr);
|
||||
~SettingsFileReader() override;
|
||||
int32_t getSetting(const char *settingName, int32_t defaultValue) override;
|
||||
bool getSetting(const char *settingName, bool defaultValue) override;
|
||||
std::string getSetting(const char *settingName, const std::string &value) override;
|
||||
|
||||
protected:
|
||||
std::map<std::string, int32_t> settingValueMap;
|
||||
std::map<std::string, std::string> settingStringMap;
|
||||
};
|
||||
};
|
39
runtime/utilities/debug_settings_reader.cpp
Normal file
39
runtime/utilities/debug_settings_reader.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "debug_settings_reader.h"
|
||||
#include "debug_file_reader.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
const char *SettingsReader::settingsFileName = "igdrcl.config";
|
||||
|
||||
SettingsReader *SettingsReader::createFileReader() {
|
||||
std::ifstream settingsFile;
|
||||
settingsFile.open(settingsFileName);
|
||||
if (settingsFile.is_open()) {
|
||||
settingsFile.close();
|
||||
return new SettingsFileReader();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
48
runtime/utilities/debug_settings_reader.h
Normal file
48
runtime/utilities/debug_settings_reader.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class SettingsReader {
|
||||
public:
|
||||
virtual ~SettingsReader() {}
|
||||
static SettingsReader *create() {
|
||||
SettingsReader *readerImpl = createFileReader();
|
||||
if (readerImpl != nullptr)
|
||||
return readerImpl;
|
||||
|
||||
return createOsReader();
|
||||
}
|
||||
static SettingsReader *createOsReader();
|
||||
static SettingsReader *createFileReader();
|
||||
virtual int32_t getSetting(const char *settingName, int32_t defaultValue) = 0;
|
||||
virtual bool getSetting(const char *settingName, bool defaultValue) = 0;
|
||||
virtual std::string getSetting(const char *settingName, const std::string &value) = 0;
|
||||
|
||||
static const char *settingsFileName;
|
||||
};
|
||||
};
|
33
runtime/utilities/directory.h
Normal file
33
runtime/utilities/directory.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class Directory {
|
||||
public:
|
||||
static std::vector<std::string> getFiles(std::string &path);
|
||||
};
|
||||
};
|
30
runtime/utilities/heap_allocator.cpp
Normal file
30
runtime/utilities/heap_allocator.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/heap_allocator.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
bool operator<(const HeapChunk &hc1, const HeapChunk &hc2) {
|
||||
return hc1.ptr < hc2.ptr;
|
||||
}
|
||||
}
|
294
runtime/utilities/heap_allocator.h
Normal file
294
runtime/utilities/heap_allocator.h
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/helpers/aligned_memory.h"
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
struct HeapChunk {
|
||||
HeapChunk(void *ptr, size_t size) : ptr(ptr), size(size) {}
|
||||
void *ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
bool operator<(const HeapChunk &hc1, const HeapChunk &hc2);
|
||||
|
||||
class HeapAllocator {
|
||||
public:
|
||||
HeapAllocator(void *address, uint64_t size) : address(address), size(size), availableSize(size), sizeThreshold(defaultSizeThreshold) {
|
||||
pLeftBound = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(address));
|
||||
pRightBound = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(address) + (size_t)size);
|
||||
freedChunksBig.reserve(10);
|
||||
freedChunksSmall.reserve(50);
|
||||
}
|
||||
|
||||
HeapAllocator(void *address, uint64_t size, size_t threshold) : address(address), size(size), availableSize(size), sizeThreshold(threshold) {
|
||||
pLeftBound = reinterpret_cast<uint64_t>(address);
|
||||
pRightBound = reinterpret_cast<uint64_t>(address) + size;
|
||||
freedChunksBig.reserve(10);
|
||||
freedChunksSmall.reserve(50);
|
||||
}
|
||||
|
||||
~HeapAllocator() {
|
||||
}
|
||||
|
||||
void *allocate(size_t &sizeToAllocate) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
sizeToAllocate = alignUp(sizeToAllocate, allocationAlignment);
|
||||
void *ptrReturn = nullptr;
|
||||
|
||||
DBG_LOG(PrintDebugMessages, __FUNCTION__, "Allocator usage == ", this->getUsage());
|
||||
|
||||
if (availableSize < sizeToAllocate) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<HeapChunk> &freedChunks = (sizeToAllocate > sizeThreshold) ? freedChunksBig : freedChunksSmall;
|
||||
size_t sizeOfFreedChunk = 0;
|
||||
uint32_t defragmentCount = 0;
|
||||
|
||||
while (ptrReturn == nullptr) {
|
||||
|
||||
ptrReturn = getFromFreedChunks(sizeToAllocate, freedChunks, sizeOfFreedChunk);
|
||||
|
||||
if (ptrReturn == nullptr) {
|
||||
if (sizeToAllocate > sizeThreshold) {
|
||||
if (pLeftBound + sizeToAllocate <= pRightBound) {
|
||||
ptrReturn = reinterpret_cast<void *>(pLeftBound);
|
||||
pLeftBound += sizeToAllocate;
|
||||
}
|
||||
} else {
|
||||
if (pRightBound - sizeToAllocate >= pLeftBound) {
|
||||
pRightBound -= sizeToAllocate;
|
||||
ptrReturn = reinterpret_cast<void *>(pRightBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ptrReturn != nullptr) {
|
||||
if (sizeOfFreedChunk > 0) {
|
||||
availableSize -= sizeOfFreedChunk;
|
||||
sizeToAllocate = sizeOfFreedChunk;
|
||||
} else {
|
||||
availableSize -= sizeToAllocate;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptrReturn == nullptr) {
|
||||
if (defragmentCount == 1)
|
||||
break;
|
||||
defragment();
|
||||
defragmentCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return ptrReturn;
|
||||
}
|
||||
|
||||
void free(void *ptr, size_t size) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
uintptr_t ptrIn = reinterpret_cast<uintptr_t>(ptr);
|
||||
if (ptrIn == 0u)
|
||||
return;
|
||||
|
||||
DBG_LOG(PrintDebugMessages, __FUNCTION__, "Allocator usage == ", this->getUsage());
|
||||
|
||||
if (ptrIn == pRightBound) {
|
||||
pRightBound = ptrIn + size;
|
||||
mergeLastFreedSmall();
|
||||
} else if (ptrIn == (pLeftBound - size)) {
|
||||
pLeftBound = (pLeftBound - size);
|
||||
mergeLastFreedBig();
|
||||
} else {
|
||||
if (ptrIn < pLeftBound) {
|
||||
DEBUG_BREAK_IF(size <= sizeThreshold);
|
||||
storeInFreedChunks(ptr, size, freedChunksBig);
|
||||
} else {
|
||||
storeInFreedChunks(ptr, size, freedChunksSmall);
|
||||
}
|
||||
}
|
||||
availableSize += size;
|
||||
}
|
||||
|
||||
uint64_t getLeftSize() {
|
||||
return availableSize;
|
||||
}
|
||||
|
||||
uint64_t getUsedSize() {
|
||||
return size - availableSize;
|
||||
}
|
||||
|
||||
NO_SANITIZE
|
||||
double getUsage() {
|
||||
return 1.0 * (size - availableSize) / (size * 1.0);
|
||||
}
|
||||
|
||||
protected:
|
||||
void *address;
|
||||
uint64_t size;
|
||||
uint64_t availableSize;
|
||||
uint64_t pLeftBound, pRightBound;
|
||||
const size_t defaultSizeThreshold = 4096 * 1024;
|
||||
const size_t sizeThreshold;
|
||||
size_t allocationAlignment = MemoryConstants::pageSize;
|
||||
|
||||
std::vector<HeapChunk> freedChunksSmall;
|
||||
std::vector<HeapChunk> freedChunksBig;
|
||||
std::mutex mtx;
|
||||
|
||||
void *getFromFreedChunks(size_t size, std::vector<HeapChunk> &freedChunks, size_t &sizeOfFreedChunk) {
|
||||
size_t elements = freedChunks.size();
|
||||
size_t bestFitIndex = -1;
|
||||
size_t bestFitSize = 0;
|
||||
sizeOfFreedChunk = 0;
|
||||
|
||||
for (size_t i = 0; i < elements; i++) {
|
||||
if (freedChunks[i].size == size) {
|
||||
void *ptr = freedChunks[i].ptr;
|
||||
freedChunks.erase(freedChunks.begin() + i);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (freedChunks[i].size > size) {
|
||||
if (freedChunks[i].size < bestFitSize || bestFitSize == 0) {
|
||||
bestFitIndex = i;
|
||||
bestFitSize = freedChunks[i].size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestFitSize != 0) {
|
||||
if (bestFitSize < (size << 1)) {
|
||||
void *ptr = freedChunks[bestFitIndex].ptr;
|
||||
sizeOfFreedChunk = freedChunks[bestFitIndex].size;
|
||||
freedChunks.erase(freedChunks.begin() + bestFitIndex);
|
||||
return ptr;
|
||||
} else {
|
||||
size_t sizeDelta = freedChunks[bestFitIndex].size - size;
|
||||
|
||||
DEBUG_BREAK_IF(!((size <= sizeThreshold) || ((size > sizeThreshold) && (sizeDelta > sizeThreshold))));
|
||||
|
||||
void *ptr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(freedChunks[bestFitIndex].ptr) + sizeDelta);
|
||||
freedChunks[bestFitIndex].size = sizeDelta;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void storeInFreedChunks(void *ptr, size_t size, std::vector<HeapChunk> &freedChunks) {
|
||||
size_t elements = freedChunks.size();
|
||||
uintptr_t pLeft = reinterpret_cast<uintptr_t>(ptr);
|
||||
uintptr_t pRight = reinterpret_cast<uintptr_t>(ptr) + size;
|
||||
bool freedChunkStored = false;
|
||||
|
||||
for (size_t i = 0; i < elements; i++) {
|
||||
if (freedChunks[i].ptr == reinterpret_cast<void *>(pRight)) {
|
||||
freedChunks[i].ptr = reinterpret_cast<void *>(pLeft);
|
||||
freedChunks[i].size += size;
|
||||
freedChunkStored = true;
|
||||
} else if ((reinterpret_cast<uintptr_t>(freedChunks[i].ptr) + freedChunks[i].size) == pLeft) {
|
||||
freedChunks[i].size += size;
|
||||
freedChunkStored = true;
|
||||
}
|
||||
|
||||
if (freedChunkStored == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (freedChunkStored == false) {
|
||||
freedChunks.emplace_back(ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void mergeLastFreedSmall() {
|
||||
|
||||
size_t maxSizeOfSmallChunks = freedChunksSmall.size();
|
||||
|
||||
if (maxSizeOfSmallChunks > 0) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(freedChunksSmall[maxSizeOfSmallChunks - 1].ptr);
|
||||
size_t chunkSize = freedChunksSmall[maxSizeOfSmallChunks - 1].size;
|
||||
if (ptr == pRightBound) {
|
||||
pRightBound = ptr + chunkSize;
|
||||
freedChunksSmall.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mergeLastFreedBig() {
|
||||
size_t maxSizeOfBigChunks = freedChunksBig.size();
|
||||
|
||||
if (maxSizeOfBigChunks > 0) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(freedChunksBig[maxSizeOfBigChunks - 1].ptr);
|
||||
size_t chunkSize = freedChunksBig[maxSizeOfBigChunks - 1].size;
|
||||
|
||||
if (ptr == (pLeftBound - chunkSize)) {
|
||||
pLeftBound = (pLeftBound - chunkSize);
|
||||
freedChunksBig.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void defragment() {
|
||||
|
||||
if (freedChunksSmall.size() > 1) {
|
||||
std::sort(freedChunksSmall.rbegin(), freedChunksSmall.rend());
|
||||
size_t maxSize = freedChunksSmall.size();
|
||||
for (size_t i = maxSize - 1; i > 0; --i) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(freedChunksSmall[i].ptr);
|
||||
size_t chunkSize = freedChunksSmall[i].size;
|
||||
|
||||
if (reinterpret_cast<uintptr_t>(freedChunksSmall[i - 1].ptr) == ptr + chunkSize) {
|
||||
freedChunksSmall[i - 1].ptr = reinterpret_cast<void *>(ptr);
|
||||
freedChunksSmall[i - 1].size += chunkSize;
|
||||
freedChunksSmall.erase(freedChunksSmall.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
mergeLastFreedSmall();
|
||||
if (freedChunksBig.size() > 1) {
|
||||
std::sort(freedChunksBig.begin(), freedChunksBig.end());
|
||||
|
||||
size_t maxSize = freedChunksBig.size();
|
||||
for (size_t i = maxSize - 1; i > 0; --i) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(freedChunksBig[i].ptr);
|
||||
size_t chunkSize = freedChunksBig[i].size;
|
||||
if ((reinterpret_cast<uintptr_t>(freedChunksBig[i - 1].ptr) + freedChunksBig[i - 1].size) == ptr) {
|
||||
freedChunksBig[i - 1].size += chunkSize;
|
||||
freedChunksBig.erase(freedChunksBig.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
mergeLastFreedBig();
|
||||
DBG_LOG(PrintDebugMessages, __FUNCTION__, "Allocator usage == ", this->getUsage());
|
||||
}
|
||||
};
|
||||
} // namespace OCLRT
|
486
runtime/utilities/idlist.h
Normal file
486
runtime/utilities/idlist.h
Normal file
@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct IDNode {
|
||||
IDNode()
|
||||
: prev(nullptr),
|
||||
next(nullptr) {
|
||||
}
|
||||
|
||||
void insertOneNext(NodeObjectType &nd) {
|
||||
nd.next = next;
|
||||
if (next != nullptr) {
|
||||
next->prev = &nd;
|
||||
}
|
||||
nd.prev = static_cast<NodeObjectType *>(this);
|
||||
next = &nd;
|
||||
}
|
||||
|
||||
void insertOnePrev(NodeObjectType &nd) {
|
||||
if (prev != nullptr) {
|
||||
prev->next = &nd;
|
||||
}
|
||||
nd.next = static_cast<NodeObjectType *>(this);
|
||||
nd.prev = prev;
|
||||
prev = &nd;
|
||||
}
|
||||
|
||||
NodeObjectType *slice() {
|
||||
NodeObjectType *rest = next;
|
||||
next = nullptr;
|
||||
if (rest != nullptr) {
|
||||
rest->prev = nullptr;
|
||||
}
|
||||
return rest;
|
||||
}
|
||||
|
||||
void insertAllNext(NodeObjectType &rhs) {
|
||||
NodeObjectType *rhsTail = rhs.getTail();
|
||||
rhsTail->next = next;
|
||||
if (next != nullptr) {
|
||||
next->prev = rhsTail;
|
||||
}
|
||||
rhs.prev = static_cast<NodeObjectType *>(this);
|
||||
next = &rhs;
|
||||
}
|
||||
|
||||
NodeObjectType *getTail() {
|
||||
NodeObjectType *curr = static_cast<NodeObjectType *>(this);
|
||||
while (curr->next != nullptr) {
|
||||
curr = curr->next;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
NodeObjectType *getHead() {
|
||||
NodeObjectType *curr = static_cast<NodeObjectType *>(this);
|
||||
while (curr->prev != nullptr) {
|
||||
curr = curr->prev;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> deleteThisAndAllNext() {
|
||||
NodeObjectType *curr = this->next;
|
||||
while (curr != nullptr) {
|
||||
auto n = curr->next;
|
||||
delete curr;
|
||||
curr = n;
|
||||
}
|
||||
if (this->prev != nullptr) {
|
||||
this->prev->next = nullptr;
|
||||
}
|
||||
this->next = nullptr;
|
||||
return std::unique_ptr<NodeObjectType>(static_cast<NodeObjectType *>(this));
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> deleteThisAndAllPrev() {
|
||||
NodeObjectType *curr = this->prev;
|
||||
while (curr != nullptr) {
|
||||
auto n = curr->prev;
|
||||
delete curr;
|
||||
curr = n;
|
||||
}
|
||||
if (this->next != nullptr) {
|
||||
this->next->prev = nullptr;
|
||||
}
|
||||
this->prev = nullptr;
|
||||
return std::unique_ptr<NodeObjectType>(static_cast<NodeObjectType *>(this));
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> deleteThisAndAllConnected() {
|
||||
deleteThisAndAllNext().release();
|
||||
return deleteThisAndAllPrev();
|
||||
}
|
||||
|
||||
size_t countSuccessors() const {
|
||||
const NodeObjectType *curr = static_cast<const NodeObjectType *>(this);
|
||||
size_t successors = 0;
|
||||
while (curr->next != nullptr) {
|
||||
curr = curr->next;
|
||||
++successors;
|
||||
}
|
||||
return successors;
|
||||
}
|
||||
|
||||
size_t countPredecessors() const {
|
||||
const NodeObjectType *curr = static_cast<const NodeObjectType *>(this);
|
||||
size_t successors = 0;
|
||||
while (curr->prev != nullptr) {
|
||||
curr = curr->prev;
|
||||
++successors;
|
||||
}
|
||||
return successors;
|
||||
}
|
||||
|
||||
size_t countThisAndAllConnected() const {
|
||||
return 1 + countPredecessors() + countSuccessors();
|
||||
}
|
||||
|
||||
bool isPredecessorOf(NodeObjectType &rhs) const {
|
||||
NodeObjectType *curr = next;
|
||||
while (curr != nullptr) {
|
||||
if (curr == &rhs) {
|
||||
return true;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSuccessorOf(NodeObjectType &lhs) const {
|
||||
NodeObjectType *curr = prev;
|
||||
while (curr != nullptr) {
|
||||
if (curr == &lhs) {
|
||||
return true;
|
||||
}
|
||||
curr = curr->prev;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isConnectedWith(NodeObjectType &node) const {
|
||||
if (this == &node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isSuccessorOf(node) || isPredecessorOf(node);
|
||||
}
|
||||
|
||||
NodeObjectType *prev;
|
||||
NodeObjectType *next;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType, bool ThreadSafe = true, bool OwnsNodes = false, bool SupportRecursiveLock = true>
|
||||
class IDList {
|
||||
public:
|
||||
using ThisType = IDList<NodeObjectType, ThreadSafe, OwnsNodes, SupportRecursiveLock>;
|
||||
|
||||
IDList()
|
||||
: head(nullptr), tail(nullptr), locked(), spinLockedListener(nullptr) {
|
||||
locked.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
IDList(NodeObjectType *node)
|
||||
: head(node), tail(nullptr), locked(), spinLockedListener(nullptr) {
|
||||
locked.clear(std::memory_order_release);
|
||||
head = node;
|
||||
if (node == nullptr) {
|
||||
tail = nullptr;
|
||||
} else {
|
||||
tail = node->getTail();
|
||||
}
|
||||
}
|
||||
|
||||
~IDList() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
IDList(const IDList &) = delete;
|
||||
IDList &operator=(const IDList &) = delete;
|
||||
|
||||
void pushFrontOne(NodeObjectType &node) {
|
||||
processLocked<ThisType, &ThisType::pushFrontOneImpl>(&node);
|
||||
}
|
||||
|
||||
void pushTailOne(NodeObjectType &node) {
|
||||
processLocked<ThisType, &ThisType::pushTailOneImpl>(&node);
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> removeOne(NodeObjectType &node) {
|
||||
return std::unique_ptr<NodeObjectType>(processLocked<ThisType, &ThisType::removeOneImpl>(&node));
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> removeFrontOne() {
|
||||
return std::unique_ptr<NodeObjectType>(processLocked<ThisType, &ThisType::removeFrontOneImpl>(nullptr));
|
||||
}
|
||||
|
||||
NodeObjectType *detachSequence(NodeObjectType &first, NodeObjectType &last) {
|
||||
return processLocked<ThisType, &ThisType::detachSequenceImpl>(&first, &last);
|
||||
}
|
||||
|
||||
NodeObjectType *detachNodes() {
|
||||
return processLocked<ThisType, &ThisType::detachNodesImpl>();
|
||||
}
|
||||
|
||||
void splice(NodeObjectType &nodes) {
|
||||
processLocked<ThisType, &ThisType::spliceImpl>(&nodes);
|
||||
}
|
||||
|
||||
void deleteAll() {
|
||||
NodeObjectType *nodes = detachNodes();
|
||||
nodes->deleteThisAndAllNext();
|
||||
}
|
||||
|
||||
NodeObjectType *peekHead() {
|
||||
return processLocked<ThisType, &ThisType::peekHeadImpl>();
|
||||
}
|
||||
|
||||
NodeObjectType *peekTail() {
|
||||
return processLocked<ThisType, &ThisType::peekTailImpl>();
|
||||
}
|
||||
|
||||
bool peekIsEmpty() {
|
||||
return (peekHead() == nullptr);
|
||||
}
|
||||
|
||||
bool peekContains(NodeObjectType &node) {
|
||||
return (processLocked<ThisType, &ThisType::peekContainsImpl>(&node) != nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
NodeObjectType *peekHeadImpl(NodeObjectType *, void *) {
|
||||
return head;
|
||||
}
|
||||
NodeObjectType *peekTailImpl(NodeObjectType *, void *) {
|
||||
return tail;
|
||||
}
|
||||
template <bool C = OwnsNodes>
|
||||
typename std::enable_if<C, void>::type cleanup() {
|
||||
if (head != nullptr) {
|
||||
head->deleteThisAndAllNext();
|
||||
}
|
||||
head = nullptr;
|
||||
tail = nullptr;
|
||||
}
|
||||
|
||||
template <bool C = OwnsNodes>
|
||||
typename std::enable_if<!C, void>::type cleanup() {
|
||||
;
|
||||
}
|
||||
|
||||
void notifySpinLocked() {
|
||||
if (spinLockedListener != nullptr) {
|
||||
(*spinLockedListener)(*this);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, NodeObjectType *(T::*Process)(NodeObjectType *node1, void *data), bool C1 = ThreadSafe, bool C2 = SupportRecursiveLock>
|
||||
typename std::enable_if<C1 && !C2, NodeObjectType *>::type processLocked(NodeObjectType *node1 = nullptr, void *data = nullptr) {
|
||||
while (locked.test_and_set(std::memory_order_acquire)) {
|
||||
notifySpinLocked();
|
||||
}
|
||||
|
||||
NodeObjectType *ret = nullptr;
|
||||
try {
|
||||
ret = (static_cast<T *>(this)->*Process)(node1, data);
|
||||
} catch (...) {
|
||||
locked.clear(std::memory_order_release);
|
||||
throw;
|
||||
}
|
||||
|
||||
locked.clear(std::memory_order_release);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, NodeObjectType *(T::*Process)(NodeObjectType *node1, void *data), bool C1 = ThreadSafe, bool C2 = SupportRecursiveLock>
|
||||
typename std::enable_if<C1 && C2, NodeObjectType *>::type processLocked(NodeObjectType *node1 = nullptr, void *data = nullptr) {
|
||||
std::thread::id currentThreadId = std::this_thread::get_id();
|
||||
if (lockOwner == currentThreadId) {
|
||||
return (static_cast<T *>(this)->*Process)(node1, data);
|
||||
}
|
||||
|
||||
while (locked.test_and_set(std::memory_order_acquire)) {
|
||||
notifySpinLocked();
|
||||
}
|
||||
|
||||
lockOwner = currentThreadId;
|
||||
|
||||
NodeObjectType *ret = nullptr;
|
||||
try {
|
||||
ret = (static_cast<T *>(this)->*Process)(node1, data);
|
||||
} catch (...) {
|
||||
lockOwner = std::thread::id();
|
||||
locked.clear(std::memory_order_release);
|
||||
throw;
|
||||
}
|
||||
|
||||
lockOwner = std::thread::id();
|
||||
locked.clear(std::memory_order_release);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, NodeObjectType *(T::*Process)(NodeObjectType *node, void *data), bool C = ThreadSafe>
|
||||
typename std::enable_if<!C, NodeObjectType *>::type processLocked(NodeObjectType *node = nullptr, void *data = nullptr) {
|
||||
return (this->*Process)(node, data);
|
||||
}
|
||||
|
||||
NodeObjectType *pushFrontOneImpl(NodeObjectType *node, void *) {
|
||||
if (head == nullptr) {
|
||||
DEBUG_BREAK_IF(tail != nullptr);
|
||||
pushTailOneImpl(node, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node->prev = nullptr;
|
||||
node->next = head;
|
||||
head->prev = node;
|
||||
head = node;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeObjectType *pushTailOneImpl(NodeObjectType *node, void *) {
|
||||
if (tail == nullptr) {
|
||||
DEBUG_BREAK_IF(head != nullptr);
|
||||
node->prev = nullptr;
|
||||
node->next = nullptr;
|
||||
head = node;
|
||||
tail = node;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node->next = nullptr;
|
||||
node->prev = tail;
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeObjectType *removeOneImpl(NodeObjectType *node, void *) {
|
||||
if (node->prev != nullptr) {
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
if (node->next != nullptr) {
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
if (tail == node) {
|
||||
tail = node->prev;
|
||||
}
|
||||
if (head == node) {
|
||||
head = node->next;
|
||||
}
|
||||
node->prev = nullptr;
|
||||
node->next = nullptr;
|
||||
return node;
|
||||
}
|
||||
|
||||
NodeObjectType *removeFrontOneImpl(NodeObjectType *, void *) {
|
||||
if (head == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return removeOneImpl(head, nullptr);
|
||||
}
|
||||
|
||||
NodeObjectType *detachSequenceImpl(NodeObjectType *node, void *data) {
|
||||
NodeObjectType *first = node;
|
||||
NodeObjectType *last = static_cast<NodeObjectType *>(data);
|
||||
if (first == last) {
|
||||
return removeOneImpl(first, nullptr);
|
||||
}
|
||||
|
||||
if (first->prev != nullptr) {
|
||||
first->prev->next = last->next;
|
||||
}
|
||||
|
||||
if (last->next != nullptr) {
|
||||
last->next->prev = first->prev;
|
||||
}
|
||||
|
||||
if (head == first) {
|
||||
head = last->next;
|
||||
}
|
||||
|
||||
if (tail == last) {
|
||||
tail = first->prev;
|
||||
}
|
||||
|
||||
first->prev = nullptr;
|
||||
last->next = nullptr;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
NodeObjectType *detachNodesImpl(NodeObjectType *, void *) {
|
||||
NodeObjectType *rest = head;
|
||||
head = nullptr;
|
||||
tail = nullptr;
|
||||
return rest;
|
||||
}
|
||||
|
||||
NodeObjectType *spliceImpl(NodeObjectType *node, void *) {
|
||||
if (tail == nullptr) {
|
||||
DEBUG_BREAK_IF(head != nullptr);
|
||||
head = node;
|
||||
node->prev = nullptr;
|
||||
tail = node->getTail();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tail->next = node;
|
||||
node->prev = tail;
|
||||
tail = node->getTail();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeObjectType *peekContainsImpl(NodeObjectType *node, void *) {
|
||||
NodeObjectType *curr = head;
|
||||
while (curr != nullptr) {
|
||||
if (curr == node) {
|
||||
return node;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeObjectType *head;
|
||||
NodeObjectType *tail;
|
||||
|
||||
std::atomic_flag locked;
|
||||
std::atomic<std::thread::id> lockOwner;
|
||||
void (*spinLockedListener)(ThisType &list);
|
||||
};
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct IDNodeRef : IDNode<IDNodeRef<NodeObjectType>> {
|
||||
IDNodeRef(NodeObjectType *ref)
|
||||
: ref(ref) {
|
||||
}
|
||||
NodeObjectType *ref;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType, bool ThreadSafe = true, bool OwnsNodes = true>
|
||||
class IDRefList : public IDList<IDNodeRef<NodeObjectType>, ThreadSafe, OwnsNodes> {
|
||||
public:
|
||||
void pushRefFrontOne(NodeObjectType &node) {
|
||||
auto refNode = std::unique_ptr<IDNodeRef<NodeObjectType>>(new IDNodeRef<NodeObjectType>(&node));
|
||||
this->pushFrontOne(*refNode);
|
||||
refNode.release();
|
||||
}
|
||||
};
|
||||
}
|
209
runtime/utilities/iflist.h
Normal file
209
runtime/utilities/iflist.h
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
template <typename NodeObjectType, bool Atomic>
|
||||
struct PtrType {
|
||||
};
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct PtrType<NodeObjectType, true> {
|
||||
using type = std::atomic<NodeObjectType *>;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct PtrType<NodeObjectType, false> {
|
||||
using type = NodeObjectType *;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType, bool Atomic>
|
||||
using PtrType_t = typename PtrType<NodeObjectType, Atomic>::type;
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct IFNode {
|
||||
IFNode()
|
||||
: next(nullptr) {
|
||||
}
|
||||
|
||||
void insertOneNext(NodeObjectType &nd) {
|
||||
nd.next = next;
|
||||
next = &nd;
|
||||
}
|
||||
|
||||
NodeObjectType *slice() {
|
||||
NodeObjectType *rest = next;
|
||||
next = nullptr;
|
||||
return rest;
|
||||
}
|
||||
|
||||
void insertAllNext(NodeObjectType &rhs) {
|
||||
NodeObjectType *rhsTail = rhs.getTail();
|
||||
rhsTail->next = next;
|
||||
next = &rhs;
|
||||
}
|
||||
|
||||
NodeObjectType *getTail() {
|
||||
NodeObjectType *curr = static_cast<NodeObjectType *>(this);
|
||||
while (curr->next != nullptr) {
|
||||
curr = curr->next;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeObjectType> deleteThisAndAllNext() {
|
||||
NodeObjectType *curr = this->next;
|
||||
while (curr != nullptr) {
|
||||
auto n = curr->next;
|
||||
delete curr;
|
||||
curr = n;
|
||||
}
|
||||
this->next = nullptr;
|
||||
return std::unique_ptr<NodeObjectType>(static_cast<NodeObjectType *>(this));
|
||||
}
|
||||
|
||||
size_t countSuccessors() const {
|
||||
const NodeObjectType *curr = static_cast<const NodeObjectType *>(this);
|
||||
size_t successors = 0;
|
||||
while (curr->next != nullptr) {
|
||||
curr = curr->next;
|
||||
++successors;
|
||||
}
|
||||
return successors;
|
||||
}
|
||||
|
||||
NodeObjectType *next;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType, bool ThreadSafe = true, bool OwnsNodes = false>
|
||||
class IFList {
|
||||
public:
|
||||
IFList()
|
||||
: head(nullptr) {
|
||||
}
|
||||
|
||||
IFList(NodeObjectType *node) {
|
||||
head = node;
|
||||
}
|
||||
|
||||
~IFList() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
IFList(const IFList &) = delete;
|
||||
IFList &operator=(const IFList &) = delete;
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<C, void>::type pushFrontOne(NodeObjectType &node) {
|
||||
node.next = head;
|
||||
compareExchangeHead(node.next, &node);
|
||||
}
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<C, NodeObjectType *>::type detachNodes() {
|
||||
NodeObjectType *rest = head;
|
||||
compareExchangeHead(rest, nullptr);
|
||||
return rest;
|
||||
}
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<!C, void>::type pushFrontOne(NodeObjectType &node) {
|
||||
node.next = head;
|
||||
head = &node;
|
||||
}
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<!C, NodeObjectType *>::type detachNodes() {
|
||||
NodeObjectType *rest = head;
|
||||
head = nullptr;
|
||||
return rest;
|
||||
}
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<!C, void>::type splice(NodeObjectType &nodes) {
|
||||
if (head == nullptr) {
|
||||
head = &nodes;
|
||||
} else {
|
||||
head->getTail()->next = &nodes;
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAll() {
|
||||
NodeObjectType *nodes = detachNodes();
|
||||
if (nodes != nullptr) {
|
||||
nodes->deleteThisAndAllNext();
|
||||
}
|
||||
}
|
||||
|
||||
NodeObjectType *peekHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
bool peekIsEmpty() {
|
||||
return (peekHead() == nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <bool C = OwnsNodes>
|
||||
typename std::enable_if<C, void>::type cleanup() {
|
||||
deleteAll();
|
||||
}
|
||||
|
||||
template <bool C = OwnsNodes>
|
||||
typename std::enable_if<!C, void>::type cleanup() {
|
||||
;
|
||||
}
|
||||
|
||||
template <bool C = ThreadSafe>
|
||||
typename std::enable_if<C, void>::type compareExchangeHead(NodeObjectType *&expected, NodeObjectType *desired) {
|
||||
while (!std::atomic_compare_exchange_weak(&head, &expected, desired)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
PtrType_t<NodeObjectType, ThreadSafe> head;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType>
|
||||
struct IFNodeRef : IFNode<IFNodeRef<NodeObjectType>> {
|
||||
IFNodeRef(NodeObjectType *ref)
|
||||
: ref(ref) {
|
||||
}
|
||||
NodeObjectType *ref;
|
||||
};
|
||||
|
||||
template <typename NodeObjectType, bool ThreadSafe = true, bool OwnsNodes = true>
|
||||
class IFRefList : public IFList<IFNodeRef<NodeObjectType>, ThreadSafe, OwnsNodes> {
|
||||
public:
|
||||
void pushRefFrontOne(NodeObjectType &node) {
|
||||
auto up = std::unique_ptr<IFNodeRef<NodeObjectType>>(new IFNodeRef<NodeObjectType>(&node));
|
||||
this->pushFrontOne(*up);
|
||||
up.release();
|
||||
}
|
||||
};
|
||||
}
|
50
runtime/utilities/linux/cpu_info.cpp
Normal file
50
runtime/utilities/linux/cpu_info.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/cpu_info.h"
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
void cpuidex_linux_wrapper(int *cpuInfo, int functionId, int subfunctionId) {
|
||||
__cpuid_count(functionId, subfunctionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
|
||||
}
|
||||
|
||||
void (*CpuInfo::cpuidexFunc)(int *, int, int) = cpuidex_linux_wrapper;
|
||||
|
||||
const CpuInfo CpuInfo::instance;
|
||||
|
||||
void CpuInfo::cpuid(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId) const {
|
||||
__cpuid_count(functionId, 0, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
|
||||
}
|
||||
|
||||
void CpuInfo::cpuidex(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId,
|
||||
uint32_t subfunctionId) const {
|
||||
cpuidexFunc(reinterpret_cast<int *>(cpuInfo), functionId, subfunctionId);
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
36
runtime/utilities/linux/debug_env_reader.h
Normal file
36
runtime/utilities/linux/debug_env_reader.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "runtime/os_interface/debug_settings_manager.h"
|
||||
#include "runtime/utilities/debug_settings_reader.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class EnvironmentVariableReader : public SettingsReader {
|
||||
public:
|
||||
int32_t getSetting(const char *settingName, int32_t defaultValue) override;
|
||||
bool getSetting(const char *settingName, bool defaultValue) override;
|
||||
std::string getSetting(const char *settingName, const std::string &value) override;
|
||||
};
|
||||
}
|
54
runtime/utilities/linux/directory.cpp
Normal file
54
runtime/utilities/linux/directory.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/directory.h"
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
std::vector<std::string> Directory::getFiles(std::string &path) {
|
||||
std::vector<std::string> files;
|
||||
|
||||
DIR *dir = opendir(path.c_str());
|
||||
if (dir == nullptr) {
|
||||
return files;
|
||||
}
|
||||
|
||||
struct dirent *entry = nullptr;
|
||||
while ((entry = readdir(dir)) != nullptr) {
|
||||
if (entry->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string fullPath;
|
||||
fullPath += path;
|
||||
fullPath += "/";
|
||||
fullPath += entry->d_name;
|
||||
|
||||
files.push_back(fullPath);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return files;
|
||||
}
|
||||
};
|
111
runtime/utilities/linux/timer_util.cpp
Normal file
111
runtime/utilities/linux/timer_util.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include "runtime/utilities/timer_util.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class Timer::TimerImpl {
|
||||
|
||||
public:
|
||||
TimerImpl() {
|
||||
}
|
||||
|
||||
~TimerImpl() {
|
||||
}
|
||||
|
||||
void start() {
|
||||
*((std::chrono::high_resolution_clock::time_point *)&m_startTime) = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void end() {
|
||||
*((std::chrono::high_resolution_clock::time_point *)&m_endTime) = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
long long int get() {
|
||||
long long int nanosecondTime = 0;
|
||||
std::chrono::duration<double> diffTime = std::chrono::duration_cast<std::chrono::duration<double>>(*(reinterpret_cast<std::chrono::high_resolution_clock::time_point *>(&m_endTime)) - *(reinterpret_cast<std::chrono::high_resolution_clock::time_point *>(&m_startTime)));
|
||||
nanosecondTime = (long long int)(diffTime.count() * (double)1000000000.0);
|
||||
return nanosecondTime;
|
||||
}
|
||||
|
||||
long long getStart() {
|
||||
long long ret = (long long)(reinterpret_cast<std::chrono::high_resolution_clock::time_point *>(&m_startTime)->time_since_epoch().count());
|
||||
return ret;
|
||||
}
|
||||
|
||||
long long getEnd() {
|
||||
long long ret = (long long)(reinterpret_cast<std::chrono::high_resolution_clock::time_point *>(&m_endTime)->time_since_epoch().count());
|
||||
return ret;
|
||||
}
|
||||
|
||||
TimerImpl &operator=(const TimerImpl &t) {
|
||||
m_startTime = t.m_startTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void setFreq() {
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point m_startTime;
|
||||
std::chrono::high_resolution_clock::time_point m_endTime;
|
||||
};
|
||||
|
||||
Timer::Timer() {
|
||||
timerImpl = new TimerImpl();
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
delete timerImpl;
|
||||
}
|
||||
|
||||
void Timer::start() {
|
||||
timerImpl->start();
|
||||
}
|
||||
|
||||
void Timer::end() {
|
||||
timerImpl->end();
|
||||
}
|
||||
|
||||
long long int Timer::get() {
|
||||
return timerImpl->get();
|
||||
}
|
||||
|
||||
long long Timer::getStart() {
|
||||
return timerImpl->getStart();
|
||||
}
|
||||
|
||||
long long Timer::getEnd() {
|
||||
return timerImpl->getEnd();
|
||||
}
|
||||
|
||||
Timer &Timer::operator=(const Timer &t) {
|
||||
*timerImpl = *(t.timerImpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Timer::setFreq() {
|
||||
TimerImpl::setFreq();
|
||||
}
|
||||
};
|
191
runtime/utilities/perf_profiler.cpp
Normal file
191
runtime/utilities/perf_profiler.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/os_interface/os_inc.h"
|
||||
#include "runtime/utilities/perf_profiler.h"
|
||||
#include <runtime/utilities/stackvec.h>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
std::atomic<int> PerfProfiler::counter(0);
|
||||
|
||||
PerfProfiler *PerfProfiler::objects[PerfProfiler::objectsNumber] = {
|
||||
nullptr,
|
||||
};
|
||||
|
||||
PerfProfiler *PerfProfiler::create(bool dumpToFile) {
|
||||
if (gPerfProfiler == nullptr) {
|
||||
int old = counter.fetch_add(1);
|
||||
if (!dumpToFile) {
|
||||
std::unique_ptr<std::stringstream> logs = std::unique_ptr<std::stringstream>(new std::stringstream());
|
||||
std::unique_ptr<std::stringstream> sysLogs = std::unique_ptr<std::stringstream>(new std::stringstream());
|
||||
gPerfProfiler = new PerfProfiler(old, std::move(logs), std::move(sysLogs));
|
||||
} else {
|
||||
gPerfProfiler = new PerfProfiler(old);
|
||||
}
|
||||
objects[old] = gPerfProfiler;
|
||||
}
|
||||
return gPerfProfiler;
|
||||
}
|
||||
|
||||
void PerfProfiler::destroyAll() {
|
||||
int count = counter;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (objects[i] != nullptr) {
|
||||
delete objects[i];
|
||||
objects[i] = nullptr;
|
||||
}
|
||||
}
|
||||
counter = 0;
|
||||
gPerfProfiler = nullptr;
|
||||
}
|
||||
|
||||
PerfProfiler::PerfProfiler(int id, std::unique_ptr<std::ostream> logOut, std::unique_ptr<std::ostream> sysLogOut) : totalSystemTime(0) {
|
||||
ApiTimer.setFreq();
|
||||
|
||||
systemLogs.reserve(20);
|
||||
|
||||
if (logOut != nullptr) {
|
||||
this->logFile = std::move(logOut);
|
||||
} else {
|
||||
stringstream filename;
|
||||
filename << "PerfReport_Thread_" << id << ".xml";
|
||||
|
||||
std::unique_ptr<std::ofstream> logToFile = std::unique_ptr<std::ofstream>(new std::ofstream());
|
||||
logToFile->exceptions(std::ios::failbit | std::ios::badbit);
|
||||
logToFile->open(filename.str().c_str(), ios::trunc);
|
||||
this->logFile = std::move(logToFile);
|
||||
}
|
||||
|
||||
*logFile << "<report>" << std::endl;
|
||||
|
||||
if (sysLogOut != nullptr) {
|
||||
this->sysLogFile = std::move(sysLogOut);
|
||||
} else {
|
||||
stringstream filename;
|
||||
filename << "SysPerfReport_Thread_" << id << ".xml";
|
||||
|
||||
std::unique_ptr<std::ofstream> sysLogToFile = std::unique_ptr<std::ofstream>(new std::ofstream());
|
||||
sysLogToFile->exceptions(std::ios::failbit | std::ios::badbit);
|
||||
sysLogToFile->open(filename.str().c_str(), ios::trunc);
|
||||
this->sysLogFile = std::move(sysLogToFile);
|
||||
}
|
||||
|
||||
*sysLogFile << "<report>" << std::endl;
|
||||
}
|
||||
|
||||
PerfProfiler::~PerfProfiler() {
|
||||
*logFile << "</report>" << std::endl;
|
||||
logFile->flush();
|
||||
*sysLogFile << "</report>" << std::endl;
|
||||
sysLogFile->flush();
|
||||
gPerfProfiler = nullptr;
|
||||
}
|
||||
|
||||
void PerfProfiler::readAndVerify(std::istream &stream, const std::string &token) {
|
||||
StackVec<char, 4096> buff;
|
||||
buff.resize(token.size());
|
||||
size_t numRead = static_cast<size_t>(stream.readsome(&buff[0], token.size()));
|
||||
if ((numRead != token.size()) || (0 != std::strncmp(&buff[0], token.c_str(), token.size()))) {
|
||||
throw std::runtime_error("ReadAndVerify failed");
|
||||
}
|
||||
}
|
||||
|
||||
void PerfProfiler::LogBuilder::write(std::ostream &str, long long start, long long end, long long span, unsigned long long totalSystem, const char *function) {
|
||||
str << "<api name=\"" << function << "\">\n";
|
||||
str << "<data start=\"" << start << "\" end=\"" << end << "\" time=\""
|
||||
<< span << "\" api=\"" << span - totalSystem << "\" system=\"" << totalSystem << "\" />\n";
|
||||
str << "</api>\n";
|
||||
}
|
||||
|
||||
void PerfProfiler::LogBuilder::read(std::istream &str, long long &start, long long &end, long long &span, unsigned long long &totalSystem, std::string &function) {
|
||||
StackVec<char, 4096> funcNameBuff;
|
||||
readAndVerify(str, "<api name=\"");
|
||||
while ((str.eof() == false) && (str.peek() != '\"')) {
|
||||
char c;
|
||||
str.read(&c, 1);
|
||||
funcNameBuff.push_back(c);
|
||||
}
|
||||
if (str.eof()) {
|
||||
throw std::runtime_error("Could not read function name");
|
||||
}
|
||||
readAndVerify(str, "\">\n");
|
||||
readAndVerify(str, "<data start=\"");
|
||||
str >> start;
|
||||
readAndVerify(str, "\" end=\"");
|
||||
str >> end;
|
||||
readAndVerify(str, "\" time=\"");
|
||||
str >> span;
|
||||
readAndVerify(str, "\" api=\"");
|
||||
str >> totalSystem;
|
||||
readAndVerify(str, "\" system=\"");
|
||||
str >> totalSystem;
|
||||
readAndVerify(str, "\" />\n");
|
||||
readAndVerify(str, "</api>\n");
|
||||
|
||||
function.assign(funcNameBuff.begin(), funcNameBuff.end());
|
||||
}
|
||||
|
||||
void PerfProfiler::SysLogBuilder::write(std::ostream &str, long long start, unsigned long long time, unsigned int id) {
|
||||
str << "<sys id=\"" << id << "\">\n";
|
||||
str << "<data start=\"" << start << "\" time=\"" << time << "\" />\n";
|
||||
str << "</sys>\n";
|
||||
}
|
||||
|
||||
void PerfProfiler::SysLogBuilder::read(std::istream &str, long long &start, unsigned long long &time, unsigned int &id) {
|
||||
readAndVerify(str, "<sys id=\"");
|
||||
str >> id;
|
||||
readAndVerify(str, "\">\n");
|
||||
readAndVerify(str, "<data start=\"");
|
||||
str >> start;
|
||||
readAndVerify(str, "\" time=\"");
|
||||
str >> time;
|
||||
readAndVerify(str, "\" />\n");
|
||||
readAndVerify(str, "</sys>\n");
|
||||
}
|
||||
|
||||
void PerfProfiler::logTimes(long long start, long long end, long long span, unsigned long long totalSystem, const char *function) {
|
||||
stringstream str;
|
||||
LogBuilder::write(str, start, end, span, totalSystem, function);
|
||||
*logFile << str.str();
|
||||
logFile->flush();
|
||||
|
||||
auto it = systemLogs.begin();
|
||||
while (it != systemLogs.end()) {
|
||||
str.str(std::string());
|
||||
SysLogBuilder::write(str, it->start, it->time, it->id);
|
||||
*sysLogFile << str.str();
|
||||
it++;
|
||||
}
|
||||
sysLogFile->flush();
|
||||
}
|
||||
|
||||
void PerfProfiler::logSysTimes(long long start, unsigned long long time, unsigned int id) {
|
||||
systemLogs.emplace_back(SystemLog{id, start, time});
|
||||
}
|
||||
}
|
131
runtime/utilities/perf_profiler.h
Normal file
131
runtime/utilities/perf_profiler.h
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/helpers/options.h"
|
||||
#include "runtime/os_interface/os_inc.h"
|
||||
#include "runtime/utilities/timer_util.h"
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace OCLRT {
|
||||
class PerfProfiler {
|
||||
|
||||
struct SystemLog {
|
||||
unsigned int id;
|
||||
long long start;
|
||||
unsigned long long time;
|
||||
};
|
||||
|
||||
public:
|
||||
struct LogBuilder {
|
||||
static void write(std::ostream &str, long long start, long long end, long long span, unsigned long long totalSystem, const char *function);
|
||||
static void read(std::istream &str, long long &start, long long &end, long long &span, unsigned long long &totalSystem, std::string &function);
|
||||
};
|
||||
|
||||
struct SysLogBuilder {
|
||||
static void write(std::ostream &str, long long start, unsigned long long time, unsigned int id);
|
||||
static void read(std::istream &str, long long &start, unsigned long long &time, unsigned int &id);
|
||||
};
|
||||
|
||||
static void readAndVerify(std::istream &stream, const std::string &token);
|
||||
|
||||
PerfProfiler(int id, std::unique_ptr<std::ostream> logOut = {nullptr},
|
||||
std::unique_ptr<std::ostream> sysLogOut = {nullptr});
|
||||
~PerfProfiler();
|
||||
|
||||
void apiEnter() {
|
||||
totalSystemTime = 0;
|
||||
systemLogs.clear();
|
||||
systemLogs.reserve(20);
|
||||
ApiTimer.start();
|
||||
}
|
||||
|
||||
void apiLeave(const char *func) {
|
||||
ApiTimer.end();
|
||||
logTimes(ApiTimer.getStart(), ApiTimer.getEnd(), ApiTimer.get(), totalSystemTime, func);
|
||||
}
|
||||
|
||||
void logTimes(long long start, long long end, long long span, unsigned long long totalSystem, const char *function);
|
||||
void logSysTimes(long long start, unsigned long long time, unsigned int id);
|
||||
|
||||
void systemEnter() {
|
||||
SystemTimer.start();
|
||||
}
|
||||
|
||||
void systemLeave(unsigned int id) {
|
||||
SystemTimer.end();
|
||||
logSysTimes(SystemTimer.getStart(), SystemTimer.get(), id);
|
||||
totalSystemTime += SystemTimer.get();
|
||||
}
|
||||
|
||||
std::ostream *getLogStream() {
|
||||
return logFile.get();
|
||||
}
|
||||
|
||||
std::ostream *getSystemLogStream() {
|
||||
return sysLogFile.get();
|
||||
}
|
||||
|
||||
static PerfProfiler *create(bool dumpToFile = true);
|
||||
static void destroyAll();
|
||||
|
||||
static int getCurrentCounter() {
|
||||
return counter.load();
|
||||
}
|
||||
|
||||
static PerfProfiler *getObject(unsigned int id) {
|
||||
return objects[id];
|
||||
}
|
||||
|
||||
static const unsigned int objectsNumber = 4096;
|
||||
|
||||
protected:
|
||||
static std::atomic<int> counter;
|
||||
static PerfProfiler *objects[PerfProfiler::objectsNumber];
|
||||
Timer ApiTimer;
|
||||
Timer SystemTimer;
|
||||
unsigned long long totalSystemTime;
|
||||
std::unique_ptr<std::ostream> logFile;
|
||||
std::unique_ptr<std::ostream> sysLogFile;
|
||||
std::vector<SystemLog> systemLogs;
|
||||
};
|
||||
|
||||
#if OCL_RUNTIME_PROFILING == 1
|
||||
struct PerfProfilerApiWrapper {
|
||||
PerfProfilerApiWrapper(const char *funcName)
|
||||
: funcName(funcName) {
|
||||
PerfProfiler::create();
|
||||
gPerfProfiler->apiEnter();
|
||||
}
|
||||
|
||||
~PerfProfilerApiWrapper() {
|
||||
gPerfProfiler->apiLeave(funcName);
|
||||
}
|
||||
|
||||
const char *funcName;
|
||||
};
|
||||
#endif
|
||||
}; // namespace OCLRT
|
49
runtime/utilities/range.h
Normal file
49
runtime/utilities/range.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
template <typename T>
|
||||
struct Range {
|
||||
Range(T *base, size_t count)
|
||||
: Beg(base), End(base + count) {
|
||||
}
|
||||
|
||||
T *begin() {
|
||||
return Beg;
|
||||
}
|
||||
|
||||
T *end() {
|
||||
return End;
|
||||
}
|
||||
|
||||
T *Beg;
|
||||
T *End;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Range<T> CreateRange(T *base, size_t count) {
|
||||
return Range<T>(base, count);
|
||||
}
|
||||
}
|
183
runtime/utilities/reference_tracked_object.h
Normal file
183
runtime/utilities/reference_tracked_object.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
template <typename CT = int32_t>
|
||||
class RefCounter {
|
||||
public:
|
||||
RefCounter()
|
||||
: val(0) {
|
||||
}
|
||||
|
||||
CT peek() const {
|
||||
CT curr = val.load();
|
||||
DEBUG_BREAK_IF(curr < 0);
|
||||
return curr;
|
||||
}
|
||||
|
||||
void inc() {
|
||||
CT curr = ++val;
|
||||
DEBUG_BREAK_IF(curr < 1);
|
||||
((void)(curr));
|
||||
}
|
||||
|
||||
bool dec() {
|
||||
CT curr = --val;
|
||||
DEBUG_BREAK_IF(curr < 0);
|
||||
return (curr == 0);
|
||||
}
|
||||
|
||||
bool peekIsZero() const {
|
||||
return (val == 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::atomic<CT> val;
|
||||
};
|
||||
|
||||
template <typename DerivedClass>
|
||||
class ReferenceTrackedObject;
|
||||
|
||||
template <typename DataType>
|
||||
class unique_ptr_if_unused : public std::unique_ptr<DataType, void (*)(DataType *)> {
|
||||
using DeleterFuncType = void (*)(DataType *);
|
||||
|
||||
public:
|
||||
unique_ptr_if_unused()
|
||||
: std::unique_ptr<DataType, DeleterFuncType>(nullptr, dontDelete) {
|
||||
}
|
||||
|
||||
unique_ptr_if_unused(DataType *ptr, bool unused, DeleterFuncType customDeleter = nullptr)
|
||||
: std::unique_ptr<DataType, DeleterFuncType>(ptr, unused ? chooseDeleter(ptr, customDeleter) : dontDelete) {
|
||||
}
|
||||
|
||||
bool isUnused() const {
|
||||
return (this->get_deleter() != dontDelete);
|
||||
}
|
||||
|
||||
private:
|
||||
static DeleterFuncType chooseDeleter(DataType *inPtr, DeleterFuncType customDeleter) {
|
||||
DeleterFuncType deleter = customDeleter;
|
||||
if (customDeleter == nullptr) {
|
||||
deleter = getObjDeleter(inPtr);
|
||||
}
|
||||
|
||||
if (deleter == nullptr) {
|
||||
deleter = &doDelete;
|
||||
}
|
||||
|
||||
return deleter;
|
||||
}
|
||||
|
||||
template <typename DT = DataType>
|
||||
static typename std::enable_if<std::is_base_of<ReferenceTrackedObject<DataType>, DT>::value, DeleterFuncType>::type getObjDeleter(DataType *inPtr) {
|
||||
if (inPtr != nullptr) {
|
||||
return inPtr->getCustomDeleter();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename DT = DataType>
|
||||
static typename std::enable_if<!std::is_base_of<ReferenceTrackedObject<DataType>, DT>::value, DeleterFuncType>::type getObjDeleter(DataType *inPtr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void doDelete(DataType *ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
static void dontDelete(DataType *ptr) {
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
// This class is needed for having both internal and external (api)
|
||||
// reference counters
|
||||
// Note : we need both counters because an OCL app can release an OCL object
|
||||
// while this object is still needed/valid (e.g. events with callbacks),
|
||||
// so we need to have a way of tracking internal usage of these object.
|
||||
// At the same time, we can't use one refcount for both internal and external
|
||||
// (retain/release api) usage because an OCL application can query object's
|
||||
// refcount (this refcount should not be contaminated by our internal usage models)
|
||||
// Note : internal refcount accumulates also api refcounts (i.e. incrementing/decrementing
|
||||
// api refcount will increment/decrement internal refcount as well) - so, object
|
||||
// deletion is based on single/atomic decision "if(--internalRefcount == 0)"
|
||||
template <typename DerivedClass>
|
||||
class ReferenceTrackedObject {
|
||||
public:
|
||||
virtual ~ReferenceTrackedObject() = default;
|
||||
|
||||
int32_t getRefInternalCount() const {
|
||||
return refInternal.peek();
|
||||
}
|
||||
|
||||
void incRefInternal() {
|
||||
refInternal.inc();
|
||||
}
|
||||
|
||||
unique_ptr_if_unused<DerivedClass> decRefInternal() {
|
||||
auto customDeleter = tryGetCustomDeleter();
|
||||
bool unused = refInternal.dec();
|
||||
return unique_ptr_if_unused<DerivedClass>(static_cast<DerivedClass *>(this), unused, customDeleter);
|
||||
}
|
||||
|
||||
int32_t getRefApiCount() const {
|
||||
return refApi.peek();
|
||||
}
|
||||
|
||||
void incRefApi() {
|
||||
refApi.inc();
|
||||
refInternal.inc();
|
||||
}
|
||||
|
||||
unique_ptr_if_unused<DerivedClass> decRefApi() {
|
||||
refApi.dec();
|
||||
return decRefInternal();
|
||||
}
|
||||
|
||||
using DeleterFuncType = void (*)(DerivedClass *);
|
||||
DeleterFuncType getCustomDeleter() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool peekHasZeroRefcounts() const {
|
||||
return refInternal.peekIsZero();
|
||||
}
|
||||
|
||||
private:
|
||||
DeleterFuncType tryGetCustomDeleter() const {
|
||||
const DerivedClass *asDerivedObj = static_cast<const DerivedClass *>(this);
|
||||
return asDerivedObj->getCustomDeleter();
|
||||
}
|
||||
|
||||
RefCounter<> refInternal;
|
||||
RefCounter<> refApi;
|
||||
};
|
||||
}
|
244
runtime/utilities/stackvec.h
Normal file
244
runtime/utilities/stackvec.h
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
template <typename DataType, uint32_t OnStackCapacity>
|
||||
class StackVec {
|
||||
public:
|
||||
static const uint32_t onStackCaps = OnStackCapacity;
|
||||
|
||||
StackVec()
|
||||
: dynamicMem(nullptr) {
|
||||
}
|
||||
|
||||
template <typename ItType>
|
||||
StackVec(ItType beginIt, ItType endIt)
|
||||
: dynamicMem(nullptr) {
|
||||
size_t count = (endIt - beginIt);
|
||||
if (count > OnStackCapacity) {
|
||||
dynamicMem = new std::vector<DataType>(beginIt, endIt);
|
||||
return;
|
||||
}
|
||||
|
||||
while (beginIt != endIt) {
|
||||
push_back(*beginIt);
|
||||
++beginIt;
|
||||
}
|
||||
onStackSize = static_cast<uint32_t>(count);
|
||||
}
|
||||
|
||||
StackVec(const StackVec &rhs)
|
||||
: dynamicMem(nullptr) {
|
||||
if (onStackCaps < rhs.size()) {
|
||||
dynamicMem = new std::vector<DataType>(rhs.begin(), rhs.end());
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &v : rhs) {
|
||||
push_back(v);
|
||||
}
|
||||
}
|
||||
StackVec &operator=(const StackVec &rhs) {
|
||||
clear();
|
||||
|
||||
if (this->dynamicMem != nullptr) {
|
||||
this->dynamicMem->insert(dynamicMem->end(), rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (onStackCaps < rhs.size()) {
|
||||
this->dynamicMem = new std::vector<DataType>(rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
for (const auto &v : rhs) {
|
||||
push_back(v);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
StackVec(StackVec &&rhs)
|
||||
: dynamicMem(nullptr) {
|
||||
if (rhs.dynamicMem != nullptr) {
|
||||
std::swap(this->dynamicMem, rhs.dynamicMem);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &v : rhs) {
|
||||
push_back(v);
|
||||
}
|
||||
}
|
||||
StackVec &operator=(StackVec &&rhs) {
|
||||
clear();
|
||||
|
||||
if (rhs.dynamicMem != nullptr) {
|
||||
std::swap(this->dynamicMem, rhs.dynamicMem);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (this->dynamicMem != nullptr) {
|
||||
this->dynamicMem->insert(this->dynamicMem->end(), rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
for (const auto &v : rhs) {
|
||||
push_back(v);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~StackVec() {
|
||||
if (dynamicMem != nullptr) {
|
||||
delete dynamicMem;
|
||||
return;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->size();
|
||||
}
|
||||
return onStackSize;
|
||||
}
|
||||
|
||||
size_t capacity() const {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->capacity();
|
||||
}
|
||||
return OnStackCapacity;
|
||||
}
|
||||
|
||||
void reserve(size_t newCapacity) {
|
||||
if (newCapacity > onStackCaps) {
|
||||
ensureDynamicMem();
|
||||
dynamicMem->reserve(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (dynamicMem) {
|
||||
dynamicMem->clear();
|
||||
return;
|
||||
}
|
||||
clearStackObjets();
|
||||
}
|
||||
|
||||
void push_back(const DataType &v) { // NOLINT
|
||||
if (onStackSize == onStackCaps) {
|
||||
ensureDynamicMem();
|
||||
}
|
||||
|
||||
if (dynamicMem) {
|
||||
dynamicMem->push_back(v);
|
||||
return;
|
||||
}
|
||||
|
||||
new (onStackMem + onStackSize) DataType(v);
|
||||
++onStackSize;
|
||||
}
|
||||
|
||||
DataType &operator[](std::size_t idx) {
|
||||
if (dynamicMem) {
|
||||
return (*dynamicMem)[idx];
|
||||
}
|
||||
return *(onStackMem + idx);
|
||||
}
|
||||
|
||||
const DataType &operator[](std::size_t idx) const {
|
||||
if (dynamicMem) {
|
||||
return (*dynamicMem)[idx];
|
||||
}
|
||||
return *(onStackMem + idx);
|
||||
}
|
||||
|
||||
DataType *begin() {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->data();
|
||||
}
|
||||
|
||||
return onStackMem;
|
||||
}
|
||||
|
||||
const DataType *begin() const {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->data();
|
||||
}
|
||||
|
||||
return onStackMem;
|
||||
}
|
||||
|
||||
DataType *end() {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->data() + dynamicMem->size();
|
||||
}
|
||||
|
||||
return onStackMem + onStackSize;
|
||||
}
|
||||
|
||||
const DataType *end() const {
|
||||
if (dynamicMem) {
|
||||
return dynamicMem->data() + dynamicMem->size();
|
||||
}
|
||||
|
||||
return onStackMem + onStackSize;
|
||||
}
|
||||
|
||||
void resize(size_t newCapacity) {
|
||||
if (newCapacity > onStackCaps) {
|
||||
ensureDynamicMem();
|
||||
dynamicMem->resize(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ensureDynamicMem() {
|
||||
if (dynamicMem == nullptr) {
|
||||
dynamicMem = new std::vector<DataType>();
|
||||
if (onStackSize > 0) {
|
||||
dynamicMem->reserve(onStackSize);
|
||||
for (auto it = onStackMem, end = onStackMem + onStackSize; it != end; ++it) {
|
||||
dynamicMem->push_back(std::move(*it));
|
||||
}
|
||||
clearStackObjets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clearStackObjets() {
|
||||
for (auto it = onStackMem, end = onStackMem + onStackSize; it != end; ++it) {
|
||||
it->~DataType();
|
||||
}
|
||||
onStackSize = 0;
|
||||
}
|
||||
|
||||
alignas(alignof(DataType)) char onStackMemRawBytes[sizeof(DataType[onStackCaps])];
|
||||
std::vector<DataType> *dynamicMem;
|
||||
DataType *const onStackMem = reinterpret_cast<DataType *const>(onStackMemRawBytes);
|
||||
uint32_t onStackSize = 0;
|
||||
};
|
155
runtime/utilities/tag_allocator.h
Normal file
155
runtime/utilities/tag_allocator.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/helpers/aligned_memory.h"
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
#include "runtime/memory_manager/memory_manager.h"
|
||||
#include "runtime/utilities/idlist.h"
|
||||
#include "runtime/utilities/tag_allocator_base.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace OCLRT {
|
||||
class GraphicsAllocation;
|
||||
|
||||
template <typename TagType>
|
||||
struct TagNode : public IDNode<TagNode<TagType>> {
|
||||
public:
|
||||
TagType *tag;
|
||||
GraphicsAllocation *getGraphicsAllocation() {
|
||||
return gfxAllocation;
|
||||
}
|
||||
|
||||
protected:
|
||||
TagNode() = default;
|
||||
GraphicsAllocation *gfxAllocation;
|
||||
|
||||
template <typename TagType2>
|
||||
friend class TagAllocator;
|
||||
};
|
||||
|
||||
template <typename TagType>
|
||||
class TagAllocator : public TagAllocatorBase {
|
||||
public:
|
||||
using NodeType = TagNode<TagType>;
|
||||
|
||||
TagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment, size_t maxTagPoolCount) : memoryManager(memMngr),
|
||||
maxTagPoolCount(maxTagPoolCount),
|
||||
tagCount(tagCount),
|
||||
tagAlignment(tagAlignment) {
|
||||
if (maxTagPoolCount) {
|
||||
gfxAllocations.reserve(maxTagPoolCount);
|
||||
tagPoolMemory.reserve(maxTagPoolCount);
|
||||
} else {
|
||||
gfxAllocations.reserve(PrefferedProfilingTagPoolCount);
|
||||
tagPoolMemory.reserve(PrefferedProfilingTagPoolCount);
|
||||
}
|
||||
populateFreeTags();
|
||||
}
|
||||
|
||||
~TagAllocator() override {
|
||||
cleanUpResources();
|
||||
}
|
||||
|
||||
void cleanUpResources() override {
|
||||
size_t size = gfxAllocations.size();
|
||||
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
memoryManager->freeGraphicsMemory(gfxAllocations[i]);
|
||||
}
|
||||
gfxAllocations.clear();
|
||||
|
||||
size = tagPoolMemory.size();
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
delete[] tagPoolMemory[i];
|
||||
}
|
||||
tagPoolMemory.clear();
|
||||
}
|
||||
|
||||
NodeType *getTag() {
|
||||
NodeType *node = freeTags.removeFrontOne().release();
|
||||
if (!node) {
|
||||
populateFreeTags();
|
||||
node = freeTags.removeFrontOne().release();
|
||||
}
|
||||
if (node)
|
||||
usedTags.pushFrontOne(*node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void returnTag(NodeType *node) {
|
||||
NodeType *usedNode = usedTags.removeOne(*node).release();
|
||||
DEBUG_BREAK_IF(usedNode == nullptr);
|
||||
((void)(usedNode));
|
||||
freeTags.pushFrontOne(*node);
|
||||
}
|
||||
size_t peekMaxTagPoolCount() { return maxTagPoolCount; }
|
||||
|
||||
protected:
|
||||
IDList<NodeType> freeTags;
|
||||
IDList<NodeType> usedTags;
|
||||
std::vector<GraphicsAllocation *> gfxAllocations;
|
||||
std::vector<NodeType *> tagPoolMemory;
|
||||
|
||||
MemoryManager *memoryManager;
|
||||
const size_t maxTagPoolCount;
|
||||
size_t tagCount;
|
||||
size_t tagAlignment;
|
||||
|
||||
std::mutex allocationsMutex;
|
||||
|
||||
void populateFreeTags() {
|
||||
|
||||
size_t tagSize = sizeof(TagType);
|
||||
tagSize = alignUp(tagSize, tagAlignment);
|
||||
size_t allocationSizeRequired = tagCount * tagSize;
|
||||
|
||||
std::unique_lock<std::mutex> lock(allocationsMutex);
|
||||
|
||||
size_t tagPoolCount = gfxAllocations.size();
|
||||
if (tagPoolCount < maxTagPoolCount || maxTagPoolCount == 0) {
|
||||
GraphicsAllocation *graphicsAllocation = memoryManager->allocateGraphicsMemory(allocationSizeRequired);
|
||||
gfxAllocations.push_back(graphicsAllocation);
|
||||
|
||||
uintptr_t Size = graphicsAllocation->getUnderlyingBufferSize();
|
||||
uintptr_t Start = reinterpret_cast<uintptr_t>(graphicsAllocation->getUnderlyingBuffer());
|
||||
uintptr_t End = Start + Size;
|
||||
size_t nodeCount = Size / tagSize;
|
||||
|
||||
NodeType *nodesMemory = new NodeType[nodeCount];
|
||||
|
||||
for (size_t i = 0; i < nodeCount; ++i) {
|
||||
nodesMemory[i].gfxAllocation = graphicsAllocation;
|
||||
nodesMemory[i].tag = reinterpret_cast<TagType *>(Start);
|
||||
freeTags.pushTailOne(nodesMemory[i]);
|
||||
Start += tagSize;
|
||||
}
|
||||
DEBUG_BREAK_IF(Start > End);
|
||||
((void)(End));
|
||||
tagPoolMemory.push_back(nodesMemory);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace OCLRT
|
41
runtime/utilities/tag_allocator_base.h
Normal file
41
runtime/utilities/tag_allocator_base.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace OCLRT {
|
||||
constexpr size_t UnlimitedProfilingCount = 0;
|
||||
constexpr size_t ProfilingTagCount = 512;
|
||||
constexpr size_t PrefferedProfilingTagPoolCount = 10;
|
||||
|
||||
constexpr size_t UnlimitedPerfCounterCount = 0;
|
||||
constexpr size_t PerfCounterTagCount = 512;
|
||||
|
||||
class TagAllocatorBase {
|
||||
public:
|
||||
virtual ~TagAllocatorBase(){};
|
||||
virtual void cleanUpResources() = 0;
|
||||
|
||||
protected:
|
||||
TagAllocatorBase() = default;
|
||||
};
|
||||
}
|
52
runtime/utilities/timer_util.h
Normal file
52
runtime/utilities/timer_util.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
Timer();
|
||||
Timer(const Timer &) = delete;
|
||||
|
||||
~Timer();
|
||||
|
||||
void start();
|
||||
|
||||
void end();
|
||||
|
||||
long long int get();
|
||||
|
||||
long long getStart();
|
||||
long long getEnd();
|
||||
|
||||
Timer &operator=(const Timer &t);
|
||||
|
||||
static void setFreq();
|
||||
|
||||
private:
|
||||
class TimerImpl;
|
||||
TimerImpl *timerImpl;
|
||||
};
|
||||
};
|
82
runtime/utilities/vec.h
Normal file
82
runtime/utilities/vec.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
|
||||
namespace OCLRT {
|
||||
template <typename T>
|
||||
struct Vec3 {
|
||||
Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
|
||||
Vec3(const Vec3 &v) : x(v.x), y(v.y), z(v.z) {}
|
||||
Vec3(const T *arr) {
|
||||
if (arr == nullptr) {
|
||||
x = y = z = 0;
|
||||
} else {
|
||||
x = arr[0];
|
||||
y = arr[1];
|
||||
z = arr[2];
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 &operator=(const Vec3 &arr) {
|
||||
x = arr.x;
|
||||
y = arr.y;
|
||||
z = arr.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec3<T> &operator=(const T arr[3]) {
|
||||
x = arr[0];
|
||||
y = arr[1];
|
||||
z = arr[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Vec3<T> &vec) const {
|
||||
return ((x == vec.x) && (y == vec.y) && (z == vec.z));
|
||||
}
|
||||
|
||||
bool operator!=(const Vec3<T> &vec) const {
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
unsigned int getSimplifiedDim() const {
|
||||
if (z > 1) {
|
||||
return 3;
|
||||
}
|
||||
if (y > 1) {
|
||||
return 2;
|
||||
}
|
||||
if (x >= 1) {
|
||||
return 1;
|
||||
}
|
||||
DEBUG_BREAK_IF((y != 0) || (z != 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
};
|
||||
}
|
49
runtime/utilities/windows/cpu_info.cpp
Normal file
49
runtime/utilities/windows/cpu_info.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/cpu_info.h"
|
||||
#include <intrin.h>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
void cpuidex_windows_wrapper(int *cpuInfo, int functionId, int subfunctionId) {
|
||||
__cpuidex(cpuInfo, functionId, subfunctionId);
|
||||
}
|
||||
|
||||
void (*CpuInfo::cpuidexFunc)(int *, int, int) = cpuidex_windows_wrapper;
|
||||
|
||||
const CpuInfo CpuInfo::instance;
|
||||
|
||||
void CpuInfo::cpuid(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId) const {
|
||||
__cpuid(reinterpret_cast<int *>(cpuInfo), functionId);
|
||||
}
|
||||
|
||||
void CpuInfo::cpuidex(
|
||||
uint32_t cpuInfo[4],
|
||||
uint32_t functionId,
|
||||
uint32_t subfunctionId) const {
|
||||
cpuidexFunc(reinterpret_cast<int *>(cpuInfo), functionId, subfunctionId);
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
54
runtime/utilities/windows/directory.cpp
Normal file
54
runtime/utilities/windows/directory.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/utilities/directory.h"
|
||||
#include "runtime/os_interface/windows/windows_wrapper.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
std::vector<std::string> Directory::getFiles(std::string &path) {
|
||||
std::vector<std::string> files;
|
||||
std::string newPath;
|
||||
|
||||
WIN32_FIND_DATAA ffd;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (path.c_str()[path.size() - 1] == '/') {
|
||||
return files;
|
||||
} else {
|
||||
newPath = path + "/*";
|
||||
}
|
||||
|
||||
hFind = FindFirstFileA(newPath.c_str(), &ffd);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hFind) {
|
||||
return files;
|
||||
}
|
||||
|
||||
do {
|
||||
files.push_back(path + "/" + ffd.cFileName);
|
||||
} while (FindNextFileA(hFind, &ffd) != 0);
|
||||
|
||||
FindClose(hFind);
|
||||
return files;
|
||||
}
|
||||
};
|
127
runtime/utilities/windows/timer_util.cpp
Normal file
127
runtime/utilities/windows/timer_util.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "runtime/helpers/debug_helpers.h"
|
||||
#include "runtime/os_interface/windows/windows_wrapper.h"
|
||||
#include "runtime/utilities/timer_util.h"
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
class Timer::TimerImpl {
|
||||
public:
|
||||
TimerImpl() {
|
||||
memset(&m_startTime, 0, sizeof(LARGE_INTEGER));
|
||||
memset(&m_endTime, 0, sizeof(LARGE_INTEGER));
|
||||
}
|
||||
|
||||
~TimerImpl() {
|
||||
}
|
||||
|
||||
LARGE_INTEGER start() {
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&m_startTime);
|
||||
return m_startTime;
|
||||
}
|
||||
|
||||
LARGE_INTEGER end() {
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&m_endTime);
|
||||
return m_endTime;
|
||||
}
|
||||
|
||||
long long int get() {
|
||||
long long int nanosecondTime = 0;
|
||||
auto timeDelta = (double)(m_endTime.QuadPart - m_startTime.QuadPart);
|
||||
timeDelta /= (double)mFrequency.QuadPart;
|
||||
timeDelta *= 1000000000.0;
|
||||
|
||||
if (m_endTime.QuadPart < m_startTime.QuadPart) {
|
||||
DEBUG_BREAK_IF(true);
|
||||
}
|
||||
return (long long)timeDelta;
|
||||
}
|
||||
|
||||
long long getStart() {
|
||||
return (long long)(((LARGE_INTEGER *)&m_startTime)->QuadPart);
|
||||
}
|
||||
|
||||
long long getEnd() {
|
||||
|
||||
return (long long)(((LARGE_INTEGER *)&m_endTime)->QuadPart);
|
||||
}
|
||||
|
||||
TimerImpl &operator=(const TimerImpl &t) {
|
||||
m_startTime = t.m_startTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void setFreq() {
|
||||
QueryPerformanceFrequency(&mFrequency);
|
||||
}
|
||||
|
||||
public:
|
||||
static LARGE_INTEGER mFrequency;
|
||||
|
||||
private:
|
||||
LARGE_INTEGER m_startTime;
|
||||
LARGE_INTEGER m_endTime;
|
||||
};
|
||||
|
||||
LARGE_INTEGER Timer::TimerImpl::mFrequency = {
|
||||
{{0}},
|
||||
};
|
||||
|
||||
Timer::Timer() {
|
||||
timerImpl = new TimerImpl();
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
delete timerImpl;
|
||||
}
|
||||
|
||||
void Timer::start() {
|
||||
timerImpl->start();
|
||||
}
|
||||
|
||||
void Timer::end() {
|
||||
timerImpl->end();
|
||||
}
|
||||
|
||||
long long int Timer::get() {
|
||||
return timerImpl->get();
|
||||
}
|
||||
|
||||
long long Timer::getStart() {
|
||||
return timerImpl->getStart();
|
||||
}
|
||||
|
||||
long long Timer::getEnd() {
|
||||
return timerImpl->getEnd();
|
||||
}
|
||||
|
||||
Timer &Timer::operator=(const Timer &t) {
|
||||
*timerImpl = *(t.timerImpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Timer::setFreq() {
|
||||
TimerImpl::setFreq();
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user