|  | #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); | 
|  | } |