linux/include/linux/lockdep.h

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Runtime locking correctness validator
 *
 *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <[email protected]>
 *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
 *
 * see Documentation/locking/lockdep-design.rst for more details.
 */
#ifndef __LINUX_LOCKDEP_H
#define __LINUX_LOCKDEP_H

#include <linux/lockdep_types.h>
#include <linux/smp.h>
#include <asm/percpu.h>

struct task_struct;

#ifdef CONFIG_LOCKDEP

#include <linux/linkage.h>
#include <linux/list.h>
#include <linux/debug_locks.h>
#include <linux/stacktrace.h>

static inline void lockdep_copy_map(struct lockdep_map *to,
				    struct lockdep_map *from)
{}

/*
 * Every lock has a list of other locks that were taken after it.
 * We only grow the list, never remove from it:
 */
struct lock_list {};

/**
 * struct lock_chain - lock dependency chain record
 *
 * @irq_context: the same as irq_context in held_lock below
 * @depth:       the number of held locks in this chain
 * @base:        the index in chain_hlocks for this chain
 * @entry:       the collided lock chains in lock_chain hash list
 * @chain_key:   the hash key of this lock_chain
 */
struct lock_chain {};

/*
 * Initialization, self-test and debugging-output methods:
 */
extern void lockdep_init(void);
extern void lockdep_reset(void);
extern void lockdep_reset_lock(struct lockdep_map *lock);
extern void lockdep_free_key_range(void *start, unsigned long size);
extern asmlinkage void lockdep_sys_exit(void);
extern void lockdep_set_selftest_task(struct task_struct *task);

extern void lockdep_init_task(struct task_struct *task);

/*
 * Split the recursion counter in two to readily detect 'off' vs recursion.
 */
#define LOCKDEP_RECURSION_BITS
#define LOCKDEP_OFF
#define LOCKDEP_RECURSION_MASK

/*
 * lockdep_{off,on}() are macros to avoid tracing and kprobes; not inlines due
 * to header dependencies.
 */

#define lockdep_off()

#define lockdep_on()

extern void lockdep_register_key(struct lock_class_key *key);
extern void lockdep_unregister_key(struct lock_class_key *key);

/*
 * These methods are used by specific locking variants (spinlocks,
 * rwlocks, mutexes and rwsems) to pass init/acquire/release events
 * to lockdep:
 */

extern void lockdep_init_map_type(struct lockdep_map *lock, const char *name,
	struct lock_class_key *key, int subclass, u8 inner, u8 outer, u8 lock_type);

static inline void
lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
		       struct lock_class_key *key, int subclass, u8 inner, u8 outer)
{}

static inline void
lockdep_init_map_wait(struct lockdep_map *lock, const char *name,
		      struct lock_class_key *key, int subclass, u8 inner)
{}

static inline void lockdep_init_map(struct lockdep_map *lock, const char *name,
			     struct lock_class_key *key, int subclass)
{}

/*
 * Reinitialize a lock key - for cases where there is special locking or
 * special initialization of locks so that the validator gets the scope
 * of dependencies wrong: they are either too broad (they need a class-split)
 * or they are too narrow (they suffer from a false class-split):
 */
#define lockdep_set_class(lock, key)

#define lockdep_set_class_and_name(lock, key, name)

#define lockdep_set_class_and_subclass(lock, key, sub)

#define lockdep_set_subclass(lock, sub)

/**
 * lockdep_set_novalidate_class: disable checking of lock ordering on a given
 * lock
 * @lock: Lock to mark
 *
 * Lockdep will still record that this lock has been taken, and print held
 * instances when dumping locks
 */
#define lockdep_set_novalidate_class(lock)

/**
 * lockdep_set_notrack_class: disable lockdep tracking of a given lock entirely
 * @lock: Lock to mark
 *
 * Bigger hammer than lockdep_set_novalidate_class: so far just for bcachefs,
 * which takes more locks than lockdep is able to track (48).
 */
#define lockdep_set_notrack_class(lock)

/*
 * Compare locking classes
 */
#define lockdep_match_class(lock, key)

static inline int lockdep_match_key(struct lockdep_map *lock,
				    struct lock_class_key *key)
{}

/*
 * Acquire a lock.
 *
 * Values for "read":
 *
 *   0: exclusive (write) acquire
 *   1: read-acquire (no recursion allowed)
 *   2: read-acquire with same-instance recursion allowed
 *
 * Values for check:
 *
 *   0: simple checks (freeing, held-at-exit-time, etc.)
 *   1: full validation
 */
extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
			 int trylock, int read, int check,
			 struct lockdep_map *nest_lock, unsigned long ip);

