| 1 | /* rdtsc-smp |
| 2 | * |
| 3 | * Test TSC |
| 4 | */ |
| 5 | |
| 6 | |
| 7 | #include <linux/jiffies.h> |
| 8 | #include <linux/compiler.h> |
| 9 | #include <linux/init.h> |
| 10 | #include <linux/module.h> |
| 11 | #include <linux/workqueue.h> |
| 12 | |
| 13 | static atomic_t busy_wait; |
| 14 | static struct delayed_work testwork[NR_CPUS]; |
| 15 | |
| 16 | |
| 17 | static void do_work(struct work_struct *work) |
| 18 | { |
| 19 | cycles_t val; |
| 20 | int cpu1, cpu2; |
| 21 | int num_online = num_online_cpus(); |
| 22 | int copybusy; |
| 23 | int i; |
| 24 | |
| 25 | cpu1 = smp_processor_id(); |
| 26 | printk("Busy waiting on cpu %d\n", cpu1); |
| 27 | |
| 28 | /* Prime busy_wait in cache */ |
| 29 | for(i=0; i<100; i++) { |
| 30 | copybusy = atomic_read(&busy_wait); |
| 31 | } |
| 32 | barrier(); |
| 33 | atomic_inc(&busy_wait); |
| 34 | while(atomic_read(&busy_wait) != num_online) { |
| 35 | barrier(); |
| 36 | } |
| 37 | |
| 38 | val = get_cycles(); |
| 39 | |
| 40 | cpu2 = smp_processor_id(); |
| 41 | BUG_ON(cpu1 != cpu2); |
| 42 | printk("Cycle count on cpu %d is %llu\n", cpu1, val); |
| 43 | } |
| 44 | |
| 45 | |
| 46 | static int ltt_test_init(void) |
| 47 | { |
| 48 | int cpu; |
| 49 | |
| 50 | printk(KERN_ALERT "test init\n"); |
| 51 | |
| 52 | atomic_set(&busy_wait, 0); |
| 53 | for_each_online_cpu(cpu) { |
| 54 | INIT_DELAYED_WORK(&testwork[cpu], do_work); |
| 55 | schedule_delayed_work_on(cpu, &testwork[cpu], 0); |
| 56 | } |
| 57 | return 0; |
| 58 | } |
| 59 | |
| 60 | static void ltt_test_exit(void) |
| 61 | { |
| 62 | /* Test program... wait for output before unload */ |
| 63 | printk(KERN_ALERT "test exit\n"); |
| 64 | } |
| 65 | |
| 66 | module_init(ltt_test_init) |
| 67 | module_exit(ltt_test_exit) |
| 68 | |
| 69 | MODULE_LICENSE("GPL"); |
| 70 | MODULE_AUTHOR("Mathieu Desnoyers"); |
| 71 | MODULE_DESCRIPTION("Linux Trace Toolkit Test"); |
| 72 | |