Skip to content

Commit 2da2ca2

Browse files
committed
Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fixes from Thomas Gleixner: "A set of fixes and updates for the locking code: - Prevent lockdep from updating irq state within its own code and thereby confusing itself. - Buid fix for older GCCs which mistreat anonymous unions - Add a missing lockdep annotation in down_read_non_onwer() which causes up_read_non_owner() to emit a lockdep splat - Remove the custom alpha dec_and_lock() implementation which is incorrect in terms of ordering and use the generic one. The remaining two commits are not strictly fixes. They provide irqsave variants of atomic_dec_and_lock() and refcount_dec_and_lock(). These are required to merge the relevant updates and cleanups into different maintainer trees for 4.19, so routing them into mainline without actual users is the sanest approach. They should have been in -rc1, but last weekend I took the liberty to just avoid computers in order to regain some mental sanity" * 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking/qspinlock: Fix build for anonymous union in older GCC compilers locking/lockdep: Do not record IRQ state within lockdep code locking/rwsem: Fix up_read_non_owner() warning with DEBUG_RWSEMS locking/refcounts: Implement refcount_dec_and_lock_irqsave() atomic: Add irqsave variant of atomic_dec_and_lock() alpha: Remove custom dec_and_lock() implementation
2 parents a43de48 + 6cc65be commit 2da2ca2

File tree

11 files changed

+61
-64
lines changed

11 files changed

+61
-64
lines changed

arch/alpha/Kconfig

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -555,11 +555,6 @@ config SMP
555555

556556
If you don't know what to do here, say N.
557557

558-
config HAVE_DEC_LOCK
559-
bool
560-
depends on SMP
561-
default y
562-
563558
config NR_CPUS
564559
int "Maximum number of CPUs (2-32)"
565560
range 2 32

arch/alpha/lib/Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
3535
callback_srm.o srm_puts.o srm_printk.o \
3636
fls.o
3737

38-
lib-$(CONFIG_SMP) += dec_and_lock.o
39-
4038
# The division routines are built from single source, with different defines.
4139
AFLAGS___divqu.o = -DDIV
4240
AFLAGS___remqu.o = -DREM

arch/alpha/lib/dec_and_lock.c

Lines changed: 0 additions & 44 deletions
This file was deleted.

include/asm-generic/qspinlock_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ typedef struct qspinlock {
6363
/*
6464
* Initializier
6565
*/
66-
#define __ARCH_SPIN_LOCK_UNLOCKED { .val = ATOMIC_INIT(0) }
66+
#define __ARCH_SPIN_LOCK_UNLOCKED { { .val = ATOMIC_INIT(0) } }
6767

6868
/*
6969
* Bitfields in the atomic value:

include/linux/refcount.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,7 @@ extern __must_check bool refcount_dec_if_one(refcount_t *r);
9898
extern __must_check bool refcount_dec_not_one(refcount_t *r);
9999
extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock);
100100
extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
101-
101+
extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
102+
spinlock_t *lock,
103+
unsigned long *flags);
102104
#endif /* _LINUX_REFCOUNT_H */

include/linux/spinlock.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
427427
#define atomic_dec_and_lock(atomic, lock) \
428428
__cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
429429

430+
extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
431+
unsigned long *flags);
432+
#define atomic_dec_and_lock_irqsave(atomic, lock, flags) \
433+
__cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags)))
434+
430435
int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
431436
size_t max_size, unsigned int cpu_mult,
432437
gfp_t gfp);

kernel/locking/lockdep.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,11 +1265,11 @@ unsigned long lockdep_count_forward_deps(struct lock_class *class)
12651265
this.parent = NULL;
12661266
this.class = class;
12671267

1268-
local_irq_save(flags);
1268+
raw_local_irq_save(flags);
12691269
arch_spin_lock(&lockdep_lock);
12701270
ret = __lockdep_count_forward_deps(&this);
12711271
arch_spin_unlock(&lockdep_lock);
1272-
local_irq_restore(flags);
1272+
raw_local_irq_restore(flags);
12731273