extern void lock_release(struct lockdep_map *lock, unsigned long ip);

extern void lock_sync(struct lockdep_map *lock, unsigned int subclass,
		      int read, int check, struct lockdep_map *nest_lock,
		      unsigned long ip);

/* lock_is_held_type() returns */
#define LOCK_STATE_UNKNOWN
#define LOCK_STATE_NOT_HELD
#define LOCK_STATE_HELD

/*
 * Same "read" as for lock_acquire(), except -1 means any.
 */
extern int lock_is_held_type(const struct lockdep_map *lock, int read);

static inline int lock_is_held(const struct lockdep_map *lock)
{}

#define lockdep_is_held(lock)
#define lockdep_is_held_type(lock, r)

extern void lock_set_class(struct lockdep_map *lock, const char *name,
			   struct lock_class_key *key, unsigned int subclass,
			   unsigned long ip);

#define lock_set_novalidate_class(l, n, i)

static inline void lock_set_subclass(struct lockdep_map *lock,
		unsigned int subclass, unsigned long ip)
{}

extern void lock_downgrade(struct lockdep_map *lock, unsigned long ip);

#define NIL_COOKIE

extern struct pin_cookie lock_pin_lock(struct lockdep_map *lock);
extern void lock_repin_lock(struct lockdep_map *lock, struct pin_cookie);
extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);

#define lockdep_depth(tsk)

#define lockdep_assert(cond)

#define lockdep_assert_once(cond)

#define lockdep_assert_held(l)

#define lockdep_assert_not_held(l)

#define lockdep_assert_held_write(l)

#define lockdep_assert_held_read(l)

#define lockdep_assert_held_once(l)

#define lockdep_assert_none_held_once()

#define lockdep_recursing(tsk)

#define lockdep_pin_lock(l)
#define lockdep_repin_lock(l,c)
#define lockdep_unpin_lock(l,c)

/*
 * Must use lock_map_aquire_try() with override maps to avoid
 * lockdep thinking they participate in the block chain.
 */
#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type)

#else /* !CONFIG_LOCKDEP */

static inline void lockdep_init_task(struct task_struct *task)
{
}

static inline void lockdep_off(void)
{
}

static inline void lockdep_on(void)
{
}

static inline void lockdep_set_selftest_task(struct task_struct *task)
{
}

#define lock_acquire
#define lock_release
#define lock_downgrade
#define lock_set_class
#define lock_set_novalidate_class
#define lock_set_subclass
#define lockdep_init
#define lockdep_init_map_type
#define lockdep_init_map_waits
#define lockdep_init_map_wait
#define lockdep_init_map
#define lockdep_set_class
#define lockdep_set_class_and_name
#define lockdep_set_class_and_subclass
#define lockdep_set_subclass

#define lockdep_set_novalidate_class
#define lockdep_set_notrack_class

/*
 * We don't define lockdep_match_class() and lockdep_match_key() for !LOCKDEP
 * case since the result is not well defined and the caller should rather
 * #ifdef the call himself.
 */

#define lockdep_reset
#define lockdep_free_key_range
#define lockdep_sys_exit

static inline void lockdep_register_key(struct lock_class_key *key)
{
}

static inline void lockdep_unregister_key(struct lock_class_key *key)
{
}

#define lockdep_depth

/*
 * Dummy forward declarations, allow users to write less ifdef-y code
 * and depend on dead code elimination.
 */
extern int lock_is_held(const void *);
extern int lockdep_is_held(const void *);
#define lockdep_is_held_type

#define lockdep_assert
#define lockdep_assert_once

#define lockdep_assert_held
#define lockdep_assert_not_held
#define lockdep_assert_held_write
#define lockdep_assert_held_read
#define lockdep_assert_held_once
#define lockdep_assert_none_held_once

#define lockdep_recursing

#define NIL_COOKIE

#define lockdep_pin_lock
#define lockdep_repin_lock
#define lockdep_unpin_lock

#define DEFINE_WAIT_OVERRIDE_MAP

#endif /* !LOCKDEP */

#ifdef CONFIG_PROVE_LOCKING
void lockdep_set_lock_cmp_fn(struct lockdep_map *, lock_cmp_fn, lock_print_fn);

#define lock_set_cmp_fn(lock, ...)
#else
#define lock_set_cmp_fn
#endif

enum xhlock_context_t {};

/*
 * To initialize a lockdep_map statically use this macro.
 * Note that _name must not be NULL.
 */
#define STATIC_LOCKDEP_MAP_INIT(_name, _key)

static inline void lockdep_invariant_state(bool force) {}
static inline void lockdep_free_task(struct task_struct *task) {}

#ifdef CONFIG_LOCK_STAT

extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
extern void lock_acquired(struct lockdep_map *lock, unsigned long ip);

#define LOCK_CONTENDED(_lock, try, lock)

#define LOCK_CONTENDED_RETURN(_lock, try, lock)

#else /* CONFIG_LOCK_STAT */

#define lock_contended
#define lock_acquired

#define LOCK_CONTENDED

#define LOCK_CONTENDED_RETURN

#endif /* CONFIG_LOCK_STAT */

#ifdef CONFIG_PROVE_LOCKING
extern void print_irqtrace_events(struct task_struct *curr);
#else
static inline void print_irqtrace_events(struct task_struct *curr)
{
}
#endif

/* Variable used to make lockdep treat read_lock() as recursive in selftests */
#ifdef CONFIG_DEBUG_LOCKING_API_SELFTESTS
extern unsigned int force_read_lock_recursive;
#else /* CONFIG_DEBUG_LOCKING_API_SELFTESTS */
#define force_read_lock_recursive
#endif /* CONFIG_DEBUG_LOCKING_API_SELFTESTS */

#ifdef CONFIG_LOCKDEP
extern bool read_lock_is_recursive(void);
#else /* CONFIG_LOCKDEP */
/* If !LOCKDEP, the value is meaningless */
#define read_lock_is_recursive
#endif

/*
 * For trivial one-depth nesting of a lock-class, the following
 * global define can be used. (Subsystems with multiple levels
 * of nesting should define their own lock-nesting subclasses.)
 */
#define SINGLE_DEPTH_NESTING

/*
 * Map the dependency ops to NOP or to real lockdep ops, depending
 * on the per lock-class debug mode:
 */

#define lock_acquire_exclusive(l, s, t, n, i)
#define lock_acquire_shared(l, s, t, n, i)
#define lock_acquire_shared_recursive(l, s, t, n, i)

#define spin_acquire(l, s, t, i)
#define spin_acquire_nest(l, s, t, n, i)
#define spin_release(l, i)

#define rwlock_acquire(l, s, t, i)
#define rwlock_acquire_read(l, s, t, i)

#define rwlock_release(l, i)

#define seqcount_acquire(l, s, t, i)
#define seqcount_acquire_read(l, s, t, i)
#define seqcount_release(l, i)

#define mutex_acquire(l, s, t, i)
#define mutex_acquire_nest(l, s, t, n, i)
#define mutex_release(l, i)

#define rwsem_acquire(l, s, t, i)
#define rwsem_acquire_nest(l, s, t, n, i)
#define rwsem_acquire_read(l, s, t, i)
#define rwsem_release(l, i)

#define lock_map_acquire(l)
#define lock_map_acquire_try(l)
#define lock_map_acquire_read(l)
#define lock_map_acquire_tryread(l)
#define lock_map_release(l)
#define lock_map_sync(l)

#ifdef CONFIG_PROVE_LOCKING
#define might_lock(lock)
#define might_lock_read(lock)
#define might_lock_nested(lock, subclass)

DECLARE_PER_CPU(int, hardirqs_enabled);
DECLARE_PER_CPU(int, hardirq_context);
DECLARE_PER_CPU(unsigned int, lockdep_recursion);

#define __lockdep_enabled

#define lockdep_assert_irqs_enabled()

#define lockdep_assert_irqs_disabled()

#define lockdep_assert_in_irq()

#define lockdep_assert_no_hardirq()

#define lockdep_assert_preemption_enabled()

#define lockdep_assert_preemption_disabled()

/*
 * Acceptable for protecting per-CPU resources accessed from BH.
 * Much like in_softirq() - semantics are ambiguous, use carefully.
 */
#define lockdep_assert_in_softirq()

extern void lockdep_assert_in_softirq_func(void);

#else
#define might_lock
#define might_lock_read
#define might_lock_nested

#define lockdep_assert_irqs_enabled
#define lockdep_assert_irqs_disabled
#define lockdep_assert_in_irq
#define lockdep_assert_no_hardirq

#define lockdep_assert_preemption_enabled
#define lockdep_assert_preemption_disabled
#define lockdep_assert_in_softirq
#define lockdep_assert_in_softirq_func
#endif

#ifdef CONFIG_PROVE_RAW_LOCK_NESTING

#define lockdep_assert_RT_in_threaded_ctx()

#else

#define lockdep_assert_RT_in_threaded_ctx

#endif

#ifdef CONFIG_LOCKDEP
void lockdep_rcu_suspicious(const char *file, const int line, const char *s);
#else
static inline void
lockdep_rcu_suspicious(const char *file, const int line, const char *s)
{
}
#endif

#endif /* __LINUX_LOCKDEP_H */