diff --git a/level_zero/core/test/unit_tests/sources/device/test_device.cpp b/level_zero/core/test/unit_tests/sources/device/test_device.cpp index 4e2ae799f4..83437fa25d 100644 --- a/level_zero/core/test/unit_tests/sources/device/test_device.cpp +++ b/level_zero/core/test/unit_tests/sources/device/test_device.cpp @@ -527,23 +527,31 @@ TEST_F(DeviceTest, whenGetGlobalTimestampIsCalledThenSuccessIsReturnedAndValuesS EXPECT_NE(0u, deviceTs); } -class FalseCpuGpuTime : public NEO::OSTime { +class FalseCpuGpuDeviceTime : public NEO::DeviceTime { public: - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) override { return false; } - bool getCpuTime(uint64_t *timeStamp) override { - return true; - }; - double getHostTimerResolution() const override { - return 0; - } double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { return NEO::OSTime::getDeviceTimerResolution(hwInfo); } uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override { return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); } +}; + +class FalseCpuGpuTime : public NEO::OSTime { + public: + FalseCpuGpuTime() { + this->deviceTime = std::make_unique(); + } + + bool getCpuTime(uint64_t *timeStamp) override { + return true; + }; + double getHostTimerResolution() const override { + return 0; + } uint64_t getCpuRawTimestamp() override { return 0; } @@ -630,23 +638,30 @@ TEST_F(GlobalTimestampTest, whenQueryingForTimerResolutionWithUseCyclesPerSecond EXPECT_EQ(deviceProps.timerResolution, timerClock); } -class FalseCpuTime : public NEO::OSTime { +class FalseCpuDeviceTime : public NEO::DeviceTime { public: - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, NEO::OSTime *) override { return true; } - bool getCpuTime(uint64_t *timeStamp) override { - return false; - }; - double getHostTimerResolution() const override { - return 0; - } double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { return NEO::OSTime::getDeviceTimerResolution(hwInfo); } uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override { return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); } +}; + +class FalseCpuTime : public NEO::OSTime { + public: + FalseCpuTime() { + this->deviceTime = std::make_unique(); + } + bool getCpuTime(uint64_t *timeStamp) override { + return false; + }; + double getHostTimerResolution() const override { + return 0; + } uint64_t getCpuRawTimestamp() override { return 0; } diff --git a/opencl/test/unit_test/api/cl_get_device_and_host_timer.inl b/opencl/test/unit_test/api/cl_get_device_and_host_timer.inl index 27fec169f8..24d62db687 100644 --- a/opencl/test/unit_test/api/cl_get_device_and_host_timer.inl +++ b/opencl/test/unit_test/api/cl_get_device_and_host_timer.inl @@ -12,11 +12,18 @@ using namespace NEO; -struct FailOSTime : public MockOSTime { - public: - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { +struct FailDeviceTime : public MockDeviceTime { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *) override { return false; } +}; + +struct FailOSTime : public MockOSTime { + public: + FailOSTime() { + this->deviceTime = std::make_unique(); + } + bool getCpuTime(uint64_t *timeStamp) override { return false; }; diff --git a/opencl/test/unit_test/gen12lp/profiling_tests_gen12lp.inl b/opencl/test/unit_test/gen12lp/profiling_tests_gen12lp.inl index ee0891afdd..35975562e4 100644 --- a/opencl/test/unit_test/gen12lp/profiling_tests_gen12lp.inl +++ b/opencl/test/unit_test/gen12lp/profiling_tests_gen12lp.inl @@ -82,12 +82,7 @@ struct MockTagNode : public TagNode { } }; -class MyOSTime : public OSTime { - public: - static int instanceNum; - MyOSTime() { - instanceNum++; - } +class MyDeviceTime : public DeviceTime { double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { EXPECT_FALSE(true); return 1.0; @@ -96,10 +91,20 @@ class MyOSTime : public OSTime { EXPECT_FALSE(true); return 0; } - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *) override { EXPECT_FALSE(true); return false; } +}; + +class MyOSTime : public OSTime { + public: + static int instanceNum; + MyOSTime() { + instanceNum++; + this->deviceTime.reset(new MyDeviceTime()); + } + bool getCpuTime(uint64_t *timeStamp) override { EXPECT_FALSE(true); return false; diff --git a/opencl/test/unit_test/mocks/mock_ostime.h b/opencl/test/unit_test/mocks/mock_ostime.h index e2304f5d50..bf30b894c4 100644 --- a/opencl/test/unit_test/mocks/mock_ostime.h +++ b/opencl/test/unit_test/mocks/mock_ostime.h @@ -10,13 +10,28 @@ namespace NEO { static int PerfTicks = 0; -class MockOSTime : public OSTime { - public: - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { +class MockDeviceTime : public DeviceTime { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) override { pGpuCpuTime->GPUTimeStamp = ++PerfTicks; pGpuCpuTime->CPUTimeinNS = PerfTicks; return true; } + + double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { + return OSTime::getDeviceTimerResolution(hwInfo); + } + + uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override { + return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); + } +}; + +class MockOSTime : public OSTime { + public: + MockOSTime() { + this->deviceTime = std::make_unique(); + } + bool getCpuTime(uint64_t *timeStamp) override { *timeStamp = ++PerfTicks; return true; @@ -24,12 +39,7 @@ class MockOSTime : public OSTime { double getHostTimerResolution() const override { return 0; } - double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { - return OSTime::getDeviceTimerResolution(hwInfo); - } - uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override { - return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); - } + uint64_t getCpuRawTimestamp() override { return 0; } diff --git a/opencl/test/unit_test/mocks/mock_ostime_win.h b/opencl/test/unit_test/mocks/mock_ostime_win.h index bb81a44614..4e071a712e 100644 --- a/opencl/test/unit_test/mocks/mock_ostime_win.h +++ b/opencl/test/unit_test/mocks/mock_ostime_win.h @@ -6,17 +6,14 @@ */ #pragma once +#include "shared/source/os_interface/windows/device_time_wddm.h" #include "shared/source/os_interface/windows/os_time_win.h" namespace NEO { class MockOSTimeWin : public OSTimeWin { public: - MockOSTimeWin(Wddm *inWddm) { - wddm = inWddm; + MockOSTimeWin(Wddm *wddm) { + this->deviceTime = std::make_unique(wddm); } - - double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { - return OSTimeWin::getDynamicDeviceTimerResolution(hwInfo); - }; }; } // namespace NEO diff --git a/opencl/test/unit_test/os_interface/linux/mock_os_time_linux.h b/opencl/test/unit_test/os_interface/linux/mock_os_time_linux.h index 5671a9de54..b8210d2265 100644 --- a/opencl/test/unit_test/os_interface/linux/mock_os_time_linux.h +++ b/opencl/test/unit_test/os_interface/linux/mock_os_time_linux.h @@ -6,13 +6,23 @@ */ #pragma once +#include "shared/source/os_interface/linux/device_time_drm.h" #include "shared/source/os_interface/linux/os_interface.h" #include "shared/source/os_interface/linux/os_time_linux.h" namespace NEO { +class MockDeviceTimeDrm : public DeviceTimeDrm { + public: + using DeviceTimeDrm::pDrm; + MockDeviceTimeDrm() : DeviceTimeDrm(nullptr) { + } +}; + class MockOSTimeLinux : public OSTimeLinux { public: - MockOSTimeLinux(OSInterface *osInterface) : OSTimeLinux(osInterface){}; + MockOSTimeLinux(OSInterface *osInterface) + : OSTimeLinux(osInterface, std::make_unique()) { + } void setResolutionFunc(resolutionFunc_t func) { this->resolutionFunc = func; } @@ -21,11 +31,15 @@ class MockOSTimeLinux : public OSTimeLinux { } void updateDrm(Drm *drm) { osInterface->get()->setDrm(drm); - pDrm = drm; - timestampTypeDetect(); + static_cast(this->deviceTime.get())->pDrm = drm; + static_cast(this->deviceTime.get())->timestampTypeDetect(); } static std::unique_ptr create(OSInterface *osInterface) { return std::unique_ptr(new MockOSTimeLinux(osInterface)); } + + MockDeviceTimeDrm *getDeviceTime() { + return static_cast(this->deviceTime.get()); + } }; } // namespace NEO diff --git a/opencl/test/unit_test/os_interface/linux/os_time_test.cpp b/opencl/test/unit_test/os_interface/linux/os_time_test.cpp index b43f9e0c6e..e217e4f7de 100644 --- a/opencl/test/unit_test/os_interface/linux/os_time_test.cpp +++ b/opencl/test/unit_test/os_interface/linux/os_time_test.cpp @@ -74,13 +74,13 @@ TEST_F(DrmTimeTest, WhenGettingGpuTimeThenSuceeds) { uint64_t time = 0; auto pDrm = new DrmMockTime(); osTime->updateDrm(pDrm); - auto error = osTime->getGpuTime32(&time); + auto error = osTime->getDeviceTime()->getGpuTime32(&time); EXPECT_TRUE(error); EXPECT_NE(0ULL, time); - error = osTime->getGpuTime36(&time); + error = osTime->getDeviceTime()->getGpuTime36(&time); EXPECT_TRUE(error); EXPECT_NE(0ULL, time); - error = osTime->getGpuTimeSplitted(&time); + error = osTime->getDeviceTime()->getGpuTimeSplitted(&time); EXPECT_TRUE(error); EXPECT_NE(0ULL, time); } @@ -89,11 +89,11 @@ TEST_F(DrmTimeTest, GivenInvalidDrmWhenGettingGpuTimeThenFails) { uint64_t time = 0; auto pDrm = new DrmMockFail(); osTime->updateDrm(pDrm); - auto error = osTime->getGpuTime32(&time); + auto error = osTime->getDeviceTime()->getGpuTime32(&time); EXPECT_FALSE(error); - error = osTime->getGpuTime36(&time); + error = osTime->getDeviceTime()->getGpuTime36(&time); EXPECT_FALSE(error); - error = osTime->getGpuTimeSplitted(&time); + error = osTime->getDeviceTime()->getGpuTimeSplitted(&time); EXPECT_FALSE(error); } @@ -159,15 +159,15 @@ TEST_F(DrmTimeTest, WhenGettingTimeThenTimeIsCorrect) { osTime->updateDrm(drm); { - auto p = osTime->getGpuTime; - EXPECT_EQ(p, &OSTimeLinux::getGpuTime36); + auto p = osTime->getDeviceTime()->getGpuTime; + EXPECT_EQ(p, &DeviceTimeDrm::getGpuTime36); } { drm->ioctl_res = -1; - osTime->timestampTypeDetect(); - auto p = osTime->getGpuTime; - EXPECT_EQ(p, &OSTimeLinux::getGpuTime32); + osTime->getDeviceTime()->timestampTypeDetect(); + auto p = osTime->getDeviceTime()->getGpuTime; + EXPECT_EQ(p, &DeviceTimeDrm::getGpuTime32); } DrmMockCustom::IoctlResExt ioctlToPass = {1, 0}; @@ -175,9 +175,9 @@ TEST_F(DrmTimeTest, WhenGettingTimeThenTimeIsCorrect) { drm->reset(); drm->ioctl_res = -1; drm->ioctl_res_ext = &ioctlToPass; // 2nd ioctl is successful - osTime->timestampTypeDetect(); - auto p = osTime->getGpuTime; - EXPECT_EQ(p, &OSTimeLinux::getGpuTimeSplitted); + osTime->getDeviceTime()->timestampTypeDetect(); + auto p = osTime->getDeviceTime()->getGpuTime; + EXPECT_EQ(p, &DeviceTimeDrm::getGpuTimeSplitted); drm->ioctl_res_ext = &drm->NONE; } } diff --git a/opencl/test/unit_test/profiling/profiling_tests.cpp b/opencl/test/unit_test/profiling/profiling_tests.cpp index acb9f78880..9da56d228b 100644 --- a/opencl/test/unit_test/profiling/profiling_tests.cpp +++ b/opencl/test/unit_test/profiling/profiling_tests.cpp @@ -418,12 +418,7 @@ struct MockTagNode : public TagNode { } }; -class MyOSTime : public OSTime { - public: - static int instanceNum; - MyOSTime() { - instanceNum++; - } +class MyOSDeviceTime : public DeviceTime { double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override { EXPECT_FALSE(true); return 1.0; @@ -432,10 +427,20 @@ class MyOSTime : public OSTime { EXPECT_FALSE(true); return 0; } - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override { + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *) override { EXPECT_FALSE(true); return false; } +}; + +class MyOSTime : public OSTime { + public: + static int instanceNum; + MyOSTime() { + instanceNum++; + this->deviceTime = std::make_unique(); + } + bool getCpuTime(uint64_t *timeStamp) override { EXPECT_FALSE(true); return false; diff --git a/shared/source/os_interface/linux/CMakeLists.txt b/shared/source/os_interface/linux/CMakeLists.txt index a2e8adfc93..26566671aa 100644 --- a/shared/source/os_interface/linux/CMakeLists.txt +++ b/shared/source/os_interface/linux/CMakeLists.txt @@ -9,6 +9,8 @@ set(NEO_CORE_OS_INTERFACE_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/allocator_helper.h ${CMAKE_CURRENT_SOURCE_DIR}/cache_info.h ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/cache_info_impl.h + ${CMAKE_CURRENT_SOURCE_DIR}/device_time_drm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/device_time_drm.h ${CMAKE_CURRENT_SOURCE_DIR}/driver_info_linux.cpp ${CMAKE_CURRENT_SOURCE_DIR}/driver_info_linux.h ${CMAKE_CURRENT_SOURCE_DIR}/drm_allocation.cpp diff --git a/shared/source/os_interface/linux/device_time_drm.cpp b/shared/source/os_interface/linux/device_time_drm.cpp new file mode 100644 index 0000000000..146b66e955 --- /dev/null +++ b/shared/source/os_interface/linux/device_time_drm.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/linux/device_time_drm.h" + +#include "shared/source/os_interface/linux/drm_neo.h" +#include "shared/source/os_interface/linux/os_interface.h" + +#include "drm/i915_drm.h" + +#include + +namespace NEO { + +DeviceTimeDrm::DeviceTimeDrm(OSInterface *osInterface) { + if (osInterface) { + pDrm = osInterface->get()->getDrm(); + } + timestampTypeDetect(); +} + +void DeviceTimeDrm::timestampTypeDetect() { + struct drm_i915_reg_read reg = {}; + int err; + + if (pDrm == nullptr) + return; + + reg.offset = (TIMESTAMP_LOW_REG | 1); + err = pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®); + if (err) { + reg.offset = TIMESTAMP_HIGH_REG; + err = pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®); + if (err) { + getGpuTime = &DeviceTimeDrm::getGpuTime32; + timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS_FALLBACK; + } else { + getGpuTime = &DeviceTimeDrm::getGpuTimeSplitted; + timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS; + } + } else { + getGpuTime = &DeviceTimeDrm::getGpuTime36; + timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS; + } +} + +bool DeviceTimeDrm::getGpuTime32(uint64_t *timestamp) { + struct drm_i915_reg_read reg = {}; + + reg.offset = TIMESTAMP_LOW_REG; + + if (pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®)) { + return false; + } + *timestamp = reg.val >> 32; + return true; +} + +bool DeviceTimeDrm::getGpuTime36(uint64_t *timestamp) { + struct drm_i915_reg_read reg = {}; + + reg.offset = TIMESTAMP_LOW_REG | 1; + + if (pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®)) { + return false; + } + *timestamp = reg.val; + return true; +} + +bool DeviceTimeDrm::getGpuTimeSplitted(uint64_t *timestamp) { + struct drm_i915_reg_read reg_hi = {}; + struct drm_i915_reg_read reg_lo = {}; + uint64_t tmp_hi; + int err = 0, loop = 3; + + reg_hi.offset = TIMESTAMP_HIGH_REG; + reg_lo.offset = TIMESTAMP_LOW_REG; + + err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_hi); + do { + tmp_hi = reg_hi.val; + err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_lo); + err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_hi); + } while (err == 0 && reg_hi.val != tmp_hi && --loop); + + if (err) { + return false; + } + + *timestamp = reg_lo.val | (reg_hi.val << 32); + return true; +} + +bool DeviceTimeDrm::getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) { + if (nullptr == this->getGpuTime) { + return false; + } + if (!(this->*getGpuTime)(&pGpuCpuTime->GPUTimeStamp)) { + return false; + } + if (!osTime->getCpuTime(&pGpuCpuTime->CPUTimeinNS)) { + return false; + } + + return true; +} + +double DeviceTimeDrm::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { + if (pDrm) { + drm_i915_getparam_t getParam = {}; + int frequency = 0; + + getParam.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY; + getParam.value = &frequency; + auto error = pDrm->ioctl(DRM_IOCTL_I915_GETPARAM, &getParam); + + if (!error) { + return 1000000000.0 / frequency; + } + } + return OSTime::getDeviceTimerResolution(hwInfo); +} + +uint64_t DeviceTimeDrm::getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const { + if (pDrm) { + drm_i915_getparam_t getParam = {}; + int frequency = 0; + + getParam.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY; + getParam.value = &frequency; + auto error = pDrm->ioctl(DRM_IOCTL_I915_GETPARAM, &getParam); + + if (!error) { + return static_cast(frequency); + } + } + return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); +} + +} // namespace NEO diff --git a/shared/source/os_interface/linux/device_time_drm.h b/shared/source/os_interface/linux/device_time_drm.h new file mode 100644 index 0000000000..eadfe53271 --- /dev/null +++ b/shared/source/os_interface/linux/device_time_drm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/os_interface/linux/drm_neo.h" +#include "shared/source/os_interface/os_time.h" + +#define OCLRT_NUM_TIMESTAMP_BITS (36) +#define OCLRT_NUM_TIMESTAMP_BITS_FALLBACK (32) +#define TIMESTAMP_HIGH_REG 0x0235C +#define TIMESTAMP_LOW_REG 0x02358 + +namespace NEO { + +class DeviceTimeDrm : public DeviceTime { + public: + DeviceTimeDrm(OSInterface *osInterface); + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) override; + typedef bool (DeviceTimeDrm::*TimestampFunction)(uint64_t *); + void timestampTypeDetect(); + TimestampFunction getGpuTime = nullptr; + bool getGpuTime32(uint64_t *timestamp); + bool getGpuTime36(uint64_t *timestamp); + bool getGpuTimeSplitted(uint64_t *timestamp); + double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override; + uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override; + + protected: + Drm *pDrm = nullptr; + unsigned timestampSizeInBits; +}; + +} // namespace NEO diff --git a/shared/source/os_interface/linux/drm_null_device.h b/shared/source/os_interface/linux/drm_null_device.h index a96dfaaed2..53f89d6ea1 100644 --- a/shared/source/os_interface/linux/drm_null_device.h +++ b/shared/source/os_interface/linux/drm_null_device.h @@ -6,8 +6,8 @@ */ #pragma once +#include "shared/source/os_interface/linux/device_time_drm.h" #include "shared/source/os_interface/linux/drm_neo.h" -#include "shared/source/os_interface/linux/os_time_linux.h" #include "drm/i915_drm.h" diff --git a/shared/source/os_interface/linux/os_time_linux.cpp b/shared/source/os_interface/linux/os_time_linux.cpp index 17322c7aef..bfa877df00 100644 --- a/shared/source/os_interface/linux/os_time_linux.cpp +++ b/shared/source/os_interface/linux/os_time_linux.cpp @@ -7,50 +7,18 @@ #include "shared/source/os_interface/linux/os_time_linux.h" -#include "shared/source/os_interface/linux/drm_neo.h" -#include "shared/source/os_interface/linux/os_interface.h" - -#include "drm/i915_drm.h" +#include "shared/source/os_interface/linux/device_time_drm.h" +#include "shared/source/os_interface/os_interface.h" #include namespace NEO { -OSTimeLinux::OSTimeLinux(OSInterface *osInterface) { +OSTimeLinux::OSTimeLinux(OSInterface *osInterface, std::unique_ptr deviceTime) { this->osInterface = osInterface; resolutionFunc = &clock_getres; getTimeFunc = &clock_gettime; - if (osInterface) { - pDrm = osInterface->get()->getDrm(); - } - timestampTypeDetect(); -} - -OSTimeLinux::~OSTimeLinux(){}; - -void OSTimeLinux::timestampTypeDetect() { - struct drm_i915_reg_read reg = {}; - int err; - - if (pDrm == nullptr) - return; - - reg.offset = (TIMESTAMP_LOW_REG | 1); - err = pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®); - if (err) { - reg.offset = TIMESTAMP_HIGH_REG; - err = pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®); - if (err) { - getGpuTime = &OSTimeLinux::getGpuTime32; - timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS_FALLBACK; - } else { - getGpuTime = &OSTimeLinux::getGpuTimeSplitted; - timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS; - } - } else { - getGpuTime = &OSTimeLinux::getGpuTime36; - timestampSizeInBits = OCLRT_NUM_TIMESTAMP_BITS; - } + this->deviceTime = std::move(deviceTime); } bool OSTimeLinux::getCpuTime(uint64_t *timestamp) { @@ -65,72 +33,6 @@ bool OSTimeLinux::getCpuTime(uint64_t *timestamp) { return true; } -bool OSTimeLinux::getGpuTime32(uint64_t *timestamp) { - struct drm_i915_reg_read reg = {}; - - reg.offset = TIMESTAMP_LOW_REG; - - if (pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®)) { - return false; - } - *timestamp = reg.val >> 32; - return true; -} - -bool OSTimeLinux::getGpuTime36(uint64_t *timestamp) { - struct drm_i915_reg_read reg = {}; - - reg.offset = TIMESTAMP_LOW_REG | 1; - - if (pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®)) { - return false; - } - *timestamp = reg.val; - return true; -} - -bool OSTimeLinux::getGpuTimeSplitted(uint64_t *timestamp) { - struct drm_i915_reg_read reg_hi = {}; - struct drm_i915_reg_read reg_lo = {}; - uint64_t tmp_hi; - int err = 0, loop = 3; - - reg_hi.offset = TIMESTAMP_HIGH_REG; - reg_lo.offset = TIMESTAMP_LOW_REG; - - err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_hi); - do { - tmp_hi = reg_hi.val; - err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_lo); - err += pDrm->ioctl(DRM_IOCTL_I915_REG_READ, ®_hi); - } while (err == 0 && reg_hi.val != tmp_hi && --loop); - - if (err) { - return false; - } - - *timestamp = reg_lo.val | (reg_hi.val << 32); - return true; -} - -bool OSTimeLinux::getCpuGpuTime(TimeStampData *pGpuCpuTime) { - if (nullptr == this->getGpuTime) { - return false; - } - if (!(this->*getGpuTime)(&pGpuCpuTime->GPUTimeStamp)) { - return false; - } - if (!getCpuTime(&pGpuCpuTime->CPUTimeinNS)) { - return false; - } - - return true; -} - -std::unique_ptr OSTime::create(OSInterface *osInterface) { - return std::unique_ptr(new OSTimeLinux(osInterface)); -} - double OSTimeLinux::getHostTimerResolution() const { struct timespec ts; if (resolutionFunc(CLOCK_MONOTONIC_RAW, &ts)) { @@ -139,38 +41,6 @@ double OSTimeLinux::getHostTimerResolution() const { return static_cast(ts.tv_nsec + ts.tv_sec * NSEC_PER_SEC); } -double OSTimeLinux::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { - if (pDrm) { - drm_i915_getparam_t getParam = {}; - int frequency = 0; - - getParam.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY; - getParam.value = &frequency; - auto error = pDrm->ioctl(DRM_IOCTL_I915_GETPARAM, &getParam); - - if (!error) { - return 1000000000.0 / frequency; - } - } - return OSTime::getDeviceTimerResolution(hwInfo); -} - -uint64_t OSTimeLinux::getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const { - if (pDrm) { - drm_i915_getparam_t getParam = {}; - int frequency = 0; - - getParam.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY; - getParam.value = &frequency; - auto error = pDrm->ioctl(DRM_IOCTL_I915_GETPARAM, &getParam); - - if (!error) { - return static_cast(frequency); - } - } - return static_cast(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo)); -} - uint64_t OSTimeLinux::getCpuRawTimestamp() { uint64_t timesInNsec = 0; uint64_t ticksInNsec = 0; @@ -183,4 +53,9 @@ uint64_t OSTimeLinux::getCpuRawTimestamp() { } return timesInNsec / ticksInNsec; } + +std::unique_ptr OSTime::create(OSInterface *osInterface) { + return std::unique_ptr(new OSTimeLinux(osInterface, std::make_unique(osInterface))); +} + } // namespace NEO diff --git a/shared/source/os_interface/linux/os_time_linux.h b/shared/source/os_interface/linux/os_time_linux.h index 5a06fa4a73..0f72f22105 100644 --- a/shared/source/os_interface/linux/os_time_linux.h +++ b/shared/source/os_interface/linux/os_time_linux.h @@ -9,35 +9,20 @@ #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/os_time.h" -#define OCLRT_NUM_TIMESTAMP_BITS (36) -#define OCLRT_NUM_TIMESTAMP_BITS_FALLBACK (32) -#define TIMESTAMP_HIGH_REG 0x0235C -#define TIMESTAMP_LOW_REG 0x02358 +#include namespace NEO { class OSTimeLinux : public OSTime { public: - OSTimeLinux(OSInterface *osInterface); - ~OSTimeLinux() override; + OSTimeLinux(OSInterface *osInterface, std::unique_ptr deviceTime); bool getCpuTime(uint64_t *timeStamp) override; - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override; - typedef bool (OSTimeLinux::*TimestampFunction)(uint64_t *); - void timestampTypeDetect(); - TimestampFunction getGpuTime = nullptr; - bool getGpuTime32(uint64_t *timestamp); - bool getGpuTime36(uint64_t *timestamp); - bool getGpuTimeSplitted(uint64_t *timestamp); double getHostTimerResolution() const override; - double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override; - uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override; uint64_t getCpuRawTimestamp() override; protected: typedef int (*resolutionFunc_t)(clockid_t, struct timespec *); typedef int (*getTimeFunc_t)(clockid_t, struct timespec *); - Drm *pDrm = nullptr; - unsigned timestampSizeInBits; resolutionFunc_t resolutionFunc; getTimeFunc_t getTimeFunc; }; diff --git a/shared/source/os_interface/os_time.h b/shared/source/os_interface/os_time.h index cc87ca7227..08be00ebf2 100644 --- a/shared/source/os_interface/os_time.h +++ b/shared/source/os_interface/os_time.h @@ -20,25 +20,44 @@ struct TimeStampData { uint64_t CPUTimeinNS; // CPU time in ns }; +class OSTime; + +class DeviceTime { + public: + virtual ~DeviceTime() = default; + virtual bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) = 0; + virtual double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const = 0; + virtual uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const = 0; +}; + class OSTime { public: static std::unique_ptr create(OSInterface *osInterface); virtual ~OSTime() = default; virtual bool getCpuTime(uint64_t *timeStamp) = 0; - virtual bool getCpuGpuTime(TimeStampData *pGpuCpuTime) = 0; virtual double getHostTimerResolution() const = 0; - virtual double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const = 0; - virtual uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const = 0; virtual uint64_t getCpuRawTimestamp() = 0; OSInterface *getOSInterface() const { return osInterface; } static double getDeviceTimerResolution(HardwareInfo const &hwInfo); + bool getCpuGpuTime(TimeStampData *gpuCpuTime) { + return deviceTime->getCpuGpuTime(gpuCpuTime, this); + } + + double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { + return deviceTime->getDynamicDeviceTimerResolution(hwInfo); + } + + uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const { + return deviceTime->getDynamicDeviceTimerClock(hwInfo); + } protected: OSTime() {} OSInterface *osInterface = nullptr; + std::unique_ptr deviceTime; }; } // namespace NEO diff --git a/shared/source/os_interface/windows/CMakeLists.txt b/shared/source/os_interface/windows/CMakeLists.txt index a2756e7c3a..d611e61884 100644 --- a/shared/source/os_interface/windows/CMakeLists.txt +++ b/shared/source/os_interface/windows/CMakeLists.txt @@ -19,6 +19,8 @@ set(NEO_CORE_OS_INTERFACE_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/debug_registry_reader.h ${CMAKE_CURRENT_SOURCE_DIR}/deferrable_deletion_win.cpp ${CMAKE_CURRENT_SOURCE_DIR}/deferrable_deletion_win.h + ${CMAKE_CURRENT_SOURCE_DIR}/device_time_wddm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/device_time_wddm.h ${CMAKE_CURRENT_SOURCE_DIR}/driver_info_windows.cpp ${CMAKE_CURRENT_SOURCE_DIR}/driver_info_windows.h ${CMAKE_CURRENT_SOURCE_DIR}/environment_variables.h diff --git a/shared/source/os_interface/windows/device_time_wddm.cpp b/shared/source/os_interface/windows/device_time_wddm.cpp new file mode 100644 index 0000000000..ead99b0d04 --- /dev/null +++ b/shared/source/os_interface/windows/device_time_wddm.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/windows/device_time_wddm.h" + +#include "shared/source/execution_environment/root_device_environment.h" +#include "shared/source/os_interface/hw_info_config.h" +#include "shared/source/os_interface/windows/os_interface.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" +#include "shared/source/os_interface/windows/windows_wrapper.h" + +#include + +#undef WIN32_NO_STATUS + +namespace NEO { + +bool runEscape(Wddm *wddm, TimeStampDataHeader &escapeInfo) { + if (wddm) { + D3DKMT_ESCAPE escapeCommand = {0}; + + GTDIGetGpuCpuTimestampsIn in = {GTDI_FNC_GET_GPU_CPU_TIMESTAMPS}; + uint32_t outSize = sizeof(GTDIGetGpuCpuTimestampsOut); + + escapeInfo.m_Header.EscapeCode = GFX_ESCAPE_IGPA_INSTRUMENTATION_CONTROL; + escapeInfo.m_Header.Size = outSize; + escapeInfo.m_Data.m_In = in; + + escapeCommand.Flags.Value = 0; + escapeCommand.hAdapter = (D3DKMT_HANDLE)0; + escapeCommand.hContext = (D3DKMT_HANDLE)0; + escapeCommand.hDevice = (D3DKMT_HANDLE)wddm->getDevice(); + escapeCommand.pPrivateDriverData = &escapeInfo; + escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo); + escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE; + + auto status = wddm->escape(escapeCommand); + + if (status == STATUS_SUCCESS) { + return true; + } + } + + return false; +} + +bool DeviceTimeWddm::getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) { + bool retVal = false; + + pGpuCpuTime->CPUTimeinNS = 0; + pGpuCpuTime->GPUTimeStamp = 0; + + TimeStampDataHeader escapeInfo = {0}; + + if (runEscape(wddm, escapeInfo)) { + auto productFamily = wddm->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily; + auto *hwInfoConfig = HwInfoConfig::get(productFamily); + hwInfoConfig->convertTimestampsFromOaToCsDomain(escapeInfo.m_Data.m_Out.gpuPerfTicks); + double cpuNanoseconds = escapeInfo.m_Data.m_Out.cpuPerfTicks * + (1000000000.0 / escapeInfo.m_Data.m_Out.cpuPerfFreq); + + pGpuCpuTime->CPUTimeinNS = (unsigned long long)cpuNanoseconds; + pGpuCpuTime->GPUTimeStamp = (unsigned long long)escapeInfo.m_Data.m_Out.gpuPerfTicks; + retVal = true; + } + + return retVal; +} + +DeviceTimeWddm::DeviceTimeWddm(Wddm *wddm) { + this->wddm = wddm; +} + +double DeviceTimeWddm::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { + double retVal = 0u; + if (wddm) { + retVal = 1000000000.0 / static_cast(wddm->getTimestampFrequency()); + } + + return retVal; +} + +uint64_t DeviceTimeWddm::getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const { + uint64_t retVal = 0u; + if (wddm) { + retVal = static_cast(wddm->getTimestampFrequency()); + } + + return retVal; +} + +} // namespace NEO diff --git a/shared/source/os_interface/windows/device_time_wddm.h b/shared/source/os_interface/windows/device_time_wddm.h new file mode 100644 index 0000000000..9a22bfeaf5 --- /dev/null +++ b/shared/source/os_interface/windows/device_time_wddm.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/os_interface/os_time.h" +#include "shared/source/os_interface/windows/windows_wrapper.h" + +#include "gfxEscape.h" + +namespace NEO { +class Wddm; + +class DeviceTimeWddm : public DeviceTime { + public: + DeviceTimeWddm(Wddm *wddm); + bool getCpuGpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime) override; + double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override; + uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override; + + protected: + Wddm *wddm = nullptr; +}; + +typedef enum GTDI_ESCAPE_FUNCTION_ENUM { + GTDI_FNC_GET_GPU_CPU_TIMESTAMPS = 25 +} GTDI_ESCAPE_FUNCTION; + +typedef struct GTDIBaseInStruct { + GTDI_ESCAPE_FUNCTION Function; +} GTDIHeaderIn; + +typedef GTDIHeaderIn GTDIGetGpuCpuTimestampsIn; + +typedef enum GTDI_RETURN_CODE_ENUM { + GTDI_RET_OK = 0, + GTDI_RET_FAILED, + GTDI_RET_NOT_CONNECTED, + GTDI_RET_HW_METRICS_NOT_ENABLED, + GTDI_RET_CONTEXT_ID_MISMATCH, + GTDI_RET_NOT_SUPPORTED, + GTDI_RET_PENDING, + GTDI_RET_INVALID_CONFIGURATION, + GTDI_RET_CONCURRENT_API_ENABLED, + GTDI_RET_NO_INFORMATION, // for GTDI_FNC_GET_ERROR_INFO escape only + // ... + GTDI_RET_MAX = 0xFFFFFFFF +} GTDI_RETURN_CODE; + +typedef struct GTDIGetGpuCpuTimestampsOutStruct { + GTDI_RETURN_CODE RetCode; // Result of the call + uint64_t gpuPerfTicks; // in GPU_timestamp_ticks + uint64_t cpuPerfTicks; // in CPU_timestamp_ticks + uint64_t gpuPerfFreq; // in GPU_timestamp_ticks/s + uint64_t cpuPerfFreq; // in CPU_timestamp_ticks/s +} GTDIGetGpuCpuTimestampsOut; + +struct TimeStampDataHeader { + GFX_ESCAPE_HEADER_T m_Header; + union { + GTDIGetGpuCpuTimestampsIn m_In; + GTDIGetGpuCpuTimestampsOut m_Out; + } m_Data; +}; + +} // namespace NEO diff --git a/shared/source/os_interface/windows/os_time_win.cpp b/shared/source/os_interface/windows/os_time_win.cpp index 56b292838e..ab97f6f193 100644 --- a/shared/source/os_interface/windows/os_time_win.cpp +++ b/shared/source/os_interface/windows/os_time_win.cpp @@ -7,10 +7,8 @@ #include "shared/source/os_interface/windows/os_time_win.h" -#include "shared/source/execution_environment/root_device_environment.h" -#include "shared/source/os_interface/hw_info_config.h" +#include "shared/source/os_interface/windows/device_time_wddm.h" #include "shared/source/os_interface/windows/os_interface.h" -#include "shared/source/os_interface/windows/wddm/wddm.h" #include @@ -18,58 +16,6 @@ namespace NEO { -bool runEscape(Wddm *wddm, TimeStampDataHeader &escapeInfo) { - if (wddm) { - D3DKMT_ESCAPE escapeCommand = {0}; - - GTDIGetGpuCpuTimestampsIn in = {GTDI_FNC_GET_GPU_CPU_TIMESTAMPS}; - uint32_t outSize = sizeof(GTDIGetGpuCpuTimestampsOut); - - escapeInfo.m_Header.EscapeCode = GFX_ESCAPE_IGPA_INSTRUMENTATION_CONTROL; - escapeInfo.m_Header.Size = outSize; - escapeInfo.m_Data.m_In = in; - - escapeCommand.Flags.Value = 0; - escapeCommand.hAdapter = (D3DKMT_HANDLE)0; - escapeCommand.hContext = (D3DKMT_HANDLE)0; // escape is not context specific - escapeCommand.hDevice = (D3DKMT_HANDLE)wddm->getDevice(); // escape not device specific, passing only for instrumentation - escapeCommand.pPrivateDriverData = &escapeInfo; - escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo); - escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE; - - auto status = wddm->escape(escapeCommand); - - if (status == STATUS_SUCCESS) { - return true; - } - } - - return false; -} - -bool OSTimeWin::getCpuGpuTime(TimeStampData *pGpuCpuTime) { - bool retVal = false; - - pGpuCpuTime->CPUTimeinNS = 0; - pGpuCpuTime->GPUTimeStamp = 0; - - TimeStampDataHeader escapeInfo = {0}; - - if (runEscape(wddm, escapeInfo)) { - auto productFamily = wddm->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily; - auto *hwInfoConfig = HwInfoConfig::get(productFamily); - hwInfoConfig->convertTimestampsFromOaToCsDomain(escapeInfo.m_Data.m_Out.gpuPerfTicks); - double cpuNanoseconds = escapeInfo.m_Data.m_Out.cpuPerfTicks * - (1000000000.0 / escapeInfo.m_Data.m_Out.cpuPerfFreq); - - pGpuCpuTime->CPUTimeinNS = (unsigned long long)cpuNanoseconds; - pGpuCpuTime->GPUTimeStamp = (unsigned long long)escapeInfo.m_Data.m_Out.gpuPerfTicks; - retVal = true; - } - - return retVal; -} - bool OSTimeWin::getCpuTime(uint64_t *timeStamp) { uint64_t time; this->QueryPerfomanceCounterFnc((LARGE_INTEGER *)&time); @@ -84,9 +30,8 @@ std::unique_ptr OSTime::create(OSInterface *osInterface) { OSTimeWin::OSTimeWin(OSInterface *osInterface) { this->osInterface = osInterface; - if (osInterface) { - wddm = osInterface->get()->getWddm(); - } + Wddm *wddm = osInterface ? osInterface->get()->getWddm() : nullptr; + this->deviceTime = std::make_unique(wddm); QueryPerformanceFrequency(&frequency); } @@ -98,24 +43,6 @@ double OSTimeWin::getHostTimerResolution() const { return retValue; } -double OSTimeWin::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { - double retVal = 0u; - if (wddm) { - retVal = 1000000000.0 / static_cast(wddm->getTimestampFrequency()); - } - - return retVal; -} - -uint64_t OSTimeWin::getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const { - uint64_t retVal = 0u; - if (wddm) { - retVal = static_cast(wddm->getTimestampFrequency()); - } - - return retVal; -} - uint64_t OSTimeWin::getCpuRawTimestamp() { LARGE_INTEGER cpuRawTimestamp = {}; this->QueryPerfomanceCounterFnc(&cpuRawTimestamp); diff --git a/shared/source/os_interface/windows/os_time_win.h b/shared/source/os_interface/windows/os_time_win.h index 64c85110c6..da00467666 100644 --- a/shared/source/os_interface/windows/os_time_win.h +++ b/shared/source/os_interface/windows/os_time_win.h @@ -19,58 +19,13 @@ class OSTimeWin : public OSTime { public: OSTimeWin(OSInterface *osInterface); bool getCpuTime(uint64_t *timeStamp) override; - bool getCpuGpuTime(TimeStampData *pGpuCpuTime) override; double getHostTimerResolution() const override; - double getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const override; - uint64_t getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const override; uint64_t getCpuRawTimestamp() override; protected: - Wddm *wddm = nullptr; LARGE_INTEGER frequency; OSTimeWin() = default; decltype(&QueryPerformanceCounter) QueryPerfomanceCounterFnc = QueryPerformanceCounter; }; -typedef enum GTDI_ESCAPE_FUNCTION_ENUM { - GTDI_FNC_GET_GPU_CPU_TIMESTAMPS = 25 -} GTDI_ESCAPE_FUNCTION; - -typedef struct GTDIBaseInStruct { - GTDI_ESCAPE_FUNCTION Function; -} GTDIHeaderIn; - -typedef GTDIHeaderIn GTDIGetGpuCpuTimestampsIn; - -typedef enum GTDI_RETURN_CODE_ENUM { - GTDI_RET_OK = 0, - GTDI_RET_FAILED, - GTDI_RET_NOT_CONNECTED, - GTDI_RET_HW_METRICS_NOT_ENABLED, - GTDI_RET_CONTEXT_ID_MISMATCH, - GTDI_RET_NOT_SUPPORTED, - GTDI_RET_PENDING, - GTDI_RET_INVALID_CONFIGURATION, - GTDI_RET_CONCURRENT_API_ENABLED, - GTDI_RET_NO_INFORMATION, // for GTDI_FNC_GET_ERROR_INFO escape only - // ... - GTDI_RET_MAX = 0xFFFFFFFF -} GTDI_RETURN_CODE; - -typedef struct GTDIGetGpuCpuTimestampsOutStruct { - GTDI_RETURN_CODE RetCode; // Result of the call - uint64_t gpuPerfTicks; // in GPU_timestamp_ticks - uint64_t cpuPerfTicks; // in CPU_timestamp_ticks - uint64_t gpuPerfFreq; // in GPU_timestamp_ticks/s - uint64_t cpuPerfFreq; // in CPU_timestamp_ticks/s -} GTDIGetGpuCpuTimestampsOut; - -struct TimeStampDataHeader { - GFX_ESCAPE_HEADER_T m_Header; - union { - GTDIGetGpuCpuTimestampsIn m_In; - GTDIGetGpuCpuTimestampsOut m_Out; - } m_Data; -}; - } // namespace NEO diff --git a/shared/test/common/mock_gdi/mock_gdi.h b/shared/test/common/mock_gdi/mock_gdi.h index dc8564c507..8c3a428a7a 100644 --- a/shared/test/common/mock_gdi/mock_gdi.h +++ b/shared/test/common/mock_gdi/mock_gdi.h @@ -8,6 +8,7 @@ #pragma once #include "shared/source/gmm_helper/gmm_lib.h" +#include "shared/source/os_interface/windows/device_time_wddm.h" #include "shared/source/os_interface/windows/os_time_win.h" #include "umKmInc/sharedata.h"