Skip to content

Commit 1eefdec

Browse files
committed
Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking updates from Ingo Molnar: "The main change in this cycle are initial preparatory bits of dynamic lockdep keys support from Bart Van Assche. There are also misc changes, a comment cleanup and a data structure cleanup" * 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/fair: Clean up comment in nohz_idle_balance() locking/lockdep: Stop using RCU primitives to access 'all_lock_classes' locking/lockdep: Make concurrent lockdep_reset_lock() calls safe locking/lockdep: Remove a superfluous INIT_LIST_HEAD() statement locking/lockdep: Introduce lock_class_cache_is_registered() locking/lockdep: Inline __lockdep_init_map() locking/lockdep: Declare local symbols static tools/lib/lockdep/tests: Test the lockdep_reset_lock() implementation tools/lib/lockdep: Add dummy print_irqtrace_events() implementation tools/lib/lockdep: Rename "trywlock" into "trywrlock" tools/lib/lockdep/tests: Run lockdep tests a second time under Valgrind tools/lib/lockdep/tests: Improve testing accuracy tools/lib/lockdep/tests: Fix shellcheck warnings tools/lib/lockdep/tests: Display compiler warning and error messages locking/lockdep: Remove ::version from lock_class structure
2 parents 684019d + 80eb865 commit 1eefdec

File tree

26 files changed

+131
-53
lines changed

26 files changed

+131
-53
lines changed

