Re: [PATCH v1] cleanup: adjust scoped_guard() to avoid potential warning

From: Andy Shevchenko
Date: Thu Oct 03 2024 - 08:43:32 EST


On Thu, Oct 03, 2024 at 01:39:06PM +0200, Przemek Kitszel wrote:
> Change scoped_guard() to make reasoning about it easier for static
> analysis tools (smatch, compiler diagnostics), especially to enable them
> to tell if the given scoped_guard() is conditional (interruptible-locks,
> try-locks) or not (like simple mutex_lock()).
>
> Add compile-time error if scoped_cond_guard() is used for non-conditional
> lock class.
>
> Beyond easier tooling and a little shrink reported by bloat-o-meter:
> add/remove: 3/2 grow/shrink: 45/55 up/down: 1573/-2069 (-496)
> this patch enables developer to write code like:
>
> int foo(struct my_drv *adapter)
> {
> scoped_guard(spinlock, &adapter->some_spinlock)
> return adapter->spinlock_protected_var;
> }
>
> Current scoped_guard() implementation does not support that,
> due to compiler complaining:
> error: control reaches end of non-void function [-Werror=return-type]
>
> Technical stuff about the change:
> scoped_guard() macro uses common idiom of using "for" statement to declare
> a scoped variable. Unfortunately, current logic is too hard for compiler
> diagnostics to be sure that there is exactly one loop step; fix that.
>
> To make any loop so trivial that there is no above warning, it must not
> depend on any non-const variable to tell if there are more steps. There is
> no obvious solution for that in C, but one could use the compound
> statement expression with "goto" jumping past the "loop", effectively
> leaving only the subscope part of the loop semantics.
>
> More impl details:
> one more level of macro indirection is now needed to avoid duplicating
> label names;
> I didn't spot any other place that is using the
> "for (...; goto label) if (0) label: break;" idiom, so it's not packed
> for reuse, what makes actual macros code cleaner.
>
> There was also a need to introduce const true/false variable per lock
> class, it is used to aid compiler diagnostics reasoning about "exactly
> 1 step" loops (note that converting that to function would undo the whole
> benefit).

...

> +#define __scoped_guard_labeled(_label, _name, args...) \
> + for (CLASS(_name, scope)(args); \
> + __guard_ptr(_name)(&scope) || !__is_cond_ptr(_name); \
> + ({ goto _label; })) \
> + if (0) \
> + _label: \
> + break; \
> + else

I believe the following will folow more the style we use in the kernel:

#define __scoped_guard_labeled(_label, _name, args...) \
for (CLASS(_name, scope)(args); \
__guard_ptr(_name)(&scope) || !__is_cond_ptr(_name); \
({ goto _label; })) \
if (0) { \
_label: \
break; \
} else

...

> - *done = NULL; !done; done = (void *)1) \
> + *done = NULL; !done; done = (void *)1 + \

You have TABs/spaces mix in this line now.

--
With Best Regards,
Andy Shevchenko