Skip to content
Snippets Groups Projects
lockdep.c 68.3 KiB
Newer Older
Ingo Molnar's avatar
Ingo Molnar committed
	/*
	 * Debugging checks.
	 *
	 * Depth must not be zero for a non-head lock:
	 */
	if (!depth)
		goto out_bug;
	/*
	 * At least two relevant locks must exist for this
	 * to be a head:
	 */
	if (curr->held_locks[depth].irq_context !=
			curr->held_locks[depth-1].irq_context)
		goto out_bug;

	for (;;) {
		hlock = curr->held_locks + depth-1;
		/*
		 * Only non-recursive-read entries get new dependencies
		 * added:
		 */
		if (hlock->read != 2) {
			if (!check_prev_add(curr, hlock, next))
				return 0;
Ingo Molnar's avatar
Ingo Molnar committed
			/*
			 * Stop after the first non-trylock entry,
			 * as non-trylock entries have added their
			 * own direct dependencies already, so this
			 * lock is connected to them indirectly:
			 */
			if (!hlock->trylock)
				break;
		}
		depth--;
		/*
		 * End of lock-stack?
		 */
		if (!depth)
			break;
		/*
		 * Stop the search if we cross into another context:
		 */
		if (curr->held_locks[depth].irq_context !=
				curr->held_locks[depth-1].irq_context)
			break;
	}
	return 1;
out_bug:
	__raw_spin_unlock(&hash_lock);
	DEBUG_LOCKS_WARN_ON(1);

	return 0;
}


/*
 * Is this the address of a static object:
 */
static int static_obj(void *obj)
{
	unsigned long start = (unsigned long) &_stext,
		      end   = (unsigned long) &_end,
		      addr  = (unsigned long) obj;
#ifdef CONFIG_SMP
	int i;
#endif

	/*
	 * static variable?
	 */
	if ((addr >= start) && (addr < end))
		return 1;

#ifdef CONFIG_SMP
	/*
	 * percpu var?
	 */
	for_each_possible_cpu(i) {
		start = (unsigned long) &__per_cpu_start + per_cpu_offset(i);
		end   = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM
					+ per_cpu_offset(i);
Ingo Molnar's avatar
Ingo Molnar committed

		if ((addr >= start) && (addr < end))
			return 1;
	}
#endif

	/*
	 * module var?
	 */
	return is_module_address(addr);
}

/*
 * To make lock name printouts unique, we calculate a unique
 * class->name_version generation counter:
 */
static int count_matching_names(struct lock_class *new_class)
{
	struct lock_class *class;
	int count = 0;

	if (!new_class->name)
		return 0;

	list_for_each_entry(class, &all_lock_classes, lock_entry) {
		if (new_class->key - new_class->subclass == class->key)
			return class->name_version;
		if (class->name && !strcmp(class->name, new_class->name))
			count = max(count, class->name_version);
	}

	return count + 1;
}

/*
 * Register a lock's class in the hash-table, if the class is not present
 * 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 *
look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
Ingo Molnar's avatar
Ingo Molnar committed
{
	struct lockdep_subclass_key *key;
	struct list_head *hash_head;
	struct lock_class *class;

#ifdef CONFIG_DEBUG_LOCKDEP
	/*
	 * If the architecture calls into lockdep before initializing
	 * the hashes then we'll warn about it later. (we cannot printk
	 * right now)
	 */
	if (unlikely(!lockdep_initialized)) {
		lockdep_init();
		lockdep_init_error = 1;
	}
#endif

	/*
	 * Static locks do not have their class-keys yet - for them the key
	 * is the lock object itself:
	 */
	if (unlikely(!lock->key))
		lock->key = (void *)lock;

	/*
	 * NOTE: the class-key must be unique. For dynamic locks, a static
	 * lock_class_key variable is passed in through the mutex_init()
	 * (or spin_lock_init()) call - which acts as the key. For static
	 * locks we use the lock object itself as the key.
	 */
	BUILD_BUG_ON(sizeof(struct lock_class_key) > sizeof(struct lock_class));
