xref: /freebsd/sys/compat/linuxkpi/common/include/linux/cleanup.h (revision 3f48a0fe53ca7e001852f4a406c1bdfab1cd2f6d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024-2025 The FreeBSD Foundation
5  *
6  * This software was developed by Björn Zeeb under sponsorship from
7  * the FreeBSD Foundation.
8  */
9 
10 #ifndef	_LINUXKPI_LINUX_CLEANUP_H
11 #define	_LINUXKPI_LINUX_CLEANUP_H
12 
13 #define	__cleanup(_f)		__attribute__((__cleanup__(_f)))
14 
15 /*
16  * Note: "_T" are special as they are exposed into common code for
17  * statements.  Extra care should be taken when changing the code.
18  */
19 #define	DEFINE_GUARD(_n, _dt, _lock, _unlock)				\
20 									\
21     typedef _dt guard_ ## _n ## _t;					\
22 									\
23     static inline _dt							\
24     guard_ ## _n ## _create( _dt _T)					\
25     {									\
26 	_dt c;								\
27 									\
28 	c = ({ _lock; _T; });						\
29 	return (c);							\
30     }									\
31 									\
32     static inline void							\
33     guard_ ## _n ## _destroy(_dt *t)					\
34     {									\
35 	_dt _T;								\
36 									\
37 	_T = *t;							\
38 	if (_T) { _unlock; };						\
39     }
40 
41 /* We need to keep these calls unique. */
42 #define	guard(_n)							\
43     guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__			\
44 	__cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create
45 
46 #define	DEFINE_FREE(_n, _t, _f)						\
47     static inline void							\
48     __free_ ## _n(void *p)						\
49     {									\
50 	_t _T;								\
51 									\
52 	_T = *(_t *)p;							\
53 	_f;								\
54     }
55 
56 #define	__free(_n)		__cleanup(__free_##_n)
57 
58 /*
59  * Given this is a _0 version it should likely be broken up into parts.
60  * But we have no idead what a _1, _2, ... version would do different
61  * until we see a call.
62  * This is used for a not-real-type (rcu).   We use a bool to "simulate"
63  * the lock held.  Also _T still special, may not always be used, so tag
64  * with __unused (or better the LinuxKPI __maybe_unused).
65  */
66 #define	DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...)			\
67 									\
68     typedef struct {							\
69 	bool lock;							\
70 	__VA_ARGS__;							\
71     } guard_ ## _n ## _t;	    					\
72 									\
73     static inline void							\
74     guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T)			\
75     {									\
76 	if (_T->lock) {							\
77 	    _unlock;							\
78 	}								\
79     }									\
80 									\
81     static inline guard_ ## _n ## _t					\
82     guard_ ## _n ## _create(void)					\
83     {									\
84 	guard_ ## _n ## _t _tmp;					\
85 	guard_ ## _n ## _t *_T __maybe_unused;				\
86 									\
87 	_tmp.lock = true;						\
88 	_T = &_tmp;							\
89 	_lock;								\
90 	return (_tmp);							\
91     }
92 
93 #endif	/* _LINUXKPI_LINUX_CLEANUP_H */
94