include/linux/lockdep.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ struct lock_class {
9797
* Generation counter, when doing certain classes of graph walking,
9898
* to ensure that we check one node only once:
9999
*/
100-
unsigned int version;
101-
102100
int name_version;
103101
const char *name;
104102

kernel/locking/lockdep.c

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
138138
* get freed - this significantly simplifies the debugging code.
139139
*/
140140
unsigned long nr_lock_classes;
141+
#ifndef CONFIG_DEBUG_LOCKDEP
142+
static
143+
#endif
141144
struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
142145

143146
static inline struct lock_class *hlock_class(struct held_lock *hlock)
@@ -626,7 +629,8 @@ static int static_obj(void *obj)
626629

627630
/*
628631
* To make lock name printouts unique, we calculate a unique
629-
* class->name_version generation counter:
632+
* class->name_version generation counter. The caller must hold the graph
633+
* lock.
630634
*/
631635
static int count_matching_names(struct lock_class *new_class)
632636
{
@@ -636,7 +640,7 @@ static int count_matching_names(struct lock_class *new_class)
636640
if (!new_class->name)
637641
return 0;
638642

639-
list_for_each_entry_rcu(class, &all_lock_classes, lock_entry) {
643+
list_for_each_entry(class, &all_lock_classes, lock_entry) {
640644
if (new_class->key - new_class->subclass == class->key)
641645
return class->name_version;
642646
if (class->name && !strcmp(class->name, new_class->name))
@@ -789,7 +793,6 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
789793
class->key = key;
790794
class->name = lock->name;
791795
class->subclass = subclass;
792-
INIT_LIST_HEAD(&class->lock_entry);
793796
INIT_LIST_HEAD(&class->locks_before);
794797
INIT_LIST_HEAD(&class->locks_after);
795798
class->name_version = count_matching_names(class);
@@ -801,7 +804,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
801804
/*
802805
* Add it to the global list of classes:
803806
*/
804-
list_add_tail_rcu(&class->lock_entry, &all_lock_classes);
807+
list_add_tail(&class->lock_entry, &all_lock_classes);
805808

806809
if (verbose(class)) {
807810
graph_unlock();
@@ -3088,7 +3091,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
30883091
/*
30893092
* Initialize a lock instance's lock-class mapping info:
30903093
*/
3091-
static void __lockdep_init_map(struct lockdep_map *lock, const char *name,
3094+
void lockdep_init_map(struct lockdep_map *lock, const char *name,
30923095
struct lock_class_key *key, int subclass)
30933096
{
30943097
int i;
@@ -3144,12 +3147,6 @@ static void __lockdep_init_map(struct lockdep_map *lock, const char *name,
31443147
raw_local_irq_restore(flags);
31453148
}
31463149
}
3147-
3148-
void lockdep_init_map(struct lockdep_map *lock, const char *name,
3149-
struct lock_class_key *key, int subclass)
3150-
{
3151-
__lockdep_init_map(lock, name, key, subclass);
3152-
}
31533150
EXPORT_SYMBOL_GPL(lockdep_init_map);
31543151

31553152
struct lock_class_key __lockdep_no_validate__;
@@ -4126,6 +4123,9 @@ void lockdep_reset(void)
41264123
raw_local_irq_restore(flags);
41274124
}
41284125

4126+
/*
4127+
* Remove all references to a lock class. The caller must hold the graph lock.
4128+
*/
41294129
static void zap_class(struct lock_class *class)
41304130
{
41314131
int i;
@@ -4142,7 +4142,7 @@ static void zap_class(struct lock_class *class)
41424142
* Unhash the class and remove it from the all_lock_classes list:
41434143
*/
41444144
hlist_del_rcu(&class->hash_entry);
4145-
list_del_rcu(&class->lock_entry);
4145+
list_del(&class->lock_entry);
41464146

41474147
RCU_INIT_POINTER(class->key, NULL);
41484148
RCU_INIT_POINTER(class->name, NULL);
@@ -4204,15 +4204,36 @@ void lockdep_free_key_range(void *start, unsigned long size)
42044204
*/
42054205
}
42064206

4207-
void lockdep_reset_lock(struct lockdep_map *lock)
4207+
/*
4208+
* Check whether any element of the @lock->class_cache[] array refers to a
4209+
* registered lock class. The caller must hold either the graph lock or the
4210+
* RCU read lock.
4211+
*/
4212+
static bool lock_class_cache_is_registered(struct lockdep_map *lock)
42084213
{
42094214
struct lock_class *class;
42104215
struct hlist_head *head;
4211-
unsigned long flags;
42124216
int i, j;
4213-
int locked;
4217+
4218+
for (i = 0; i < CLASSHASH_SIZE; i++) {
4219+
head = classhash_table + i;
4220+
hlist_for_each_entry_rcu(class, head, hash_entry) {
4221+
for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
4222+
if (lock->class_cache[j] == class)
4223+
return true;
4224+
}
4225+
}
4226+
return false;
4227+
}
4228+
4229+
void lockdep_reset_lock(struct lockdep_map *lock)
4230+
{
4231+
struct lock_class *class;
4232+
unsigned long flags;
4233+
int j, locked;
42144234

42154235
raw_local_irq_save(flags);
4236+
locked = graph_lock();
42164237

42174238
/*
42184239
* Remove all classes this lock might have:
@@ -4229,25 +4250,14 @@ void lockdep_reset_lock(struct lockdep_map *lock)
42294250
* Debug check: in the end all mapped classes should
42304251
* be gone.
42314252
*/
4232-
locked = graph_lock();
4233-
for (i = 0; i < CLASSHASH_SIZE; i++) {
4234-
head = classhash_table + i;
4235-
hlist_for_each_entry_rcu(class, head, hash_entry) {
4236-
int match = 0;
4237-
4238-
for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
4239-
match |= class == lock->class_cache[j];
4240-
4241-
if (unlikely(match)) {
4242-
if (debug_locks_off_graph_unlock()) {
4243-
/*
4244-
* We all just reset everything, how did it match?
4245-
*/
4246-
WARN_ON(1);
4247-
}
4248-
goto out_restore;
4249-
}
4253+
if (unlikely(lock_class_cache_is_registered(lock))) {
4254+
if (debug_locks_off_graph_unlock()) {
4255+
/*
4256+
* We all just reset everything, how did it match?
4257+
*/
4258+
WARN_ON(1);
42504259
}
4260+
goto out_restore;
42514261
}
42524262
if (locked)
42534263
graph_unlock();

kernel/sched/fair.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9533,9 +9533,7 @@ static bool nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle)
95339533
return false;
95349534
}
95359535

9536-
/*
9537-
* barrier, pairs with nohz_balance_enter_idle(), ensures ...
9538-
*/
9536+
/* could be _relaxed() */
95399537
flags = atomic_fetch_andnot(NOHZ_KICK_MASK, nohz_flags(this_cpu));
95409538
if (!(flags & NOHZ_KICK_MASK))
95419539
return false;

tools/lib/lockdep/include/liblockdep/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
4444
struct lockdep_map *nest_lock, unsigned long ip);
4545
void lock_release(struct lockdep_map *lock, int nested,
4646
unsigned long ip);
47+
void lockdep_reset_lock(struct lockdep_map *lock);
4748
extern void debug_check_no_locks_freed(const void *from, unsigned long len);
4849

4950
#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \

tools/lib/lockdep/include/liblockdep/mutex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *l
5454

5555
static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
5656
{
57+
lockdep_reset_lock(&lock->dep_map);
5758
return pthread_mutex_destroy(&lock->mutex);
5859
}
5960

tools/lib/lockdep/include/liblockdep/rwlock.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_
6060
return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
6161
}
6262

63-
static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock)
63+
static inline int liblockdep_pthread_rwlock_trywrlock(liblockdep_pthread_rwlock_t *lock)
6464
{
6565
lock_acquire(&lock->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_);
66-
return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0;
66+
return pthread_rwlock_trywrlock(&lock->rwlock) == 0 ? 1 : 0;
6767
}
6868

6969
static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
@@ -79,7 +79,7 @@ static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
7979
#define pthread_rwlock_unlock liblockdep_pthread_rwlock_unlock
8080
#define pthread_rwlock_wrlock liblockdep_pthread_rwlock_wrlock
8181
#define pthread_rwlock_tryrdlock liblockdep_pthread_rwlock_tryrdlock
82-
#define pthread_rwlock_trywlock liblockdep_pthread_rwlock_trywlock
82+
#define pthread_rwlock_trywrlock liblockdep_pthread_rwlock_trywrlock
8383
#define pthread_rwlock_destroy liblockdep_rwlock_destroy
8484

8585
#endif

tools/lib/lockdep/lockdep.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ u32 prandom_u32(void)
1515
abort();
1616
}
1717

18+
void print_irqtrace_events(struct task_struct *curr)
19+
{
20+
abort();
21+
}
22+
1823
static struct new_utsname *init_utsname(void)
1924
{
2025
static struct new_utsname n = (struct new_utsname) {

tools/lib/lockdep/run_tests.sh

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,47 @@
11
#! /bin/bash
22
# SPDX-License-Identifier: GPL-2.0
33

4-
make &> /dev/null
4+
if ! make >/dev/null; then
5+
echo "Building liblockdep failed."
6+
echo "FAILED!"
7+
exit 1
8+
fi
59

6-
for i in `ls tests/*.c`; do
10+
find tests -name '*.c' | sort | while read -r i; do
711
testname=$(basename "$i" .c)
8-
gcc -o tests/$testname -pthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
912
echo -ne "$testname... "
10-
if [ $(timeout 1 ./tests/$testname 2>&1 | wc -l) -gt 0 ]; then
13+
if gcc -o "tests/$testname" -pthread "$i" liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &&
14+
timeout 1 "tests/$testname" 2>&1 | "tests/${testname}.sh"; then
1115
echo "PASSED!"
1216
else
1317
echo "FAILED!"
1418
fi
15-
if [ -f "tests/$testname" ]; then
16-
rm tests/$testname
17-
fi
19+
rm -f "tests/$testname"
1820
done
1921

20-
for i in `ls tests/*.c`; do
22+
find tests -name '*.c' | sort | while read -r i; do
2123
testname=$(basename "$i" .c)
22-
gcc -o tests/$testname -pthread -Iinclude $i &> /dev/null
2324
echo -ne "(PRELOAD) $testname... "
24-
if [ $(timeout 1 ./lockdep ./tests/$testname 2>&1 | wc -l) -gt 0 ]; then
25+
if gcc -o "tests/$testname" -pthread -Iinclude "$i" &&
26+
timeout 1 ./lockdep "tests/$testname" 2>&1 |
27+
"tests/${testname}.sh"; then
2528
echo "PASSED!"
2629
else
2730
echo "FAILED!"
2831
fi
29-
if [ -f "tests/$testname" ]; then
30-
rm tests/$testname
32+
rm -f "tests/$testname"
33+
done
34+
35+
find tests -name '*.c' | sort | while read -r i; do
36+
testname=$(basename "$i" .c)
37+
echo -ne "(PRELOAD + Valgrind) $testname... "
38+
if gcc -o "tests/$testname" -pthread -Iinclude "$i" &&
39+
{ timeout 10 valgrind --read-var-info=yes ./lockdep "./tests/$testname" >& "tests/${testname}.vg.out"; true; } &&
40+
"tests/${testname}.sh" < "tests/${testname}.vg.out" &&
41+
! grep -Eq '(^==[0-9]*== (Invalid |Uninitialised ))|Mismatched free|Source and destination overlap| UME ' "tests/${testname}.vg.out"; then
42+
echo "PASSED!"
43+
else
44+
echo "FAILED!"
3145
fi
46+
rm -f "tests/$testname"
3247
done

tools/lib/lockdep/tests/AA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible recursive locking detected'

tools/lib/lockdep/tests/ABA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible recursive locking detected'

tools/lib/lockdep/tests/ABBA.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ void main(void)
1111

1212
LOCK_UNLOCK_2(a, b);
1313
LOCK_UNLOCK_2(b, a);
14+
15+
pthread_mutex_destroy(&b);
16+
pthread_mutex_destroy(&a);
1417
}

tools/lib/lockdep/tests/ABBA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/ABBCCA.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ void main(void)
1313
LOCK_UNLOCK_2(a, b);
1414
LOCK_UNLOCK_2(b, c);
1515
LOCK_UNLOCK_2(c, a);
16+
17+
pthread_mutex_destroy(&c);
18+
pthread_mutex_destroy(&b);
19+
pthread_mutex_destroy(&a);
1620
}

tools/lib/lockdep/tests/ABBCCA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/ABBCCDDA.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ void main(void)
1515
LOCK_UNLOCK_2(b, c);
1616
LOCK_UNLOCK_2(c, d);
1717
LOCK_UNLOCK_2(d, a);
18+
19+
pthread_mutex_destroy(&d);
20+
pthread_mutex_destroy(&c);
21+
pthread_mutex_destroy(&b);
22+
pthread_mutex_destroy(&a);
1823
}

tools/lib/lockdep/tests/ABBCCDDA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/ABCABC.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ void main(void)
1313
LOCK_UNLOCK_2(a, b);
1414
LOCK_UNLOCK_2(c, a);
1515
LOCK_UNLOCK_2(b, c);
16+
17+
pthread_mutex_destroy(&c);
18+
pthread_mutex_destroy(&b);
19+
pthread_mutex_destroy(&a);
1620
}

