3 * Test TSC synchronization
7 #include <linux/module.h>
8 #include <linux/timer.h>
10 #include <linux/jiffies.h>
11 #include <linux/cpu.h>
12 #include <linux/kthread.h>
14 #define MAX_CYCLES_DELTA 1000ULL
16 static DEFINE_PER_CPU(cycles_t
, tsc_count
) = 0;
18 static atomic_t wait_sync
;
19 static atomic_t wait_end_sync
;
21 /* Mark it noinline so we make sure it is not unrolled.
22 * Wait until value is reached. */
23 static noinline
void tsc_barrier(int value
)
26 atomic_dec(&wait_sync
);
29 } while(unlikely(atomic_read(&wait_sync
) > value
));
30 __get_cpu_var(tsc_count
) = get_cycles_sync();
33 /* worker thread called on each CPU.
34 * First wait with interrupts enabled, then wait with interrupt disabled,
35 * for precision. We are already bound to one CPU. */
36 static void test_sync(void *arg
)
40 local_irq_save(flags
);
41 tsc_barrier(2); /* Make sure the instructions are in I-CACHE */
43 atomic_dec(&wait_end_sync
);
46 } while(unlikely(atomic_read(&wait_end_sync
)));
47 local_irq_restore(flags
);
50 /* Do loops (making sure no unexpected event changes the timing), keep the
51 * best one. The result of each loop is the highest tsc delta between the
52 * master CPU and the slaves. */
53 static int test_synchronization(void)
56 cycles_t max_diff
= 0, diff
, best_loop
, worse_loop
= 0;
60 master
= smp_processor_id();
61 for_each_online_cpu(cpu
) {
64 best_loop
= ULLONG_MAX
;
65 for (i
= 0; i
< 10; i
++) {
66 /* Each CPU (master and slave) must decrement the
67 * wait_sync value twice (one for priming in cache) */
68 atomic_set(&wait_sync
, 4);
69 atomic_set(&wait_end_sync
, 2);
70 smp_call_function_single(cpu
, test_sync
, NULL
, 1, 0);
72 diff
= abs(per_cpu(tsc_count
, cpu
)
73 - per_cpu(tsc_count
, master
));
74 best_loop
= min(best_loop
, diff
);
75 worse_loop
= max(worse_loop
, diff
);
77 max_diff
= max(best_loop
, max_diff
);
80 if (max_diff
>= MAX_CYCLES_DELTA
) {
81 printk("Synchronization tsc : %llu cycles delta is over "
82 "threshold %llu\n", max_diff
, MAX_CYCLES_DELTA
);
83 printk("Synchronization tsc (worse loop) : %llu cycles delta\n",
86 return max_diff
< MAX_CYCLES_DELTA
;
89 static int __init
test_init(void)
93 ret
= test_synchronization();
97 static void __exit
test_exit(void)
101 module_init(test_init
);
102 module_exit(test_exit
);
104 MODULE_LICENSE("GPL");
105 MODULE_AUTHOR("Mathieu Desnoyers");
106 MODULE_DESCRIPTION("sync tsc test");
This page took 0.044999 seconds and 4 git commands to generate.