Ingo Molnar's avatar
Ingo Molnar committed

	key = lock->key->subkeys + subclass;

	hash_head = classhashentry(key);

	/*
	 * We can walk the hash lockfree, because the hash only
	 * grows, and we are careful when adding entries to the end:
	 */
	list_for_each_entry(class, hash_head, hash_entry)
		if (class->key == key)
			return class;

	return NULL;
}

/*
 * Register a lock's class in the hash-table, if the class is not present
 * 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 *
register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
{
	struct lockdep_subclass_key *key;
	struct list_head *hash_head;
	struct lock_class *class;
	unsigned long flags;

	class = look_up_lock_class(lock, subclass);
	if (likely(class))
		return class;
Ingo Molnar's avatar
Ingo Molnar committed

	/*
	 * Debug-check: all keys must be persistent!
 	 */
	if (!static_obj(lock->key)) {
		debug_locks_off();
		printk("INFO: trying to register non-static key.\n");
		printk("the code is fine but needs lockdep annotation.\n");
		printk("turning off the locking correctness validator.\n");
		dump_stack();

		return NULL;
	}

	key = lock->key->subkeys + subclass;
	hash_head = classhashentry(key);

	raw_local_irq_save(flags);
Ingo Molnar's avatar
Ingo Molnar committed
	__raw_spin_lock(&hash_lock);
	/*
	 * We have to do the hash-walk again, to avoid races
	 * with another CPU:
	 */
	list_for_each_entry(class, hash_head, hash_entry)
		if (class->key == key)
			goto out_unlock_set;
	/*
	 * Allocate a new key from the static array, and add it to
	 * the hash:
	 */
	if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
		__raw_spin_unlock(&hash_lock);
		raw_local_irq_restore(flags);
Ingo Molnar's avatar
Ingo Molnar committed
		debug_locks_off();
		printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
		printk("turning off the locking correctness validator.\n");
		return NULL;
	}
	class = lock_classes + nr_lock_classes++;
	debug_atomic_inc(&nr_unused_locks);
	class->key = key;
	class->name = lock->name;
	class->subclass = subclass;
	INIT_LIST_HEAD(&class->lock_entry);
	INIT_LIST_HEAD(&class->locks_before);
	INIT_LIST_HEAD(&class->locks_after);
	class->name_version = count_matching_names(class);
	/*
	 * We use RCU's safe list-add method to make
	 * parallel walking of the hash-list safe:
	 */
	list_add_tail_rcu(&class->hash_entry, hash_head);

	if (verbose(class)) {
		__raw_spin_unlock(&hash_lock);
		raw_local_irq_restore(flags);
Ingo Molnar's avatar
Ingo Molnar committed
		printk("\nnew class %p: %s", class->key, class->name);
		if (class->name_version > 1)
			printk("#%d", class->name_version);
		printk("\n");
		dump_stack();
		raw_local_irq_save(flags);
Ingo Molnar's avatar
Ingo Molnar committed
		__raw_spin_lock(&hash_lock);
	}
out_unlock_set:
	__raw_spin_unlock(&hash_lock);
	raw_local_irq_restore(flags);
		lock->class_cache = class;
Ingo Molnar's avatar
Ingo Molnar committed

	DEBUG_LOCKS_WARN_ON(class->subclass != subclass);

	return class;
}

/*
 * Look up a dependency chain. If the key is not present yet then
 * add it and return 0 - in this case the new dependency chain is
 * validated. If the key is already hashed, return 1.
 */
