Update Scheduler APIs as per latest spec

Change-Id: Ia8558ab30c83f1e30dae94cc7eb489ea7a8897da
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2020-07-31 16:04:29 +05:30
committed by sys_ocldev
parent fa8e39fe16
commit 94a26db5ba
17 changed files with 428 additions and 253 deletions

View File

@@ -6,6 +6,7 @@
set(L0_SRCS_TOOLS_SYSMAN_SCHEDULER
${CMAKE_CURRENT_SOURCE_DIR}/scheduler.h
${CMAKE_CURRENT_SOURCE_DIR}/scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scheduler_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scheduler_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/os_scheduler.h

View File

@@ -17,6 +17,7 @@ const std::string LinuxSchedulerImp::timesliceDurationMilliSecs("engine/rcs0/tim
const std::string LinuxSchedulerImp::defaultTimesliceDurationMilliSecs("engine/rcs0/.defaults/timeslice_duration_ms");
const std::string LinuxSchedulerImp::heartbeatIntervalMilliSecs("engine/rcs0/heartbeat_interval_ms");
const std::string LinuxSchedulerImp::defaultHeartbeatIntervalMilliSecs("engine/rcs0/.defaults/heartbeat_interval_ms");
const std::string LinuxSchedulerImp::computeEngineDir("engine/rcs0");
constexpr uint16_t milliSecsToMicroSecs = 1000;
ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) {
@@ -73,6 +74,14 @@ ze_result_t LinuxSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) {
return pSysfsAccess->write(heartbeatIntervalMilliSecs, heartbeat);
}
ze_bool_t LinuxSchedulerImp::canControlScheduler() {
return 1;
}
bool LinuxSchedulerImp::isSchedulerSupported() {
return (ZE_RESULT_SUCCESS == pSysfsAccess->canRead(computeEngineDir));
}
LinuxSchedulerImp::LinuxSchedulerImp(OsSysman *pOsSysman) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();

View File

@@ -25,6 +25,8 @@ class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass {
ze_result_t setPreemptTimeout(uint64_t timeout) override;
ze_result_t setTimesliceDuration(uint64_t timeslice) override;
ze_result_t setHeartbeatInterval(uint64_t heartbeat) override;
ze_bool_t canControlScheduler() override;
bool isSchedulerSupported() override;
LinuxSchedulerImp() = default;
LinuxSchedulerImp(OsSysman *pOsSysman);
~LinuxSchedulerImp() override = default;
@@ -39,6 +41,7 @@ class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass {
static const std::string defaultTimesliceDurationMilliSecs;
static const std::string heartbeatIntervalMilliSecs;
static const std::string defaultHeartbeatIntervalMilliSecs;
static const std::string computeEngineDir;
};
} // namespace L0

View File

@@ -18,6 +18,8 @@ class OsScheduler {
virtual ze_result_t setPreemptTimeout(uint64_t timeout) = 0;
virtual ze_result_t setTimesliceDuration(uint64_t timeslice) = 0;
virtual ze_result_t setHeartbeatInterval(uint64_t heartbeat) = 0;
virtual ze_bool_t canControlScheduler() = 0;
virtual bool isSchedulerSupported() = 0;
static OsScheduler *create(OsSysman *pOsSysman);
virtual ~OsScheduler() = default;
};

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/helpers/basic_math.h"
#include "level_zero/tools/source/sysman/scheduler/scheduler_imp.h"
namespace L0 {
SchedulerHandleContext::~SchedulerHandleContext() {
for (Scheduler *pScheduler : handleList) {
delete pScheduler;
}
}
void SchedulerHandleContext::init() {
Scheduler *pScheduler = new SchedulerImp(pOsSysman);
if (pScheduler->initSuccess == true) {
handleList.push_back(pScheduler);
} else {
delete pScheduler;
}
}
ze_result_t SchedulerHandleContext::schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler) {
uint32_t handleListSize = static_cast<uint32_t>(handleList.size());
uint32_t numToCopy = std::min(*pCount, handleListSize);
if (0 == *pCount || *pCount > handleListSize) {
*pCount = handleListSize;
}
if (nullptr != phScheduler) {
for (uint32_t i = 0; i < numToCopy; i++) {
phScheduler[i] = handleList[i]->toHandle();
}
}
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@@ -6,21 +6,45 @@
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include <level_zero/zes_api.h>
namespace L0 {
#include <vector>
class Scheduler {
struct _zes_sched_handle_t {
virtual ~_zes_sched_handle_t() = default;
};
namespace L0 {
struct OsSysman;
class Scheduler : _zes_sched_handle_t {
public:
virtual ~Scheduler(){};
virtual ze_result_t schedulerGetProperties(zes_sched_properties_t *pProperties) = 0;
virtual ze_result_t getCurrentMode(zes_sched_mode_t *pMode) = 0;
virtual ze_result_t getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) = 0;
virtual ze_result_t getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) = 0;
virtual ze_result_t setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReboot) = 0;
virtual ze_result_t setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) = 0;
virtual ze_result_t setExclusiveMode(ze_bool_t *pNeedReboot) = 0;
virtual ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReboot) = 0;
virtual void init() = 0;
virtual ze_result_t setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) = 0;
virtual ze_result_t setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) = 0;
virtual ze_result_t setExclusiveMode(ze_bool_t *pNeedReload) = 0;
virtual ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReload) = 0;
static Scheduler *fromHandle(zes_sched_handle_t handle) {
return static_cast<Scheduler *>(handle);
}
inline zes_sched_handle_t toHandle() { return this; }
bool initSuccess = false;
};
struct SchedulerHandleContext : NEO::NonCopyableOrMovableClass {
SchedulerHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
~SchedulerHandleContext();
void init();
ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler);
OsSysman *pOsSysman = nullptr;
std::vector<Scheduler *> handleList = {};
ze_device_handle_t hCoreDevice = nullptr;
};
} // namespace L0

