Re: [RFC][PATCH 1/2] locking: Introduce __cleanup__ based guards
From: Linus Torvalds
Date: Fri May 26 2023 - 14:23:01 EST
On Fri, May 26, 2023 at 8:23 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> The CPP is rather impenetrable -- but I'll attempt to write proper
> comments if/when people think this is worth pursuing.
Ugh.
It's not only impenetrable, it seems _unnecessarily_ so.
Yes, yes, 'for()' loops can only declare one type, and if you want
multiple typed variables you declare a struct that contains all the
types.
But you don't actually *need* multiple types.
Yes, you think you do, because you want to use that 'bool done' to
make the for-loop only execute once. Nasty limitation of the for
syntax.
But you can actually do the 'bool done' using the exact same type you
have for the guard - just make it a pointer instead, and use NULL for
"not done" and non-NULL for "done". It ends up acting exactly like a
boolean.
But that extra structure is only a detail. The real ugliness comes
from using different scoping macros.
And I think you don't actually need to have those different forms of
"scoped()" macros for different cases. I think you can just use
variable macro arguments.
IOW, something like this:
#define variable_scope(type, enter, exit) \
for (type *_done = NULL, _scope __cleanup(exit) = enter;
!_done; _done = (void *)8)
#define scoped(type, init...) \
variable_scope(scope_##type##_t, scope_##type##_init(init),
scope_##type##_cleanup)
and then you can do
scoped (rcu) {
...
}
and it will call "scope_rcu_init()" on entry, and
"scope_rcu_exit(_scope)" on exit.
And just doing
scoped (mutex, mymutex) { ... }
will call "scope_mytex_init(mymutex)" on entry, and
"scope_mytex_exit(_scope)" on exit.
And if you just make the scope_##type##_init() functions return the
right values, it all works very naturally.
I think you can also do things like
scoped(irqsave) { ... }
scoped(irqoff) { ... }
scoped(preempt) { ... }
very naturally. No need for that odd "one scope for 'void', one scope
for 'lock'" nonsense.
I dunno. I didn't *test* the above. Maybe you already tried something
like the above, and there's a reason why it doesn't work.
Linus