tools/lib/lockdep/tests/ABCABC.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/ABCDBCDA.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ void main(void)
1515
LOCK_UNLOCK_2(c, d);
1616
LOCK_UNLOCK_2(b, c);
1717
LOCK_UNLOCK_2(d, a);
18+
19+
pthread_mutex_destroy(&d);
20+
pthread_mutex_destroy(&c);
21+
pthread_mutex_destroy(&b);
22+
pthread_mutex_destroy(&a);
1823
}

tools/lib/lockdep/tests/ABCDBCDA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/ABCDBDDA.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ void main(void)
1515
LOCK_UNLOCK_2(c, d);
1616
LOCK_UNLOCK_2(b, d);
1717
LOCK_UNLOCK_2(d, a);
18+
19+
pthread_mutex_destroy(&d);
20+
pthread_mutex_destroy(&c);
21+
pthread_mutex_destroy(&b);
22+
pthread_mutex_destroy(&a);
1823
}

tools/lib/lockdep/tests/ABCDBDDA.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible circular locking dependency detected'

tools/lib/lockdep/tests/WW.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: possible recursive locking detected'

tools/lib/lockdep/tests/unlock_balance.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ void main(void)
1010
pthread_mutex_lock(&a);
1111
pthread_mutex_unlock(&a);
1212
pthread_mutex_unlock(&a);
13+
14+
pthread_mutex_destroy(&a);
1315
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
grep -q 'WARNING: bad unlock balance detected'

0 commit comments

Comments
 (0)