Skip to content

Commit 630a937

Browse files
author
Peter Zijlstra
committed
Merge tag 'lockdep-for-tip.20241220' of git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux into locking/core
Lockdep changes for v6.14: - Use swap() macro in the ww_mutex test. - Minor fixes and documentation for lockdep configs on internal data structure sizes. - Some "-Wunused-function" warning fixes for Clang. Rust locking changes for v6.14: - Add Rust locking files into LOCKING PRIMITIVES maintainer entry. - Add `Lock<(), ..>::from_raw()` function to support abstraction on low level locking. - Expose `Guard::new()` for public usage and add type alias for spinlock and mutex guards. - Add lockdep checking when creating a new lock `Guard`.
2 parents abfdccd + fbd7a5a commit 630a937

File tree

11 files changed

+95
-21
lines changed

11 files changed

+95
-21
lines changed

MAINTAINERS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13425,8 +13425,8 @@ LOCKING PRIMITIVES
1342513425
M: Peter Zijlstra <peterz@infradead.org>
1342613426
M: Ingo Molnar <mingo@redhat.com>
1342713427
M: Will Deacon <will@kernel.org>
13428+
M: Boqun Feng <boqun.feng@gmail.com> (LOCKDEP & RUST)
1342813429
R: Waiman Long <longman@redhat.com>
13429-
R: Boqun Feng <boqun.feng@gmail.com> (LOCKDEP)
1343013430
L: linux-kernel@vger.kernel.org
1343113431
S: Maintained
1343213432
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
@@ -13440,6 +13440,11 @@ F: include/linux/seqlock.h
1344013440
F: include/linux/spinlock*.h
1344113441
F: kernel/locking/
1344213442
F: lib/locking*.[ch]
13443+
F: rust/helpers/mutex.c
13444+
F: rust/helpers/spinlock.c
13445+
F: rust/kernel/sync/lock.rs
13446+
F: rust/kernel/sync/lock/
13447+
F: rust/kernel/sync/locked_by.rs
1344313448
X: kernel/locking/locktorture.c
1344413449

1344513450
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)

kernel/locking/lockdep.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,12 @@ static inline void lockdep_unlock(void)
157157
__this_cpu_dec(lockdep_recursion);
158158
}
159159

160+
#ifdef CONFIG_PROVE_LOCKING
160161
static inline bool lockdep_assert_locked(void)
161162
{
162163
return DEBUG_LOCKS_WARN_ON(__owner != current);
163164
}
165+
#endif
164166

165167
static struct task_struct *lockdep_selftest_task_struct;
166168

@@ -430,7 +432,7 @@ static inline u16 hlock_id(struct held_lock *hlock)
430432
return (hlock->class_idx | (hlock->read << MAX_LOCKDEP_KEYS_BITS));
431433
}
432434

433-
static inline unsigned int chain_hlock_class_idx(u16 hlock_id)
435+
static inline __maybe_unused unsigned int chain_hlock_class_idx(u16 hlock_id)
434436
{
435437
return hlock_id & (MAX_LOCKDEP_KEYS - 1);
436438
}

kernel/locking/lockdep_internals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ =
119119

120120
#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS)
121121

122-
#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5)
122+
#define AVG_LOCKDEP_CHAIN_DEPTH 5
123+
#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS * AVG_LOCKDEP_CHAIN_DEPTH)
123124

124125
extern struct lock_chain lock_chains[];
125126

kernel/locking/test-ww_mutex.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ static inline u32 prandom_u32_below(u32 ceil)
404404
static int *get_random_order(int count)
405405
{
406406
int *order;
407-
int n, r, tmp;
407+
int n, r;
408408

409409
order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
410410
if (!order)
@@ -415,11 +415,8 @@ static int *get_random_order(int count)
415415

416416
for (n = count - 1; n > 1; n--) {
417417
r = prandom_u32_below(n + 1);
418-
if (r != n) {
419-
tmp = order[n];
420-
order[n] = order[r];
421-
order[r] = tmp;
422-
}
418+
if (r != n)
419+
swap(order[n], order[r]);
423420
}
424421

425422
return order;

lib/Kconfig.debug

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,41 +1502,41 @@ config LOCKDEP_SMALL
15021502
bool
15031503

15041504
config LOCKDEP_BITS
1505-
int "Bitsize for MAX_LOCKDEP_ENTRIES"
1505+
int "Size for MAX_LOCKDEP_ENTRIES (as Nth power of 2)"
15061506
depends on LOCKDEP && !LOCKDEP_SMALL
1507-
range 10 30
1507+
range 10 24
15081508
default 15
15091509
help
15101510
Try increasing this value if you hit "BUG: MAX_LOCKDEP_ENTRIES too low!" message.
15111511

15121512
config LOCKDEP_CHAINS_BITS
1513-
int "Bitsize for MAX_LOCKDEP_CHAINS"
1513+
int "Size for MAX_LOCKDEP_CHAINS (as Nth power of 2)"
15141514
depends on LOCKDEP && !LOCKDEP_SMALL
15151515
range 10 21
15161516
default 16
15171517
help
15181518
Try increasing this value if you hit "BUG: MAX_LOCKDEP_CHAINS too low!" message.
15191519

15201520
config LOCKDEP_STACK_TRACE_BITS
1521-
int "Bitsize for MAX_STACK_TRACE_ENTRIES"
1521+
int "Size for MAX_STACK_TRACE_ENTRIES (as Nth power of 2)"
15221522
depends on LOCKDEP && !LOCKDEP_SMALL
1523-
range 10 30
1523+
range 10 26
15241524
default 19
15251525
help
15261526
Try increasing this value if you hit "BUG: MAX_STACK_TRACE_ENTRIES too low!" message.
15271527

15281528
config LOCKDEP_STACK_TRACE_HASH_BITS
1529-
int "Bitsize for STACK_TRACE_HASH_SIZE"
1529+
int "Size for STACK_TRACE_HASH_SIZE (as Nth power of 2)"
15301530
depends on LOCKDEP && !LOCKDEP_SMALL
1531-
range 10 30
1531+
range 10 26
15321532
default 14
15331533
help
15341534
Try increasing this value if you need large STACK_TRACE_HASH_SIZE.
15351535

15361536
config LOCKDEP_CIRCULAR_QUEUE_BITS
1537-
int "Bitsize for elements in circular_queue struct"
1537+
int "Size for elements in circular_queue struct (as Nth power of 2)"
15381538
depends on LOCKDEP
1539-
range 10 30
1539+
range 10 26
15401540
default 12
15411541
help
15421542
Try increasing this value if you hit "lockdep bfs error:-1" warning due to __cq_enqueue() failure.

rust/helpers/mutex.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ void rust_helper___mutex_init(struct mutex *mutex, const char *name,
1212
{
1313
__mutex_init(mutex, name, key);
1414
}
15+
16+
void rust_helper_mutex_assert_is_held(struct mutex *mutex)
17+
{
18+
lockdep_assert_held(mutex);
19+
}

rust/helpers/spinlock.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ int rust_helper_spin_trylock(spinlock_t *lock)
3030
{
3131
return spin_trylock(lock);
3232
}
33+
34+
void rust_helper_spin_assert_is_held(spinlock_t *lock)
35+
{
36+
lockdep_assert_held(lock);
37+
}

rust/kernel/sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub mod poll;
1616
pub use arc::{Arc, ArcBorrow, UniqueArc};
1717
pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};
1818
pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy};
19-
pub use lock::mutex::{new_mutex, Mutex};
20-
pub use lock::spinlock::{new_spinlock, SpinLock};
19+
pub use lock::mutex::{new_mutex, Mutex, MutexGuard};
20+
pub use lock::spinlock::{new_spinlock, SpinLock, SpinLockGuard};
2121
pub use locked_by::LockedBy;
2222

