[PATCH v5 04/16] drm/sched: Avoid double re-lock on the job free path
Tvrtko Ursulin
tvrtko.ursulin at igalia.com
Fri Jul 4 15:14:57 UTC 2025
On 04/07/2025 14:59, Philipp Stanner wrote:
> On Fri, 2025-07-04 at 14:30 +0100, Tvrtko Ursulin wrote:
>>
>> On 04/07/2025 13:56, Philipp Stanner wrote:
>>> On Fri, 2025-07-04 at 09:29 -0300, Maíra Canal wrote:
>>>> Hi Tvrtko,
>>>>
>>>> On 23/06/25 09:27, Tvrtko Ursulin wrote:
>>>>> Currently the job free work item will lock sched->job_list_lock
>>>>> first time
>>>>> to see if there are any jobs, free a single job, and then lock
>>>>> again to
>>>>> decide whether to re-queue itself if there are more finished
>>>>> jobs.
>>>>>
>>>>> Since drm_sched_get_finished_job() already looks at the second
>>>>> job
>>>>> in the
>>>>> queue we can simply add the signaled check and have it return
>>>>> the
>>>>> presence
>>>>> of more jobs to free to the caller. That way the work item does
>>>>> not
>>>>> have
>>>>> to lock the list again and repeat the signaled check.
>>>>>
>>>>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at igalia.com>
>>>>> Cc: Christian König <christian.koenig at amd.com>
>>>>> Cc: Danilo Krummrich <dakr at kernel.org>
>>>>> Cc: Matthew Brost <matthew.brost at intel.com>
>>>>> Cc: Philipp Stanner <phasta at kernel.org>
>>>>> ---
>>>>> drivers/gpu/drm/scheduler/sched_main.c | 39 +++++++++++-----
>>>>> -----
>>>>> -----
>>>>> 1 file changed, 16 insertions(+), 23 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c
>>>>> b/drivers/gpu/drm/scheduler/sched_main.c
>>>>> index 1f077782ec12..c6c26aec07b6 100644
>>>>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>>>>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>>>>> @@ -366,22 +366,6 @@ static void
>>>>> __drm_sched_run_free_queue(struct
>>>>> drm_gpu_scheduler *sched)
>>>>> queue_work(sched->submit_wq, &sched-
>>>>>> work_free_job);
>>>>> }
>>>>>
>>>>> -/**
>>>>> - * drm_sched_run_free_queue - enqueue free-job work if ready
>>>>> - * @sched: scheduler instance
>>>>> - */
>>>>> -static void drm_sched_run_free_queue(struct drm_gpu_scheduler
>>>>> *sched)
>>>>> -{
>>>>> - struct drm_sched_job *job;
>>>>> -
>>>>> - spin_lock(&sched->job_list_lock);
>>>>> - job = list_first_entry_or_null(&sched->pending_list,
>>>>> - struct drm_sched_job,
>>>>> list);
>>>>> - if (job && dma_fence_is_signaled(&job->s_fence-
>>>>>> finished))
>>>>> - __drm_sched_run_free_queue(sched);
>>>>> - spin_unlock(&sched->job_list_lock);
>>>>> -}
>>>>> -
>>>>> /**
>>>>> * drm_sched_job_done - complete a job
>>>>> * @s_job: pointer to the job which is done
>>>>> @@ -1102,12 +1086,13 @@ drm_sched_select_entity(struct
>>>>> drm_gpu_scheduler *sched)
>>>>> * drm_sched_get_finished_job - fetch the next finished job
>>>>> to be
>>>>> destroyed
>>>>> *
>>>>> * @sched: scheduler instance
>>>>> + * @have_more: are there more finished jobs on the list
>>>>> *
>>>>> * Returns the next finished job from the pending list (if
>>>>> there
>>>>> is one)
>>>>> * ready for it to be destroyed.
>>>>> */
>>>>> static struct drm_sched_job *
>>>>> -drm_sched_get_finished_job(struct drm_gpu_scheduler *sched)
>>>>> +drm_sched_get_finished_job(struct drm_gpu_scheduler *sched,
>>>>> bool
>>>>> *have_more)
>>>>> {
>>>>> struct drm_sched_job *job, *next;
>>>>>
>>>>> @@ -1115,22 +1100,27 @@ drm_sched_get_finished_job(struct
>>>>> drm_gpu_scheduler *sched)
>>>>>
>>>>> job = list_first_entry_or_null(&sched->pending_list,
>>>>> struct drm_sched_job,
>>>>> list);
>>>>> -
>>>>> if (job && dma_fence_is_signaled(&job->s_fence-
>>>>>> finished))
>>>>> {
>>>>> /* remove job from pending_list */
>>>>> list_del_init(&job->list);
>>>>>
>>>>> /* cancel this job's TO timer */
>>>>> cancel_delayed_work(&sched->work_tdr);
>>>>> - /* make the scheduled timestamp more accurate
>>>>> */
>>>>> +
>>>>> + *have_more = false;
>>>>> next = list_first_entry_or_null(&sched-
>>>>>> pending_list,
>>>>> typeof(*next),
>>>>> list);
>>>>> -
>>>>> if (next) {
>>>>> + /* make the scheduled timestamp more
>>>>> accurate */
>>>>> if
>>>>> (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
>>>>> &next->s_fence-
>>>>>> scheduled.flags))
>>>>> next->s_fence-
>>>>>> scheduled.timestamp
>>>>> =
>>>>> dma_fence_timestamp(&j
>>>>> ob-
>>>>>> s_fence->finished);
>>>>> +
>>>>> + if
>>>>> (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
>>>>> + &next->s_fence-
>>>>>> finished.flags))
>>>>
>>>> Shouldn't we use dma_fence_is_signaled() to keep the same check
>>>> that
>>>> we
>>>> have in drm_sched_run_free_queue()?
>>>
>>> There is a paused-ongoing discussion about this function:
>>>
>>> https://lore.kernel.org/all/20250522112540.161411-2-phasta@kernel.org/
>>>
>>>
>>> dma_fence_is_signaled() can have side effects by actually
>>> signaling,
>>> instead of just checking.
>>>
>>> Not sure if Tvrtko wanted to bypass that behavior here, though.
>>
>> No, no ulterior motives here. :)
>>
>> It is ages I wrote this, but now I revisited it, and AFAICT I don't
>> see
>> that it matters in this case.
>>
>> It is a scheduler fence which does not implement fence->ops-
>>> signaled()
>> so opportunistic signaling does not come into the picture.
>>
>> I am happy to change it to dma_fence_is_signaled() if that is the
>> preference.
>
> Its our (scheduler's) fence, so we can be sure dma_fence_is_signaled()
> is OK.
Okay, I changed it to dma_fence_is_signaled() locally.
Regards,
Tvrtko
> I'd still prefer if we could get Christian to accept a function with a
> superior name, though..
>
> P.
>
>>
>> Regards,
>>
>> Tvrtko
>>
>>>>> + *have_more = true;
>>>>> +
>>>>> /* start TO timer for next job */
>>>>> drm_sched_start_timeout(sched);
>>>>> }
>>>>
>>>>
>>>
>>
>
More information about the amd-gfx
mailing list