View File

@@ -14,6 +14,25 @@ namespace L0 {
constexpr uint64_t minTimeoutModeHeartbeat = 5000u;
constexpr uint64_t minTimeoutInMicroSeconds = 1000u;
ze_result_t SchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) {
uint64_t timeslice = 0, timeout = 0, heartbeat = 0;
*pNeedReload = false;
ze_result_t result = pOsScheduler->setPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setHeartbeatInterval(heartbeat);
return result;
}
ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) {
uint64_t timeout = 0;
uint64_t timeslice = 0;
@@ -63,7 +82,7 @@ ze_result_t SchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_
return result;
}
ze_result_t SchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReboot) {
ze_result_t SchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) {
zes_sched_mode_t currMode;
ze_result_t result = getCurrentMode(&currMode);
if (result != ZE_RESULT_SUCCESS) {
@@ -76,7 +95,7 @@ ze_result_t SchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProper
// this method, we would end up in EXCLUSIVE mode
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
*pNeedReboot = false;
*pNeedReload = false;
result = pOsScheduler->setHeartbeatInterval(pProperties->watchdogTimeout);
if ((currMode == ZES_SCHED_MODE_TIMEOUT) || (result != ZE_RESULT_SUCCESS)) {
return result;
@@ -96,13 +115,13 @@ ze_result_t SchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProper
return result;
}
ze_result_t SchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) {
ze_result_t SchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) {
if (pProperties->interval < minTimeoutInMicroSeconds) {
// interval(in usec) less than 1000 would be computed to
// 0 milli seconds interval.
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
*pNeedReboot = false;
*pNeedReload = false;
ze_result_t result = pOsScheduler->setPreemptTimeout(pProperties->yieldTimeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
@@ -116,31 +135,26 @@ ze_result_t SchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pPr
return result;
}
ze_result_t SchedulerImp::setExclusiveMode(ze_bool_t *pNeedReboot) {
uint64_t timeslice = 0, timeout = 0, heartbeat = 0;
*pNeedReboot = false;
ze_result_t result = pOsScheduler->setPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setHeartbeatInterval(heartbeat);
return result;
}
ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReboot) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
ze_result_t SchedulerImp::schedulerGetProperties(zes_sched_properties_t *pProperties) {
*pProperties = properties;
return ZE_RESULT_SUCCESS;
}
void SchedulerImp::init() {
this->initSuccess = pOsScheduler->isSchedulerSupported();
properties.onSubdevice = false;
properties.canControl = pOsScheduler->canControlScheduler();
properties.engines = ZES_ENGINE_TYPE_FLAG_COMPUTE;
properties.supportedModes = (1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE);
}
SchedulerImp::SchedulerImp(OsSysman *pOsSysman) {
if (pOsScheduler == nullptr) {
pOsScheduler = OsScheduler::create(pOsSysman);
}
UNRECOVERABLE_IF(nullptr == pOsScheduler);
}
init();
};
SchedulerImp::~SchedulerImp() {
if (nullptr != pOsScheduler) {

View File

@@ -17,22 +17,23 @@ namespace L0 {
class SchedulerImp : public Scheduler, NEO::NonCopyableOrMovableClass {
public:
void init() override;
void init();
ze_result_t schedulerGetProperties(zes_sched_properties_t *pProperties) override;
ze_result_t getCurrentMode(zes_sched_mode_t *pMode) override;
ze_result_t getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) override;
ze_result_t getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) override;
ze_result_t setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReboot) override;
ze_result_t setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) override;
ze_result_t setExclusiveMode(ze_bool_t *pNeedReboot) override;
ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReboot) override;
ze_result_t setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) override;
ze_result_t setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) override;
ze_result_t setExclusiveMode(ze_bool_t *pNeedReload) override;
ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReload) override;
SchedulerImp() = default;
OsScheduler *pOsScheduler = nullptr;
SchedulerImp(OsSysman *pOsSysman) : pOsSysman(pOsSysman) { pOsScheduler = nullptr; };
SchedulerImp(OsSysman *pOsSysman);
~SchedulerImp() override;
private:
OsSysman *pOsSysman = nullptr;
zes_sched_properties_t properties = {};
};
} // namespace L0

