Re: [PATCH v2 0/2] Lock and Pointer guards

From: Peter Zijlstra
Date: Tue Jun 06 2023 - 14:08:57 EST


On Tue, Jun 06, 2023 at 07:50:47AM -0700, Linus Torvalds wrote:
> I feel like you seem entirely too fixated on locking.

It's what I started out with... but it's certainly not everything.

The thing I have removes pretty much all the error gotos from
sched/core.c and events/core.c and while locking is ofcourse a fair
amount of that there's significant non-locking usage.

> (c) think that generally are not "nested" (you release the resources
> you've allocated, but you don't "nest" the allocations - they are just
> serial.
>
> (d) think that the syntax could be pretty nasty, because the cleanup
> is not just a trivial fixed "unlock" function

So I'm not sure you've seen the actual convertions I've done, but yes,
there's lots of those.

I've just used the guard naming because locks is what I started out
with.

+ ptr_guard(kfree, alloc) = kzalloc(event->read_size, GFP_KERNEL);
+ if (!alloc)
return -ENOMEM;


event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
NULL, NULL, cgroup_fd);
+ if (IS_ERR(event))
+ return PTR_ERR(event);
+
+ ptr_guard(free_event, event_guard) = event;


+ ptr_guard(put_task, p) = find_get_task(pid);
+ if (!p)
+ return -ESRCH;


So it does all that... you just hate the naming -- surely we can fix
that.


Would it all be less offensive if I did: s/guard/cleanup/ on the whole
thing? Then we'd have things like:


DEFINE_PTR_CLEANUP(put_task, struct task_struct *,
if (_C) put_task_struct(_C))

ptr_cleanup(put_task, p) = find_get_task(pid);
if (!p)
return -ESRCH;


DEFINE_PTR_CLEANUP(free_event, struct perf_event *,
if (!IS_ERR_OR_NULL(_C)) free_event(_C))

ptr_cleanup(free_event, event) = perf_event_alloc(...);
if (IS_ERR(event))
return PTR_ERR(event);


DEFINE_PTR_CLEANUP(kfree, void *, kfree(_C))

ptr_cleanup(kfree, foo) = kzalloc(...);
if (!foo)
return -ENOMEM;


But do we then continue with:

DEFINE_CLEANUP(mutex, struct mutex *, mutex_lock(_C), mutex_unlock(_C))

cleanup(mutex, &my_mutex);


scoped_cleanup (mutex, &my_mutex) {
...
}

etc..? or do we keep guard() there, but based internally on
ptr_cleanup() with the cleanup_## naming.