Commit 7393febc authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'locking-core-2026-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking updates from Ingo Molnar:
 "Mutexes:

   - Add killable flavor to guard definitions (Davidlohr Bueso)

   - Remove the list_head from struct mutex (Matthew Wilcox)

   - Rename mutex_init_lockep() (Davidlohr Bueso)

  rwsems:

   - Remove the list_head from struct rw_semaphore and
     replace it with a single pointer (Matthew Wilcox)

   - Fix logic error in rwsem_del_waiter() (Andrei Vagin)

  Semaphores:

   - Remove the list_head from struct semaphore (Matthew Wilcox)

  Jump labels:

   - Use ATOMIC_INIT() for initialization of .enabled (Thomas Weißschuh)

   - Remove workaround for old compilers in initializations
     (Thomas Weißschuh)

  Lock context analysis changes and improvements:

   - Add context analysis for rwsems (Peter Zijlstra)

   - Fix rwlock and spinlock lock context annotations (Bart Van Assche)

   - Fix rwlock support in <linux/spinlock_up.h> (Bart Van Assche)

   - Add lock context annotations in the spinlock implementation
     (Bart Van Assche)

   - signal: Fix the lock_task_sighand() annotation (Bart Van Assche)

   - ww-mutex: Fix the ww_acquire_ctx function annotations
     (Bart Van Assche)

   - Add lock context support in do_raw_{read,write}_trylock()
     (Bart Van Assche)

   - arm64, compiler-context-analysis: Permit alias analysis through
     __READ_ONCE() with CONFIG_LTO=y (Marco Elver)

   - Add __cond_releases() (Peter Zijlstra)

   - Add context analysis for mutexes (Peter Zijlstra)

   - Add context analysis for rtmutexes (Peter Zijlstra)

   - Convert futexes to compiler context analysis (Peter Zijlstra)

  Rust integration updates:

   - Add atomic fetch_sub() implementation (Andreas Hindborg)

   - Refactor various rust_helper_ methods for expansion (Boqun Feng)

   - Add Atomic<*{mut,const} T> support (Boqun Feng)

   - Add atomic operation helpers over raw pointers (Boqun Feng)

   - Add performance-optimal Flag type for atomic booleans, to avoid
     slow byte-sized RMWs on architectures that don't support them.
     (FUJITA Tomonori)

   - Misc cleanups and fixes (Andreas Hindborg, Boqun Feng, FUJITA
     Tomonori)

  LTO support updates:

   - arm64: Optimize __READ_ONCE() with CONFIG_LTO=y (Marco Elver)

   - compiler: Simplify generic RELOC_HIDE() (Marco Elver)

  Miscellaneous fixes and cleanups by Peter Zijlstra, Randy Dunlap,
  Thomas Weißschuh, Davidlohr Bueso and Mikhail Gavrilov"

* tag 'locking-core-2026-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits)
  compiler: Simplify generic RELOC_HIDE()
  locking: Add lock context annotations in the spinlock implementation
  locking: Add lock context support in do_raw_{read,write}_trylock()
  locking: Fix rwlock support in <linux/spinlock_up.h>
  lockdep: Raise default stack trace limits when KASAN is enabled
  cleanup: Optimize guards
  jump_label: remove workaround for old compilers in initializations
  jump_label: use ATOMIC_INIT() for initialization of .enabled
  futex: Convert to compiler context analysis
  locking/rwsem: Fix logic error in rwsem_del_waiter()
  locking/rwsem: Add context analysis
  locking/rtmutex: Add context analysis
  locking/mutex: Add context analysis
  compiler-context-analysys: Add __cond_releases()
  locking/mutex: Remove the list_head from struct mutex
  locking/semaphore: Remove the list_head from struct semaphore
  locking/rwsem: Remove the list_head from struct rw_semaphore
  rust: atomic: Update a safety comment in impl of `fetch_add()`
  rust: sync: atomic: Update documentation for `fetch_add()`
  rust: sync: atomic: Add fetch_sub()
  ...
parents e80d0338 a21c1e96
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -19,6 +19,17 @@
		"ldapr"	#sfx "\t" #regs,				\
	ARM64_HAS_LDAPR)

/*
 * Replace this with typeof_unqual() when minimum compiler versions are
 * increased to GCC 14 and Clang 19. For the time being, we need this
 * workaround, which relies on function return values dropping qualifiers.
 */
#define __rwonce_typeof_unqual(x) typeof(({				\
	__diag_push()							\
	__diag_ignore_all("-Wignored-qualifiers", "")			\
	((typeof(x)(*)(void))0)();					\
	__diag_pop() }))

/*
 * When building with LTO, there is an increased risk of the compiler
 * converting an address dependency headed by a READ_ONCE() invocation
@@ -31,9 +42,12 @@
 */
#define __READ_ONCE(x)							\
({									\
	typeof(&(x)) __x = &(x);					\
	int atomic = 1;							\
	union { __unqual_scalar_typeof(*__x) __val; char __c[1]; } __u;	\
	auto __x = &(x);						\
	auto __ret = (__rwonce_typeof_unqual(*__x) *)__x;		\
	/* Hides alias reassignment from Clang's -Wthread-safety. */	\
	auto __retp = &__ret;						\
	union { typeof(*__ret) __val; char __c[1]; } __u;		\
	*__retp = &__u.__val;						\
	switch (sizeof(x)) {						\
	case 1:								\
		asm volatile(__LOAD_RCPC(b, %w0, %1)			\
@@ -56,9 +70,9 @@
			: "Q" (*__x) : "memory");			\
		break;							\
	default:							\
		atomic = 0;						\
		__u.__val = *(volatile typeof(*__x) *)__x;		\
	}								\
	atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\
	*__ret;								\
})