View File

@@ -17,6 +17,8 @@ class WddmSchedulerImp : public OsScheduler {
ze_result_t setPreemptTimeout(uint64_t timeout) override;
ze_result_t setTimesliceDuration(uint64_t timeslice) override;
ze_result_t setHeartbeatInterval(uint64_t heartbeat) override;
ze_bool_t canControlScheduler() override;
bool isSchedulerSupported() override;
};
ze_result_t WddmSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) {
@@ -43,6 +45,14 @@ ze_result_t WddmSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_bool_t WddmSchedulerImp::canControlScheduler() {
return 0;
}
bool WddmSchedulerImp::isSchedulerSupported() {
return false;
}
OsScheduler *OsScheduler::create(OsSysman *pOsSysman) {
WddmSchedulerImp *pWddmSchedulerImp = new WddmSchedulerImp();
return static_cast<OsScheduler *>(pWddmSchedulerImp);

View File

@@ -41,6 +41,7 @@ struct SysmanDevice : _ze_device_handle_t {
virtual ze_result_t pciGetState(zes_pci_state_t *pState) = 0;
virtual ze_result_t pciGetBars(uint32_t *pCount, zes_pci_bar_properties_t *pProperties) = 0;
virtual ze_result_t pciGetStats(zes_pci_stats_t *pStats) = 0;
virtual ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler) = 0;
virtual ~SysmanDevice() = default;
};

View File

@@ -11,7 +11,6 @@
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/tools/source/sysman/global_operations/global_operations_imp.h"
#include "level_zero/tools/source/sysman/pci/pci_imp.h"
#include "level_zero/tools/source/sysman/scheduler/scheduler_imp.h"
#include "level_zero/tools/source/sysman/sysman.h"
#include <vector>
@@ -29,9 +28,11 @@ SysmanDeviceImp::SysmanDeviceImp(ze_device_handle_t hDevice) {
pTempHandleContext = new TemperatureHandleContext(pOsSysman);
pStandbyHandleContext = new StandbyHandleContext(pOsSysman);
pEngineHandleContext = new EngineHandleContext(pOsSysman);
pSchedulerHandleContext = new SchedulerHandleContext(pOsSysman);
}
SysmanDeviceImp::~SysmanDeviceImp() {
freeResource(pSchedulerHandleContext);
freeResource(pEngineHandleContext);
freeResource(pStandbyHandleContext);
freeResource(pTempHandleContext);
@@ -65,6 +66,9 @@ void SysmanDeviceImp::init() {
if (pEngineHandleContext) {
pEngineHandleContext->init();
}
if (pSchedulerHandleContext) {
pSchedulerHandleContext->init();
}
}
ze_result_t SysmanDeviceImp::frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) {
@@ -107,4 +111,8 @@ ze_result_t SysmanDeviceImp::temperatureGet(uint32_t *pCount, zes_temp_handle_t
return pTempHandleContext->temperatureGet(pCount, phTemperature);
}
ze_result_t SysmanDeviceImp::schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler) {
return pSchedulerHandleContext->schedulerGet(pCount, phScheduler);
}
} // namespace L0

