1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/*
* Copyright (C) 2020-2022 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) {
auto result = setExclusiveMode(pNeedReload);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = pOsScheduler->setComputeUnitDebugMode(pNeedReload);
return result;
}
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<std::string> &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
|