static inline int lookup_chain_cache(u64 chain_key)
{
	struct list_head *hash_head = chainhashentry(chain_key);
	struct lock_chain *chain;

	DEBUG_LOCKS_WARN_ON(!irqs_disabled());
	/*
	 * We can walk it lock-free, because entries only get added
	 * to the hash:
	 */
	list_for_each_entry(chain, hash_head, entry) {
		if (chain->chain_key == chain_key) {
cache_hit:
			debug_atomic_inc(&chain_lookup_hits);
			/*
			 * In the debugging case, force redundant checking
			 * by returning 1:
			 */
#ifdef CONFIG_DEBUG_LOCKDEP
			__raw_spin_lock(&hash_lock);
			return 1;
#endif
			return 0;
		}
	}
	/*
	 * Allocate a new chain entry from the static array, and add
	 * it to the hash:
	 */
	__raw_spin_lock(&hash_lock);
	/*
	 * We have to walk the chain again locked - to avoid duplicates:
	 */
	list_for_each_entry(chain, hash_head, entry) {
		if (chain->chain_key == chain_key) {
			__raw_spin_unlock(&hash_lock);
			goto cache_hit;
		}
	}
	if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) {
		__raw_spin_unlock(&hash_lock);
		debug_locks_off();
		printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
		printk("turning off the locking correctness validator.\n");
		return 0;
	}
	chain = lock_chains + nr_lock_chains++;
	chain->chain_key = chain_key;
	list_add_tail_rcu(&chain->entry, hash_head);
	debug_atomic_inc(&chain_lookup_misses);
#ifdef CONFIG_TRACE_IRQFLAGS
	if (current->hardirq_context)
		nr_hardirq_chains++;
	else {
		if (current->softirq_context)
			nr_softirq_chains++;
		else
			nr_process_chains++;
	}
#else
	nr_process_chains++;
#endif

	return 1;
}

/*
 * We are building curr_chain_key incrementally, so double-check
 * it from scratch, to make sure that it's done correctly:
 */
static void check_chain_key(struct task_struct *curr)
{
#ifdef CONFIG_DEBUG_LOCKDEP
	struct held_lock *hlock, *prev_hlock = NULL;
	unsigned int i, id;
	u64 chain_key = 0;

	for (i = 0; i < curr->lockdep_depth; i++) {
		hlock = curr->held_locks + i;
		if (chain_key != hlock->prev_chain_key) {
			debug_locks_off();
			printk("hm#1, depth: %u [%u], %016Lx != %016Lx\n",
				curr->lockdep_depth, i,
				(unsigned long long)chain_key,
				(unsigned long long)hlock->prev_chain_key);
			WARN_ON(1);
			return;
		}
		id = hlock->class - lock_classes;
		DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS);
		if (prev_hlock && (prev_hlock->irq_context !=
							hlock->irq_context))
			chain_key = 0;
		chain_key = iterate_chain_key(chain_key, id);
		prev_hlock = hlock;
	}
	if (chain_key != curr->curr_chain_key) {
		debug_locks_off();
		printk("hm#2, depth: %u [%u], %016Lx != %016Lx\n",
			curr->lockdep_depth, i,
			(unsigned long long)chain_key,
			(unsigned long long)curr->curr_chain_key);
		WARN_ON(1);
	}
#endif
}

#ifdef CONFIG_TRACE_IRQFLAGS

/*
 * print irq inversion bug:
 */
static int
print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
			struct held_lock *this, int forwards,
			const char *irqclass)
{
	__raw_spin_unlock(&hash_lock);
	debug_locks_off();
	if (debug_locks_silent)
		return 0;

	printk("\n=========================================================\n");
	printk(  "[ INFO: possible irq lock inversion dependency detected ]\n");
	print_kernel_version();
Ingo Molnar's avatar
Ingo Molnar committed
	printk(  "---------------------------------------------------------\n");
	printk("%s/%d just changed the state of lock:\n",
		curr->comm, curr->pid);
	print_lock(this);
	if (forwards)
		printk("but this lock took another, %s-irq-unsafe lock in the past:\n", irqclass);
	else
		printk("but this lock was taken by another, %s-irq-safe lock in the past:\n", irqclass);
	print_lock_name(other);
	printk("\n\nand interrupts could create inverse lock ordering between them.\n\n");

	printk("\nother info that might help us debug this:\n");
	lockdep_print_held_locks(curr);

	printk("\nthe first lock's dependencies:\n");
	print_lock_dependencies(this->class, 0);

	printk("\nthe second lock's dependencies:\n");
	print_lock_dependencies(other, 0);

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

	return 0;
}

/*
 * Prove that in the forwards-direction subgraph starting at <this>
 * there is no lock matching <mask>:
 */