2323
/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.

rust/kernel/sync/lock.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,20 @@ pub unsafe trait Backend {
9090
// SAFETY: The safety requirements ensure that the lock is initialised.
9191
*guard_state = unsafe { Self::lock(ptr) };
9292
}
93+
94+
/// Asserts that the lock is held using lockdep.
95+
///
96+
/// # Safety
97+
///
98+
/// Callers must ensure that [`Backend::init`] has been previously called.
99+
unsafe fn assert_is_held(ptr: *mut Self::State);
93100
}
94101

95102
/// A mutual exclusion primitive.
96103
///
97104
/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock
98105
/// [`Backend`] specified as the generic parameter `B`.
106+
#[repr(C)]
99107
#[pin_data]
100108
pub struct Lock<T: ?Sized, B: Backend> {
101109
/// The kernel lock object.
@@ -134,6 +142,28 @@ impl<T, B: Backend> Lock<T, B> {
134142
}
135143
}
136144

145+
impl<B: Backend> Lock<(), B> {
146+
/// Constructs a [`Lock`] from a raw pointer.
147+
///
148+
/// This can be useful for interacting with a lock which was initialised outside of Rust.
149+
///
150+
/// # Safety
151+
///
152+
/// The caller promises that `ptr` points to a valid initialised instance of [`State`] during
153+
/// the whole lifetime of `'a`.
154+
///
155+
/// [`State`]: Backend::State
156+
pub unsafe fn from_raw<'a>(ptr: *mut B::State) -> &'a Self {
157+
// SAFETY:
158+
// - By the safety contract `ptr` must point to a valid initialised instance of `B::State`
159+
// - Since the lock data type is `()` which is a ZST, `state` is the only non-ZST member of
160+
// the struct
161+
// - Combined with `#[repr(C)]`, this guarantees `Self` has an equivalent data layout to
162+
// `B::State`.
163+
unsafe { &*ptr.cast() }
164+
}
165+
}
166+
137167
impl<T: ?Sized, B: Backend> Lock<T, B> {
138168
/// Acquires the lock and gives the caller access to the data protected by it.
139169
pub fn lock(&self) -> Guard<'_, T, B> {
@@ -211,7 +241,10 @@ impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
211241
/// # Safety
212242
///
213243
/// The caller must ensure that it owns the lock.
214-
pub(crate) unsafe fn new(lock: &'a Lock<T, B>, state: B::GuardState) -> Self {
244+
pub unsafe fn new(lock: &'a Lock<T, B>, state: B::GuardState) -> Self {
245+
// SAFETY: The caller can only hold the lock if `Backend::init` has already been called.
246+
unsafe { B::assert_is_held(lock.state.get()) };
247+
215248
Self {
216249
lock,
217250
state,

rust/kernel/sync/lock/mutex.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ pub use new_mutex;
8686
/// [`struct mutex`]: srctree/include/linux/mutex.h
8787
pub type Mutex<T> = super::Lock<T, MutexBackend>;
8888

89+
/// A [`Guard`] acquired from locking a [`Mutex`].
90+
///
91+
/// This is simply a type alias for a [`Guard`] returned from locking a [`Mutex`]. It will unlock
92+
/// the [`Mutex`] upon being dropped.
93+
///
94+
/// [`Guard`]: super::Guard
95+
pub type MutexGuard<'a, T> = super::Guard<'a, T, MutexBackend>;
96+
8997
/// A kernel `struct mutex` lock backend.
9098
pub struct MutexBackend;
9199

@@ -126,4 +134,9 @@ unsafe impl super::Backend for MutexBackend {
126134
None
127135
}
128136
}
137+
138+
unsafe fn assert_is_held(ptr: *mut Self::State) {
139+
// SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
140+
unsafe { bindings::mutex_assert_is_held(ptr) }
141+
}
129142
}

0 commit comments

Comments
 (0)