| #include <stdbool.h> | 
 | #include <ktest.h> | 
 | #include <sys/queue.h> | 
 |  | 
 | /* Global string used to report info about the last completed test */ | 
 | char ktest_msg[1024]; | 
 |  | 
 | /* Global linked list used to store registered ktest suites */ | 
 | SLIST_HEAD(suiteq, ktest_suite); | 
 | static struct suiteq ktest_suiteq = SLIST_HEAD_INITIALIZER(ktest_suiteq); | 
 |  | 
 | void register_ktest_suite(struct ktest_suite *suite) | 
 | { | 
 | 	SLIST_INSERT_HEAD(&ktest_suiteq, suite, link); | 
 | } | 
 |  | 
 | void run_registered_ktest_suites() | 
 | { | 
 | 	struct ktest_suite *suite = NULL; | 
 |  | 
 | 	SLIST_FOREACH(suite, &ktest_suiteq, link) { | 
 | 		run_ktest_suite(suite); | 
 | 	} | 
 | } | 
 |  | 
 | void run_ktest_suite(struct ktest_suite *suite) | 
 | { | 
 | 	printk("<-- BEGIN_KERNEL_%s_TESTS -->\n", suite->name); | 
 |  | 
 | 	for (int i=0; i<suite->num_ktests; i++) { | 
 | 		struct ktest *test = &suite->ktests[i]; | 
 | 		if (test->enabled) { | 
 | 			uint64_t start = read_tsc(); | 
 | 			bool result = test->func(); | 
 | 			uint64_t end = read_tsc(); | 
 | 			uint64_t et_us = tsc2usec(end - start) % 1000000; | 
 | 			uint64_t et_s = tsc2sec(end - start); | 
 | 			char fmt[] = "\t%s   [%s](%llu.%06llus)   %s\n"; | 
 |  | 
 | 			if (result) { | 
 | 				printk(fmt, "PASSED", test->name, et_s, et_us, | 
 | 				       ""); | 
 | 			} else { | 
 | 				printk(fmt, "FAILED", test->name, et_s, et_us, | 
 | 				       ktest_msg); | 
 | 			} | 
 | 			/* Some older tests disable IRQs */ | 
 | 			enable_irq(); | 
 | 		} else { | 
 | 			printk("\tDISABLED [%s]\n", test->name); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	printk("<-- END_KERNEL_%s_TESTS -->\n", suite->name); | 
 | } |