static int
check_usage_forwards(struct task_struct *curr, struct held_lock *this,
		     enum lock_usage_bit bit, const char *irqclass)
{
	int ret;

	find_usage_bit = bit;
	/* fills in <forwards_match> */
	ret = find_usage_forwards(this->class, 0);
	if (!ret || ret == 1)
		return ret;

	return print_irq_inversion_bug(curr, forwards_match, this, 1, irqclass);
}

/*
 * Prove that in the backwards-direction subgraph starting at <this>
 * there is no lock matching <mask>:
 */
static int
check_usage_backwards(struct task_struct *curr, struct held_lock *this,
		      enum lock_usage_bit bit, const char *irqclass)
{
	int ret;

	find_usage_bit = bit;
	/* fills in <backwards_match> */
	ret = find_usage_backwards(this->class, 0);
	if (!ret || ret == 1)
		return ret;

	return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
}

static inline void print_irqtrace_events(struct task_struct *curr)
{
	printk("irq event stamp: %u\n", curr->irq_events);
	printk("hardirqs last  enabled at (%u): ", curr->hardirq_enable_event);
	print_ip_sym(curr->hardirq_enable_ip);
	printk("hardirqs last disabled at (%u): ", curr->hardirq_disable_event);
	print_ip_sym(curr->hardirq_disable_ip);
	printk("softirqs last  enabled at (%u): ", curr->softirq_enable_event);
	print_ip_sym(curr->softirq_enable_ip);
	printk("softirqs last disabled at (%u): ", curr->softirq_disable_event);
	print_ip_sym(curr->softirq_disable_ip);
}

#else
static inline void print_irqtrace_events(struct task_struct *curr)
{
}
#endif

static int
print_usage_bug(struct task_struct *curr, struct held_lock *this,
		enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
{
	__raw_spin_unlock(&hash_lock);
	debug_locks_off();
	if (debug_locks_silent)
		return 0;

	printk("\n=================================\n");
	printk(  "[ INFO: inconsistent lock state ]\n");
	print_kernel_version();
Ingo Molnar's avatar
Ingo Molnar committed
	printk(  "---------------------------------\n");

	printk("inconsistent {%s} -> {%s} usage.\n",
		usage_str[prev_bit], usage_str[new_bit]);

	printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] takes:\n",
		curr->comm, curr->pid,
		trace_hardirq_context(curr), hardirq_count() >> HARDIRQ_SHIFT,
		trace_softirq_context(curr), softirq_count() >> SOFTIRQ_SHIFT,
		trace_hardirqs_enabled(curr),
		trace_softirqs_enabled(curr));
	print_lock(this);

	printk("{%s} state was registered at:\n", usage_str[prev_bit]);
	print_stack_trace(this->class->usage_traces + prev_bit, 1);

	print_irqtrace_events(curr);
	printk("\nother info that might help us debug this:\n");
	lockdep_print_held_locks(curr);

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

	return 0;
}

/*
 * Print out an error if an invalid bit is set:
 */
static inline int
valid_state(struct task_struct *curr, struct held_lock *this,
	    enum lock_usage_bit new_bit, enum lock_usage_bit bad_bit)
{
	if (unlikely(this->class->usage_mask & (1 << bad_bit)))
		return print_usage_bug(curr, this, bad_bit, new_bit);
	return 1;
}

#define STRICT_READ_CHECKS	1

/*
 * Mark a lock with a usage bit, and validate the state transition:
 */
static int mark_lock(struct task_struct *curr, struct held_lock *this,
		     enum lock_usage_bit new_bit, unsigned long ip)
{
	unsigned int new_mask = 1 << new_bit, ret = 1;

	/*
	 * If already set then do not dirty the cacheline,
	 * nor do any checks:
	 */
	if (likely(this->class->usage_mask & new_mask))
		return 1;

	__raw_spin_lock(&hash_lock);
	/*
	 * Make sure we didnt race:
	 */
	if (unlikely(this->class->usage_mask & new_mask)) {
		__raw_spin_unlock(&hash_lock);
		return 1;
	}

