Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b367f5d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull core kernel fixes from Ingo Molnar:
 "This contains the nohz/atomic cleanup/fix for the fetch_or() ugliness
  you noted during the original nohz pull request, plus there's also
  misc fixes:

   - fix liblockdep build bug
   - fix uapi header build bug
   - print more lockdep hash collision info to help debug recent reports
     of hash collisions
   - update MAINTAINERS email address"

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  MAINTAINERS: Update my email address
  locking/lockdep: Print chain_key collision information
  uapi/linux/stddef.h: Provide __always_inline to userspace headers
  tools/lib/lockdep: Fix unsupported 'basename -s' in run_tests.sh
  locking/atomic, sched: Unexport fetch_or()
  timers/nohz: Convert tick dependency mask to atomic_t
  locking/atomic: Introduce atomic_fetch_or()
parents 17084b7e 353def94
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -6403,7 +6403,7 @@ KPROBES
M:	Ananth N Mavinakayanahalli <ananth@in.ibm.com>
M:	Ananth N Mavinakayanahalli <ananth@in.ibm.com>
M:	Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
M:	Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
M:	"David S. Miller" <davem@davemloft.net>
M:	"David S. Miller" <davem@davemloft.net>
M:	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
M:	Masami Hiramatsu <mhiramat@kernel.org>
S:	Maintained
S:	Maintained
F:	Documentation/kprobes.txt
F:	Documentation/kprobes.txt
F:	include/linux/kprobes.h
F:	include/linux/kprobes.h
+17 −17
Original line number Original line Diff line number Diff line
@@ -559,25 +559,25 @@ static inline int atomic_dec_if_positive(atomic_t *v)
#endif
#endif


/**
/**
 * fetch_or - perform *ptr |= mask and return old value of *ptr
 * atomic_fetch_or - perform *p |= mask and return old value of *p
 * @ptr: pointer to value
 * @p: pointer to atomic_t
 * @mask: mask to OR on the value
 * @mask: mask to OR on the atomic_t
 *
 * cmpxchg based fetch_or, macro so it works for different integer types
 */
 */
#ifndef fetch_or
#ifndef atomic_fetch_or
#define fetch_or(ptr, mask)						\
static inline int atomic_fetch_or(atomic_t *p, int mask)
({	typeof(*(ptr)) __old, __val = *(ptr);				\
{
	for (;;) {							\
	int old, val = atomic_read(p);
		__old = cmpxchg((ptr), __val, __val | (mask));		\

		if (__old == __val)					\
	for (;;) {
			break;						\
		old = atomic_cmpxchg(p, val, val | mask);
		__val = __old;						\
		if (old == val)
	}								\
			break;
	__old;								\
		val = old;
})
	}
#endif


	return old;
}
#endif


#ifdef CONFIG_GENERIC_ATOMIC64
#ifdef CONFIG_GENERIC_ATOMIC64
#include <asm-generic/atomic64.h>
#include <asm-generic/atomic64.h>
+2 −2
Original line number Original line Diff line number Diff line
@@ -720,7 +720,7 @@ struct signal_struct {
	struct task_cputime cputime_expires;
	struct task_cputime cputime_expires;


#ifdef CONFIG_NO_HZ_FULL
#ifdef CONFIG_NO_HZ_FULL
	unsigned long tick_dep_mask;
	atomic_t tick_dep_mask;
#endif
#endif


	struct list_head cpu_timers[3];
	struct list_head cpu_timers[3];
@@ -1549,7 +1549,7 @@ struct task_struct {
#endif
#endif


#ifdef CONFIG_NO_HZ_FULL
#ifdef CONFIG_NO_HZ_FULL
	unsigned long tick_dep_mask;
	atomic_t tick_dep_mask;
#endif
#endif
	unsigned long nvcsw, nivcsw; /* context switch counts */
	unsigned long nvcsw, nivcsw; /* context switch counts */
	u64 start_time;		/* monotonic time in nsec */
	u64 start_time;		/* monotonic time in nsec */
+4 −0
Original line number Original line Diff line number Diff line
#include <linux/compiler.h>
#include <linux/compiler.h>

#ifndef __always_inline
#define __always_inline inline
#endif
+77 −2
Original line number Original line Diff line number Diff line
@@ -1999,6 +1999,77 @@ static inline int get_first_held_lock(struct task_struct *curr,
	return ++i;
	return ++i;
}
}


/*
 * Returns the next chain_key iteration
 */
static u64 print_chain_key_iteration(int class_idx, u64 chain_key)
{
	u64 new_chain_key = iterate_chain_key(chain_key, class_idx);

	printk(" class_idx:%d -> chain_key:%016Lx",
		class_idx,
		(unsigned long long)new_chain_key);
	return new_chain_key;
}

static void
print_chain_keys_held_locks(struct task_struct *curr, struct held_lock *hlock_next)
{
	struct held_lock *hlock;
	u64 chain_key = 0;
	int depth = curr->lockdep_depth;
	int i;

	printk("depth: %u\n", depth + 1);
	for (i = get_first_held_lock(curr, hlock_next); i < depth; i++) {
		hlock = curr->held_locks + i;
		chain_key = print_chain_key_iteration(hlock->class_idx, chain_key);

		print_lock(hlock);
	}

	print_chain_key_iteration(hlock_next->class_idx, chain_key);
	print_lock(hlock_next);
}

static void print_chain_keys_chain(struct lock_chain *chain)
{
	int i;
	u64 chain_key = 0;
	int class_id;

	printk("depth: %u\n", chain->depth);
	for (i = 0; i < chain->depth; i++) {
		class_id = chain_hlocks[chain->base + i];
		chain_key = print_chain_key_iteration(class_id + 1, chain_key);

		print_lock_name(lock_classes + class_id);
		printk("\n");
	}
}

static void print_collision(struct task_struct *curr,
			struct held_lock *hlock_next,
			struct lock_chain *chain)
{
	printk("\n");
	printk("======================\n");
	printk("[chain_key collision ]\n");
	print_kernel_ident();
	printk("----------------------\n");
	printk("%s/%d: ", current->comm, task_pid_nr(current));
	printk("Hash chain already cached but the contents don't match!\n");

	printk("Held locks:");
	print_chain_keys_held_locks(curr, hlock_next);

	printk("Locks in cached chain:");
	print_chain_keys_chain(chain);

	printk("\nstack backtrace:\n");
	dump_stack();
}

/*
/*
 * Checks whether the chain and the current held locks are consistent
 * Checks whether the chain and the current held locks are consistent
 * in depth and also in content. If they are not it most likely means
 * in depth and also in content. If they are not it most likely means
@@ -2014,15 +2085,19 @@ static int check_no_collision(struct task_struct *curr,


	i = get_first_held_lock(curr, hlock);
	i = get_first_held_lock(curr, hlock);


	if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1)))
	if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) {
		print_collision(curr, hlock, chain);
		return 0;
		return 0;
	}


	for (j = 0; j < chain->depth - 1; j++, i++) {
	for (j = 0; j < chain->depth - 1; j++, i++) {
		id = curr->held_locks[i].class_idx - 1;
		id = curr->held_locks[i].class_idx - 1;


		if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id))
		if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) {
			print_collision(curr, hlock, chain);
			return 0;
			return 0;
		}
		}
	}
#endif
#endif
	return 1;
	return 1;
}
}
Loading