[Mesa-dev] [PATCH v3] gallium/util: Break recursion in pipe_resource_reference

Michel Dänzer michel at daenzer.net
Wed Jun 14 09:59:10 UTC 2017


On 14/06/17 05:42 PM, Nicolai Hähnle wrote:
> On 14.06.2017 10:05, Michel Dänzer wrote:
>> On 14/06/17 04:42 PM, Nicolai Hähnle wrote:
>>> On 14.06.2017 05:39, Michel Dänzer wrote:
>>>> From: Michel Dänzer <michel.daenzer at amd.com>
>>>>
>>>> diff --git a/src/gallium/auxiliary/util/u_inlines.h
>>>> b/src/gallium/auxiliary/util/u_inlines.h
>>>> index 6a3d5043cf..08326da03d 100644
>>>> --- a/src/gallium/auxiliary/util/u_inlines.h
>>>> +++ b/src/gallium/auxiliary/util/u_inlines.h
>>>> @@ -137,8 +137,19 @@ pipe_resource_reference(struct pipe_resource
>>>> **ptr, struct pipe_resource *tex)
>>>>         if (pipe_reference_described(&(*ptr)->reference,
>>>> &tex->reference,
>>>>                                  
>>>> (debug_reference_descriptor)debug_describe_resource)) {
>>>> -      pipe_resource_reference(&old_tex->next, NULL);
>>>> +      struct pipe_resource *next = old_tex->next;
>>>> +
>>>>          old_tex->screen->resource_destroy(old_tex->screen, old_tex);
>>>> +
>>>> +      /* Avoid recursion, which would prevent inlining this
>>>> function */
>>>> +      while (next) {
>>>> +         old_tex = next;
>>>> +         next = old_tex->next;
>>>> +         old_tex->next = NULL;
>>>
>>> Is this really necessary? I don't think so, but if it is, it's probably
>>> necessary above as well.
>>
>> The old_tex->next = NULL assignment is necessary here to complement the
>> pipe_reference_described call below it. It's not necessary above,
>> because the ->next chain only needs to be unreferenced when the "master"
>> resource is destroyed.
>>
>> The behaviour is basically the same as with the recursive
>> pipe_resource_reference(&old_tex->next, NULL) call before: the next
>> pointers are left untouched unless the "master" resource is destroyed,
>> in which case the next pointers are set to NULL and the reference counts
>> of the corresponding sub-resources decremented (and the sub-resource
>> destroyed if it goes to 0). The only slight change is that the next
>> member of the "master" resource isn't set to NULL, but that doesn't
>> matter because it's getting destroyed anyway.
> 
> Well, if (*ptr)->next is _not_ destroyed, then the new code will set
> (*ptr)->next->next to NULL anyway, while the old code would not have
> modified it.

You're right. I'm not sure it makes a difference in practice, but let's
be conservative, as that allows making the patch (and the generated
code) even smaller:


> Come to think of it, the new code should really break out of the loop
> once pipe_reference_described returns false. Maybe:
> 
> do {
>    struct pipe_resource *next = old_tex->next;
>    old_tex->screen->resource_destroy(old_tex->screen, old_tex);
>    old_tex = next;
> } while (old_tex && pipe_reference_described(&old_tex->reference, NULL,
> ...));
> 
> How does that sound?

Great! I took your suggestion almost verbatim (no need to test old_tex
separately before calling pipe_reference_described) for v4, thanks.


-- 
Earthling Michel Dänzer               |               http://www.amd.com
Libre software enthusiast             |             Mesa and X developer


More information about the mesa-dev mailing list