	this->class->usage_mask |= new_mask;

#ifdef CONFIG_TRACE_IRQFLAGS
	if (new_bit == LOCK_ENABLED_HARDIRQS ||
			new_bit == LOCK_ENABLED_HARDIRQS_READ)
		ip = curr->hardirq_enable_ip;
	else if (new_bit == LOCK_ENABLED_SOFTIRQS ||
			new_bit == LOCK_ENABLED_SOFTIRQS_READ)
		ip = curr->softirq_enable_ip;
#endif
	if (!save_trace(this->class->usage_traces + new_bit))
		return 0;

	switch (new_bit) {
#ifdef CONFIG_TRACE_IRQFLAGS
	case LOCK_USED_IN_HARDIRQ:
		if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS))
			return 0;
		if (!valid_state(curr, this, new_bit,
				 LOCK_ENABLED_HARDIRQS_READ))
			return 0;
		/*
		 * just marked it hardirq-safe, check that this lock
		 * took no hardirq-unsafe lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
					  LOCK_ENABLED_HARDIRQS, "hard"))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it hardirq-safe, check that this lock
		 * took no hardirq-unsafe-read lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
				LOCK_ENABLED_HARDIRQS_READ, "hard-read"))
			return 0;
#endif
		if (hardirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_USED_IN_SOFTIRQ:
		if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS))
			return 0;
		if (!valid_state(curr, this, new_bit,
				 LOCK_ENABLED_SOFTIRQS_READ))
			return 0;
		/*
		 * just marked it softirq-safe, check that this lock
		 * took no softirq-unsafe lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
					  LOCK_ENABLED_SOFTIRQS, "soft"))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it softirq-safe, check that this lock
		 * took no softirq-unsafe-read lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
				LOCK_ENABLED_SOFTIRQS_READ, "soft-read"))
			return 0;
#endif
		if (softirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_USED_IN_HARDIRQ_READ:
		if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS))
			return 0;
		/*
		 * just marked it hardirq-read-safe, check that this lock
		 * took no hardirq-unsafe lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
					  LOCK_ENABLED_HARDIRQS, "hard"))
			return 0;
		if (hardirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_USED_IN_SOFTIRQ_READ:
		if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS))
			return 0;
		/*
		 * just marked it softirq-read-safe, check that this lock
		 * took no softirq-unsafe lock in the past:
		 */
		if (!check_usage_forwards(curr, this,
					  LOCK_ENABLED_SOFTIRQS, "soft"))
			return 0;
		if (softirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_ENABLED_HARDIRQS:
		if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
			return 0;
		if (!valid_state(curr, this, new_bit,
				 LOCK_USED_IN_HARDIRQ_READ))
			return 0;
		/*
		 * just marked it hardirq-unsafe, check that no hardirq-safe
		 * lock in the system ever took it in the past:
		 */
		if (!check_usage_backwards(curr, this,
					   LOCK_USED_IN_HARDIRQ, "hard"))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it hardirq-unsafe, check that no
		 * hardirq-safe-read lock in the system ever took
		 * it in the past:
		 */
		if (!check_usage_backwards(curr, this,
				   LOCK_USED_IN_HARDIRQ_READ, "hard-read"))
			return 0;
#endif
		if (hardirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_ENABLED_SOFTIRQS:
		if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ))
			return 0;
		if (!valid_state(curr, this, new_bit,
				 LOCK_USED_IN_SOFTIRQ_READ))
			return 0;
		/*
		 * just marked it softirq-unsafe, check that no softirq-safe
		 * lock in the system ever took it in the past:
		 */
		if (!check_usage_backwards(curr, this,
					   LOCK_USED_IN_SOFTIRQ, "soft"))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it softirq-unsafe, check that no
		 * softirq-safe-read lock in the system ever took
		 * it in the past:
		 */
		if (!check_usage_backwards(curr, this,
				   LOCK_USED_IN_SOFTIRQ_READ, "soft-read"))
			return 0;
