⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locking-selftest.c

📁 Lib files of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "locking-selftest-spin.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_spin)#include "locking-selftest-wlock.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_wlock)#include "locking-selftest-rlock.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock)#undef E1#undef E2/* * Enabling irqs with an irq-safe lock held: */#define E1()				\					\	IRQ_ENTER();			\	LOCK(A);			\	UNLOCK(A);			\	IRQ_EXIT();#define E2()				\					\	IRQ_DISABLE();			\	LOCK(A);			\	IRQ_ENABLE();			\	UNLOCK(A);/* * Generate 24 testcases: */#include "locking-selftest-spin-hardirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin)#include "locking-selftest-rlock-hardirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock)#include "locking-selftest-wlock-hardirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_wlock)#include "locking-selftest-spin-softirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_spin)#include "locking-selftest-rlock-softirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock)#include "locking-selftest-wlock-softirq.h"GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock)#undef E1#undef E2/* * Acquiring a irq-unsafe lock while holding an irq-safe-lock: */#define E1()				\					\	LOCK(A);			\	LOCK(B);			\	UNLOCK(B);			\	UNLOCK(A);			\#define E2()				\					\	LOCK(B);			\	UNLOCK(B);#define E3()				\					\	IRQ_ENTER();			\	LOCK(A);			\	UNLOCK(A);			\	IRQ_EXIT();/* * Generate 36 testcases: */#include "locking-selftest-spin-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin)#include "locking-selftest-rlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock)#include "locking-selftest-wlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_wlock)#include "locking-selftest-spin-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_spin)#include "locking-selftest-rlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock)#include "locking-selftest-wlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock)#undef E1#undef E2#undef E3/* * If a lock turns into softirq-safe, but earlier it took * a softirq-unsafe lock: */#define E1()				\	IRQ_DISABLE();			\	LOCK(A);			\	LOCK(B);			\	UNLOCK(B);			\	UNLOCK(A);			\	IRQ_ENABLE();#define E2()				\	LOCK(B);			\	UNLOCK(B);#define E3()				\	IRQ_ENTER();			\	LOCK(A);			\	UNLOCK(A);			\	IRQ_EXIT();/* * Generate 36 testcases: */#include "locking-selftest-spin-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin)#include "locking-selftest-rlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock)#include "locking-selftest-wlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_wlock)#include "locking-selftest-spin-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_spin)#include "locking-selftest-rlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock)#include "locking-selftest-wlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock)#undef E1#undef E2#undef E3/* * read-lock / write-lock irq inversion. * * Deadlock scenario: * * CPU#1 is at #1, i.e. it has write-locked A, but has not * taken B yet. * * CPU#2 is at #2, i.e. it has locked B. * * Hardirq hits CPU#2 at point #2 and is trying to read-lock A. * * The deadlock occurs because CPU#1 will spin on B, and CPU#2 * will spin on A. */#define E1()				\					\	IRQ_DISABLE();			\	WL(A);				\	LOCK(B);			\	UNLOCK(B);			\	WU(A);				\	IRQ_ENABLE();#define E2()				\					\	LOCK(B);			\	UNLOCK(B);#define E3()				\					\	IRQ_ENTER();			\	RL(A);				\	RU(A);				\	IRQ_EXIT();/* * Generate 36 testcases: */#include "locking-selftest-spin-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_spin)#include "locking-selftest-rlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_rlock)#include "locking-selftest-wlock-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_wlock)#include "locking-selftest-spin-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_spin)#include "locking-selftest-rlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_rlock)#include "locking-selftest-wlock-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock)#undef E1#undef E2#undef E3/* * read-lock / write-lock recursion that is actually safe. */#define E1()				\					\	IRQ_DISABLE();			\	WL(A);				\	WU(A);				\	IRQ_ENABLE();#define E2()				\					\	RL(A);				\	RU(A);				\#define E3()				\					\	IRQ_ENTER();			\	RL(A);				\	L(B);				\	U(B);				\	RU(A);				\	IRQ_EXIT();/* * Generate 12 testcases: */#include "locking-selftest-hardirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_hard)#include "locking-selftest-softirq.h"GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)#undef E1#undef E2#undef E3/* * read-lock / write-lock recursion that is unsafe. */#define E1()				\					\	IRQ_DISABLE();			\	L(B);				\	WL(A);				\	WU(A);				\	U(B);				\	IRQ_ENABLE();#define E2()				\					\	RL(A);				\	RU(A);				\#define E3()				\					\	IRQ_ENTER();			\	L(B);				\	U(B);				\	IRQ_EXIT();/* * Generate 12 testcases: */#include "locking-selftest-hardirq.h"// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_hard)#include "locking-selftest-softirq.h"// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_soft)#ifdef CONFIG_DEBUG_LOCK_ALLOC# define I_SPINLOCK(x)	lockdep_reset_lock(&lock_##x.dep_map)# define I_RWLOCK(x)	lockdep_reset_lock(&rwlock_##x.dep_map)# define I_MUTEX(x)	lockdep_reset_lock(&mutex_##x.dep_map)# define I_RWSEM(x)	lockdep_reset_lock(&rwsem_##x.dep_map)#else# define I_SPINLOCK(x)# define I_RWLOCK(x)# define I_MUTEX(x)# define I_RWSEM(x)#endif#define I1(x)					\	do {					\		I_SPINLOCK(x);			\		I_RWLOCK(x);			\		I_MUTEX(x);			\		I_RWSEM(x);			\	} while (0)#define I2(x)					\	do {					\		spin_lock_init(&lock_##x);	\		rwlock_init(&rwlock_##x);	\		mutex_init(&mutex_##x);		\		init_rwsem(&rwsem_##x);		\	} while (0)static void reset_locks(void){	local_irq_disable();	I1(A); I1(B); I1(C); I1(D);	I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2);	lockdep_reset();	I2(A); I2(B); I2(C); I2(D);	init_shared_classes();	local_irq_enable();}#undef Istatic int testcase_total;static int testcase_successes;static int expected_testcase_failures;static int unexpected_testcase_failures;static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask){	unsigned long saved_preempt_count = preempt_count();	int expected_failure = 0;	WARN_ON(irqs_disabled());	testcase_fn();	/*	 * Filter out expected failures:	 */#ifndef CONFIG_PROVE_LOCKING	if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected)		expected_failure = 1;	if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected)		expected_failure = 1;	if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected)		expected_failure = 1;	if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected)		expected_failure = 1;#endif	if (debug_locks != expected) {		if (expected_failure) {			expected_testcase_failures++;			printk("failed|");		} else {			unexpected_testcase_failures++;			printk("FAILED|");			dump_stack();		}	} else {		testcase_successes++;		printk("  ok  |");	}	testcase_total++;	if (debug_locks_verbose)		printk(" lockclass mask: %x, debug_locks: %d, expected: %d\n",			lockclass_mask, debug_locks, expected);	/*	 * Some tests (e.g. double-unlock) might corrupt the preemption	 * count, so restore it:	 */	preempt_count() = saved_preempt_count;#ifdef CONFIG_TRACE_IRQFLAGS	if (softirq_count())		current->softirqs_enabled = 0;	else		current->softirqs_enabled = 1;#endif	reset_locks();}static inline void print_testname(const char *testname){	printk("%33s:", testname);}#define DO_TESTCASE_1(desc, name, nr)				\	print_testname(desc"/"#nr);				\	dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK);		\	printk("\n");#define DO_TESTCASE_1B(desc, name, nr)				\	print_testname(desc"/"#nr);				\	dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK);		\	printk("\n");#define DO_TESTCASE_3(desc, name, nr)				\	print_testname(desc"/"#nr);				\	dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN);	\	dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK);	\	dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK);	\	printk("\n");#define DO_TESTCASE_3RW(desc, name, nr)				\	print_testname(desc"/"#nr);				\	dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN|LOCKTYPE_RWLOCK);\	dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK);	\	dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK);	\	printk("\n");#define DO_TESTCASE_6(desc, name)				\	print_testname(desc);					\	dotest(name##_spin, FAILURE, LOCKTYPE_SPIN);		\	dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK);		\	dotest(name##_rlock, FAILURE, LOCKTYPE_RWLOCK);		\	dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX);		\	dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM);		\	dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM);		\	printk("\n");#define DO_TESTCASE_6_SUCCESS(desc, name)			\	print_testname(desc);					\	dotest(name##_spin, SUCCESS, LOCKTYPE_SPIN);		\	dotest(name##_wlock, SUCCESS, LOCKTYPE_RWLOCK);		\	dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK);		\	dotest(name##_mutex, SUCCESS, LOCKTYPE_MUTEX);		\	dotest(name##_wsem, SUCCESS, LOCKTYPE_RWSEM);		\	dotest(name##_rsem, SUCCESS, LOCKTYPE_RWSEM);		\	printk("\n");/* * 'read' variant: rlocks must not trigger. */#define DO_TESTCASE_6R(desc, name)				\	print_testname(desc);					\	dotest(name##_spin, FAILURE, LOCKTYPE_SPIN);		\	dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK);		\	dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK);		\	dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX);		\	dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM);		\	dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM);		\	printk("\n");#define DO_TESTCASE_2I(desc, name, nr)				\	DO_TESTCASE_1("hard-"desc, name##_hard, nr);		\	DO_TESTCASE_1("soft-"desc, name##_soft, nr);#define DO_TESTCASE_2IB(desc, name, nr)				\	DO_TESTCASE_1B("hard-"desc, name##_hard, nr);		\	DO_TESTCASE_1B("soft-"desc, name##_soft, nr);#define DO_TESTCASE_6I(desc, name, nr)				\	DO_TESTCASE_3("hard-"desc, name##_hard, nr);		\	DO_TESTCASE_3("soft-"desc, name##_soft, nr);#define DO_TESTCASE_6IRW(desc, name, nr)			\	DO_TESTCASE_3RW("hard-"desc, name##_hard, nr);		\	DO_TESTCASE_3RW("soft-"desc, name##_soft, nr);#define DO_TESTCASE_2x3(desc, name)				\	DO_TESTCASE_3(desc, name, 12);				\	DO_TESTCASE_3(desc, name, 21);#define DO_TESTCASE_2x6(desc, name)				\	DO_TESTCASE_6I(desc, name, 12);				\	DO_TESTCASE_6I(desc, name, 21);#define DO_TESTCASE_6x2(desc, name)				\	DO_TESTCASE_2I(desc, name, 123);			\	DO_TESTCASE_2I(desc, name, 132);			\	DO_TESTCASE_2I(desc, name, 213);			\	DO_TESTCASE_2I(desc, name, 231);			\	DO_TESTCASE_2I(desc, name, 312);			\	DO_TESTCASE_2I(desc, name, 321);#define DO_TESTCASE_6x2B(desc, name)				\	DO_TESTCASE_2IB(desc, name, 123);			\	DO_TESTCASE_2IB(desc, name, 132);			\	DO_TESTCASE_2IB(desc, name, 213);			\	DO_TESTCASE_2IB(desc, name, 231);			\	DO_TESTCASE_2IB(desc, name, 312);			\	DO_TESTCASE_2IB(desc, name, 321);#define DO_TESTCASE_6x6(desc, name)				\	DO_TESTCASE_6I(desc, name, 123);			\	DO_TESTCASE_6I(desc, name, 132);			\	DO_TESTCASE_6I(desc, name, 213);			\	DO_TESTCASE_6I(desc, name, 231);			\	DO_TESTCASE_6I(desc, name, 312);			\	DO_TESTCASE_6I(desc, name, 321);#define DO_TESTCASE_6x6RW(desc, name)				\	DO_TESTCASE_6IRW(desc, name, 123);			\	DO_TESTCASE_6IRW(desc, name, 132);			\	DO_TESTCASE_6IRW(desc, name, 213);			\	DO_TESTCASE_6IRW(desc, name, 231);			\	DO_TESTCASE_6IRW(desc, name, 312);			\	DO_TESTCASE_6IRW(desc, name, 321);void locking_selftest(void){	/*	 * Got a locking failure before the selftest ran?	 */	if (!debug_locks) {		printk("----------------------------------\n");		printk("| Locking API testsuite disabled |\n");		printk("----------------------------------\n");		return;	}	/*	 * Run the testsuite:	 */	printk("------------------------\n");	printk("| Locking API testsuite:\n");	printk("----------------------------------------------------------------------------\n");	printk("                                 | spin |wlock |rlock |mutex | wsem | rsem |\n");	printk("  --------------------------------------------------------------------------\n");	init_shared_classes();	debug_locks_silent = !debug_locks_verbose;	DO_TESTCASE_6R("A-A deadlock", AA);	DO_TESTCASE_6R("A-B-B-A deadlock", ABBA);	DO_TESTCASE_6R("A-B-B-C-C-A deadlock", ABBCCA);	DO_TESTCASE_6R("A-B-C-A-B-C deadlock", ABCABC);	DO_TESTCASE_6R("A-B-B-C-C-D-D-A deadlock", ABBCCDDA);	DO_TESTCASE_6R("A-B-C-D-B-D-D-A deadlock", ABCDBDDA);	DO_TESTCASE_6R("A-B-C-D-B-C-D-A deadlock", ABCDBCDA);	DO_TESTCASE_6("double unlock", double_unlock);	DO_TESTCASE_6("initialize held", init_held);	DO_TESTCASE_6_SUCCESS("bad unlock order", bad_unlock_order);	printk("  --------------------------------------------------------------------------\n");	print_testname("recursive read-lock");	printk("             |");	dotest(rlock_AA1, SUCCESS, LOCKTYPE_RWLOCK);	printk("             |");	dotest(rsem_AA1, FAILURE, LOCKTYPE_RWSEM);	printk("\n");	print_testname("recursive read-lock #2");	printk("             |");	dotest(rlock_AA1B, SUCCESS, LOCKTYPE_RWLOCK);	printk("             |");	dotest(rsem_AA1B, FAILURE, LOCKTYPE_RWSEM);	printk("\n");	print_testname("mixed read-write-lock");	printk("             |");	dotest(rlock_AA2, FAILURE, LOCKTYPE_RWLOCK);	printk("             |");	dotest(rsem_AA2, FAILURE, LOCKTYPE_RWSEM);	printk("\n");	print_testname("mixed write-read-lock");	printk("             |");	dotest(rlock_AA3, FAILURE, LOCKTYPE_RWLOCK);	printk("             |");	dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM);	printk("\n");	printk("  --------------------------------------------------------------------------\n");	/*	 * irq-context testcases:	 */	DO_TESTCASE_2x6("irqs-on + irq-safe-A", irqsafe1);	DO_TESTCASE_2x3("sirq-safe-A => hirqs-on", irqsafe2A);	DO_TESTCASE_2x6("safe-A + irqs-on", irqsafe2B);	DO_TESTCASE_6x6("safe-A + unsafe-B #1", irqsafe3);	DO_TESTCASE_6x6("safe-A + unsafe-B #2", irqsafe4);	DO_TESTCASE_6x6RW("irq lock-inversion", irq_inversion);	DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion);//	DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2);	if (unexpected_testcase_failures) {		printk("-----------------------------------------------------------------\n");		debug_locks = 0;		printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n",			unexpected_testcase_failures, testcase_total);		printk("-----------------------------------------------------------------\n");	} else if (expected_testcase_failures && testcase_successes) {		printk("--------------------------------------------------------\n");		printk("%3d out of %3d testcases failed, as expected. |\n",			expected_testcase_failures, testcase_total);		printk("----------------------------------------------------\n");		debug_locks = 1;	} else if (expected_testcase_failures && !testcase_successes) {		printk("--------------------------------------------------------\n");		printk("All %3d testcases failed, as expected. |\n",			expected_testcase_failures);		printk("----------------------------------------\n");		debug_locks = 1;	} else {		printk("-------------------------------------------------------\n");		printk("Good, all %3d testcases passed! |\n",			testcase_successes);		printk("---------------------------------\n");		debug_locks = 1;	}	debug_locks_silent = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -