From f2115781483810fb4a2d6918663c4d39dc1338af Mon Sep 17 00:00:00 2001 From: "Vilvaraj, T J Vivek" Date: Tue, 25 Aug 2020 17:08:10 +0530 Subject: [PATCH] add support for multiple engines in scheduler API. Change-Id: I2d530f88b8f4c8646c00ed712e5a07bb8439b759 Signed-off-by: Vilvaraj, T J Vivek --- .../sysman/scheduler/linux/CMakeLists.txt | 2 +- .../scheduler/linux/os_scheduler_imp.cpp | 214 +++++++++++++----- .../sysman/scheduler/linux/os_scheduler_imp.h | 8 +- .../source/sysman/scheduler/os_scheduler.h | 11 +- .../source/sysman/scheduler/scheduler.cpp | 20 +- .../tools/source/sysman/scheduler/scheduler.h | 7 +- .../source/sysman/scheduler/scheduler_imp.cpp | 12 +- .../source/sysman/scheduler/scheduler_imp.h | 3 +- .../sysman/scheduler/windows/CMakeLists.txt | 1 + .../scheduler/windows/os_scheduler_imp.cpp | 26 +-- .../scheduler/windows/os_scheduler_imp.h | 24 ++ .../scheduler/linux/mock_sysfs_scheduler.h | 190 +++++++++++----- .../scheduler/linux/test_zes_scheduler.cpp | 187 +++++++++++++-- 13 files changed, 547 insertions(+), 158 deletions(-) create mode 100644 level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h diff --git a/level_zero/tools/source/sysman/scheduler/linux/CMakeLists.txt b/level_zero/tools/source/sysman/scheduler/linux/CMakeLists.txt index 1134431af6..ca397ef494 100644 --- a/level_zero/tools/source/sysman/scheduler/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/scheduler/linux/CMakeLists.txt @@ -6,7 +6,7 @@ set(L0_SRCS_TOOLS_SYSMAN_SCHEDULER_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}/os_scheduler_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_scheduler_imp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_scheduler_imp.h ) diff --git a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.cpp b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.cpp index dc660e6246..cd98d184d1 100644 --- a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.cpp +++ b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.cpp @@ -11,86 +11,157 @@ namespace L0 { -const std::string LinuxSchedulerImp::preemptTimeoutMilliSecs("engine/rcs0/preempt_timeout_ms"); -const std::string LinuxSchedulerImp::defaultPreemptTimeouttMilliSecs("engine/rcs0/.defaults/preempt_timeout_ms"); -const std::string LinuxSchedulerImp::timesliceDurationMilliSecs("engine/rcs0/timeslice_duration_ms"); -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"); +const std::string LinuxSchedulerImp::preemptTimeoutMilliSecs("preempt_timeout_ms"); +const std::string LinuxSchedulerImp::defaultPreemptTimeouttMilliSecs(".defaults/preempt_timeout_ms"); +const std::string LinuxSchedulerImp::timesliceDurationMilliSecs("timeslice_duration_ms"); +const std::string LinuxSchedulerImp::defaultTimesliceDurationMilliSecs(".defaults/timeslice_duration_ms"); +const std::string LinuxSchedulerImp::heartbeatIntervalMilliSecs("heartbeat_interval_ms"); +const std::string LinuxSchedulerImp::defaultHeartbeatIntervalMilliSecs(".defaults/heartbeat_interval_ms"); +const std::string LinuxSchedulerImp::engineDir("engine"); constexpr uint16_t milliSecsToMicroSecs = 1000; +ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProperties) { + schedProperties.onSubdevice = false; + schedProperties.canControl = canControlScheduler(); + schedProperties.engines = this->engineType; + schedProperties.supportedModes = (1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE); + return ZE_RESULT_SUCCESS; +} + ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) { - ze_result_t result; - if (getDefault) { - result = pSysfsAccess->read(defaultPreemptTimeouttMilliSecs, timeout); + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + uint32_t i = 0; + std::vector timeoutVec = {}; + timeoutVec.resize(listOfEngines.size()); + for (auto engineName : listOfEngines) { + if (getDefault) { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + defaultPreemptTimeouttMilliSecs, timeout); + } else { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + preemptTimeoutMilliSecs, timeout); + } + if (result == ZE_RESULT_SUCCESS) { + timeout = timeout * milliSecsToMicroSecs; + timeoutVec[i] = timeout; + i++; + } else { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } + } + // check if all engines of the same type have the same scheduling param values + if (std::adjacent_find(timeoutVec.begin(), timeoutVec.end(), std::not_equal_to<>()) == timeoutVec.end()) { + timeout = timeoutVec[0]; + return result; } else { - result = pSysfsAccess->read(preemptTimeoutMilliSecs, timeout); + return ZE_RESULT_ERROR_UNKNOWN; } - if (result == ZE_RESULT_SUCCESS) { - timeout = timeout * milliSecsToMicroSecs; - } - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - return result; } ze_result_t LinuxSchedulerImp::getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) { - ze_result_t result; - if (getDefault) { - result = pSysfsAccess->read(defaultTimesliceDurationMilliSecs, timeslice); + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + uint32_t i = 0; + std::vector timesliceVec = {}; + timesliceVec.resize(listOfEngines.size()); + for (auto engineName : listOfEngines) { + if (getDefault) { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + defaultTimesliceDurationMilliSecs, timeslice); + } else { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + timesliceDurationMilliSecs, timeslice); + } + if (result == ZE_RESULT_SUCCESS) { + timeslice = timeslice * milliSecsToMicroSecs; + timesliceVec[i] = timeslice; + i++; + } else { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } + } + // check if all engines of the same type have the same scheduling param values + if (std::adjacent_find(timesliceVec.begin(), timesliceVec.end(), std::not_equal_to<>()) == timesliceVec.end()) { + timeslice = timesliceVec[0]; + return result; } else { - result = pSysfsAccess->read(timesliceDurationMilliSecs, timeslice); + return ZE_RESULT_ERROR_UNKNOWN; } - if (result == ZE_RESULT_SUCCESS) { - timeslice = timeslice * milliSecsToMicroSecs; - } - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - return result; } ze_result_t LinuxSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) { - ze_result_t result; - if (getDefault) { - result = pSysfsAccess->read(defaultHeartbeatIntervalMilliSecs, heartbeat); + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + uint32_t i = 0; + std::vector heartbeatVec = {}; + heartbeatVec.resize(listOfEngines.size()); + for (auto engineName : listOfEngines) { + if (getDefault) { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + defaultHeartbeatIntervalMilliSecs, heartbeat); + } else { + result = pSysfsAccess->read(engineDir + "/" + engineName + "/" + heartbeatIntervalMilliSecs, heartbeat); + } + if (result == ZE_RESULT_SUCCESS) { + heartbeat = heartbeat * milliSecsToMicroSecs; + heartbeatVec[i] = heartbeat; + i++; + } else { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } + } + // check if all engines of the same type have the same scheduling param values + if (std::adjacent_find(heartbeatVec.begin(), heartbeatVec.end(), std::not_equal_to<>()) == heartbeatVec.end()) { + heartbeat = heartbeatVec[0]; + return result; } else { - result = pSysfsAccess->read(heartbeatIntervalMilliSecs, heartbeat); + return ZE_RESULT_ERROR_UNKNOWN; } - if (result == ZE_RESULT_SUCCESS) { - heartbeat = heartbeat * milliSecsToMicroSecs; - } - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - return result; } ze_result_t LinuxSchedulerImp::setPreemptTimeout(uint64_t timeout) { timeout = timeout / milliSecsToMicroSecs; - ze_result_t result = pSysfsAccess->write(preemptTimeoutMilliSecs, timeout); - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + for (auto engineName : listOfEngines) { + result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + preemptTimeoutMilliSecs, timeout); + if (result != ZE_RESULT_SUCCESS) { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } } return result; } ze_result_t LinuxSchedulerImp::setTimesliceDuration(uint64_t timeslice) { timeslice = timeslice / milliSecsToMicroSecs; - ze_result_t result = pSysfsAccess->write(timesliceDurationMilliSecs, timeslice); - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + for (auto engineName : listOfEngines) { + result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + timesliceDurationMilliSecs, timeslice); + if (result != ZE_RESULT_SUCCESS) { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } } return result; } ze_result_t LinuxSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) { heartbeat = heartbeat / milliSecsToMicroSecs; - ze_result_t result = pSysfsAccess->write(heartbeatIntervalMilliSecs, heartbeat); - if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + for (auto engineName : listOfEngines) { + result = pSysfsAccess->write(engineDir + "/" + engineName + "/" + heartbeatIntervalMilliSecs, heartbeat); + if (result != ZE_RESULT_SUCCESS) { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } } return result; } @@ -99,17 +170,52 @@ ze_bool_t LinuxSchedulerImp::canControlScheduler() { return 1; } -bool LinuxSchedulerImp::isSchedulerSupported() { - return (ZE_RESULT_SUCCESS == pSysfsAccess->canRead(computeEngineDir)); +static const std::multimap level0EngineTypeToSysfsEngineMap = { + {ZES_ENGINE_TYPE_FLAG_COMPUTE, "rcs"}, + {ZES_ENGINE_TYPE_FLAG_DMA, "bcs"}, + {ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"}, + {ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}}; + +ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map> &mapOfEngines, OsSysman *pOsSysman) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + auto pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); + std::vector localListOfAllEngines = {}; + auto result = pSysfsAccess->scanDirEntries(LinuxSchedulerImp::engineDir, localListOfAllEngines); + if (ZE_RESULT_SUCCESS != result) { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; + } + for_each(localListOfAllEngines.begin(), localListOfAllEngines.end(), + [&](std::string &mappedEngine) { + for (auto itr = level0EngineTypeToSysfsEngineMap.begin(); itr != level0EngineTypeToSysfsEngineMap.end(); itr++) { + char digits[] = "0123456789"; + auto mappedEngineName = mappedEngine.substr(0, mappedEngine.find_first_of(digits, 0)); + if (0 == mappedEngineName.compare(itr->second.c_str())) { + auto ret = mapOfEngines.find(itr->first); + if (ret != mapOfEngines.end()) { + ret->second.push_back(mappedEngine); + } else { + std::vector engineVec = {}; + engineVec.push_back(mappedEngine); + mapOfEngines.emplace(itr->first, engineVec); + } + } + } + }); + return result; } -LinuxSchedulerImp::LinuxSchedulerImp(OsSysman *pOsSysman) { +LinuxSchedulerImp::LinuxSchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); + engineType = type; + this->listOfEngines = listOfEngines; } -OsScheduler *OsScheduler::create(OsSysman *pOsSysman) { - LinuxSchedulerImp *pLinuxSchedulerImp = new LinuxSchedulerImp(pOsSysman); +OsScheduler *OsScheduler::create(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines) { + LinuxSchedulerImp *pLinuxSchedulerImp = new LinuxSchedulerImp(pOsSysman, type, listOfEngines); return static_cast(pLinuxSchedulerImp); } diff --git a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h index 0ea9b3e4fc..24c700c615 100644 --- a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h +++ b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h @@ -26,13 +26,15 @@ class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass { 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 getProperties(zes_sched_properties_t &properties) override; LinuxSchedulerImp() = default; - LinuxSchedulerImp(OsSysman *pOsSysman); + LinuxSchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines); ~LinuxSchedulerImp() override = default; + static const std::string engineDir; protected: SysfsAccess *pSysfsAccess = nullptr; + zes_engine_type_flag_t engineType = ZES_ENGINE_TYPE_FLAG_OTHER; private: static const std::string preemptTimeoutMilliSecs; @@ -41,7 +43,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; + std::vector listOfEngines = {}; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/scheduler/os_scheduler.h b/level_zero/tools/source/sysman/scheduler/os_scheduler.h index bb3132a52e..d1fc005f64 100644 --- a/level_zero/tools/source/sysman/scheduler/os_scheduler.h +++ b/level_zero/tools/source/sysman/scheduler/os_scheduler.h @@ -8,8 +8,14 @@ #pragma once #include +#include +#include +#include + namespace L0 { struct OsSysman; +using namespace std; + class OsScheduler { public: virtual ze_result_t getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) = 0; @@ -19,8 +25,9 @@ class OsScheduler { 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 ze_result_t getProperties(zes_sched_properties_t &properties) = 0; + static OsScheduler *create(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector &listOfEngines); + static ze_result_t getNumEngineTypeAndInstances(std::map> &listOfEngines, OsSysman *pOsSysman); virtual ~OsScheduler() = default; }; diff --git a/level_zero/tools/source/sysman/scheduler/scheduler.cpp b/level_zero/tools/source/sysman/scheduler/scheduler.cpp index 93a172b49d..8028e1ce8e 100644 --- a/level_zero/tools/source/sysman/scheduler/scheduler.cpp +++ b/level_zero/tools/source/sysman/scheduler/scheduler.cpp @@ -6,23 +6,33 @@ */ #include "shared/source/helpers/basic_math.h" +#include "shared/source/helpers/debug_helpers.h" #include "level_zero/tools/source/sysman/scheduler/scheduler_imp.h" +class OsScheduler; namespace L0 { +SchedulerHandleContext::SchedulerHandleContext(OsSysman *pOsSysman) { + this->pOsSysman = pOsSysman; +} + SchedulerHandleContext::~SchedulerHandleContext() { for (Scheduler *pScheduler : handleList) { delete pScheduler; } + handleList.clear(); +} +void SchedulerHandleContext::createHandle(zes_engine_type_flag_t engineType, std::vector &listOfEngines) { + Scheduler *pScheduler = new SchedulerImp(pOsSysman, engineType, listOfEngines); + handleList.push_back(pScheduler); } void SchedulerHandleContext::init() { - Scheduler *pScheduler = new SchedulerImp(pOsSysman); - if (pScheduler->initSuccess == true) { - handleList.push_back(pScheduler); - } else { - delete pScheduler; + std::map> engineTypeInstance = {}; + OsScheduler::getNumEngineTypeAndInstances(engineTypeInstance, pOsSysman); + for (auto itr = engineTypeInstance.begin(); itr != engineTypeInstance.end(); ++itr) { + createHandle(itr->first, itr->second); } } diff --git a/level_zero/tools/source/sysman/scheduler/scheduler.h b/level_zero/tools/source/sysman/scheduler/scheduler.h index cb6f7fa9b1..237131b728 100644 --- a/level_zero/tools/source/sysman/scheduler/scheduler.h +++ b/level_zero/tools/source/sysman/scheduler/scheduler.h @@ -10,6 +10,8 @@ #include +#include +#include #include struct _zes_sched_handle_t { @@ -37,7 +39,7 @@ class Scheduler : _zes_sched_handle_t { }; struct SchedulerHandleContext : NEO::NonCopyableOrMovableClass { - SchedulerHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){}; + SchedulerHandleContext(OsSysman *pOsSysman); ~SchedulerHandleContext(); void init(); ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler); @@ -45,6 +47,9 @@ struct SchedulerHandleContext : NEO::NonCopyableOrMovableClass { OsSysman *pOsSysman = nullptr; std::vector handleList = {}; ze_device_handle_t hCoreDevice = nullptr; + + private: + void createHandle(zes_engine_type_flag_t engineType, std::vector &listOfEngines); }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp b/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp index 5a34b0d3a9..bdace8eaa5 100644 --- a/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp +++ b/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp @@ -141,17 +141,11 @@ ze_result_t SchedulerImp::schedulerGetProperties(zes_sched_properties_t *pProper } 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); + pOsScheduler->getProperties(this->properties); } -SchedulerImp::SchedulerImp(OsSysman *pOsSysman) { - if (pOsScheduler == nullptr) { - pOsScheduler = OsScheduler::create(pOsSysman); - } +SchedulerImp::SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector &listOfEngines) { + pOsScheduler = OsScheduler::create(pOsSysman, engineType, listOfEngines); UNRECOVERABLE_IF(nullptr == pOsScheduler); init(); }; diff --git a/level_zero/tools/source/sysman/scheduler/scheduler_imp.h b/level_zero/tools/source/sysman/scheduler/scheduler_imp.h index 2d34f1876e..d7d53ee8f8 100644 --- a/level_zero/tools/source/sysman/scheduler/scheduler_imp.h +++ b/level_zero/tools/source/sysman/scheduler/scheduler_imp.h @@ -29,8 +29,9 @@ class SchedulerImp : public Scheduler, NEO::NonCopyableOrMovableClass { SchedulerImp() = default; OsScheduler *pOsScheduler = nullptr; - SchedulerImp(OsSysman *pOsSysman); + SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines); ~SchedulerImp() override; + zes_engine_type_flag_t engineType; private: zes_sched_properties_t properties = {}; diff --git a/level_zero/tools/source/sysman/scheduler/windows/CMakeLists.txt b/level_zero/tools/source/sysman/scheduler/windows/CMakeLists.txt index e122461899..06359d53e9 100644 --- a/level_zero/tools/source/sysman/scheduler/windows/CMakeLists.txt +++ b/level_zero/tools/source/sysman/scheduler/windows/CMakeLists.txt @@ -6,6 +6,7 @@ set(L0_SRCS_TOOLS_SYSMAN_SCHEDULER_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_scheduler_imp.h ${CMAKE_CURRENT_SOURCE_DIR}/os_scheduler_imp.cpp ) diff --git a/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.cpp b/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.cpp index 73d1e412e1..a82090f804 100644 --- a/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.cpp +++ b/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.cpp @@ -5,22 +5,12 @@ * */ -#include "sysman/scheduler/os_scheduler.h" +#include "level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h" + +#include "sysman/scheduler/scheduler_imp.h" namespace L0 { -class WddmSchedulerImp : public OsScheduler { - public: - ze_result_t getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) override; - ze_result_t getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) override; - ze_result_t getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) override; - 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) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } @@ -49,11 +39,15 @@ ze_bool_t WddmSchedulerImp::canControlScheduler() { return 0; } -bool WddmSchedulerImp::isSchedulerSupported() { - return false; +ze_result_t WddmSchedulerImp::getProperties(zes_sched_properties_t &properties) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -OsScheduler *OsScheduler::create(OsSysman *pOsSysman) { +ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map> &listOfEngines, OsSysman *pOsSysman) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +OsScheduler *OsScheduler::create(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines) { WddmSchedulerImp *pWddmSchedulerImp = new WddmSchedulerImp(); return static_cast(pWddmSchedulerImp); } diff --git a/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h b/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h new file mode 100644 index 0000000000..492e7fcb12 --- /dev/null +++ b/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "sysman/scheduler/scheduler_imp.h" + +namespace L0 { + +class WddmSchedulerImp : public OsScheduler { + public: + ze_result_t getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) override; + ze_result_t getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) override; + ze_result_t getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) override; + 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; + ze_result_t getProperties(zes_sched_properties_t &properties) override; +}; + +} // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler.h b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler.h index 935fc7d6fa..be3f166027 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler.h @@ -13,24 +13,30 @@ namespace L0 { namespace ult { -const std::string preemptTimeoutMilliSecs("engine/rcs0/preempt_timeout_ms"); -const std::string defaultPreemptTimeoutMilliSecs("engine/rcs0/.defaults/preempt_timeout_ms"); -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"); +const std::string preemptTimeoutMilliSecs("preempt_timeout_ms"); +const std::string defaultPreemptTimeoutMilliSecs(".defaults/preempt_timeout_ms"); +const std::string timesliceDurationMilliSecs("timeslice_duration_ms"); +const std::string defaultTimesliceDurationMilliSecs(".defaults/timeslice_duration_ms"); +const std::string heartbeatIntervalMilliSecs("heartbeat_interval_ms"); +const std::string defaultHeartbeatIntervalMilliSecs(".defaults/heartbeat_interval_ms"); +const std::string engineDir("engine"); +const std::vector listOfMockedEngines = {"rcs0", "bcs0", "vcs0", "vcs1", "vecs0"}; class SchedulerSysfsAccess : public SysfsAccess {}; +typedef struct SchedulerConfigValues { + uint64_t defaultVal; + uint64_t actualVal; +} SchedulerConfigValues_t; + +typedef struct SchedulerConfig { + SchedulerConfigValues_t timeOut; + SchedulerConfigValues_t timeSclice; + SchedulerConfigValues_t heartBeat; +} SchedulerConfig_t; template <> struct Mock : public SysfsAccess { - uint64_t mockValPreemptTimeoutMilliSecs = 0; - uint64_t mockValTimesliceDurationMilliSecs = 0; - uint64_t mockValHeartbeatIntervalMilliSecs = 0; - uint64_t mockValDefaultPreemptTimeoutMilliSecs = 0; - uint64_t mockValDefaultTimesliceDurationMilliSecs = 0; - uint64_t mockValDefaultHeartbeatIntervalMilliSecs = 0; + std::map engineSchedMap; ze_result_t getValForError(const std::string file, uint64_t &val) { return ZE_RESULT_ERROR_NOT_AVAILABLE; @@ -40,55 +46,133 @@ struct Mock : public SysfsAccess { return ZE_RESULT_ERROR_NOT_AVAILABLE; } + void cleanUpMap() { + for (std::string mappedEngine : listOfMockedEngines) { + auto it = engineSchedMap.find(mappedEngine); + if (it != engineSchedMap.end()) { + delete it->second; + } + } + } ze_result_t getVal(const std::string file, uint64_t &val) { - if (file.compare(preemptTimeoutMilliSecs) == 0) { - val = mockValPreemptTimeoutMilliSecs; + for (std::string mappedEngine : listOfMockedEngines) { + if (file.find(mappedEngine) == std::string::npos) { + continue; + } + auto it = engineSchedMap.find(mappedEngine); + if (it == engineSchedMap.end()) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + if (file.compare((file.length() - preemptTimeoutMilliSecs.length()), + preemptTimeoutMilliSecs.length(), + preemptTimeoutMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + val = it->second->timeOut.defaultVal; + } else { + val = it->second->timeOut.actualVal; + } + return ZE_RESULT_SUCCESS; + } + if (file.compare((file.length() - timesliceDurationMilliSecs.length()), + timesliceDurationMilliSecs.length(), + timesliceDurationMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + val = it->second->timeSclice.defaultVal; + } else { + val = it->second->timeSclice.actualVal; + } + return ZE_RESULT_SUCCESS; + } + if (file.compare((file.length() - heartbeatIntervalMilliSecs.length()), + heartbeatIntervalMilliSecs.length(), + heartbeatIntervalMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + val = it->second->heartBeat.defaultVal; + } else { + val = it->second->heartBeat.actualVal; + } + return ZE_RESULT_SUCCESS; + } } - if (file.compare(timesliceDurationMilliSecs) == 0) { - val = mockValTimesliceDurationMilliSecs; - } - if (file.compare(heartbeatIntervalMilliSecs) == 0) { - val = mockValHeartbeatIntervalMilliSecs; - } - if (file.compare(defaultPreemptTimeoutMilliSecs) == 0) { - val = mockValDefaultPreemptTimeoutMilliSecs; - } - if (file.compare(defaultTimesliceDurationMilliSecs) == 0) { - val = mockValDefaultTimesliceDurationMilliSecs; - } - if (file.compare(defaultHeartbeatIntervalMilliSecs) == 0) { - val = mockValDefaultHeartbeatIntervalMilliSecs; - } - return ZE_RESULT_SUCCESS; + return ZE_RESULT_ERROR_NOT_AVAILABLE; } ze_result_t setVal(const std::string file, const uint64_t val) { - if (file.compare(preemptTimeoutMilliSecs) == 0) { - mockValPreemptTimeoutMilliSecs = val; + for (std::string mappedEngine : listOfMockedEngines) { + if (file.find(mappedEngine) == std::string::npos) { + continue; + } + SchedulerConfig_t *schedConfig = new SchedulerConfig_t(); + if (file.compare((file.length() - preemptTimeoutMilliSecs.length()), + preemptTimeoutMilliSecs.length(), + preemptTimeoutMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + schedConfig->timeOut.defaultVal = val; + } else { + schedConfig->timeOut.actualVal = val; + } + auto ret = engineSchedMap.emplace(mappedEngine, schedConfig); + if (ret.second == false) { + auto itr = engineSchedMap.find(mappedEngine); + if (file.find(".defaults") != std::string::npos) { + itr->second->timeOut.defaultVal = val; + } else { + itr->second->timeOut.actualVal = val; + } + delete schedConfig; + } + return ZE_RESULT_SUCCESS; + } + if (file.compare((file.length() - timesliceDurationMilliSecs.length()), + timesliceDurationMilliSecs.length(), + timesliceDurationMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + schedConfig->timeSclice.defaultVal = val; + } else { + schedConfig->timeSclice.actualVal = val; + } + auto ret = engineSchedMap.emplace(mappedEngine, schedConfig); + if (ret.second == false) { + auto itr = engineSchedMap.find(mappedEngine); + if (file.find(".defaults") != std::string::npos) { + itr->second->timeSclice.defaultVal = val; + } else { + itr->second->timeSclice.actualVal = val; + } + delete schedConfig; + } + return ZE_RESULT_SUCCESS; + } + if (file.compare((file.length() - heartbeatIntervalMilliSecs.length()), + heartbeatIntervalMilliSecs.length(), + heartbeatIntervalMilliSecs) == 0) { + if (file.find(".defaults") != std::string::npos) { + schedConfig->heartBeat.defaultVal = val; + } else { + schedConfig->heartBeat.actualVal = val; + } + auto ret = engineSchedMap.emplace(mappedEngine, schedConfig); + if (ret.second == false) { + auto itr = engineSchedMap.find(mappedEngine); + if (file.find(".defaults") != std::string::npos) { + itr->second->heartBeat.defaultVal = val; + } else { + itr->second->heartBeat.actualVal = val; + } + delete schedConfig; + } + return ZE_RESULT_SUCCESS; + } } - if (file.compare(timesliceDurationMilliSecs) == 0) { - mockValTimesliceDurationMilliSecs = val; - } - if (file.compare(heartbeatIntervalMilliSecs) == 0) { - mockValHeartbeatIntervalMilliSecs = val; - } - if (file.compare(defaultPreemptTimeoutMilliSecs) == 0) { - mockValDefaultPreemptTimeoutMilliSecs = val; - } - if (file.compare(defaultTimesliceDurationMilliSecs) == 0) { - mockValDefaultTimesliceDurationMilliSecs = val; - } - if (file.compare(defaultHeartbeatIntervalMilliSecs) == 0) { - mockValDefaultHeartbeatIntervalMilliSecs = val; - } - return ZE_RESULT_SUCCESS; + return ZE_RESULT_ERROR_NOT_AVAILABLE; } - ze_result_t getCanReadStatus(const std::string file) { - if (file.compare(computeEngineDir) == 0) { + ze_result_t getscanDirEntries(const std::string file, std::vector &listOfEntries) { + if (file.compare(engineDir) == 0) { + listOfEntries = listOfMockedEngines; return ZE_RESULT_SUCCESS; } return ZE_RESULT_ERROR_NOT_AVAILABLE; } - ze_result_t getCanReadStatusReturnError(const std::string file) { + ze_result_t getscanDirEntriesStatusReturnError(const std::string file, std::vector &listOfEntries) { return ZE_RESULT_ERROR_NOT_AVAILABLE; } @@ -96,7 +180,7 @@ struct Mock : public SysfsAccess { 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)); + MOCK_METHOD(ze_result_t, scanDirEntries, (const std::string file, std::vector &listOfEntries), (override)); }; class PublicLinuxSchedulerImp : public L0::LinuxSchedulerImp { diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler.cpp b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler.cpp index 5a8d11b315..40bd32dfee 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler.cpp @@ -9,9 +9,12 @@ #include "mock_sysfs_scheduler.h" +using ::testing::DoDefault; +using ::testing::Return; + namespace L0 { namespace ult { -constexpr uint32_t handleComponentCount = 1u; +constexpr uint32_t handleComponentCount = 4u; constexpr uint64_t convertMilliToMicro = 1000u; constexpr uint64_t defaultTimeoutMilliSecs = 650u; constexpr uint64_t defaultTimesliceMilliSecs = 1u; @@ -25,6 +28,7 @@ constexpr uint64_t expectedDefaultTimesliceMicroSecs = defaultTimesliceMilliSecs constexpr uint64_t expectedHeartbeatTimeoutMicroSecs = heartbeatMilliSecs * convertMilliToMicro; constexpr uint64_t expectedTimeoutMicroSecs = timeoutMilliSecs * convertMilliToMicro; constexpr uint64_t expectedTimesliceMicroSecs = timesliceMilliSecs * convertMilliToMicro; + class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { protected: @@ -36,24 +40,27 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess; pSysfsAccess = std::make_unique>>(); 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); - + for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), + [=](std::string engineName) { + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + defaultPreemptTimeoutMilliSecs, defaultTimeoutMilliSecs); + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + defaultTimesliceDurationMilliSecs, defaultTimesliceMilliSecs); + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + defaultHeartbeatIntervalMilliSecs, defaultHeartbeatMilliSecs); + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + preemptTimeoutMilliSecs, timeoutMilliSecs); + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + timesliceDurationMilliSecs, timesliceMilliSecs); + pSysfsAccess->setVal(engineDir + "/" + engineName + "/" + heartbeatIntervalMilliSecs, heartbeatMilliSecs); + }); ON_CALL(*pSysfsAccess.get(), read(_, _)) .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getVal)); ON_CALL(*pSysfsAccess.get(), write(_, _)) .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::setVal)); - ON_CALL(*pSysfsAccess.get(), canRead(_)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getCanReadStatus)); + ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntries)); pSysmanDeviceImp->pSchedulerHandleContext->init(); } void TearDown() override { + pSysfsAccess->cleanUpMap(); SysmanDeviceFixture::TearDown(); pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld; } @@ -87,8 +94,8 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { }; TEST_F(SysmanDeviceSchedulerFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumSchedulersAndSysfsCanReadReturnsErrorThenZeroCountIsReturned) { - ON_CALL(*pSysfsAccess.get(), canRead(_)) - .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getCanReadStatusReturnError)); + ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getscanDirEntriesStatusReturnError)); auto pSchedulerHandleContextTest = std::make_unique(pOsSysman); pSchedulerHandleContextTest->init(); @@ -126,6 +133,22 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesThenVerifyzesSchedulerGetTimeoutModePropertiesForDifferingValues) { + auto handles = get_sched_handles(handleComponentCount); + pSysfsAccess->setVal(engineDir + "/" + "vcs1" + "/" + heartbeatIntervalMilliSecs, (heartbeatMilliSecs + 5)); + + for (auto handle : handles) { + zes_sched_properties_t properties = {}; + zes_sched_timeout_properties_t config; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + ze_result_t result = zesSchedulerGetTimeoutModeProperties(handle, false, &config); + EXPECT_NE(ZE_RESULT_SUCCESS, result); + } + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesWithDefaultsThenVerifyzesSchedulerGetTimeoutModePropertiesCallSucceeds) { auto handles = get_sched_handles(handleComponentCount); for (auto handle : handles) { @@ -143,6 +166,111 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimescliceModePropertiesThenVerifyzesSchedulerGetTimescliceModePropertiesForDifferingPreemptTimeoutValues) { + auto handles = get_sched_handles(handleComponentCount); + pSysfsAccess->setVal(engineDir + "/" + "vcs1" + "/" + preemptTimeoutMilliSecs, (timeoutMilliSecs + 5)); + + for (auto handle : handles) { + zes_sched_properties_t properties = {}; + zes_sched_timeslice_properties_t config; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + ze_result_t result = zesSchedulerGetTimesliceModeProperties(handle, false, &config); + EXPECT_NE(ZE_RESULT_SUCCESS, result); + } + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimescliceModePropertiesThenVerifyzesSchedulerGetTimescliceModePropertiesForDifferingTimesliceDurationValues) { + auto handles = get_sched_handles(handleComponentCount); + pSysfsAccess->setVal(engineDir + "/" + "vcs1" + "/" + timesliceDurationMilliSecs, (timesliceMilliSecs + 5)); + + for (auto handle : handles) { + zes_sched_properties_t properties = {}; + zes_sched_timeslice_properties_t config; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + ze_result_t result = zesSchedulerGetTimesliceModeProperties(handle, false, &config); + EXPECT_NE(ZE_RESULT_SUCCESS, result); + } + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesThenVerifyzesSchedulerGetTimeoutModePropertiesForReadFileFailureFileUnavailable) { + auto handles = get_sched_handles(handleComponentCount); + + for (auto handle : handles) { + zes_sched_properties_t properties = {}; + zes_sched_timeout_properties_t config; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + EXPECT_CALL(*pSysfsAccess.get(), read(_, _)) + .WillOnce(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)) + .WillRepeatedly(DoDefault()); + ze_result_t result = zesSchedulerGetTimeoutModeProperties(handle, false, &config); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + } + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesThenVerifyzesSchedulerGetTimeoutModePropertiesForReadFileFailureInsufficientPermissions) { + auto handles = get_sched_handles(handleComponentCount); + + for (auto handle : handles) { + zes_sched_properties_t properties = {}; + zes_sched_timeout_properties_t config; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + EXPECT_CALL(*pSysfsAccess.get(), read(_, _)) + .WillOnce(Return(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS)) + .WillRepeatedly(DoDefault()); + ze_result_t result = zesSchedulerGetTimeoutModeProperties(handle, false, &config); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result); + } + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimescliceModePropertiesThenVerifyzesSchedulerGetTimescliceModePropertiesForReadFileFailureDueToUnavailable) { + auto handles = get_sched_handles(handleComponentCount); + for (auto handle : handles) { + zes_sched_timeslice_properties_t config; + zes_sched_properties_t properties = {}; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + EXPECT_CALL(*pSysfsAccess.get(), read(_, _)) + .WillOnce(Return(ZE_RESULT_SUCCESS)) + .WillOnce(Return(ZE_RESULT_SUCCESS)) + .WillOnce(Return(ZE_RESULT_SUCCESS)) //3 reads to satisfy Prempt timeout reads + .WillOnce(Return(ZE_RESULT_ERROR_NOT_AVAILABLE)) // failure in timesclice read. + .WillRepeatedly(DoDefault()); + result = zesSchedulerGetTimesliceModeProperties(handle, false, &config); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + } + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimescliceModePropertiesThenVerifyzesSchedulerGetTimescliceModePropertiesForReadFileFailureDueToInsufficientPermissions) { + auto handles = get_sched_handles(handleComponentCount); + for (auto handle : handles) { + zes_sched_timeslice_properties_t config; + zes_sched_properties_t properties = {}; + ze_result_t result = zesSchedulerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + EXPECT_CALL(*pSysfsAccess.get(), read(_, _)) + .WillOnce(Return(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS)) + .WillRepeatedly(DoDefault()); + result = zesSchedulerGetTimesliceModeProperties(handle, false, &config); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result); + } + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimesliceModePropertiesWithDefaultsThenVerifyzesSchedulerGetTimesliceModePropertiesCallSucceeds) { auto handles = get_sched_handles(handleComponentCount); for (auto handle : handles) { @@ -244,6 +372,22 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimeoutModeWhenSysfsNodeWithoutPermissionsThenFailureIsReturned) { + ON_CALL(*pSysfsAccess.get(), write(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValForErrorWhileWrite)); + auto handles = get_sched_handles(handleComponentCount); + for (auto handle : handles) { + ze_bool_t needReboot; + zes_sched_timeout_properties_t setConfig; + setConfig.watchdogTimeout = 10000u; + EXPECT_CALL(*pSysfsAccess.get(), write(_, _)) + .WillOnce(Return(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS)) + .WillRepeatedly(DoDefault()); + ze_result_t result = zesSchedulerSetTimeoutMode(handle, &setConfig, &needReboot); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result); + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimesliceModeWhenSysfsNodeIsAbsentThenFailureIsReturned) { ON_CALL(*pSysfsAccess.get(), write(_, _)) .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValForErrorWhileWrite)); @@ -258,6 +402,23 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimesliceModeWhenSysfsNodeWithoutPermissionsThenFailureIsReturned) { + ON_CALL(*pSysfsAccess.get(), write(_, _)) + .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock::getValForErrorWhileWrite)); + 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; + EXPECT_CALL(*pSysfsAccess.get(), write(_, _)) + .WillOnce(Return(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS)) + .WillRepeatedly(DoDefault()); + ze_result_t result = zesSchedulerSetTimesliceMode(handle, &setConfig, &needReboot); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result); + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetPropertiesThenVerifyzesSchedulerGetPropertiesCallSucceeds) { auto handles = get_sched_handles(handleComponentCount); for (auto handle : handles) { @@ -265,7 +426,7 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul 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_LE(properties.engines, ZES_ENGINE_TYPE_FLAG_DMA); EXPECT_EQ(properties.supportedModes, static_cast((1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE))); } }