[Intel-gfx] [PATCH 04/41] drm/i915: Teach the i915_dependency to use a double-lock
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Tue Jan 26 09:40:17 UTC 2021
On 25/01/2021 21:37, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2021-01-25 15:34:53)
>>
>> On 25/01/2021 14:00, Chris Wilson wrote:
>>> @@ -390,24 +410,27 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
>>> {
>>> bool ret = false;
>>>
>>> - spin_lock_irq(&schedule_lock);
>>> + /* The signal->lock is always the outer lock in this double-lock. */
>>> + spin_lock(&signal->lock);
>>>
>>> if (!node_signaled(signal)) {
>>> INIT_LIST_HEAD(&dep->dfs_link);
>>> dep->signaler = signal;
>>> - dep->waiter = node;
>>> + dep->waiter = node_get(node);
>>> dep->flags = flags;
>>>
>>> /* All set, now publish. Beware the lockless walkers. */
>>> + spin_lock_nested(&node->lock, SINGLE_DEPTH_NESTING);
>>> list_add_rcu(&dep->signal_link, &node->signalers_list);
>>> list_add_rcu(&dep->wait_link, &signal->waiters_list);
>>> + spin_unlock(&node->lock);
>>>
>>> /* Propagate the chains */
>>> node->flags |= signal->flags;
>>> ret = true;
>>> }
>>>
>>> - spin_unlock_irq(&schedule_lock);
>>> + spin_unlock(&signal->lock);
>>
>> So we have to be sure another entry point cannot try to lock the same
>> nodes in reverse, that is with reversed roles. Situation where nodes are
>> simultaneously both each other waiters and signalers does indeed sound
>> impossible so I think this is fine.
>>
>> Only if some entry point would lock something which is a waiter, and
>> then went to boost the priority of a signaler. That is still one with a
>> global lock. So the benefit of this patch is just to reduce contention
>> between adding and re-scheduling?
>
> We remove the global schedule_lock in the next patch. This patch tackles
> the "simpler" list management by noting that the chains can always be
> taken in order of (signaler, waiter) so we have strict nesting for a
> local double lock.
>
>> And __i915_schedule does walk the list of signalers without holding this
>> new lock. What is the safety net there? RCU? Do we need
>> list_for_each_entry_rcu and explicit rcu_read_(un)lock in there then?
>
> Yes, we are already supposedly RCU safe for the list of signalers, as
> we've been depending on that for a while.
>
> #define for_each_signaler(p__, rq__) \
> list_for_each_entry_rcu(p__, \
> &(rq__)->sched.signalers_list, \
> signal_link)
Yeah its fine, I wasn't seeing it's for_each_signaler but for some
reason confused it with list_for_each_entry elsewhere in the function.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list