1 /*
2 * Copyright (C) 2020-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "scheduler_imp.h"
9
10 #include "shared/source/helpers/debug_helpers.h"
11
12 #include "level_zero/tools/source/sysman/sysman_const.h"
13
14 namespace L0 {
15
setExclusiveMode(ze_bool_t * pNeedReload)16 ze_result_t SchedulerImp::setExclusiveMode(ze_bool_t *pNeedReload) {
17 uint64_t timeslice = 0, timeout = 0, heartbeat = 0;
18 *pNeedReload = false;
19 ze_result_t result = pOsScheduler->setPreemptTimeout(timeout);
20 if (result != ZE_RESULT_SUCCESS) {
21 return result;
22 }
23 result = pOsScheduler->setTimesliceDuration(timeslice);
24 if (result != ZE_RESULT_SUCCESS) {
25 return result;
26 }
27 result = pOsScheduler->setHeartbeatInterval(heartbeat);
28 return result;
29 }
30
setComputeUnitDebugMode(ze_bool_t * pNeedReload)31 ze_result_t SchedulerImp::setComputeUnitDebugMode(ze_bool_t *pNeedReload) {
32 return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
33 }
34
getCurrentMode(zes_sched_mode_t * pMode)35 ze_result_t SchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) {
36 uint64_t timeout = 0;
37 uint64_t timeslice = 0;
38 ze_result_t result = pOsScheduler->getPreemptTimeout(timeout, false);
39 if (result != ZE_RESULT_SUCCESS) {
40 return result;
41 }
42 result = pOsScheduler->getTimesliceDuration(timeslice, false);
43 if (result != ZE_RESULT_SUCCESS) {
44 return result;
45 }
46 if (timeslice > 0) {
47 *pMode = ZES_SCHED_MODE_TIMESLICE;
48 } else {
49 if (timeout > 0) {
50 *pMode = ZES_SCHED_MODE_TIMEOUT;
51 } else {
52 *pMode = ZES_SCHED_MODE_EXCLUSIVE;
53 }
54 }
55 return result;
56 }
57
getTimeoutModeProperties(ze_bool_t getDefaults,zes_sched_timeout_properties_t * pConfig)58 ze_result_t SchedulerImp::getTimeoutModeProperties(ze_bool_t getDefaults, zes_sched_timeout_properties_t *pConfig) {
59 uint64_t heartbeat = 0;
60 ze_result_t result = pOsScheduler->getHeartbeatInterval(heartbeat, getDefaults);
61 if (result != ZE_RESULT_SUCCESS) {
62 return result;
63 }
64 pConfig->watchdogTimeout = heartbeat;
65
66 return result;
67 }
68
getTimesliceModeProperties(ze_bool_t getDefaults,zes_sched_timeslice_properties_t * pConfig)69 ze_result_t SchedulerImp::getTimesliceModeProperties(ze_bool_t getDefaults, zes_sched_timeslice_properties_t *pConfig) {
70 uint64_t timeout = 0, timeslice = 0;
71 ze_result_t result = pOsScheduler->getPreemptTimeout(timeout, getDefaults);
72 if (result != ZE_RESULT_SUCCESS) {
73 return result;
74 }
75 result = pOsScheduler->getTimesliceDuration(timeslice, getDefaults);
76 if (result != ZE_RESULT_SUCCESS) {
77 return result;
78 }
79 pConfig->interval = timeslice;
80 pConfig->yieldTimeout = timeout;
81 return result;
82 }
83
setTimeoutMode(zes_sched_timeout_properties_t * pProperties,ze_bool_t * pNeedReload)84 ze_result_t SchedulerImp::setTimeoutMode(zes_sched_timeout_properties_t *pProperties, ze_bool_t *pNeedReload) {
85 zes_sched_mode_t currMode;
86 ze_result_t result = getCurrentMode(&currMode);
87 if (result != ZE_RESULT_SUCCESS) {
88 return result;
89 }
90
91 if (pProperties->watchdogTimeout < minTimeoutModeHeartbeat) {
92 // watchdogTimeout(in usec) less than 5000 would be computed to
93 // 0 milli seconds preempt timeout, and then after returning from
94 // this method, we would end up in EXCLUSIVE mode
95 return ZE_RESULT_ERROR_INVALID_ARGUMENT;
96 }
97 *pNeedReload = false;
98 result = pOsScheduler->setHeartbeatInterval(pProperties->watchdogTimeout);
99 if ((currMode == ZES_SCHED_MODE_TIMEOUT) || (result != ZE_RESULT_SUCCESS)) {
100 return result;
101 }
102
103 uint64_t timeout = (pProperties->watchdogTimeout) / 5;
104 result = pOsScheduler->setPreemptTimeout(timeout);
105 if (result != ZE_RESULT_SUCCESS) {
106 return result;
107 }
108
109 uint64_t timeslice = 0;
110 result = pOsScheduler->setTimesliceDuration(timeslice);
111 if (result != ZE_RESULT_SUCCESS) {
112 return result;
113 }
114 return result;
115 }
116
setTimesliceMode(zes_sched_timeslice_properties_t * pProperties,ze_bool_t * pNeedReload)117 ze_result_t SchedulerImp::setTimesliceMode(zes_sched_timeslice_properties_t *pProperties, ze_bool_t *pNeedReload) {
118 if (pProperties->interval < minTimeoutInMicroSeconds) {
119 // interval(in usec) less than 1000 would be computed to
120 // 0 milli seconds interval.
121 return ZE_RESULT_ERROR_INVALID_ARGUMENT;
122 }
123 *pNeedReload = false;
124 ze_result_t result = pOsScheduler->setPreemptTimeout(pProperties->yieldTimeout);
125 if (result != ZE_RESULT_SUCCESS) {
126 return result;
127 }
128 result = pOsScheduler->setTimesliceDuration(pProperties->interval);
129 if (result != ZE_RESULT_SUCCESS) {
130 return result;
131 }
132 uint64_t heartbeat = 2500 * (pProperties->interval);
133 result = pOsScheduler->setHeartbeatInterval(heartbeat);
134 return result;
135 }
136
schedulerGetProperties(zes_sched_properties_t * pProperties)137 ze_result_t SchedulerImp::schedulerGetProperties(zes_sched_properties_t *pProperties) {
138 *pProperties = properties;
139 return ZE_RESULT_SUCCESS;
140 }
141
init()142 void SchedulerImp::init() {
143 pOsScheduler->getProperties(this->properties);
144 }
145
SchedulerImp(OsSysman * pOsSysman,zes_engine_type_flag_t engineType,std::vector<std::string> & listOfEngines,ze_device_handle_t deviceHandle)146 SchedulerImp::SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines, ze_device_handle_t deviceHandle) {
147 ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES};
148 Device::fromHandle(deviceHandle)->getProperties(&deviceProperties);
149 pOsScheduler = OsScheduler::create(pOsSysman, engineType, listOfEngines,
150 deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId);
151 UNRECOVERABLE_IF(nullptr == pOsScheduler);
152 init();
153 };
154
~SchedulerImp()155 SchedulerImp::~SchedulerImp() {
156 if (nullptr != pOsScheduler) {
157 delete pOsScheduler;
158 pOsScheduler = nullptr;
159 }
160 }
161
162 } // namespace L0
163