View File

@@ -33,6 +33,7 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass {
TemperatureHandleContext *pTempHandleContext = nullptr;
StandbyHandleContext *pStandbyHandleContext = nullptr;
EngineHandleContext *pEngineHandleContext = nullptr;
SchedulerHandleContext *pSchedulerHandleContext = nullptr;
ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) override;
ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) override;
@@ -44,6 +45,7 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass {
ze_result_t pciGetState(zes_pci_state_t *pState) override;
ze_result_t pciGetBars(uint32_t *pCount, zes_pci_bar_properties_t *pProperties) override;
ze_result_t pciGetStats(zes_pci_stats_t *pStats) override;
ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler) override;
private:
template <typename T>

View File

@@ -7,8 +7,8 @@
if(UNIX)
target_sources(${TARGET_NAME}
PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
# ${CMAKE_CURRENT_SOURCE_DIR}/test_sysman_scheduler.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler.h
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler.h
)
endif()
endif()

View File

@@ -6,12 +6,10 @@
*/
#pragma once
#include "level_zero/core/test/unit_tests/mock.h"
#include "level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h"
#include "sysman/linux/fs_access.h"
using ::testing::_;
namespace L0 {
namespace ult {
@@ -21,6 +19,7 @@ const std::string timesliceDurationMilliSecs("engine/rcs0/timeslice_duration_ms"
const std::string defaultTimesliceDurationMilliSecs("engine/rcs0/.defaults/timeslice_duration_ms");
const std::string heartbeatIntervalMilliSecs("engine/rcs0/heartbeat_interval_ms");
const std::string defaultHeartbeatIntervalMilliSecs("engine/rcs0/.defaults/heartbeat_interval_ms");
const std::string computeEngineDir("engine/rcs0");
class SchedulerSysfsAccess : public SysfsAccess {};
@@ -79,11 +78,21 @@ struct Mock<SchedulerSysfsAccess> : public SysfsAccess {
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getCanReadStatus(const std::string file) {
if (file.compare(computeEngineDir) == 0) {
return ZE_RESULT_SUCCESS;
}
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
ze_result_t getCanReadStatusReturnError(const std::string file) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
Mock<SchedulerSysfsAccess>() = default;
MOCK_METHOD(ze_result_t, read, (const std::string file, uint64_t &val), (override));
MOCK_METHOD(ze_result_t, write, (const std::string file, const uint64_t val), (override));
MOCK_METHOD(ze_result_t, canRead, (const std::string file), (override));
};
class PublicLinuxSchedulerImp : public L0::LinuxSchedulerImp {

View File

@@ -1,199 +0,0 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h"
#include "level_zero/tools/source/sysman/sysman_imp.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mock_sysfs_scheduler.h"
#include "sysman/scheduler/os_scheduler.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
namespace L0 {
namespace ult {
constexpr uint64_t convertMilliToMicro = 1000u;
constexpr uint64_t defaultTimeoutMilliSecs = 650u;
constexpr uint64_t defaultTimesliceMilliSecs = 1u;
constexpr uint64_t defaultHeartbeatMilliSecs = 3000u;
constexpr uint64_t timeoutMilliSecs = 640u;
constexpr uint64_t timesliceMilliSecs = 1u;
constexpr uint64_t heartbeatMilliSecs = 2500u;
constexpr uint64_t expectedDefaultHeartbeatTimeoutMicroSecs = defaultHeartbeatMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedDefaultTimeoutMicroSecs = defaultTimeoutMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedDefaultTimesliceMicroSecs = defaultTimesliceMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedHeartbeatTimeoutMicroSecs = heartbeatMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedTimeoutMicroSecs = timeoutMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedTimesliceMicroSecs = timesliceMilliSecs * convertMilliToMicro;
class SysmanSchedulerFixture : public DeviceFixture, public ::testing::Test {
protected:
std::unique_ptr<SysmanImp> sysmanImp;
zet_sysman_handle_t hSysman;
OsScheduler *pOsScheduler = nullptr;
Mock<SchedulerSysfsAccess> *pSysfsAccess = nullptr;
L0::Scheduler *pSchedPrev = nullptr;
L0::SchedulerImp schedImp;
PublicLinuxSchedulerImp linuxSchedulerImp;
void SetUp() override {
DeviceFixture::SetUp();
sysmanImp = std::make_unique<SysmanImp>(device->toHandle());
pSysfsAccess = new NiceMock<Mock<SchedulerSysfsAccess>>;
linuxSchedulerImp.pSysfsAccess = pSysfsAccess;
pOsScheduler = static_cast<OsScheduler *>(&linuxSchedulerImp);
pSysfsAccess->setVal(defaultPreemptTimeoutMilliSecs, defaultTimeoutMilliSecs);
pSysfsAccess->setVal(defaultTimesliceDurationMilliSecs, defaultTimesliceMilliSecs);
pSysfsAccess->setVal(defaultHeartbeatIntervalMilliSecs, defaultHeartbeatMilliSecs);
pSysfsAccess->setVal(preemptTimeoutMilliSecs, timeoutMilliSecs);
pSysfsAccess->setVal(timesliceDurationMilliSecs, timesliceMilliSecs);
pSysfsAccess->setVal(heartbeatIntervalMilliSecs, heartbeatMilliSecs);
ON_CALL(*pSysfsAccess, read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess, &Mock<SchedulerSysfsAccess>::getVal));
ON_CALL(*pSysfsAccess, write(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess, &Mock<SchedulerSysfsAccess>::setVal));
pSchedPrev = sysmanImp->pSched;
sysmanImp->pSched = static_cast<Scheduler *>(&schedImp);
schedImp.pOsScheduler = pOsScheduler;
schedImp.init();
hSysman = sysmanImp->toHandle();
}
void TearDown() override {
// restore state
sysmanImp->pSched = pSchedPrev;
schedImp.pOsScheduler = nullptr;
// cleanup
if (pSysfsAccess != nullptr) {
delete pSysfsAccess;
pSysfsAccess = nullptr;
}
}
zes_sched_mode_t fixtureGetCurrentMode(zet_sysman_handle_t hSysman) {
zes_sched_mode_t mode;
ze_result_t result = zetSysmanSchedulerGetCurrentMode(hSysman, &mode);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return mode;
}
zes_sched_timeout_properties_t fixtureGetTimeoutModeProperties(zet_sysman_handle_t hSysman, ze_bool_t getDefaults) {
zes_sched_timeout_properties_t config;
ze_result_t result = zetSysmanSchedulerGetTimeoutModeProperties(hSysman, getDefaults, &config);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return config;
}
zes_sched_timeslice_properties_t fixtureGetTimesliceModeProperties(zet_sysman_handle_t hSysman, ze_bool_t getDefaults) {
zes_sched_timeslice_properties_t config;
ze_result_t result = zetSysmanSchedulerGetTimesliceModeProperties(hSysman, getDefaults, &config);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return config;
}
};
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetCurrentModeThenVerifyzetSysmanSchedulerGetCurrentModeCallSucceeds) {
auto mode = fixtureGetCurrentMode(hSysman);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMESLICE);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimeoutModePropertiesThenVerifyzetSysmanSchedulerGetTimeoutModePropertiesCallSucceeds) {
auto config = fixtureGetTimeoutModeProperties(hSysman, false);
EXPECT_EQ(config.watchdogTimeout, expectedHeartbeatTimeoutMicroSecs);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimeoutModePropertiesWithDefaultsThenVerifyzetSysmanSchedulerGetTimeoutModePropertiesCallSucceeds) {
auto config = fixtureGetTimeoutModeProperties(hSysman, true);
EXPECT_EQ(config.watchdogTimeout, expectedDefaultHeartbeatTimeoutMicroSecs);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimesliceModePropertiesThenVerifyzetSysmanSchedulerGetTimesliceModePropertiesCallSucceeds) {
auto config = fixtureGetTimesliceModeProperties(hSysman, false);
EXPECT_EQ(config.interval, expectedTimesliceMicroSecs);
EXPECT_EQ(config.yieldTimeout, expectedTimeoutMicroSecs);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimesliceModePropertiesWithDefaultsThenVerifyzetSysmanSchedulerGetTimesliceModePropertiesCallSucceeds) {
auto config = fixtureGetTimesliceModeProperties(hSysman, true);
EXPECT_EQ(config.interval, expectedDefaultTimesliceMicroSecs);
EXPECT_EQ(config.yieldTimeout, expectedDefaultTimeoutMicroSecs);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerSetTimeoutModeThenVerifyzetSysmanSchedulerSetTimeoutModeCallSucceeds) {
ze_bool_t needReboot;
zes_sched_timeout_properties_t setConfig;
setConfig.watchdogTimeout = 10000u;
ze_result_t result = zetSysmanSchedulerSetTimeoutMode(hSysman, &setConfig, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto getConfig = fixtureGetTimeoutModeProperties(hSysman, false);
EXPECT_EQ(getConfig.watchdogTimeout, setConfig.watchdogTimeout);
auto mode = fixtureGetCurrentMode(hSysman);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMEOUT);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerSetTimesliceModeThenVerifyzetSysmanSchedulerSetTimesliceModeCallSucceeds) {
ze_bool_t needReboot;
zes_sched_timeslice_properties_t setConfig;
setConfig.interval = 1000u;
setConfig.yieldTimeout = 1000u;
ze_result_t result = zetSysmanSchedulerSetTimesliceMode(hSysman, &setConfig, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto getConfig = fixtureGetTimesliceModeProperties(hSysman, false);
EXPECT_EQ(getConfig.interval, setConfig.interval);
EXPECT_EQ(getConfig.yieldTimeout, setConfig.yieldTimeout);
auto mode = fixtureGetCurrentMode(hSysman);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMESLICE);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerSetExclusiveModeThenVerifyzetSysmanSchedulerSetExclusiveModeCallSucceeds) {
ze_bool_t needReboot;
ze_result_t result = zetSysmanSchedulerSetExclusiveMode(hSysman, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto mode = fixtureGetCurrentMode(hSysman);
EXPECT_EQ(mode, ZES_SCHED_MODE_EXCLUSIVE);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetCurrentModeWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess, read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess, &Mock<SchedulerSysfsAccess>::getValForError));
zes_sched_mode_t mode;
ze_result_t result = zetSysmanSchedulerGetCurrentMode(hSysman, &mode);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimeoutModePropertiesWithDefaultsWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess, read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess, &Mock<SchedulerSysfsAccess>::getValForError));
zes_sched_timeout_properties_t config;
ze_result_t result = zetSysmanSchedulerGetTimeoutModeProperties(hSysman, true, &config);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
TEST_F(SysmanSchedulerFixture, GivenValidSysmanHandleWhenCallingzetSysmanSchedulerGetTimesliceModePropertiesWithDefaultsWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess, read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess, &Mock<SchedulerSysfsAccess>::getValForError));
zes_sched_timeslice_properties_t config;
ze_result_t result = zetSysmanSchedulerGetTimesliceModeProperties(hSysman, true, &config);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
} // namespace ult
} // namespace L0

