Skip to contentSkip to conversation

locking changes for v4.7

GIT PULL Ingo Molnar 1 participant 1 message May 16, 2016

Subsystems (6)
lore
Share & tools
lore

Ingo Molnar

author maintainer
#0 lore raw

Linus,

Please pull the latest locking-core-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking-core-for-linus

# HEAD: a1cc5bcfcfca0b99f009b117785142dbdc3b87a3 locking/atomics: Flip atomic_fetch_or() arguments

The main changes in this cycle were:

- pvqspinlock statistics fixes (Davidlohr Bueso)

- flip atomic_fetch_or() arguments (Peter Zijlstra)

- locktorture simplification (Paul E. McKenney)

- documentation updates (SeongJae Park, David Howells, Davidlohr Bueso, Paul E. McKenney, Peter Zijlstra, Will Deacon)

- various fixes

Thanks,

Ingo

------------------>
David Howells (1):
locking/Documentation: State purpose of memory-barriers.txt

Davidlohr Bueso (5):
locking/Documentation: Mention smp_cond_acquire() locking/locktorture: Fix deboosting NULL pointer dereference locking/locktorture: Fix NULL pointer dereference for cleanup paths locking/pvqspinlock: Avoid double resetting of stats locking/pvqspinlock: Robustify init_qspinlock_stat()

Denys Vlasenko (1):
locking/lockdep: Deinline register_lock_class(), save 2328 bytes

Eric Engestrom (1):
locking/Documentation/lockdep: Fix spelling mistakes

Paul E. McKenney (2):
locking/Documentation: Clarify relationship of barrier() to control dependencies lcoking/locktorture: Simplify the torture_runnable computation

Peter Zijlstra (2):
locking/Documentation: Add disclaimer locking/atomics: Flip atomic_fetch_or() arguments

SeongJae Park (4):
locking/Documentation: Fix missed s/lock/acquire renames locking/Documentation: Add missed subsection in TOC locking/Documentation: Fix formatting inconsistencies locking/Documentation: Insert white spaces consistently

Will Deacon (1):
locking/Documentation: Clarify that ACQUIRE applies to loads, RELEASE applies to stores

 Documentation/locking/lockdep-design.txt |   4 +-
 Documentation/memory-barriers.txt        | 117 +++++++++++++++++++++----------
 include/linux/atomic.h                   |   4 +-
 kernel/locking/lockdep.c                 |   2 +-
 kernel/locking/locktorture.c             |  25 ++++---
 kernel/locking/qspinlock_stat.h          |  24 ++++---
 kernel/time/tick-sched.c                 |   4 +-
 7 files changed, 117 insertions(+), 63 deletions(-)
Documentation/locking/lockdep-design.txt +2 -2
index 5001280e9d82..9de1c158d44c 100644
@@ -97,7 +97,7 @@ Furthermore, the following usage based lock dependencies are not allowed
    <hardirq-safe>   ->  <hardirq-unsafe>
    <softirq-safe>   ->  <softirq-unsafe>
 
-The first rule comes from the fact the a hardirq-safe lock could be
+The first rule comes from the fact that a hardirq-safe lock could be
 taken by a hardirq context, interrupting a hardirq-unsafe lock - and
 thus could result in a lock inversion deadlock. Likewise, a softirq-safe
 lock could be taken by an softirq context, interrupting a softirq-unsafe
@@ -220,7 +220,7 @@ calculated, which hash is unique for every lock chain. The hash value,
 when the chain is validated for the first time, is then put into a hash
 table, which hash-table can be checked in a lockfree manner. If the
 locking chain occurs again later on, the hash table tells us that we
-dont have to validate the chain again.
+don't have to validate the chain again.
 
 Troubleshooting:
 ----------------
Documentation/memory-barriers.txt +80 -37

279 lines not on this page · raw message

include/linux/atomic.h +2 -2
index 506c3531832e..e451534fe54d 100644
@@ -560,11 +560,11 @@ static inline int atomic_dec_if_positive(atomic_t *v)
 
 /**
  * atomic_fetch_or - perform *p |= mask and return old value of *p
- * @p: pointer to atomic_t
  * @mask: mask to OR on the atomic_t
+ * @p: pointer to atomic_t
  */
 #ifndef atomic_fetch_or