#endif	/* !BUILD_VDSO */
+1 −1
Original line number Diff line number Diff line
@@ -1263,7 +1263,7 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)

	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));

	BUG_ON(!list_empty(&sem->wait_list));
	BUG_ON(sem->first_waiter);
	kfree(sem);
	sem = NULL;

+3 −1
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@
 *			  argument and comparison of the previous
 *			  futex value with another constant.
 *
 * @encoded_op:	encoded operation to execute
 * @op:		operation to execute
 * @oparg:	argument of the operation
 * @oval:	previous value at @uaddr on successful return
 * @uaddr:	pointer to user space address
 *
 * Return:
+11 −8
Original line number Diff line number Diff line
@@ -286,15 +286,18 @@ static __always_inline _type class_##_name##_constructor(_init_args) \
	__no_context_analysis						\
{ _type t = _init; return t; }

#define EXTEND_CLASS(_name, ext, _init, _init_args...)			\
#define EXTEND_CLASS_COND(_name, ext, _cond, _init, _init_args...)	\
typedef lock_##_name##_t lock_##_name##ext##_t;				\
typedef class_##_name##_t class_##_name##ext##_t;			\
static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *p) \
{ class_##_name##_destructor(p); }					\
static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *_T) \
{ if (_cond) return; class_##_name##_destructor(_T); }			\
static __always_inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
	__no_context_analysis \
{ class_##_name##_t t = _init; return t; }

#define EXTEND_CLASS(_name, ext, _init, _init_args...)			\
	EXTEND_CLASS_COND(_name, ext, 0, _init, _init_args)

#define CLASS(_name, var)						\
	class_##_name##_t var __cleanup(class_##_name##_destructor) =	\
		class_##_name##_constructor
@@ -394,12 +397,12 @@ static __maybe_unused const bool class_##_name##_is_conditional = _is_cond
	__DEFINE_GUARD_LOCK_PTR(_name, _T)

#define DEFINE_GUARD(_name, _type, _lock, _unlock) \
	DEFINE_CLASS(_name, _type, if (!__GUARD_IS_ERR(_T)) { _unlock; }, ({ _lock; _T; }), _type _T); \
	DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
	DEFINE_CLASS_IS_GUARD(_name)

#define DEFINE_GUARD_COND_4(_name, _ext, _lock, _cond) \
	__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
	EXTEND_CLASS(_name, _ext, \
	EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(*_T), \
		     ({ void *_t = _T; int _RET = (_lock); if (_T && !(_cond)) _t = ERR_PTR(_RET); _t; }), \
		     class_##_name##_t _T) \
	static __always_inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
@@ -488,7 +491,7 @@ typedef struct { \
static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \
	__no_context_analysis						\
{									\
	if (!__GUARD_IS_ERR(_T->lock)) { _unlock; }			\
	if (_T->lock) { _unlock; }					\
}									\
									\
__DEFINE_GUARD_LOCK_PTR(_name, &_T->lock)
@@ -565,7 +568,7 @@ __DEFINE_LOCK_GUARD_0(_name, _lock)

#define DEFINE_LOCK_GUARD_1_COND_4(_name, _ext, _lock, _cond)		\
	__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true);		\
	EXTEND_CLASS(_name, _ext,					\
	EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(_T->lock),	\
		     ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
		        int _RET = (_lock);                             \
		        if (_T->lock && !(_cond)) _T->lock = ERR_PTR(_RET);\
+32 −0
Original line number Diff line number Diff line
@@ -320,6 +320,38 @@ static inline void _context_unsafe_alias(void **p) { }
 */
#define __releases(...)		__releases_ctx_lock(__VA_ARGS__)

/*
 * Clang's analysis does not care precisely about the value, only that it is
 * either zero or non-zero. So the __cond_acquires() interface might be
 * misleading if we say that @ret is the value returned if acquired. Instead,
 * provide symbolic variants which we translate.
 */
#define __cond_acquires_impl_not_true(x, ...)     __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
#define __cond_acquires_impl_not_false(x, ...)    __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
#define __cond_acquires_impl_not_nonzero(x, ...)  __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
#define __cond_acquires_impl_not_0(x, ...)        __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
#define __cond_acquires_impl_not_nonnull(x, ...)  __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
#define __cond_acquires_impl_not_NULL(x, ...)     __try_acquires##__VA_ARGS__##_ctx_lock(1, x)

/**
 * __cond_releases() - function attribute, function conditionally
 *                     releases a context lock exclusively
 * @ret: abstract value returned by function if context lock releases
 * @x: context lock instance pointer
 *
 * Function attribute declaring that the function conditionally releases the
 * given context lock instance @x exclusively. The associated context(s) must
 * be active on entry. The function return value @ret denotes when the context
 * lock is released.
 *
 * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
 *
 * NOTE: clang does not have a native attribute for this; instead implement
 *       it as an unconditional release and a conditional acquire for the
 *       inverted condition -- which is semantically equivalent.
 */
#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x)

/**
 * __acquire() - function to acquire context lock exclusively
 * @x: context lock instance pointer
Loading