[PATCH 01/13] drm: execution context for GEM buffers v4
Christian König
christian.koenig at amd.com
Tue Jun 20 07:28:25 UTC 2023
Am 20.06.23 um 08:47 schrieb Boris Brezillon:
> On Mon, 19 Jun 2023 14:29:23 +0200
> Boris Brezillon <boris.brezillon at collabora.com> wrote:
>
>> On Mon, 19 Jun 2023 12:44:06 +0200
>> Christian König <christian.koenig at amd.com> wrote:
>>
>>> Am 19.06.23 um 12:12 schrieb Boris Brezillon:
>>>> [SNIP]
>>>> Note that the drm_exec_until_all_locked() helper I introduced is taking
>>>> an expression, so in theory, you don't have to define a separate
>>>> function.
>>>>
>>>> drm_exec_until_all_locked(&exec, {
>>>> /* inlined-code */
>>>> int ret;
>>>>
>>>> ret = blabla()
>>>> if (ret)
>>>> goto error;
>>>>
>>>> ...
>>>>
>>>> error:
>>>> /* return value. */
>>>> ret;
>>>> });
>>>>
>>>> This being said, as soon as you have several failure paths,
>>>> it makes things a lot easier/controllable if you make it a function,
>>>> and I honestly don't think the readability would suffer from having a
>>>> function defined just above the user. My main concern with the original
>>>> approach was the risk of calling continue/break_if_contended() in the
>>>> wrong place, and also the fact you can't really externalize things to
>>>> a function if you're looking for a cleaner split. At least with
>>>> drm_exec_until_all_locked() you can do both.
>>> Yeah, but that means that you can't use return inside your code block
>>> and instead has to define an error label for handling "normal"
>>> contention which is what I'm trying to avoid here.
>> Sorry, didn't pay attention to this particular concern. Indeed, if you
>> want to return inside the expression, that's a problem.
> Sorry, that's wrong again. Had trouble focusing yesterday...
>
> So, returning directly from the expression block should be perfectly
> fine. The only problem is breaking out of the retry loop early and
> propagating the error, but that's no more or less problematic than it
> was before. We just need the drm_exec_retry_on_contention() helper you
> suggested, and a drm_exec_stop() that would go to some local
> __drm_exec_stop label.
>
> int ret = 0;
>
> ret = drm_exec_until_all_locked(exec, ({
> ...
> ret = drm_exec_prepare_obj(exec, objA, 1);
> drm_exec_retry_on_contention(exec);
> if (ret)
> drm_exec_stop(exec, ret);
> ...
>
> ret = drm_exec_prepare_obj(exec, objB, 1);
> drm_exec_retry_on_contention(exec);
> if (ret)
> drm_exec_stop(exec, ret);
>
> 0;
> }));
>
> Which is pretty close to the syntax you defined initially, except for
> the '0;' oddity at the end, which is ugly, I admit.
Yeah and it looks like giving code blocks as macro argument is usually
also not a good idea.
How about this:
#define drm_exec_until_all_locked(exec) \
for (void *__drm_exec_retry_ptr; ({ \
__label__ __drm_exec_retry; \
__drm_exec_retry: \
__drm_exec_retry_ptr = &&__drm_exec_retry; \
drm_exec_cleanup(exec); \
});)
#define drm_exec_retry_on_contention(exec) \
if (unlikely(drm_exec_is_contended(exec))) \
goto *__drm_exec_retry_ptr
The problem is that you can't declare a label so that it dominates the
body of the loop.
But what you can do is to declare a void* which dominates the loop, then
assign the address of a label to it and when you need it use goto*.
The goto* syntax is a gcc extension, but BPF is already using that in
the upstream kernel.
It's quite a hack and I need to extend my testing a bit, but as far as I
can see this actually works.
Regards,
Christian.
More information about the dri-devel
mailing list