View File

@@ -0,0 +1,247 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/tools/test/unit_tests/sources/sysman/mock_sysman_fixture.h"
#include "mock_sysfs_scheduler.h"
namespace L0 {
namespace ult {
constexpr uint32_t handleComponentCount = 1u;
constexpr uint64_t convertMilliToMicro = 1000u;
constexpr uint64_t defaultTimeoutMilliSecs = 650u;
constexpr uint64_t defaultTimesliceMilliSecs = 1u;
constexpr uint64_t defaultHeartbeatMilliSecs = 3000u;
constexpr uint64_t timeoutMilliSecs = 640u;
constexpr uint64_t timesliceMilliSecs = 1u;
constexpr uint64_t heartbeatMilliSecs = 2500u;
constexpr uint64_t expectedDefaultHeartbeatTimeoutMicroSecs = defaultHeartbeatMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedDefaultTimeoutMicroSecs = defaultTimeoutMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedDefaultTimesliceMicroSecs = defaultTimesliceMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedHeartbeatTimeoutMicroSecs = heartbeatMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedTimeoutMicroSecs = timeoutMilliSecs * convertMilliToMicro;
constexpr uint64_t expectedTimesliceMicroSecs = timesliceMilliSecs * convertMilliToMicro;
class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<SchedulerSysfsAccess>> pSysfsAccess;
SysfsAccess *pSysfsAccessOld = nullptr;
void SetUp() override {
SysmanDeviceFixture::SetUp();
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pSysfsAccess = std::make_unique<NiceMock<Mock<SchedulerSysfsAccess>>>();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pSysfsAccess->setVal(defaultPreemptTimeoutMilliSecs, defaultTimeoutMilliSecs);
pSysfsAccess->setVal(defaultTimesliceDurationMilliSecs, defaultTimesliceMilliSecs);
pSysfsAccess->setVal(defaultHeartbeatIntervalMilliSecs, defaultHeartbeatMilliSecs);
pSysfsAccess->setVal(preemptTimeoutMilliSecs, timeoutMilliSecs);
pSysfsAccess->setVal(timesliceDurationMilliSecs, timesliceMilliSecs);
pSysfsAccess->setVal(heartbeatIntervalMilliSecs, heartbeatMilliSecs);
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getVal));
ON_CALL(*pSysfsAccess.get(), write(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::setVal));
ON_CALL(*pSysfsAccess.get(), canRead(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getCanReadStatus));
pSysmanDeviceImp->pSchedulerHandleContext->init();
}
void TearDown() override {
SysmanDeviceFixture::TearDown();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
}
std::vector<zes_sched_handle_t> get_sched_handles(uint32_t count) {
std::vector<zes_sched_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumSchedulers(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
return handles;
}
zes_sched_mode_t fixtureGetCurrentMode(zes_sched_handle_t hScheduler) {
zes_sched_mode_t mode;
ze_result_t result = zesSchedulerGetCurrentMode(hScheduler, &mode);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return mode;
}
zes_sched_timeout_properties_t fixtureGetTimeoutModeProperties(zes_sched_handle_t hScheduler, ze_bool_t getDefaults) {
zes_sched_timeout_properties_t config;
ze_result_t result = zesSchedulerGetTimeoutModeProperties(hScheduler, getDefaults, &config);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return config;
}
zes_sched_timeslice_properties_t fixtureGetTimesliceModeProperties(zes_sched_handle_t hScheduler, ze_bool_t getDefaults) {
zes_sched_timeslice_properties_t config;
ze_result_t result = zesSchedulerGetTimesliceModeProperties(hScheduler, getDefaults, &config);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
return config;
}
};
TEST_F(SysmanDeviceSchedulerFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumSchedulersAndSysfsCanReadReturnsErrorThenZeroCountIsReturned) {
ON_CALL(*pSysfsAccess.get(), canRead(_))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getCanReadStatusReturnError));
auto pSchedulerHandleContextTest = std::make_unique<SchedulerHandleContext>(pOsSysman);
pSchedulerHandleContextTest->init();
EXPECT_EQ(0u, static_cast<uint32_t>(pSchedulerHandleContextTest->handleList.size()));
}
TEST_F(SysmanDeviceSchedulerFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumSchedulersThenNonZeroCountIsReturnedAndVerifyCallSucceeds) {
uint32_t count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumSchedulers(device->toHandle(), &count, NULL));
EXPECT_EQ(count, handleComponentCount);
uint32_t testcount = count + 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumSchedulers(device->toHandle(), &testcount, NULL));
EXPECT_EQ(testcount, count);
count = 0;
std::vector<zes_sched_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumSchedulers(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, handleComponentCount);
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetCurrentModeThenVerifyzesSchedulerGetCurrentModeCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
auto mode = fixtureGetCurrentMode(handle);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMESLICE);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesThenVerifyzesSchedulerGetTimeoutModePropertiesCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
auto config = fixtureGetTimeoutModeProperties(handle, false);
EXPECT_EQ(config.watchdogTimeout, expectedHeartbeatTimeoutMicroSecs);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesWithDefaultsThenVerifyzesSchedulerGetTimeoutModePropertiesCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
auto config = fixtureGetTimeoutModeProperties(handle, true);
EXPECT_EQ(config.watchdogTimeout, expectedDefaultHeartbeatTimeoutMicroSecs);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimesliceModePropertiesThenVerifyzesSchedulerGetTimesliceModePropertiesCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
auto config = fixtureGetTimesliceModeProperties(handle, false);
EXPECT_EQ(config.interval, expectedTimesliceMicroSecs);
EXPECT_EQ(config.yieldTimeout, expectedTimeoutMicroSecs);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimesliceModePropertiesWithDefaultsThenVerifyzesSchedulerGetTimesliceModePropertiesCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
auto config = fixtureGetTimesliceModeProperties(handle, true);
EXPECT_EQ(config.interval, expectedDefaultTimesliceMicroSecs);
EXPECT_EQ(config.yieldTimeout, expectedDefaultTimeoutMicroSecs);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimeoutModeThenVerifyzesSchedulerSetTimeoutModeCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
ze_bool_t needReboot;
zes_sched_timeout_properties_t setConfig;
setConfig.watchdogTimeout = 10000u;
ze_result_t result = zesSchedulerSetTimeoutMode(handle, &setConfig, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto getConfig = fixtureGetTimeoutModeProperties(handle, false);
EXPECT_EQ(getConfig.watchdogTimeout, setConfig.watchdogTimeout);
auto mode = fixtureGetCurrentMode(handle);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMEOUT);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimesliceModeThenVerifyzesSchedulerSetTimesliceModeCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
ze_bool_t needReboot;
zes_sched_timeslice_properties_t setConfig;
setConfig.interval = 1000u;
setConfig.yieldTimeout = 1000u;
ze_result_t result = zesSchedulerSetTimesliceMode(handle, &setConfig, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto getConfig = fixtureGetTimesliceModeProperties(handle, false);
EXPECT_EQ(getConfig.interval, setConfig.interval);
EXPECT_EQ(getConfig.yieldTimeout, setConfig.yieldTimeout);
auto mode = fixtureGetCurrentMode(handle);
EXPECT_EQ(mode, ZES_SCHED_MODE_TIMESLICE);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetExclusiveModeThenVerifyzesSchedulerSetExclusiveModeCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
ze_bool_t needReboot;
ze_result_t result = zesSchedulerSetExclusiveMode(handle, &needReboot);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(needReboot);
auto mode = fixtureGetCurrentMode(handle);
EXPECT_EQ(mode, ZES_SCHED_MODE_EXCLUSIVE);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetCurrentModeWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getValForError));
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
zes_sched_mode_t mode;
ze_result_t result = zesSchedulerGetCurrentMode(handle, &mode);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesWithDefaultsWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getValForError));
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
zes_sched_timeout_properties_t config;
ze_result_t result = zesSchedulerGetTimeoutModeProperties(handle, true, &config);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimesliceModePropertiesWithDefaultsWhenSysfsNodeIsAbsentThenFailureIsReturned) {
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getValForError));
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
zes_sched_timeslice_properties_t config;
ze_result_t result = zesSchedulerGetTimesliceModeProperties(handle, true, &config);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
}
TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetPropertiesThenVerifyzesSchedulerGetPropertiesCallSucceeds) {
auto handles = get_sched_handles(handleComponentCount);
for (auto handle : handles) {
zes_sched_properties_t properties = {};
ze_result_t result = zesSchedulerGetProperties(handle, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(properties.canControl);
EXPECT_EQ(properties.engines, ZES_ENGINE_TYPE_FLAG_COMPUTE);
EXPECT_EQ(properties.supportedModes, static_cast<uint32_t>((1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE)));
}
}
} // namespace ult
} // namespace L0