/* * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "scheduler_imp.h" #include "shared/source/helpers/debug_helpers.h" #include "level_zero/tools/source/sysman/sysman_const.h" 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; } ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } ze_result_t SchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { uint64_t timeout = 0; uint64_t timeslice = 0; 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; } 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; } 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; } 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; } 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; } ze_result_t SchedulerImp::schedulerGetProperties(zes_sched_properties_t *pProperties) { *pProperties = properties; return ZE_RESULT_SUCCESS; } void SchedulerImp::init() { pOsScheduler->getProperties(this->properties); } SchedulerImp::SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector &listOfEngines, ze_device_handle_t deviceHandle) { ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); pOsScheduler = OsScheduler::create(pOsSysman, engineType, listOfEngines, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId); UNRECOVERABLE_IF(nullptr == pOsScheduler); init(); }; SchedulerImp::~SchedulerImp() { if (nullptr != pOsScheduler) { delete pOsScheduler; pOsScheduler = nullptr; } } } // namespace L0