diff --git a/level_zero/tools/source/sysman/linux/fs_access.h b/level_zero/tools/source/sysman/linux/fs_access.h index 8547c59716..be39825a88 100644 --- a/level_zero/tools/source/sysman/linux/fs_access.h +++ b/level_zero/tools/source/sysman/linux/fs_access.h @@ -114,12 +114,13 @@ class SysfsAccess : protected FsAccess { bool directoryExists(const std::string path) override; bool isRootUser() override; + protected: + std::vector deviceNames; + private: SysfsAccess(const std::string file); std::string fullPath(const std::string file); - - std::vector deviceNames; std::string dirname; static const std::string drmPath; static const std::string devicesPath; diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp index 2d70d3673a..ebf901293f 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp @@ -259,6 +259,43 @@ void LinuxSysmanImp::getPidFdsForOpenDevice(ProcfsAccess *pProcfsAccess, SysfsAc } } +ze_result_t LinuxSysmanImp::gpuProcessCleanup() { + ::pid_t myPid = pProcfsAccess->myProcessId(); + std::vector<::pid_t> processes; + std::vector myPidFds; + ze_result_t result = pProcfsAccess->listProcesses(processes); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "gpuProcessCleanup: listProcesses() failed with error code: %ld\n", result); + return result; + } + + for (auto &&pid : processes) { + std::vector fds; + getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds); + if (pid == myPid) { + // L0 is expected to have this file open. + // Keep list of fds. Close before unbind. + myPidFds = fds; + continue; + } + if (!fds.empty()) { + pProcfsAccess->kill(pid); + } + } + + for (auto &&fd : myPidFds) { + // Close open filedescriptors to the device + // before unbinding device. + // From this point forward, there is no + // graceful way to fail the reset call. + // All future ze calls by this process for this + // device will fail. + NEO::SysCalls::close(fd); + } + return ZE_RESULT_SUCCESS; +} + void LinuxSysmanImp::releaseSysmanDeviceResources() { getSysmanDeviceImp()->pEngineHandleContext->releaseEngines(); getSysmanDeviceImp()->pRasHandleContext->releaseRasHandles(); @@ -326,6 +363,7 @@ ze_result_t LinuxSysmanImp::initDevice() { return ZE_RESULT_SUCCESS; } + // function to clear Hot-Plug interrupt enable bit in the slot control register // this is required to prevent interrupts from being raised in the warm reset path. void LinuxSysmanImp::clearHPIE(int fd) { diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.h b/level_zero/tools/source/sysman/linux/os_sysman_imp.h index a33db5e2a5..f1422d149d 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.h +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.h @@ -71,6 +71,7 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass { MOCKABLE_VIRTUAL void getPidFdsForOpenDevice(ProcfsAccess *, SysfsAccess *, const ::pid_t, std::vector &); MOCKABLE_VIRTUAL ze_result_t osWarmReset(); MOCKABLE_VIRTUAL ze_result_t osColdReset(); + ze_result_t gpuProcessCleanup(); std::string getAddressFromPath(std::string &rootPortPath); decltype(&NEO::SysCalls::open) openFunction = NEO::SysCalls::open; decltype(&NEO::SysCalls::close) closeFunction = NEO::SysCalls::close; 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 98265f1ab7..2589a8500a 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 @@ -20,6 +20,12 @@ const std::string LinuxSchedulerImp::defaultHeartbeatIntervalMilliSecs(".default const std::string LinuxSchedulerImp::enableEuDebug(""); const std::string LinuxSchedulerImp::engineDir("engine"); +static const std::multimap level0EngineTypeToSysfsEngineMap = { + {ZES_ENGINE_TYPE_FLAG_RENDER, "rcs"}, + {ZES_ENGINE_TYPE_FLAG_DMA, "bcs"}, + {ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"}, + {ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}}; + ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProperties) { schedProperties.onSubdevice = onSubdevice; schedProperties.subdeviceId = subdeviceId; @@ -29,6 +35,183 @@ ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProper return ZE_RESULT_SUCCESS; } +ze_result_t LinuxSchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { + uint64_t timeout = 0; + uint64_t timeslice = 0; + uint64_t heartbeat = 0; + ze_result_t result = getPreemptTimeout(timeout, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getTimesliceDuration(timeslice, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getHeartbeatInterval(heartbeat, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (timeslice > 0) { + *pMode = ZES_SCHED_MODE_TIMESLICE; + } else { + if (timeout > 0) { + *pMode = ZES_SCHED_MODE_TIMEOUT; + } else { + if (heartbeat == 0) { + // If we are here, it means heartbeat = 0, timeout = 0, timeslice = 0. + if (isComputeUnitDebugModeEnabled()) { + *pMode = ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG; + } else { + *pMode = ZES_SCHED_MODE_EXCLUSIVE; + } + } else { + // If we are here it means heartbeat > 0, timeout = 0, timeslice = 0. + // And we dont know what that mode is. + *pMode = ZES_SCHED_MODE_FORCE_UINT32; + result = ZE_RESULT_ERROR_UNKNOWN; + } + } + } + return result; +} + +ze_result_t LinuxSchedulerImp::setExclusiveModeImp() { + uint64_t timeslice = 0, timeout = 0, heartbeat = 0; + ze_result_t result = setPreemptTimeout(timeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setTimesliceDuration(timeslice); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setHeartbeatInterval(heartbeat); + return result; +} + +ze_result_t LinuxSchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) { + *pNeedReload = false; + + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + return setExclusiveModeImp(); +} + +ze_result_t LinuxSchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) { + uint64_t heartbeat = 0; + ze_result_t result = getHeartbeatInterval(heartbeat, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + pConfig->watchdogTimeout = heartbeat; + + return result; +} + +ze_result_t LinuxSchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) { + uint64_t timeout = 0, timeslice = 0; + ze_result_t result = getPreemptTimeout(timeout, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getTimesliceDuration(timeslice, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + pConfig->interval = timeslice; + pConfig->yieldTimeout = timeout; + return result; +} + +ze_result_t LinuxSchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) { + *pNeedReload = false; + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (pProperties->watchdogTimeout < minTimeoutModeHeartbeat) { + // watchdogTimeout(in usec) less than 5000 would be computed to + // 0 milli seconds preempt timeout, and then after returning from + // this method, we would end up in EXCLUSIVE mode + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + result = setHeartbeatInterval(pProperties->watchdogTimeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + uint64_t timeout = (pProperties->watchdogTimeout) / 5; + result = setPreemptTimeout(timeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + uint64_t timeslice = 0; + result = setTimesliceDuration(timeslice); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + return result; +} + +ze_result_t LinuxSchedulerImp::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; + } + *pNeedReload = false; + + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + result = setPreemptTimeout(pProperties->yieldTimeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setTimesliceDuration(pProperties->interval); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + uint64_t heartbeat = 2500 * (pProperties->interval); + return setHeartbeatInterval(heartbeat); +} + ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) { ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; uint32_t i = 0; @@ -176,11 +359,14 @@ ze_result_t LinuxSchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) { return pSysfsAccess->write(enableEuDebug, 1); } -static const std::multimap level0EngineTypeToSysfsEngineMap = { - {ZES_ENGINE_TYPE_FLAG_RENDER, "rcs"}, - {ZES_ENGINE_TYPE_FLAG_DMA, "bcs"}, - {ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"}, - {ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}}; +bool LinuxSchedulerImp::isComputeUnitDebugModeEnabled() { + return false; +} + +ze_result_t LinuxSchedulerImp::disableComputeUnitDebugMode(ze_bool_t *pNeedReload) { + *pNeedReload = false; + return pSysfsAccess->write(enableEuDebug, 0); +} static ze_result_t getNumEngineTypeAndInstancesForDevice(std::map> &mapOfEngines, SysfsAccess *pSysfsAccess) { std::vector localListOfAllEngines = {}; 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 a891c93f01..e7914189f3 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 @@ -8,6 +8,7 @@ #pragma once #include "shared/source/os_interface/linux/drm_neo.h" +#include "sysman/linux/os_sysman_imp.h" #include "sysman/scheduler/scheduler_imp.h" #include @@ -22,13 +23,12 @@ struct Device; // zes_sched_timeout_properties_t. watchdogTimeout = heartbeat_interval_ms class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass { 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 setExclusiveMode(ze_bool_t *pNeedReload) 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 *pNeedReload) override; + ze_result_t setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) override; ze_result_t getProperties(zes_sched_properties_t &properties) override; ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReload) override; LinuxSchedulerImp() = default; @@ -38,11 +38,23 @@ class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass { static const std::string engineDir; protected: + LinuxSysmanImp *pLinuxSysmanImp = nullptr; SysfsAccess *pSysfsAccess = nullptr; Device *pDevice = nullptr; zes_engine_type_flag_t engineType = ZES_ENGINE_TYPE_FLAG_OTHER; ze_bool_t onSubdevice = 0; uint32_t subdeviceId = 0; + ze_result_t setExclusiveModeImp(); + ze_result_t updateComputeUnitDebugNode(uint64_t val); + ze_result_t getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault); + ze_result_t getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault); + ze_result_t getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault); + ze_result_t setPreemptTimeout(uint64_t timeout); + ze_result_t setTimesliceDuration(uint64_t timeslice); + ze_result_t setHeartbeatInterval(uint64_t heartbeat); + ze_bool_t canControlScheduler(); + ze_result_t disableComputeUnitDebugMode(ze_bool_t *pNeedReload); + bool isComputeUnitDebugModeEnabled(); private: static const std::string preemptTimeoutMilliSecs; diff --git a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp_prelim.cpp b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp_prelim.cpp index 59966163d8..73911cc90d 100644 --- a/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp_prelim.cpp +++ b/level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp_prelim.cpp @@ -8,6 +8,7 @@ #include "shared/source/os_interface/linux/engine_info.h" #include "shared/source/os_interface/linux/i915_prelim.h" +#include "level_zero/core/source/device/device_imp.h" #include "level_zero/tools/source/sysman/scheduler/linux/os_scheduler_imp.h" #include "sysman/linux/os_sysman_imp.h" @@ -52,6 +53,183 @@ static const std::map sysfsEngineMapToi915EngineClass = { {"vcs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO}, {"vecs", drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE}}; +ze_result_t LinuxSchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { + uint64_t timeout = 0; + uint64_t timeslice = 0; + uint64_t heartbeat = 0; + ze_result_t result = getPreemptTimeout(timeout, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getTimesliceDuration(timeslice, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getHeartbeatInterval(heartbeat, false); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (timeslice > 0) { + *pMode = ZES_SCHED_MODE_TIMESLICE; + } else { + if (timeout > 0) { + *pMode = ZES_SCHED_MODE_TIMEOUT; + } else { + if (heartbeat == 0) { + // If we are here, it means heartbeat = 0, timeout = 0, timeslice = 0. + if (isComputeUnitDebugModeEnabled()) { + *pMode = ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG; + } else { + *pMode = ZES_SCHED_MODE_EXCLUSIVE; + } + } else { + // If we are here it means heartbeat > 0, timeout = 0, timeslice = 0. + // And we dont know what that mode is. + *pMode = ZES_SCHED_MODE_FORCE_UINT32; + result = ZE_RESULT_ERROR_UNKNOWN; + } + } + } + return result; +} + +ze_result_t LinuxSchedulerImp::setExclusiveModeImp() { + uint64_t timeslice = 0, timeout = 0, heartbeat = 0; + ze_result_t result = setPreemptTimeout(timeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setTimesliceDuration(timeslice); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setHeartbeatInterval(heartbeat); + return result; +} + +ze_result_t LinuxSchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) { + *pNeedReload = false; + + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + return setExclusiveModeImp(); +} + +ze_result_t LinuxSchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) { + uint64_t heartbeat = 0; + ze_result_t result = getHeartbeatInterval(heartbeat, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + pConfig->watchdogTimeout = heartbeat; + + return result; +} + +ze_result_t LinuxSchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) { + uint64_t timeout = 0, timeslice = 0; + ze_result_t result = getPreemptTimeout(timeout, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = getTimesliceDuration(timeslice, getDefaults); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + pConfig->interval = timeslice; + pConfig->yieldTimeout = timeout; + return result; +} + +ze_result_t LinuxSchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) { + *pNeedReload = false; + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (pProperties->watchdogTimeout < minTimeoutModeHeartbeat) { + // watchdogTimeout(in usec) less than 5000 would be computed to + // 0 milli seconds preempt timeout, and then after returning from + // this method, we would end up in EXCLUSIVE mode + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + result = setHeartbeatInterval(pProperties->watchdogTimeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + uint64_t timeout = (pProperties->watchdogTimeout) / 5; + result = setPreemptTimeout(timeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + uint64_t timeslice = 0; + result = setTimesliceDuration(timeslice); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + return result; +} + +ze_result_t LinuxSchedulerImp::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; + } + *pNeedReload = false; + + zes_sched_mode_t currMode; + ze_result_t result = getCurrentMode(&currMode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + if (currMode == ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG) { + // Unset this mode + result = disableComputeUnitDebugMode(pNeedReload); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + } + + result = setPreemptTimeout(pProperties->yieldTimeout); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + result = setTimesliceDuration(pProperties->interval); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + uint64_t heartbeat = 2500 * (pProperties->interval); + return setHeartbeatInterval(heartbeat); +} + ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProperties) { schedProperties.onSubdevice = onSubdevice; schedProperties.subdeviceId = subdeviceId; @@ -209,10 +387,63 @@ ze_bool_t LinuxSchedulerImp::canControlScheduler() { return 1; } +ze_result_t LinuxSchedulerImp::updateComputeUnitDebugNode(uint64_t val) { + // I915 will be reloaded if we toggle value of enableEuDebug + // Hence for gracefull handling close all i915 clients before toggling enableEuDebug + auto pDevice = pLinuxSysmanImp->getDeviceHandle(); + auto devicePtr = static_cast(pDevice); + NEO::ExecutionEnvironment *executionEnvironment = devicePtr->getNEODevice()->getExecutionEnvironment(); + auto restorer = std::make_unique(executionEnvironment); + pLinuxSysmanImp->releaseDeviceResources(); + ze_result_t result = pLinuxSysmanImp->gpuProcessCleanup(); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "updateComputeUnitDebugNode: gpuProcessCleanup() failed with error code: %ld\n", result); + return result; + } + result = pSysfsAccess->write(enableEuDebug, val); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "updateComputeUnitDebugNode: Write to sysfs node %s failed with error code: %ld\n", enableEuDebug.c_str(), result); + } + pLinuxSysmanImp->initDevice(); + return result; +} + ze_result_t LinuxSchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) { + auto result = setExclusiveModeImp(); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "setComputeUnitDebugMode: Exclusive mode set(precontiion to set Debug mode) failed. Error code: %ld\n", result); + return result; + } + *pNeedReload = false; uint64_t val = 1; - return pSysfsAccess->write(enableEuDebug, val); + auto ret = pSysfsAccess->canWrite(enableEuDebug); + if (ret != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "setComputeUnitDebugMode: sysfs node %s not writable. Error code: %ld\n", enableEuDebug.c_str(), result); + return ret; + } + return updateComputeUnitDebugNode(val); +} + +bool LinuxSchedulerImp::isComputeUnitDebugModeEnabled() { + uint64_t val = 0; + auto result = pSysfsAccess->read(enableEuDebug, val); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "isComputeUnitDebugModeEnabled: Read from sysfs node %s failed with error code: %ld\n", enableEuDebug.c_str(), result); + return false; + } + return (val == 0) ? false : true; +} + +ze_result_t LinuxSchedulerImp::disableComputeUnitDebugMode(ze_bool_t *pNeedReload) { + *pNeedReload = false; + uint64_t val = 0; + return updateComputeUnitDebugNode(val); } static ze_result_t getNumEngineTypeAndInstancesForSubDevices(std::map> &mapOfEngines, @@ -289,7 +520,7 @@ ze_result_t OsScheduler::getNumEngineTypeAndInstances( LinuxSchedulerImp::LinuxSchedulerImp( OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId) : engineType(type), onSubdevice(isSubdevice), subdeviceId(subdeviceId) { - LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + pLinuxSysmanImp = static_cast(pOsSysman); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); this->listOfEngines = listOfEngines; } diff --git a/level_zero/tools/source/sysman/scheduler/os_scheduler.h b/level_zero/tools/source/sysman/scheduler/os_scheduler.h index 03f9b20bb3..4c9103383f 100644 --- a/level_zero/tools/source/sysman/scheduler/os_scheduler.h +++ b/level_zero/tools/source/sysman/scheduler/os_scheduler.h @@ -18,14 +18,13 @@ using namespace std; class OsScheduler { public: + 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 *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; - virtual ze_result_t getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) = 0; - virtual ze_result_t getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) = 0; - virtual ze_result_t getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) = 0; - 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 ze_result_t getProperties(zes_sched_properties_t &properties) = 0; static OsScheduler *create(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId); diff --git a/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp b/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp index 2d91126645..940ba09e75 100644 --- a/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp +++ b/level_zero/tools/source/sysman/scheduler/scheduler_imp.cpp @@ -14,129 +14,31 @@ namespace L0 { 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; + return pOsScheduler->setExclusiveMode(pNeedReload); } ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) { - auto result = setExclusiveMode(pNeedReload); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - result = pOsScheduler->setComputeUnitDebugMode(pNeedReload); - return result; + return pOsScheduler->setComputeUnitDebugMode(pNeedReload); } ze_result_t SchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { - uint64_t timeout = 0; - uint64_t timeslice = 0; - ze_result_t result = pOsScheduler->getPreemptTimeout(timeout, false); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - result = pOsScheduler->getTimesliceDuration(timeslice, false); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - if (timeslice > 0) { - *pMode = ZES_SCHED_MODE_TIMESLICE; - } else { - if (timeout > 0) { - *pMode = ZES_SCHED_MODE_TIMEOUT; - } else { - *pMode = ZES_SCHED_MODE_EXCLUSIVE; - } - } - return result; + return pOsScheduler->getCurrentMode(pMode); } ze_result_t SchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) { - uint64_t heartbeat = 0; - ze_result_t result = pOsScheduler->getHeartbeatInterval(heartbeat, getDefaults); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - pConfig->watchdogTimeout = heartbeat; - - return result; + return pOsScheduler->getTimeoutModeProperties(getDefaults, pConfig); } ze_result_t SchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) { - uint64_t timeout = 0, timeslice = 0; - ze_result_t result = pOsScheduler->getPreemptTimeout(timeout, getDefaults); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - result = pOsScheduler->getTimesliceDuration(timeslice, getDefaults); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - pConfig->interval = timeslice; - pConfig->yieldTimeout = timeout; - return result; + return pOsScheduler->getTimesliceModeProperties(getDefaults, pConfig); } 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) { - return result; - } - - if (pProperties->watchdogTimeout < minTimeoutModeHeartbeat) { - // watchdogTimeout(in usec) less than 5000 would be computed to - // 0 milli seconds preempt timeout, and then after returning from - // this method, we would end up in EXCLUSIVE mode - return ZE_RESULT_ERROR_INVALID_ARGUMENT; - } - *pNeedReload = false; - result = pOsScheduler->setHeartbeatInterval(pProperties->watchdogTimeout); - if ((currMode == ZES_SCHED_MODE_TIMEOUT) || (result != ZE_RESULT_SUCCESS)) { - return result; - } - - uint64_t timeout = (pProperties->watchdogTimeout) / 5; - result = pOsScheduler->setPreemptTimeout(timeout); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - - uint64_t timeslice = 0; - result = pOsScheduler->setTimesliceDuration(timeslice); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - return result; + return pOsScheduler->setTimeoutMode(pProperties, pNeedReload); } 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; - } - *pNeedReload = false; - ze_result_t result = pOsScheduler->setPreemptTimeout(pProperties->yieldTimeout); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - result = pOsScheduler->setTimesliceDuration(pProperties->interval); - if (result != ZE_RESULT_SUCCESS) { - return result; - } - uint64_t heartbeat = 2500 * (pProperties->interval); - result = pOsScheduler->setHeartbeatInterval(heartbeat); - return result; + return pOsScheduler->setTimesliceMode(pProperties, pNeedReload); } ze_result_t SchedulerImp::schedulerGetProperties(zes_sched_properties_t *pProperties) { 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 f1dbb67a03..18ffe77dd9 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 @@ -11,34 +11,30 @@ namespace L0 { -ze_result_t WddmSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) { +ze_result_t WddmSchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_result_t WddmSchedulerImp::getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) { +ze_result_t WddmSchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_result_t WddmSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) { +ze_result_t WddmSchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_result_t WddmSchedulerImp::setPreemptTimeout(uint64_t timeout) { +ze_result_t WddmSchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_result_t WddmSchedulerImp::setTimesliceDuration(uint64_t timeslice) { +ze_result_t WddmSchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_result_t WddmSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) { +ze_result_t WddmSchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ze_bool_t WddmSchedulerImp::canControlScheduler() { - return 0; -} - ze_result_t WddmSchedulerImp::getProperties(zes_sched_properties_t &properties) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } 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 index c4e3250ac3..5cb9ebc327 100644 --- a/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h +++ b/level_zero/tools/source/sysman/scheduler/windows/os_scheduler_imp.h @@ -13,15 +13,14 @@ 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; + 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 *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; + 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_prelim.h b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler_prelim.h index b1a8398c9a..6a3d92a906 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler_prelim.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/mock_sysfs_scheduler_prelim.h @@ -183,7 +183,70 @@ class SchedulerFileProperties { } }; -class SchedulerSysfsAccess : public SysfsAccess {}; +class MockSchedulerProcfsAccess : public ProcfsAccess { + public: + MockSchedulerProcfsAccess() = default; + + const pid_t pid1 = 1234; + const pid_t pid2 = 1235; + const pid_t pid3 = 1236; + const pid_t pid4 = 1237; + + ze_result_t listProcessesResult = ZE_RESULT_SUCCESS; + ze_result_t listProcesses(std::vector<::pid_t> &list) override { + if (listProcessesResult != ZE_RESULT_SUCCESS) { + return listProcessesResult; + } + list.push_back(pid1); + list.push_back(pid2); + list.push_back(pid3); + list.push_back(pid4); + return ZE_RESULT_SUCCESS; + } + + ze_result_t getFileDescriptorsResult; + ze_result_t getFileDescriptors(const ::pid_t pid, std::vector &list) override { + // push dummy fd numbers in list vector + if (pid == pid1) { + list.push_back(1); + list.push_back(2); + } else if (pid == pid2) { + list.push_back(1); + list.push_back(2); + } else if (pid == pid3) { + list.push_back(1); + list.push_back(2); + } else if (pid == pid4) { + list.push_back(1); + list.push_back(3); + } + return ZE_RESULT_SUCCESS; + } + + ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val) override { + if (fd == 1) { + val = "/dev/null"; // assuming after opening /dev/null fd received is 1 + return ZE_RESULT_SUCCESS; + } + if (fd == 2) { + val = "/dev/dri/renderD128"; // assuming after opening /dev/dri/renderD128 fd received is 2 + return ZE_RESULT_SUCCESS; + } + if (fd == 3) { + val = "/dev/dummy"; // assuming after opening /dev/dummy fd received is 3 + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ::pid_t myProcessId() override { + return pid2; + } + + ADDMETHOD_NOBASE_VOIDRETURN(kill, (const ::pid_t pid)); +}; + +//class SchedulerSysfsAccess : public SysfsAccess {}; typedef struct SchedulerConfigValues { uint64_t defaultVal; @@ -197,10 +260,21 @@ typedef struct SchedulerConfig { uint64_t euDebugEnable; } SchedulerConfig_t; -struct MockSchedulerSysfsAccess : public SchedulerSysfsAccess { +class CalledTimesUpdate { + public: + CalledTimesUpdate(int &calledTimes) : calledTimesVar(calledTimes) {} + ~CalledTimesUpdate() { + calledTimesVar++; + } + + private: + int &calledTimesVar; +}; + +struct MockSchedulerSysfsAccess : public SysfsAccess { + using SysfsAccess::deviceNames; ze_result_t mockReadFileFailureError = ZE_RESULT_SUCCESS; - ze_result_t mockWriteFileStatus = ZE_RESULT_SUCCESS; ze_result_t mockGetScanDirEntryError = ZE_RESULT_SUCCESS; std::vector mockReadReturnValues{ZE_RESULT_SUCCESS, ZE_RESULT_SUCCESS, ZE_RESULT_SUCCESS, ZE_RESULT_ERROR_NOT_AVAILABLE}; @@ -252,6 +326,21 @@ struct MockSchedulerSysfsAccess : public SchedulerSysfsAccess { return ZE_RESULT_ERROR_UNKNOWN; } + ze_result_t canWrite(const std::string file) override { + SchedulerFileProperties fileProperties; + ze_result_t result = getFileProperties(file, fileProperties); + if (ZE_RESULT_SUCCESS == result) { + if (!fileProperties.getAvailability()) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + if (!fileProperties.hasMode(S_IWUSR)) { + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + } + return result; + } + return ZE_RESULT_ERROR_UNKNOWN; + } + ze_result_t read(const std::string file, uint64_t &val) override { if (mockReadReturnStatus == true) { @@ -350,10 +439,15 @@ struct MockSchedulerSysfsAccess : public SchedulerSysfsAccess { return ZE_RESULT_ERROR_NOT_AVAILABLE; } + int writeCalled = 0; + std::vector writeResult{ZE_RESULT_SUCCESS}; ze_result_t write(const std::string file, const uint64_t val) override { - - if (mockWriteFileStatus != ZE_RESULT_SUCCESS) { - return mockWriteFileStatus; + CalledTimesUpdate update(writeCalled); // increment this method's call count while exiting this method + if (writeCalled < static_cast(writeResult.size())) { + if (writeResult[writeCalled] != ZE_RESULT_SUCCESS) { + // If we are here, it means test simply wants to validate failure values from this method + return writeResult[writeCalled]; + } } if (mockGetValueForErrorWhileWrite == true) { @@ -499,8 +593,13 @@ struct MockSchedulerSysfsAccess : public SchedulerSysfsAccess { class PublicLinuxSchedulerImp : public L0::LinuxSchedulerImp { public: + using LinuxSchedulerImp::isComputeUnitDebugModeEnabled; using LinuxSchedulerImp::pDevice; using LinuxSchedulerImp::pSysfsAccess; + using LinuxSchedulerImp::setExclusiveModeImp; + using LinuxSchedulerImp::setHeartbeatInterval; + using LinuxSchedulerImp::setPreemptTimeout; + using LinuxSchedulerImp::setTimesliceDuration; using LinuxSchedulerImp::subdeviceId; }; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler_prelim.cpp b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler_prelim.cpp index cdbe0b72be..2a1957f625 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler_prelim.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/linux/test_zes_scheduler_prelim.cpp @@ -40,6 +40,7 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { std::unique_ptr pSysfsAccess; SysfsAccess *pSysfsAccessOld = nullptr; std::vector deviceHandles; + PublicLinuxSchedulerImp *pLinuxSchedulerImp = nullptr; void SetUp() override { if (!sysmanUltsEnable) { @@ -48,6 +49,7 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { SysmanDeviceFixture::SetUp(); pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess; pSysfsAccess = std::make_unique(); + pSysfsAccess->deviceNames = {"card0", "controlD64", "renderD128"}; pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { @@ -123,6 +125,16 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture { EXPECT_EQ(ZE_RESULT_SUCCESS, result); return config; } + + void setComputeUnitDebugModeMock(zes_sched_handle_t hScheduler) { + auto pSchedulerImp = static_cast(Scheduler::fromHandle(hScheduler)); + auto pOsScheduler = static_cast(pSchedulerImp->pOsScheduler); + + EXPECT_EQ(ZE_RESULT_SUCCESS, pOsScheduler->setExclusiveModeImp()); + uint64_t val = 1; + pSysfsAccess->write(enableEuDebug, val); + EXPECT_EQ(ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG, fixtureGetCurrentMode(hScheduler)); + } }; TEST_F(SysmanDeviceSchedulerFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumSchedulersAndSysfsCanReadReturnsErrorThenZeroCountIsReturned) { @@ -172,6 +184,19 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenSomeInvalidSchedulerModeWhenCheckingForCurrentModeThenAPIReportUnknownMode) { + auto handles = getSchedHandles(handleComponentCount); + auto pSchedulerImp = static_cast(Scheduler::fromHandle(handles[0])); + auto pOsScheduler = static_cast(pSchedulerImp->pOsScheduler); + uint64_t timeslice = 0, timeout = 0, heartbeat = 3000; + pOsScheduler->setPreemptTimeout(timeout); + pOsScheduler->setTimesliceDuration(timeslice); + pOsScheduler->setHeartbeatInterval(heartbeat); + zes_sched_mode_t mode; + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesSchedulerGetCurrentMode(handles[0], &mode)); + EXPECT_EQ(ZES_SCHED_MODE_FORCE_UINT32, mode); +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetTimeoutModePropertiesThenVerifyzesSchedulerGetTimeoutModePropertiesForDifferingValues) { auto handles = getSchedHandles(handleComponentCount); @@ -341,6 +366,50 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenCallingzesSchedulerSetTimeoutModeThenVerifyCallSucceeds) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + ze_bool_t needReboot; + zes_sched_timeout_properties_t setConfig; + setConfig.watchdogTimeout = 10000u; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesSchedulerSetTimeoutMode(handles[0], &setConfig, &needReboot)); + EXPECT_FALSE(needReboot); + auto getConfig = fixtureGetTimeoutModeProperties(handles[0], false); + EXPECT_EQ(getConfig.watchdogTimeout, setConfig.watchdogTimeout); + auto mode = fixtureGetCurrentMode(handles[0]); + EXPECT_EQ(mode, ZES_SCHED_MODE_TIMEOUT); + + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenSettingTimeoutModeAndDebugModeCantBeChangedThenVerifyCallFails) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + pMockSchedulerProcfsAccess->listProcessesResult = ZE_RESULT_ERROR_NOT_AVAILABLE; // Expect failure when calling gpuProcessCleanup() + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + ze_bool_t needReboot; + zes_sched_timeout_properties_t setConfig; + setConfig.watchdogTimeout = 10000u; + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zesSchedulerSetTimeoutMode(handles[0], &setConfig, &needReboot)); + EXPECT_FALSE(needReboot); + EXPECT_EQ(ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG, fixtureGetCurrentMode(handles[0])); + + delete pMockSchedulerProcfsAccess; +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimeoutModeWhenTimeoutLessThanMinimumThenVerifyzesSchedulerSetTimeoutModeCallFails) { auto handles = getSchedHandles(handleComponentCount); for (auto handle : handles) { @@ -369,15 +438,14 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimeoutModeWhenHeartBeatSettingFailsThenVerifyzesSchedulerSetTimeoutModeCallFails) { for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { - pSysfsAccess->setFileProperties(engineName, heartbeatIntervalMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + pSysfsAccess->setFileProperties(engineName, heartbeatIntervalMilliSecs, true, S_IRUSR | S_IRGRP | S_IROTH); }); auto handles = getSchedHandles(handleComponentCount); for (auto handle : handles) { ze_bool_t needReboot; zes_sched_timeout_properties_t setTimeOutConfig; setTimeOutConfig.watchdogTimeout = 10000u; - ze_result_t result = zesSchedulerSetTimeoutMode(handle, &setTimeOutConfig, &needReboot); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, zesSchedulerSetTimeoutMode(handle, &setTimeOutConfig, &needReboot)); } } @@ -444,6 +512,69 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenCallingzesSchedulerSetTimesliceModeThenVerifyCallSucceeds) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + ze_bool_t needReboot; + zes_sched_timeslice_properties_t setConfig; + setConfig.interval = 1000u; + setConfig.yieldTimeout = 1000u; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesSchedulerSetTimesliceMode(handles[0], &setConfig, &needReboot)); + EXPECT_FALSE(needReboot); + auto getConfig = fixtureGetTimesliceModeProperties(handles[0], false); + EXPECT_EQ(getConfig.interval, setConfig.interval); + EXPECT_EQ(getConfig.yieldTimeout, setConfig.yieldTimeout); + auto mode = fixtureGetCurrentMode(handles[0]); + EXPECT_EQ(mode, ZES_SCHED_MODE_TIMESLICE); + + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenSettingTimesliceModeAndDebugModeCantBeChangedThenVerifyCallFails) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + pMockSchedulerProcfsAccess->listProcessesResult = ZE_RESULT_ERROR_NOT_AVAILABLE; // Expect failure when calling gpuProcessCleanup() + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + ze_bool_t needReboot; + zes_sched_timeslice_properties_t setConfig; + setConfig.interval = 1000u; + setConfig.yieldTimeout = 1000u; + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zesSchedulerSetTimesliceMode(handles[0], &setConfig, &needReboot)); + EXPECT_FALSE(needReboot); + EXPECT_EQ(ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG, fixtureGetCurrentMode(handles[0])); + + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenGetCurrentModeFailsWhenCallingzesSchedulerSetTimesliceModeThenVerifyzesSchedulerSetTimesliceModeCallFails) { + for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), + [=](std::string engineName) { + pSysfsAccess->setFileProperties(engineName, preemptTimeoutMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + }); + auto handles = getSchedHandles(handleComponentCount); + for (auto handle : handles) { + ze_bool_t needReboot; + zes_sched_timeslice_properties_t setConfig; + setConfig.interval = 1000u; + setConfig.yieldTimeout = 1000u; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesSchedulerSetTimesliceMode(handle, &setConfig, &needReboot)); + EXPECT_FALSE(needReboot); + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimesliceModeWhenIntervalIsLessThanMinimumThenVerifyzesSchedulerSetTimesliceModeCallFails) { auto handles = getSchedHandles(handleComponentCount); for (auto handle : handles) { @@ -472,7 +603,7 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } -TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetTimesliceModeWhenNoAccessToHeartBeatIntervalThenVerifyzesSchedulerSetTimesliceModeCallFails) { +TEST_F(SysmanDeviceSchedulerFixture, GivenNoAccessToHeartBeatIntervalWhenSettingTimesliceModeThenThenVerifyzesSchedulerSetTimesliceModeCallFails) { for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { pSysfsAccess->setFileProperties(engineName, heartbeatIntervalMilliSecs, true, S_IRUSR | S_IRGRP | S_IROTH); @@ -488,7 +619,19 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } -TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetExclusiveModeThenVerifyzesSchedulerSetExclusiveModeCallSucceeds) { +TEST_F(SysmanDeviceSchedulerFixture, GivenHeartBeatIntervalFileNotPresentWhenSettingHeartbeatIntervalThenThenCallFails) { + for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), + [=](std::string engineName) { + pSysfsAccess->setFileProperties(engineName, heartbeatIntervalMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH); + }); + + auto handles = getSchedHandles(handleComponentCount); + auto pSchedulerImp = static_cast(Scheduler::fromHandle(handles[0])); + auto pOsScheduler = static_cast(pSchedulerImp->pOsScheduler); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsScheduler->setHeartbeatInterval(2000)); +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetExclusiveModeThenVerifyCallSucceeds) { auto handles = getSchedHandles(handleComponentCount); for (auto handle : handles) { ze_bool_t needReboot; @@ -500,6 +643,43 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenCallingzesSchedulerSetExclusiveModeThenVerifyCallSucceeds) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + ze_bool_t needReload; + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + EXPECT_EQ(ZE_RESULT_SUCCESS, zesSchedulerSetExclusiveMode(handles[0], &needReload)); + EXPECT_FALSE(needReload); + EXPECT_EQ(ZES_SCHED_MODE_EXCLUSIVE, fixtureGetCurrentMode(handles[0])); + + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenCurrentModeIsDebugModeWhenSettingExclusiveModeAndDebugModeCantBeChangedThenVerifyCallFails) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + pMockSchedulerProcfsAccess->listProcessesResult = ZE_RESULT_ERROR_NOT_AVAILABLE; // Expect failure when calling gpuProcessCleanup() + + // First set compute unit debug mode + auto handles = getSchedHandles(handleComponentCount); + ze_bool_t needReload; + setComputeUnitDebugModeMock(handles[0]); + + // Change mode to ZES_SCHED_MODE_EXCLUSIVE and validate + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zesSchedulerSetExclusiveMode(handles[0], &needReload)); + EXPECT_FALSE(needReload); + EXPECT_EQ(ZES_SCHED_MODE_COMPUTE_UNIT_DEBUG, fixtureGetCurrentMode(handles[0])); + + delete pMockSchedulerProcfsAccess; +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetExclusiveModeWhenPreEmptTimeoutNotAvailableThenVerifyzesSchedulerSetExclusiveModeCallFails) { for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { @@ -565,6 +745,19 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } } +TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetCurrentModeWhenHeartBeatIntervalNotAvailableThenFailureIsReturned) { + for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), + [=](std::string engineName) { + pSysfsAccess->setFileProperties(engineName, heartbeatIntervalMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + }); + auto handles = getSchedHandles(handleComponentCount); + for (auto handle : handles) { + zes_sched_mode_t mode; + ze_result_t result = zesSchedulerGetCurrentMode(handle, &mode); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + } +} + TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerGetCurrentModeWhenTimeSliceDurationHasNoPermissionThenFailureIsReturned) { for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { @@ -579,19 +772,79 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul } TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedulerSetComputeUnitDebugModeThenSuccessIsReturned) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + auto handles = getSchedHandles(handleComponentCount); uint64_t val = 0; pSysfsAccess->read(enableEuDebug, val); EXPECT_EQ(val, 0u); - for (auto handle : handles) { - ze_bool_t needReload; - val = 0; - pSysfsAccess->write(enableEuDebug, val); - ze_result_t result = zesSchedulerSetComputeUnitDebugMode(handle, &needReload); - EXPECT_EQ(ZE_RESULT_SUCCESS, result); - pSysfsAccess->read(enableEuDebug, val); - EXPECT_EQ(val, 1u); - } + + ze_bool_t needReload; + val = 0; + pSysfsAccess->write(enableEuDebug, val); + ze_result_t result = zesSchedulerSetComputeUnitDebugMode(handles[0], &needReload); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + pSysfsAccess->read(enableEuDebug, val); + EXPECT_EQ(val, 1u); + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenGpuProcessCleanupFailedWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorIsReturned) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + pMockSchedulerProcfsAccess->listProcessesResult = ZE_RESULT_ERROR_NOT_AVAILABLE; // Expect failure when calling gpuProcessCleanup() + + auto handles = getSchedHandles(handleComponentCount); + uint64_t val = 0; + pSysfsAccess->read(enableEuDebug, val); + EXPECT_EQ(val, 0u); + + ze_bool_t needReload; + val = 0; + pSysfsAccess->write(enableEuDebug, val); + ze_result_t result = zesSchedulerSetComputeUnitDebugMode(handles[0], &needReload); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result); + pSysfsAccess->read(enableEuDebug, val); + EXPECT_EQ(val, 0u); + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenEuDebugNodeWriteFailsWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorIsReturned) { + VariableBackup backup(&pLinuxSysmanImp->pProcfsAccess); + auto pMockSchedulerProcfsAccess = new MockSchedulerProcfsAccess; + pLinuxSysmanImp->pProcfsAccess = pMockSchedulerProcfsAccess; + + auto handles = getSchedHandles(handleComponentCount); + uint64_t val = 0; + pSysfsAccess->read(enableEuDebug, val); + EXPECT_EQ(val, 0u); + + ze_bool_t needReload; + val = 0; + pSysfsAccess->write(enableEuDebug, val); + pSysfsAccess->writeCalled = 0; // Lets initialize write methods call times to zero from this point for this test + pSysfsAccess->writeResult.clear(); // Initialize write Results + pSysfsAccess->writeResult.push_back(ZE_RESULT_SUCCESS); // This write call would be success for setting exclusive mode + pSysfsAccess->writeResult.push_back(ZE_RESULT_SUCCESS); // This write call would be success for setting exclusive mode + pSysfsAccess->writeResult.push_back(ZE_RESULT_SUCCESS); // This write call would be success for setting exclusive mode + pSysfsAccess->writeResult.push_back(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE); // Failure while writing eu debug enable node + ze_result_t result = zesSchedulerSetComputeUnitDebugMode(handles[0], &needReload); + EXPECT_EQ(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE, result); + pSysfsAccess->read(enableEuDebug, val); + EXPECT_EQ(val, 0u); + delete pMockSchedulerProcfsAccess; +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenNodeRequiredToEnableEuDebugNotPresentWhenCheckingForDebugModeThenCallReturnsFalse) { + auto handles = getSchedHandles(handleComponentCount); + auto pSchedulerImp = static_cast(Scheduler::fromHandle(handles[0])); + auto pOsScheduler = static_cast(pSchedulerImp->pOsScheduler); + std::string dummy; + pSysfsAccess->setFileProperties(dummy, enableEuDebug, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + EXPECT_FALSE(pOsScheduler->isComputeUnitDebugModeEnabled()); } TEST_F(SysmanDeviceSchedulerFixture, GivenPrelimEnableEuDebugNodeNotAvailableWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorReturned) { @@ -605,7 +858,22 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenPrelimEnableEuDebugNodeNotAvailableWhe } } -TEST_F(SysmanDeviceSchedulerFixture, GivenExclusiveModeSetFailWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorReturned) { +TEST_F(SysmanDeviceSchedulerFixture, GivenExclusiveModeSetFailWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorReturned1) { + // Fail exclusive mode set due to preemptTimeoutMilliSecs file not available + for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), + [=](std::string engineName) { + pSysfsAccess->setFileProperties(engineName, preemptTimeoutMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + }); + auto handles = getSchedHandles(handleComponentCount); + for (auto handle : handles) { + ze_bool_t needReload; + ze_result_t result = zesSchedulerSetComputeUnitDebugMode(handle, &needReload); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + } +} + +TEST_F(SysmanDeviceSchedulerFixture, GivenExclusiveModeSetFailWhenCallingzesSchedulerSetComputeUnitDebugModeThenErrorReturned2) { + // Fail exclusive mode set due to timesliceDurationMilliSecs file not available for_each(listOfMockedEngines.begin(), listOfMockedEngines.end(), [=](std::string engineName) { pSysfsAccess->setFileProperties(engineName, timesliceDurationMilliSecs, false, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); @@ -668,7 +936,9 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul setConfig.interval = 1000u; setConfig.yieldTimeout = 1000u; - pSysfsAccess->mockWriteFileStatus = ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + pSysfsAccess->writeCalled = 0; // Lets initialize write methods call times to zero from this point for this test + pSysfsAccess->writeResult.clear(); // Initialize write Results + pSysfsAccess->writeResult.push_back(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS); ze_result_t result = zesSchedulerSetTimesliceMode(handle, &setConfig, &needReboot); EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result); diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/CMakelists.txt b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/CMakelists.txt index 50da5b7de8..63761e85d0 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/CMakelists.txt +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/CMakelists.txt @@ -9,6 +9,5 @@ if(WIN32) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_sysman_scheduler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/mock_zes_sysman_scheduler.h ) endif() \ No newline at end of file diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/mock_zes_sysman_scheduler.h b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/mock_zes_sysman_scheduler.h deleted file mode 100644 index a5471632f5..0000000000 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/mock_zes_sysman_scheduler.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2022 Intel Corporation - * - * SPDX-License-Identifier: MIT - * - */ - -#pragma once -#include "level_zero/tools/source/sysman/scheduler/os_scheduler.h" -#include "level_zero/tools/source/sysman/scheduler/scheduler_imp.h" -#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_sysman_fixture.h" - -namespace L0 { -namespace ult { - -struct OsSchedulerMock : public OsScheduler { - - OsSchedulerMock() = default; - - ADDMETHOD_NOBASE(setComputeUnitDebugMode, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (ze_bool_t * pNeedReload)); - ADDMETHOD_NOBASE(getPreemptTimeout, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t & timeout, ze_bool_t getDefault)); - ADDMETHOD_NOBASE(getTimesliceDuration, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t & timeslice, ze_bool_t getDefault)); - ADDMETHOD_NOBASE(getHeartbeatInterval, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t & heartbeat, ze_bool_t getDefault)); - ADDMETHOD_NOBASE(setPreemptTimeout, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t timeout)); - ADDMETHOD_NOBASE(setTimesliceDuration, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t timeslice)); - ADDMETHOD_NOBASE(setHeartbeatInterval, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (uint64_t heartbeat)); - ADDMETHOD_NOBASE(canControlScheduler, ze_bool_t, false, ()); - ADDMETHOD_NOBASE(getProperties, ze_result_t, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, (zes_sched_properties_t & properties)); -}; - -} // namespace ult -} // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/test_zes_sysman_scheduler.cpp b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/test_zes_sysman_scheduler.cpp index 4b883f2aa2..f55bbb3fc4 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/test_zes_sysman_scheduler.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/test_zes_sysman_scheduler.cpp @@ -5,7 +5,9 @@ * */ -#include "level_zero/tools/test/unit_tests/sources/sysman/scheduler/windows/mock_zes_sysman_scheduler.h" +#include "level_zero/tools/source/sysman/scheduler/os_scheduler.h" +#include "level_zero/tools/source/sysman/scheduler/scheduler_imp.h" +#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_sysman_fixture.h" extern bool sysmanUltsEnable; @@ -16,7 +18,6 @@ namespace ult { class ZesSchedulerFixture : public SysmanDeviceFixture { protected: - std::unique_ptr pOsSchedulerMock; FirmwareUtil *pFwUtilInterfaceOld = nullptr; void SetUp() override { @@ -39,38 +40,64 @@ TEST_F(ZesSchedulerFixture, GivenComponentCountZeroWhenQueryingSchedulerHandlesT EXPECT_EQ(count, 0u); } -TEST_F(ZesSchedulerFixture, GivenSetExclusiveModeNotFailWhenTryingToSetComputeUnitDebugModeThenErrorIsReturned) { +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenGettingCurrentModeThenErrorIsReturned) { std::vector listOfEngines = {"rcs0"}; auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); - auto pOsSchedulerBackup = pSchedulerImp->pOsScheduler; - auto pOsSchedulerMock = new OsSchedulerMock(); - pSchedulerImp->pOsScheduler = pOsSchedulerMock; - ze_bool_t pNeedReload = false; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setComputeUnitDebugMode(&pNeedReload)); - pSchedulerImp->pOsScheduler = pOsSchedulerBackup; - delete pOsSchedulerMock; + zes_sched_mode_t mode; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->getCurrentMode(&mode)); } -TEST_F(ZesSchedulerFixture, GivenSetExclusiveModeNotSuccessWhenTryingToSetComputeUnitDebugModeThenErrorIsReturned) { +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenGettingTimeoutModePropertiesThenErrorIsReturned) { std::vector listOfEngines = {"rcs0"}; auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); - auto pOsSchedulerBackup = pSchedulerImp->pOsScheduler; - auto pOsSchedulerMock = new OsSchedulerMock(); - pOsSchedulerMock->setPreemptTimeoutResult = ZE_RESULT_SUCCESS; - pOsSchedulerMock->setTimesliceDurationResult = ZE_RESULT_SUCCESS; - pOsSchedulerMock->setHeartbeatIntervalResult = ZE_RESULT_SUCCESS; - pSchedulerImp->pOsScheduler = pOsSchedulerMock; - ze_bool_t pNeedReload = false; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setComputeUnitDebugMode(&pNeedReload)); - pSchedulerImp->pOsScheduler = pOsSchedulerBackup; - delete pOsSchedulerMock; + ze_bool_t getDefaults = 0; + zes_sched_timeout_properties_t config; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->getTimeoutModeProperties(getDefaults, &config)); } -TEST_F(ZesSchedulerFixture, whenCallingOsSpecificSetComputeUnitDebugModeThenErrorIsReturned) { +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenGettingTimesliceModePropertiesThenErrorIsReturned) { std::vector listOfEngines = {"rcs0"}; auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); - ze_bool_t pNeedReload = false; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->pOsScheduler->setComputeUnitDebugMode(&pNeedReload)); + ze_bool_t getDefaults = 0; + zes_sched_timeslice_properties_t config; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->getTimesliceModeProperties(getDefaults, &config)); +} + +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenSettingTimeoutModeThenErrorIsReturned) { + std::vector listOfEngines = {"rcs0"}; + auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); + zes_sched_timeout_properties_t properties; + ze_bool_t needReload; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setTimeoutMode(&properties, &needReload)); +} + +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenSettingTimesliceModeThenErrorIsReturned) { + std::vector listOfEngines = {"rcs0"}; + auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); + zes_sched_timeslice_properties_t properties; + ze_bool_t needReload; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setTimesliceMode(&properties, &needReload)); +} + +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenSettingExclusiveModeThenErrorIsReturned) { + std::vector listOfEngines = {"rcs0"}; + auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); + ze_bool_t needReload; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setExclusiveMode(&needReload)); +} + +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenSettingDebugModeThenErrorIsReturned) { + std::vector listOfEngines = {"rcs0"}; + auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); + ze_bool_t needReload; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pSchedulerImp->setComputeUnitDebugMode(&needReload)); +} + +TEST_F(ZesSchedulerFixture, GivenValidDeviceHandleWhenGettingSchedulerPropertiesThenSuccessIsReturned) { + std::vector listOfEngines = {"rcs0"}; + auto pSchedulerImp = std::make_unique(pOsSysman, ZES_ENGINE_TYPE_FLAG_RENDER, listOfEngines, device->toHandle()); + zes_sched_properties_t properties; + EXPECT_EQ(ZE_RESULT_SUCCESS, pSchedulerImp->schedulerGetProperties(&properties)); } } // namespace ult