#endif
		if (softirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_ENABLED_HARDIRQS_READ:
		if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it hardirq-read-unsafe, check that no
		 * hardirq-safe lock in the system ever took it in the past:
		 */
		if (!check_usage_backwards(curr, this,
					   LOCK_USED_IN_HARDIRQ, "hard"))
			return 0;
#endif
		if (hardirq_verbose(this->class))
			ret = 2;
		break;
	case LOCK_ENABLED_SOFTIRQS_READ:
		if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ))
			return 0;
#if STRICT_READ_CHECKS
		/*
		 * just marked it softirq-read-unsafe, check that no
		 * softirq-safe lock in the system ever took it in the past:
		 */
		if (!check_usage_backwards(curr, this,
					   LOCK_USED_IN_SOFTIRQ, "soft"))
			return 0;
#endif
		if (softirq_verbose(this->class))
			ret = 2;
		break;
#endif
	case LOCK_USED:
		/*
		 * Add it to the global list of classes:
		 */
		list_add_tail_rcu(&this->class->lock_entry, &all_lock_classes);
		debug_atomic_dec(&nr_unused_locks);
		break;
	default:
		__raw_spin_unlock(&hash_lock);
Ingo Molnar's avatar
Ingo Molnar committed
		debug_locks_off();
		WARN_ON(1);
		return 0;
	}

	__raw_spin_unlock(&hash_lock);

	/*
	 * We must printk outside of the hash_lock:
	 */
	if (ret == 2) {
		printk("\nmarked lock as {%s}:\n", usage_str[new_bit]);
		print_lock(this);
		print_irqtrace_events(curr);
		dump_stack();
	}

	return ret;
}

#ifdef CONFIG_TRACE_IRQFLAGS
/*
 * Mark all held locks with a usage bit:
 */
static int
mark_held_locks(struct task_struct *curr, int hardirq, unsigned long ip)
{
	enum lock_usage_bit usage_bit;
	struct held_lock *hlock;
	int i;

	for (i = 0; i < curr->lockdep_depth; i++) {
		hlock = curr->held_locks + i;

		if (hardirq) {
			if (hlock->read)
				usage_bit = LOCK_ENABLED_HARDIRQS_READ;
			else
				usage_bit = LOCK_ENABLED_HARDIRQS;
		} else {
			if (hlock->read)
				usage_bit = LOCK_ENABLED_SOFTIRQS_READ;
			else
				usage_bit = LOCK_ENABLED_SOFTIRQS;
		}
		if (!mark_lock(curr, hlock, usage_bit, ip))
			return 0;
	}

	return 1;
}

/*
 * Debugging helper: via this flag we know that we are in
 * 'early bootup code', and will warn about any invalid irqs-on event:
 */
static int early_boot_irqs_enabled;

void early_boot_irqs_off(void)
{
	early_boot_irqs_enabled = 0;
}

void early_boot_irqs_on(void)
{
	early_boot_irqs_enabled = 1;
}

/*
 * Hardirqs will be enabled:
 */
void trace_hardirqs_on(void)
{
	struct task_struct *curr = current;
	unsigned long ip;

	if (unlikely(!debug_locks || current->lockdep_recursion))
		return;

	if (DEBUG_LOCKS_WARN_ON(unlikely(!early_boot_irqs_enabled)))
		return;

	if (unlikely(curr->hardirqs_enabled)) {
		debug_atomic_inc(&redundant_hardirqs_on);
		return;
	}
	/* we'll do an OFF -> ON transition: */
	curr->hardirqs_enabled = 1;
	ip = (unsigned long) __builtin_return_address(0);

	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
		return;
	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
		return;
	/*
	 * We are going to turn hardirqs on, so set the
	 * usage bit for all held locks:
	 */
	if (!mark_held_locks(curr, 1, ip))
		return;
	/*
	 * If we have softirqs enabled, then set the usage
	 * bit for all held locks. (disabled hardirqs prevented
	 * this bit from being set before)
	 */
	if (curr->softirqs_enabled)
		if (!mark_held_locks(curr, 0, ip))
			return;

	curr->hardirq_enable_ip = ip;
	curr->hardirq_enable_event = ++curr->irq_events;
	debug_atomic_inc(&hardirqs_on_events);
}

