Implement scheduler APIs

Add logic to implement following scheduler APIs
-zetSysmanSchedulerGetCurrentMode
-zetSysmanSchedulerGetTimeoutModeProperties
-zetSysmanSchedulerGetTimesliceModeProperties
-zetSysmanSchedulerSetTimeoutMode
-zetSysmanSchedulerSetTimesliceMode
-zetSysmanSchedulerSetExclusiveMode

Change-Id: I134b200ffd6b13bc50b1f38e955dd584455b4b38
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2020-04-15 13:16:36 +05:30
parent 49f2a5157a
commit 5374a0ffc1
12 changed files with 312 additions and 41 deletions

View File

@@ -360,6 +360,24 @@ ze_result_t SysfsAccess::read(const std::string file, double &val) {
return ZE_RESULT_SUCCESS;
}
ze_result_t SysfsAccess::read(const std::string file, uint64_t &val) {
std::string str;
ze_result_t result;
result = FsAccess::read(fullPath(file), str);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
std::istringstream stream(str);
stream >> val;
if (stream.fail()) {
return ZE_RESULT_ERROR_UNKNOWN;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t SysfsAccess::read(const std::string file, std::vector<std::string> &val) {
// Prepend sysfs directory path and call the base read
return FsAccess::read(fullPath(file), val);
@@ -390,6 +408,16 @@ ze_result_t SysfsAccess::write(const std::string file, const double val) {
return FsAccess::write(fullPath(file), stream.str());
}
ze_result_t SysfsAccess::write(const std::string file, const uint64_t val) {
std::ostringstream stream;
stream << val;
if (stream.fail()) {
return ZE_RESULT_ERROR_UNKNOWN;
}
return FsAccess::write(fullPath(file), stream.str());
}
ze_result_t SysfsAccess::readSymLink(const std::string path, std::string &val) {
// Prepend sysfs directory path and call the base readSymLink
return FsAccess::readSymLink(fullPath(path).c_str(), val);

View File

@@ -79,11 +79,13 @@ class SysfsAccess : private FsAccess {
ze_result_t read(const std::string file, std::string &val);
ze_result_t read(const std::string file, int &val);
ze_result_t read(const std::string file, uint64_t &val);
ze_result_t read(const std::string file, double &val);
ze_result_t read(const std::string file, std::vector<std::string> &val);
ze_result_t write(const std::string file, const std::string val);
ze_result_t write(const std::string file, const int val);
ze_result_t write(const std::string file, const uint64_t val);
ze_result_t write(const std::string file, const double val);
ze_result_t readSymLink(const std::string path, std::string &buf);

View File

@@ -9,22 +9,75 @@
#include "sysman/scheduler/scheduler_imp.h"
namespace L0 {
class LinuxSchedulerImp : public OsScheduler {
// Following below mappings of scheduler properties with sysfs nodes
// zet_sched_timeslice_properties_t.interval = timeslice_duration_ms
// zet_sched_timeslice_properties_t.yieldTimeout = preempt_timeout_ms
// zet_sched_timeout_properties_t. watchdogTimeout = heartbeat_interval_ms
class LinuxSchedulerImp : public NEO::NonCopyableClass, public OsScheduler {
public:
ze_result_t getPreemptTimeout(uint64_t &timeout) override;
ze_result_t getTimesliceDuration(uint64_t &timeslice) override;
ze_result_t getHeartbeatInterval(uint64_t &heartbeat) 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;
LinuxSchedulerImp(OsSysman *pOsSysman);
~LinuxSchedulerImp() override = default;
// Don't allow copies of the LinuxSchedulerImp object
LinuxSchedulerImp(const LinuxSchedulerImp &obj) = delete;
LinuxSchedulerImp &operator=(const LinuxSchedulerImp &obj) = delete;
private:
SysfsAccess *pSysfsAccess;
static const std::string preemptTimeoutMilliSecs;
static const std::string timesliceDurationMilliSecs;
static const std::string heartbeatIntervalMilliSecs;
};
const std::string LinuxSchedulerImp::preemptTimeoutMilliSecs("vcs0/preempt_timeout_ms");
const std::string LinuxSchedulerImp::timesliceDurationMilliSecs("vcs0/timeslice_duration_ms");
const std::string LinuxSchedulerImp::heartbeatIntervalMilliSecs("vcs0/heartbeat_interval_ms");
constexpr uint16_t milliSecsToMicroSecs = 1000;
ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout) {
ze_result_t result = pSysfsAccess->read(preemptTimeoutMilliSecs, timeout);
if (result == ZE_RESULT_SUCCESS) {
timeout = timeout * milliSecsToMicroSecs;
}
return result;
}
ze_result_t LinuxSchedulerImp::getTimesliceDuration(uint64_t &timeslice) {
ze_result_t result = pSysfsAccess->read(timesliceDurationMilliSecs, timeslice);
if (result == ZE_RESULT_SUCCESS) {
timeslice = timeslice * milliSecsToMicroSecs;
}
return result;
}
ze_result_t LinuxSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat) {
ze_result_t result = pSysfsAccess->read(heartbeatIntervalMilliSecs, heartbeat);
if (result == ZE_RESULT_SUCCESS) {
heartbeat = heartbeat * milliSecsToMicroSecs;
}
return result;
}
ze_result_t LinuxSchedulerImp::setPreemptTimeout(uint64_t timeout) {
timeout = timeout / milliSecsToMicroSecs;
return pSysfsAccess->write(preemptTimeoutMilliSecs, timeout);
}
ze_result_t LinuxSchedulerImp::setTimesliceDuration(uint64_t timeslice) {
timeslice = timeslice / milliSecsToMicroSecs;
return pSysfsAccess->write(timesliceDurationMilliSecs, timeslice);
}
ze_result_t LinuxSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) {
heartbeat = heartbeat / milliSecsToMicroSecs;
return pSysfsAccess->write(heartbeatIntervalMilliSecs, heartbeat);
}
LinuxSchedulerImp::LinuxSchedulerImp(OsSysman *pOsSysman) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
}

View File

@@ -12,8 +12,14 @@ namespace L0 {
struct OsSysman;
class OsScheduler {
public:
virtual ze_result_t getPreemptTimeout(uint64_t &timeout) = 0;
virtual ze_result_t getTimesliceDuration(uint64_t &timeslice) = 0;
virtual ze_result_t getHeartbeatInterval(uint64_t &heartbeat) = 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;
static OsScheduler *create(OsSysman *pOsSysman);
virtual ~OsScheduler() {}
virtual ~OsScheduler() = default;
};
} // namespace L0

View File

@@ -20,7 +20,7 @@ class Scheduler {
virtual ze_result_t setTimesliceMode(zet_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) = 0;
virtual ze_result_t setExclusiveMode(ze_bool_t *pNeedReboot) = 0;
virtual ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReboot) = 0;
virtual void init() = 0;
virtual ze_result_t init() = 0;
};
} // namespace L0

View File

@@ -12,38 +12,161 @@
namespace L0 {
ze_result_t SchedulerImp::getCurrentMode(zet_sched_mode_t *pMode) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
uint64_t timeout = 0;
uint64_t timeslice = 0;
ze_result_t result = pOsScheduler->getPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->getTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
if (timeslice != 0) {
*pMode = ZET_SCHED_MODE_TIMESLICE;
} else {
if (timeout > 0) {
*pMode = ZET_SCHED_MODE_TIMEOUT;
} else {
*pMode = ZET_SCHED_MODE_EXCLUSIVE;
}
}
return result;
}
ze_result_t SchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zet_sched_timeout_properties_t *pConfig) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
if (getDefaults) {
pConfig->watchdogTimeout = defaultHeartbeat;
return ZE_RESULT_SUCCESS;
}
uint64_t heartbeat = 0;
ze_result_t result = pOsScheduler->getHeartbeatInterval(heartbeat);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
pConfig->watchdogTimeout = heartbeat;
return result;
}
ze_result_t SchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zet_sched_timeslice_properties_t *pConfig) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
if (getDefaults) {
pConfig->interval = defaultTimeslice;
pConfig->yieldTimeout = defaultPreemptTimeout;
return ZE_RESULT_SUCCESS;
}
uint64_t timeout = 0, timeslice = 0;
ze_result_t result = pOsScheduler->getPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->getTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
pConfig->interval = timeslice;
pConfig->yieldTimeout = timeout;
return result;
}
ze_result_t SchedulerImp::setTimeoutMode(zet_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReboot) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
zet_sched_mode_t currMode;
ze_result_t result = getCurrentMode(&currMode);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
if (pProperties->watchdogTimeout < 5000) {
// 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;
}
*pNeedReboot = false;
result = pOsScheduler->setHeartbeatInterval(pProperties->watchdogTimeout);
if ((currMode == ZET_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;
}
ze_result_t SchedulerImp::setTimesliceMode(zet_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
if (pProperties->interval < 1) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
*pNeedReboot = 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;
}
ze_result_t SchedulerImp::setExclusiveMode(ze_bool_t *pNeedReboot) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
uint64_t timeslice = 0, timeout = 0, heartbeat = 0;
*pNeedReboot = false;
ze_result_t result = pOsScheduler->setPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setHeartbeatInterval(heartbeat);
return result;
}
ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReboot) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
void SchedulerImp::init() {
ze_result_t SchedulerImp::init() {
if (pOsScheduler == nullptr) {
pOsScheduler = OsScheduler::create(pOsSysman);
}
UNRECOVERABLE_IF(nullptr == pOsScheduler);
if (nullptr == pOsScheduler) {
return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
uint64_t timeout = 0;
uint64_t timeslice = 0;
uint64_t heartbeat = 0;
ze_result_t result = pOsScheduler->getPreemptTimeout(timeout);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->getTimesliceDuration(timeslice);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->getHeartbeatInterval(heartbeat);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
defaultPreemptTimeout = timeout;
defaultTimeslice = timeslice;
defaultHeartbeat = heartbeat;
return result;
}
SchedulerImp::~SchedulerImp() {

View File

@@ -6,6 +6,8 @@
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include <level_zero/zet_api.h>
#include "os_scheduler.h"
@@ -13,9 +15,9 @@
namespace L0 {
class SchedulerImp : public Scheduler {
class SchedulerImp : public NEO::NonCopyableClass, public Scheduler {
public:
void init() override;
ze_result_t init() override;
ze_result_t getCurrentMode(zet_sched_mode_t *pMode) override;
ze_result_t getTimeoutModeProperties(ze_bool_t getDefaults, zet_sched_timeout_properties_t *pConfig) override;
ze_result_t getTimesliceModeProperties(ze_bool_t getDefaults, zet_sched_timeslice_properties_t *pConfig) override;
@@ -24,15 +26,16 @@ class SchedulerImp : public Scheduler {
ze_result_t setExclusiveMode(ze_bool_t *pNeedReboot) override;
ze_result_t setComputeUnitDebugMode(ze_bool_t *pNeedReboot) override;
SchedulerImp() = default;
OsScheduler *pOsScheduler = nullptr;
SchedulerImp(OsSysman *pOsSysman) : pOsSysman(pOsSysman) { pOsScheduler = nullptr; };
~SchedulerImp() override;
// Don't allow copies of the SchedulerImp object
SchedulerImp(const SchedulerImp &obj) = delete;
SchedulerImp &operator=(const SchedulerImp &obj) = delete;
private:
OsSysman *pOsSysman;
OsScheduler *pOsScheduler;
OsSysman *pOsSysman = nullptr;
uint64_t defaultPreemptTimeout = 0;
uint64_t defaultTimeslice = 0;
uint64_t defaultHeartbeat = 0;
};
} // namespace L0

View File

@@ -5,11 +5,43 @@
*
*/
#include "level_zero/tools/source/sysman/scheduler/os_scheduler.h"
#include "sysman/scheduler/os_scheduler.h"
namespace L0 {
class WddmSchedulerImp : public OsScheduler {};
class WddmSchedulerImp : public OsScheduler {
public:
ze_result_t getPreemptTimeout(uint64_t &timeout) override;
ze_result_t getTimesliceDuration(uint64_t &timeslice) override;
ze_result_t getHeartbeatInterval(uint64_t &heartbeat) 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_result_t WddmSchedulerImp::getPreemptTimeout(uint64_t &timeout) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmSchedulerImp::getTimesliceDuration(uint64_t &timeslice) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmSchedulerImp::setPreemptTimeout(uint64_t timeout) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmSchedulerImp::setTimesliceDuration(uint64_t timeslice) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
OsScheduler *OsScheduler::create(OsSysman *pOsSysman) {
WddmSchedulerImp *pWddmSchedulerImp = new WddmSchedulerImp();

View File

@@ -81,7 +81,10 @@ void SysmanImp::init() {
pPci->init();
}
if (pSched) {
pSched->init();
if (pSched->init() != ZE_RESULT_SUCCESS) {
delete pSched;
pSched = nullptr;
}
}
if (pSysmanDevice) {
pSysmanDevice->init();
@@ -93,31 +96,52 @@ ze_result_t SysmanImp::deviceGetProperties(zet_sysman_properties_t *pProperties)
}
ze_result_t SysmanImp::schedulerGetCurrentMode(zet_sched_mode_t *pMode) {
if (pSched) {
return pSched->getCurrentMode(pMode);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerGetTimeoutModeProperties(ze_bool_t getDefaults, zet_sched_timeout_properties_t *pConfig) {
if (pSched) {
return pSched->getTimeoutModeProperties(getDefaults, pConfig);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerGetTimesliceModeProperties(ze_bool_t getDefaults, zet_sched_timeslice_properties_t *pConfig) {
if (pSched) {
return pSched->getTimesliceModeProperties(getDefaults, pConfig);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerSetTimeoutMode(zet_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReboot) {
if (pSched) {
return pSched->setTimeoutMode(pProperties, pNeedReboot);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerSetTimesliceMode(zet_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReboot) {
if (pSched) {
return pSched->setTimesliceMode(pProperties, pNeedReboot);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerSetExclusiveMode(ze_bool_t *pNeedReboot) {
if (pSched) {
return pSched->setExclusiveMode(pNeedReboot);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::schedulerSetComputeUnitDebugMode(ze_bool_t *pNeedReboot) {
if (pSched) {
return pSched->setComputeUnitDebugMode(pNeedReboot);
}
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t SysmanImp::processesGetState(uint32_t *pCount, zet_process_state_t *pProcesses) {