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