+++ /dev/null
-/* test-tsc.c
- *
- * Test TSC synchronization
- */
-
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <asm/timex.h>
-#include <linux/jiffies.h>
-#include <linux/cpu.h>
-#include <linux/kthread.h>
-
-#define MAX_CYCLES_DELTA 1000ULL
-
-static DEFINE_PER_CPU(cycles_t, tsc_count) = 0;
-
-static atomic_t wait_sync;
-static atomic_t wait_end_sync;
-
-/* Mark it noinline so we make sure it is not unrolled.
- * Wait until value is reached. */
-static noinline void tsc_barrier(int value)
-{
- sync_core();
- atomic_dec(&wait_sync);
- do {
- barrier();
- } while(unlikely(atomic_read(&wait_sync) > value));
- __get_cpu_var(tsc_count) = get_cycles_sync();
-}
-
-/* worker thread called on each CPU.
- * First wait with interrupts enabled, then wait with interrupt disabled,
- * for precision. We are already bound to one CPU. */
-static void test_sync(void *arg)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- tsc_barrier(2); /* Make sure the instructions are in I-CACHE */
- tsc_barrier(0);
- atomic_dec(&wait_end_sync);
- do {
- barrier();
- } while(unlikely(atomic_read(&wait_end_sync)));
- local_irq_restore(flags);
-}
-
-/* Do loops (making sure no unexpected event changes the timing), keep the
- * best one. The result of each loop is the highest tsc delta between the
- * master CPU and the slaves. */
-static int test_synchronization(void)
-{
- int cpu, master;
- cycles_t max_diff = 0, diff, best_loop, worse_loop = 0;
- int i;
-
- preempt_disable();
- master = smp_processor_id();
- for_each_online_cpu(cpu) {
- if (master == cpu)
- continue;
- best_loop = ULLONG_MAX;
- for (i = 0; i < 10; i++) {
- /* Each CPU (master and slave) must decrement the
- * wait_sync value twice (one for priming in cache) */
- atomic_set(&wait_sync, 4);
- atomic_set(&wait_end_sync, 2);
- smp_call_function_single(cpu, test_sync, NULL, 1, 0);
- test_sync(NULL);
- diff = abs(per_cpu(tsc_count, cpu)
- - per_cpu(tsc_count, master));
- best_loop = min(best_loop, diff);
- worse_loop = max(worse_loop, diff);
- }
- max_diff = max(best_loop, max_diff);
- }
- preempt_enable();
- if (max_diff >= MAX_CYCLES_DELTA) {
- printk("Synchronization tsc : %llu cycles delta is over "
- "threshold %llu\n", max_diff, MAX_CYCLES_DELTA);
- printk("Synchronization tsc (worse loop) : %llu cycles delta\n",
- worse_loop);
- }
- return max_diff < MAX_CYCLES_DELTA;
-}
-
-static int __init test_init(void)
-{
- int ret;
-
- ret = test_synchronization();
- return 0;
-}
-
-static void __exit test_exit(void)
-{
-}
-
-module_init(test_init);
-module_exit(test_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("sync tsc test");
-