12741274
return ret;
12751275
}
@@ -1292,11 +1292,11 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class)
12921292
this.parent = NULL;
12931293
this.class = class;
12941294

1295-
local_irq_save(flags);
1295+
raw_local_irq_save(flags);
12961296
arch_spin_lock(&lockdep_lock);
12971297
ret = __lockdep_count_backward_deps(&this);
12981298
arch_spin_unlock(&lockdep_lock);
1299-
local_irq_restore(flags);
1299+
raw_local_irq_restore(flags);
13001300

13011301
return ret;
13021302
}
@@ -4411,7 +4411,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
44114411
if (unlikely(!debug_locks))
44124412
return;
44134413

4414-
local_irq_save(flags);
4414+
raw_local_irq_save(flags);
44154415
for (i = 0; i < curr->lockdep_depth; i++) {
44164416
hlock = curr->held_locks + i;
44174417

@@ -4422,7 +4422,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
44224422
print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock);
44234423
break;
44244424
}
4425-
local_irq_restore(flags);
4425+
raw_local_irq_restore(flags);
44264426
}
44274427
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
44284428

kernel/locking/rwsem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ void down_read_non_owner(struct rw_semaphore *sem)
181181
might_sleep();
182182

183183
__down_read(sem);
184+
rwsem_set_reader_owned(sem);
184185
}
185186

186187
EXPORT_SYMBOL(down_read_non_owner);

lib/Makefile

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
2323
sha1.o chacha20.o irq_regs.o argv_split.o \
2424
flex_proportions.o ratelimit.o show_mem.o \
2525
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
26-
earlycpio.o seq_buf.o siphash.o \
26+
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
2727
nmi_backtrace.o nodemask.o win_minmax.o
2828

2929
lib-$(CONFIG_PRINTK) += dump_stack.o
@@ -95,10 +95,6 @@ obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
9595
obj-$(CONFIG_DEBUG_LIST) += list_debug.o
9696
obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
9797

98-
ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
99-
lib-y += dec_and_lock.o
100-
endif
101-
10298
obj-$(CONFIG_BITREVERSE) += bitrev.o
10399
obj-$(CONFIG_RATIONAL) += rational.o
104100
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o

lib/dec_and_lock.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,19 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
3333
}
3434

3535
EXPORT_SYMBOL(_atomic_dec_and_lock);
36+
37+
int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
38+
unsigned long *flags)
39+
{
40+
/* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
41+
if (atomic_add_unless(atomic, -1, 1))
42+
return 0;
43+
44+
/* Otherwise do it the slow way */
45+
spin_lock_irqsave(lock, *flags);
46+
if (atomic_dec_and_test(atomic))
47+
return 1;
48+
spin_unlock_irqrestore(lock, *flags);
49+
return 0;
50+
}
51+
EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave);

lib/refcount.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,31 @@ bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock)
350350
}
351351
EXPORT_SYMBOL(refcount_dec_and_lock);
352352

353+
/**
354+
* refcount_dec_and_lock_irqsave - return holding spinlock with disabled
355+
* interrupts if able to decrement refcount to 0
356+
* @r: the refcount
357+
* @lock: the spinlock to be locked
358+
* @flags: saved IRQ-flags if the is acquired
359+
*
360+
* Same as refcount_dec_and_lock() above except that the spinlock is acquired
361+
* with disabled interupts.
362+
*
363+
* Return: true and hold spinlock if able to decrement refcount to 0, false
364+
* otherwise
365+
*/
366+
bool refcount_dec_and_lock_irqsave(refcount_t *r, spinlock_t *lock,
367+
unsigned long *flags)
368+
{
369+
if (refcount_dec_not_one(r))
370+
return false;
371+
372+
spin_lock_irqsave(lock, *flags);
373+
if (!refcount_dec_and_test(r)) {
374+
spin_unlock_irqrestore(lock, *flags);
375+
return false;
376+
}
377+
378+
return true;
379+
}
380+
EXPORT_SYMBOL(refcount_dec_and_lock_irqsave);

0 commit comments

Comments
 (0)