| 162 | } |
| 163 | |
| 164 | void LaunchWorker::LaunchHwCommand(std::shared_ptr<HwCommand> hw_cmd) |
| 165 | { |
| 166 | XDEBG("launch hw_cmd (%p) idx " FMT_64D, hw_cmd.get(), hw_cmd->GetIdx()); |
| 167 | // If a HwCommand is deactivated, all non-idempotent HwCommands launched after it should also |
| 168 | // be deactivated. Otherwise the XPU will become inconsist. So, if a HwCommand is not |
| 169 | // deactivatable, it should wait until all in-flight deactivatable HwCommands are completed. |
| 170 | // This is unnecessary under kPreemptLevelBlock. |
| 171 | bool wait_deactivatable = level_ >= kPreemptLevelDeactivate && |
| 172 | (kCommandPropertyNone == hw_cmd->GetProps( |
| 173 | kCommandPropertyDeactivatable | kCommandPropertyIdempotent)); |
| 174 | |
| 175 | hw_cmd->BeforeLaunch(); |
| 176 | std::unique_lock<MutexLock> lock(*mtx_); |
| 177 | |
| 178 | // If the HwCommand is not deactivatable and non-idempoent, |
| 179 | // wait until all previous in-flight deactivatable HwCommand are completed. |
| 180 | if (wait_deactivatable) { |
| 181 | // Find the last synchronizable HwCommand after the last deactivatable HwCommand. |
| 182 | bool has_deactivatable = false; |
| 183 | std::shared_ptr<HwCommand> command_to_sync = nullptr; |
| 184 | for (auto it = cmd_log_.rbegin(); it != cmd_log_.rend(); ++it) { |
| 185 | if ((*it)->Synchronizable()) command_to_sync = *it; |
| 186 | if ((*it)->GetProps(kCommandPropertyDeactivatable)) { |
| 187 | has_deactivatable = true; |
| 188 | break; |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | if (has_deactivatable) { |
| 193 | // If there is a synchronizable HwCommand, sync it. Otherwise, sync the HwQueue. |
| 194 | lock = (command_to_sync == nullptr) |
| 195 | ? SyncAllWithLock(std::move(lock)) |
| 196 | : SyncCmdWithLock(std::move(lock), command_to_sync); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | if (cmd_log_.size() >= (size_t)threshold_) { |
| 201 | // The command log is full (in-flight HwCommand reaches threshold), wait for a empty slot. |
| 202 | std::shared_ptr<HwCommand> command_to_sync = nullptr; |
| 203 | int64_t front_command_idx = cmd_log_.front()->GetIdx(); |
| 204 | |
| 205 | for (auto cmd : sync_cmd_log_) { |
| 206 | // Make sure after syncing the HwCommand, there will be at least one empty slot. |
| 207 | if (cmd->GetIdx() >= front_command_idx) { |
| 208 | command_to_sync = cmd; |
| 209 | break; |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | // If there is a synchronizable HwCommand, sync it. Otherwise, sync the HwQueue. |
| 214 | lock = (command_to_sync == nullptr) |
| 215 | ? SyncAllWithLock(std::move(lock)) |
| 216 | : SyncCmdWithLock(std::move(lock), command_to_sync); |
| 217 | |
| 218 | } else { |
| 219 | // Wait if the worker is paused. |
| 220 | while (true) { |
| 221 | if (state_ == kWorkerStateRunning) { |
nothing calls this directly
no test coverage detected