if (num_sched_list && !sched_list[0]->sched_rq) { /* Since every entry covered by num_sched_list *shouldbenon-NULLandthereforewewarndrivers *nottodothisandtofixtheirDRMcallingorder.
*/
pr_warn("%s: called with uninitialized scheduler\n", __func__);
} elseif (num_sched_list) { /* The "priority" of an entity cannot exceed the number of run-queues of a *scheduler.Protectagainstnum_rqsbeing0,byconvertingtosigned.Choose *thelowestpriorityavailable.
*/ if (entity->priority >= sched_list[0]->num_rqs) {
dev_err(sched_list[0]->dev, "entity has out-of-bounds priority: %u. num_rqs: %u\n",
entity->priority, sched_list[0]->num_rqs);
entity->priority = max_t(s32, (s32) sched_list[0]->num_rqs - 1,
(s32) DRM_SCHED_PRIORITY_KERNEL);
}
entity->rq = sched_list[0]->sched_rq[entity->priority];
}
init_completion(&entity->entity_idle);
/* We start in an idle state. */
complete_all(&entity->entity_idle);
/* Wait for all dependencies to avoid data corruptions */
xa_for_each(&job->dependencies, index, f) { struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
if (s_fence && f == &s_fence->scheduled) { /* The dependencies array had a reference on the scheduled *fence,andthefinishedfencerefcountmighthave *droppedtozero.Usedma_fence_get_rcu()soweget *aNULLfenceinthatcase.
*/
f = dma_fence_get_rcu(&s_fence->finished);
/* Now that we have a reference on the finished fence, *wecanreleasethereferencethedependenciesarray *hadonthescheduledfence.
*/
dma_fence_put(&s_fence->scheduled);
}
xa_erase(&job->dependencies, index); if (f && !dma_fence_add_callback(f, &job->finish_cb,
drm_sched_entity_kill_jobs_cb)) return;
/* Signal the scheduler finished fence when the entity in question is killed. */ staticvoid drm_sched_entity_kill_jobs_cb(struct dma_fence *f, struct dma_fence_cb *cb)
{ struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb);
/* Remove the entity from the scheduler and kill all pending jobs */ staticvoid drm_sched_entity_kill(struct drm_sched_entity *entity)
{ struct drm_sched_job *job; struct dma_fence *prev;
/* Make sure this entity is not used by the scheduler at the moment */
wait_for_completion(&entity->entity_idle);
/* The entity is guaranteed to not be used by the scheduler */
prev = rcu_dereference_check(entity->last_scheduled, true);
dma_fence_get(prev); while ((job = drm_sched_entity_queue_pop(entity))) { struct drm_sched_fence *s_fence = job->s_fence;
/** *drm_sched_entity_flush-Flushacontextentity * *@entity:schedulerentity *@timeout:timetowaitinforQtobecomeemptyinjiffies. * *Splittingdrm_sched_entity_fini()intotwofunctions,Thefirstonedoesthe *waiting,removestheentityfromtherunqueueandreturnsanerrorwhenthe *processwaskilled. * *Returnstheremainingtimeinjiffiesleftfromtheinputtimeout
*/ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout)
{ struct drm_gpu_scheduler *sched; struct task_struct *last_user; long ret = timeout;
if (!entity->rq) return0;
sched = entity->rq->sched; /** *TheclientwillnotqueuemoreIBsduringthisfini,consumeexisting *queuedIBsordiscardthemonSIGKILL
*/ if (current->flags & PF_EXITING) { if (timeout)
ret = wait_event_timeout(
sched->job_scheduled,
drm_sched_entity_is_idle(entity),
timeout);
} else {
wait_event_killable(sched->job_scheduled,
drm_sched_entity_is_idle(entity));
}
/* For killed process disable any more IBs enqueue right now */
last_user = cmpxchg(&entity->last_user, current->group_leader, NULL); if (last_user == current->group_leader &&
(current->flags & PF_EXITING) && (current->exit_code == SIGKILL))
drm_sched_entity_kill(entity);
/* We keep the fence around, so we can iterate over all dependencies *indrm_sched_entity_kill_jobs_cb()toensurealldepsaresignaled *beforekillingthejob.
*/
f = xa_load(&job->dependencies, job->last_dependency); if (f) {
job->last_dependency++; return dma_fence_get(f);
}
if (job->sched->ops->prepare_job) return job->sched->ops->prepare_job(job, entity);
sched_job = drm_sched_entity_queue_peek(entity); if (!sched_job) return NULL;
while ((entity->dependency =
drm_sched_job_dependency(sched_job, entity))) { if (drm_sched_entity_add_dependency_cb(entity, sched_job)) return NULL;
}
/* skip jobs from entity that marked guilty */ if (entity->guilty && atomic_read(entity->guilty))
dma_fence_set_error(&sched_job->s_fence->finished, -ECANCELED);
/* Jobs and entities might have different lifecycles. Since we're *removingthejobfromtheentitiesqueue,setthejobsentitypointer *toNULLtopreventanyfutureaccessoftheentitythroughthisjob.
*/
sched_job->entity = NULL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.