EXPORT_SYMBOL(trace_hardirqs_on);

/*
 * Hardirqs were disabled:
 */
void trace_hardirqs_off(void)
{
	struct task_struct *curr = current;

	if (unlikely(!debug_locks || current->lockdep_recursion))
		return;

	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
		return;

	if (curr->hardirqs_enabled) {
		/*
		 * We have done an ON -> OFF transition:
		 */
		curr->hardirqs_enabled = 0;
		curr->hardirq_disable_ip = _RET_IP_;
		curr->hardirq_disable_event = ++curr->irq_events;
		debug_atomic_inc(&hardirqs_off_events);
	} else
		debug_atomic_inc(&redundant_hardirqs_off);
}

EXPORT_SYMBOL(trace_hardirqs_off);

/*
 * Softirqs will be enabled:
 */
void trace_softirqs_on(unsigned long ip)
{
	struct task_struct *curr = current;

	if (unlikely(!debug_locks))
		return;

	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
		return;

	if (curr->softirqs_enabled) {
		debug_atomic_inc(&redundant_softirqs_on);
		return;
	}

	/*
	 * We'll do an OFF -> ON transition:
	 */
	curr->softirqs_enabled = 1;
	curr->softirq_enable_ip = ip;
	curr->softirq_enable_event = ++curr->irq_events;
	debug_atomic_inc(&softirqs_on_events);
	/*
	 * We are going to turn softirqs on, so set the
	 * usage bit for all held locks, if hardirqs are
	 * enabled too:
	 */
	if (curr->hardirqs_enabled)
		mark_held_locks(curr, 0, ip);
}

/*
 * Softirqs were disabled:
 */
void trace_softirqs_off(unsigned long ip)
{
	struct task_struct *curr = current;

	if (unlikely(!debug_locks))
		return;

	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
		return;

	if (curr->softirqs_enabled) {
		/*
		 * We have done an ON -> OFF transition:
		 */
		curr->softirqs_enabled = 0;
		curr->softirq_disable_ip = ip;
		curr->softirq_disable_event = ++curr->irq_events;
		debug_atomic_inc(&softirqs_off_events);
		DEBUG_LOCKS_WARN_ON(!softirq_count());
	} else
		debug_atomic_inc(&redundant_softirqs_off);
}

#endif

/*
 * Initialize a lock instance's lock-class mapping info:
 */
void lockdep_init_map(struct lockdep_map *lock, const char *name,
		      struct lock_class_key *key, int subclass)
Ingo Molnar's avatar
Ingo Molnar committed
{
	if (unlikely(!debug_locks))
		return;

	if (DEBUG_LOCKS_WARN_ON(!key))
		return;
	if (DEBUG_LOCKS_WARN_ON(!name))
		return;
	/*
	 * Sanity check, the lock-class key must be persistent:
	 */
	if (!static_obj(key)) {
		printk("BUG: key %p not in .data!\n", key);
		DEBUG_LOCKS_WARN_ON(1);
		return;
	}
	lock->name = name;
	lock->key = key;
	lock->class_cache = NULL;
	if (subclass)
		register_lock_class(lock, subclass, 1);
Ingo Molnar's avatar
Ingo Molnar committed
}

EXPORT_SYMBOL_GPL(lockdep_init_map);

/*
 * This gets called for every mutex_lock*()/spin_lock*() operation.
 * We maintain the dependency maps and validate the locking attempt:
 */
static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
			  int trylock, int read, int check, int hardirqs_off,
			  unsigned long ip)
{
	struct task_struct *curr = current;
	struct lock_class *class = NULL;
Ingo Molnar's avatar
Ingo Molnar committed
	struct held_lock *hlock;
	unsigned int depth, id;
	int chain_head = 0;
	u64 chain_key;

	if (unlikely(!debug_locks))
		return 0;

	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
		return 0;

	if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
		debug_locks_off();
		printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n");
		printk("turning off the locking correctness validator.\n");
		return 0;
	}

	if (!subclass)
		class = lock->class_cache;
	/*
	 * Not cached yet or subclass?