-static inline int atomic_fetch_or(atomic_t *p, int mask)
+static inline int atomic_fetch_or(int mask, atomic_t *p)
 {
 	int old, val = atomic_read(p);
 
kernel/locking/lockdep.c +1 -1
index 78c1c0ee6dc1..874d53eaf389 100644
@@ -708,7 +708,7 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
  * yet. Otherwise we look it up. We cache the result in the lock object
  * itself, so actual lookup of the hash should be once per lock object.
  */
-static inline struct lock_class *
+static struct lock_class *
 register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
 {
 	struct lockdep_subclass_key *key;
kernel/locking/locktorture.c +16 -9
index 8ef1919d63b2..f8c5af52a131 100644
@@ -75,12 +75,7 @@ struct lock_stress_stats {
 	long n_lock_acquired;
 };
 
-#if defined(MODULE)
-#define LOCKTORTURE_RUNNABLE_INIT 1
-#else
-#define LOCKTORTURE_RUNNABLE_INIT 0
-#endif
-int torture_runnable = LOCKTORTURE_RUNNABLE_INIT;
+int torture_runnable = IS_ENABLED(MODULE);
 module_param(torture_runnable, int, 0444);
 MODULE_PARM_DESC(torture_runnable, "Start locktorture at module init");
 
@@ -394,12 +389,12 @@ static void torture_rtmutex_boost(struct torture_random_state *trsp)
 
 	if (!rt_task(current)) {
 		/*
-		 * (1) Boost priority once every ~50k operations. When the
+		 * Boost priority once every ~50k operations. When the
 		 * task tries to take the lock, the rtmutex it will account
 		 * for the new priority, and do any corresponding pi-dance.
 		 */
-		if (!(torture_random(trsp) %
-		      (cxt.nrealwriters_stress * factor))) {
+		if (trsp && !(torture_random(trsp) %
+			      (cxt.nrealwriters_stress * factor))) {
 			policy = SCHED_FIFO;
 			param.sched_priority = MAX_RT_PRIO - 1;
 		} else /* common case, do nothing */
@@ -748,6 +743,15 @@ static void lock_torture_cleanup(void)
 	if (torture_cleanup_begin())
 		return;
 
+	/*
+	 * Indicates early cleanup, meaning that the test has not run,
+	 * such as when passing bogus args when loading the module. As
+	 * such, only perform the underlying torture-specific cleanups,
+	 * and avoid anything related to locktorture.
+	 */
+	if (!cxt.lwsa)
+		goto end;
+
 	if (writer_tasks) {
 		for (i = 0; i < cxt.nrealwriters_stress; i++)
 			torture_stop_kthread(lock_torture_writer,
@@ -776,6 +780,7 @@ static void lock_torture_cleanup(void)
 	else
 		lock_torture_print_module_parms(cxt.cur_ops,
 						"End of test: SUCCESS");
+end:
 	torture_cleanup_end();
 }
 
@@ -870,6 +875,7 @@ static int __init lock_torture_init(void)
 			VERBOSE_TOROUT_STRING("cxt.lrsa: Out of memory");
 			firsterr = -ENOMEM;
 			kfree(cxt.lwsa);
+			cxt.lwsa = NULL;
 			goto unwind;
 		}
 
@@ -878,6 +884,7 @@ static int __init lock_torture_init(void)
 			cxt.lrsa[i].n_lock_acquired = 0;
 		}
 	}
+
 	lock_torture_print_module_parms(cxt.cur_ops, "Start of test");
 
 	/* Prepare torture context. */
kernel/locking/qspinlock_stat.h +14 -10
index d734b7502001..22e025309845 100644
@@ -191,8 +191,6 @@ static ssize_t qstat_write(struct file *file, const char __user *user_buf,
 
 		for (i = 0 ; i < qstat_num; i++)
 			WRITE_ONCE(ptr[i], 0);
-		for (i = 0 ; i < qstat_num; i++)
-			WRITE_ONCE(ptr[i], 0);
 	}
 	return count;
 }
@@ -214,10 +212,8 @@ static int __init init_qspinlock_stat(void)
 	struct dentry *d_qstat = debugfs_create_dir("qlockstat", NULL);
 	int i;
 
-	if (!d_qstat) {
-		pr_warn("Could not create 'qlockstat' debugfs directory\n");
-		return 0;
-	}
+	if (!d_qstat)
+		goto out;
 
 	/*
 	 * Create the debugfs files
@@ -227,12 +223,20 @@ static int __init init_qspinlock_stat(void)
 	 * performance.
 	 */
 	for (i = 0; i < qstat_num; i++)
-		debugfs_create_file(qstat_names[i], 0400, d_qstat,
-				   (void *)(long)i, &fops_qstat);
+		if (!debugfs_create_file(qstat_names[i], 0400, d_qstat,
+					 (void *)(long)i, &fops_qstat))
+			goto fail_undo;
+
+	if (!debugfs_create_file(qstat_names[qstat_reset_cnts], 0200, d_qstat,
+				 (void *)(long)qstat_reset_cnts, &fops_qstat))
+		goto fail_undo;
 
-	debugfs_create_file(qstat_names[qstat_reset_cnts], 0200, d_qstat,
-			   (void *)(long)qstat_reset_cnts, &fops_qstat);
 	return 0;
+fail_undo:
+	debugfs_remove_recursive(d_qstat);
+out:
+	pr_warn("Could not create 'qlockstat' debugfs entries\n");
+	return -ENOMEM;
 }
 fs_initcall(init_qspinlock_stat);
 
kernel/time/tick-sched.c +2 -2
index 58e3310c9b21..3daa49ff0719 100644
@@ -262,7 +262,7 @@ static void tick_nohz_dep_set_all(atomic_t *dep,
 {
 	int prev;
 
-	prev = atomic_fetch_or(dep, BIT(bit));
+	prev = atomic_fetch_or(BIT(bit), dep);
 	if (!prev)
 		tick_nohz_full_kick_all();
 }
@@ -292,7 +292,7 @@ void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit)
 
 	ts = per_cpu_ptr(&tick_cpu_sched, cpu);
 
-	prev = atomic_fetch_or(&ts->tick_dep_mask, BIT(bit));
+	prev = atomic_fetch_or(BIT(bit), &ts->tick_dep_mask);
 	if (!prev) {
 		preempt_disable();
 		/* Perf needs local kick that is NMI safe */