Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157466844
D54808.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D54808.id.diff
View Options
diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h
--- a/sys/compat/linuxkpi/common/include/linux/cleanup.h
+++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2024-2025 The FreeBSD Foundation
+ * Copyright (c) 2024-2026 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -10,18 +10,26 @@
#ifndef _LINUXKPI_LINUX_CLEANUP_H
#define _LINUXKPI_LINUX_CLEANUP_H
+#include <linux/err.h>
+
+#define CLEANUP_NAME(_n, _s) __CONCAT(__CONCAT(cleanup_, _n), _s)
+
#define __cleanup(_f) __attribute__((__cleanup__(_f)))
+#define DECLARE(_n, _x) \
+ CLEANUP_NAME(_n, _t) _x __cleanup(CLEANUP_NAME(_n, _destroy)) = \
+ CLEANUP_NAME(_n, _create)
+
/*
* Note: "_T" are special as they are exposed into common code for
* statements. Extra care should be taken when changing the code.
*/
#define DEFINE_GUARD(_n, _dt, _lock, _unlock) \
\
- typedef _dt guard_ ## _n ## _t; \
+ typedef _dt CLEANUP_NAME(_n, _t); \
\
static inline _dt \
- guard_ ## _n ## _create( _dt _T) \
+ CLEANUP_NAME(_n, _create)( _dt _T) \
{ \
_dt c; \
\
@@ -30,7 +38,7 @@
} \
\
static inline void \
- guard_ ## _n ## _destroy(_dt *t) \
+ CLEANUP_NAME(_n, _destroy)(_dt *t) \
{ \
_dt _T; \
\
@@ -39,9 +47,10 @@
}
/* We need to keep these calls unique. */
+#define _guard(_n, _x) \
+ DECLARE(_n, _x)
#define guard(_n) \
- guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \
- __cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create
+ _guard(_n, guard_ ## _n ## _ ## __COUNTER__)
#define DEFINE_FREE(_n, _t, _f) \
static inline void \
@@ -56,38 +65,100 @@
#define __free(_n) __cleanup(__free_##_n)
/*
- * Given this is a _0 version it should likely be broken up into parts.
- * But we have no idead what a _1, _2, ... version would do different
- * until we see a call.
- * This is used for a not-real-type (rcu). We use a bool to "simulate"
- * the lock held. Also _T still special, may not always be used, so tag
- * with __unused (or better the LinuxKPI __maybe_unused).
+ * Our initial version go broken up. Some simplifications like using
+ * "bool" for the lock had to be changed to a more general type.
+ * _T is still special and, like other bits, may not always be used,
+ * so tag with __unused (or better the LinuxKPI __maybe_unused).
*/
-#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \
+#define _DEFINE_LOCK_GUARD_0(_n, _lock) \
+ static inline CLEANUP_NAME(_n, _t) \
+ CLEANUP_NAME(_n, _create)(void) \
+ { \
+ CLEANUP_NAME(_n, _t) _tmp; \
+ CLEANUP_NAME(_n, _t) *_T __maybe_unused; \
+ \
+ _tmp.lock = (void *)1; \
+ _T = &_tmp; \
+ _lock; \
+ return (_tmp); \
+ }
+
+#define _DEFINE_LOCK_GUARD_1(_n, _type, _lock) \
+ static inline CLEANUP_NAME(_n, _t) \
+ CLEANUP_NAME(_n, _create)(_type *l) \
+ { \
+ CLEANUP_NAME(_n, _t) _tmp; \
+ CLEANUP_NAME(_n, _t) *_T __maybe_unused; \
\
+ _tmp.lock = l; \
+ _T = &_tmp; \
+ _lock; \
+ return (_tmp); \
+ }
+
+#define _GUARD_IS_ERR(_v) \
+ ({ \
+ uintptr_t x = (uintptr_t)(void *)(_v); \
+ IS_ERR_VALUE(x); \
+ })
+
+#define __is_cond_ptr(_n) \
+ CLEANUP_NAME(_n, _is_cond)
+#define __guard_ptr(_n) \
+ CLEANUP_NAME(_n, _ptr)
+
+#define _DEFINE_CLEANUP_IS_CONDITIONAL(_n, _b) \
+ static const bool CLEANUP_NAME(_n, _is_cond) __maybe_unused = _b
+
+#define _DEFINE_GUARD_LOCK_PTR(_n, _lp) \
+ static inline void * \
+ CLEANUP_NAME(_n, _lock_ptr)(CLEANUP_NAME(_n, _t) *_T) \
+ { \
+ void *_p; \
+ \
+ _p = (void *)(uintptr_t)*(_lp); \
+ if (IS_ERR(_p)) \
+ _p = NULL; \
+ return (_p); \
+ }
+
+#define _DEFINE_UNLOCK_GUARD(_n, _type, _unlock, ...) \
typedef struct { \
- bool lock; \
+ _type *lock; \
__VA_ARGS__; \
- } guard_ ## _n ## _t; \
+ } CLEANUP_NAME(_n, _t); \
\
static inline void \
- guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T) \
+ CLEANUP_NAME(_n, _destroy)(CLEANUP_NAME(_n, _t) *_T) \
{ \
- if (_T->lock) { \
+ if (!_GUARD_IS_ERR(_T->lock)) { \
_unlock; \
} \
} \
\
- static inline guard_ ## _n ## _t \
- guard_ ## _n ## _create(void) \
- { \
- guard_ ## _n ## _t _tmp; \
- guard_ ## _n ## _t *_T __maybe_unused; \
- \
- _tmp.lock = true; \
- _T = &_tmp; \
- _lock; \
- return (_tmp); \
- }
+ _DEFINE_GUARD_LOCK_PTR(_n, &_T->lock)
+
+#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \
+ _DEFINE_CLEANUP_IS_CONDITIONAL(_n, false); \
+ _DEFINE_UNLOCK_GUARD(_n, void, _unlock, __VA_ARGS__) \
+ _DEFINE_LOCK_GUARD_0(_n, _lock)
+
+/* This allows the type to be set. */
+#define DEFINE_LOCK_GUARD_1(_n, _t, _lock, _unlock, ...) \
+ _DEFINE_CLEANUP_IS_CONDITIONAL(_n, false); \
+ _DEFINE_UNLOCK_GUARD(_n, _t, _unlock, __VA_ARGS__) \
+ _DEFINE_LOCK_GUARD_1(_n, _t, _lock)
+
+#define _scoped_guard(_n, _l, ...) \
+ for (DECLARE(_n, _scoped)(__VA_ARGS__); \
+ 1 /*__guard_ptr(_n)(&_scoped) || !__is_cond_ptr(_n) */; \
+ ({ goto _l; })) \
+ if (0) { \
+_l: \
+ break; \
+ } else
+
+#define scoped_guard(_n, ...) \
+ _scoped_guard(_n, ___label_ ## __COUNTER__, ##__VA_ARGS__)
#endif /* _LINUXKPI_LINUX_CLEANUP_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/spinlock.h b/sys/compat/linuxkpi/common/include/linux/spinlock.h
--- a/sys/compat/linuxkpi/common/include/linux/spinlock.h
+++ b/sys/compat/linuxkpi/common/include/linux/spinlock.h
@@ -36,6 +36,7 @@
#include <sys/mutex.h>
#include <sys/kdb.h>
+#include <linux/cleanup.h>
#include <linux/compiler.h>
#include <linux/rwlock.h>
#include <linux/bottom_half.h>
@@ -198,4 +199,13 @@
#define raw_spin_trylock_irqsave(rl, f) spin_trylock_irqsave(&(rl)->lock, (f))
#define raw_spin_unlock_irqrestore(rl, f) spin_unlock_irqrestore(&(rl)->lock, (f))
+/*
+ * cleanup.h related pre-defined cases.
+ */
+DEFINE_LOCK_GUARD_1(spinlock_irqsave,
+ spinlock_t,
+ spin_lock_irqsave(_T->lock, _T->flags),
+ spin_unlock_irqrestore(_T->lock, _T->flags),
+ unsigned long flags)
+
#endif /* _LINUXKPI_LINUX_SPINLOCK_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 22, 6:58 PM (13 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33428001
Default Alt Text
D54808.id.diff (6 KB)
Attached To
Mode
D54808: LinuxKPI: add scoped_guard(), spinlock guard support
Attached
Detach File
Event Timeline
Log In to Comment