add test-tsc
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 20 Mar 2007 20:36:29 +0000 (20:36 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 20 Mar 2007 20:36:29 +0000 (20:36 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@2446 04897980-b3bd-0310-b5e0-8ef037075253

tests/kernel/Makefile
tests/kernel/test-tsc-sync.c
tests/kernel/test-tsc.c [new file with mode: 0644]

index 69d5ff2a4ecba173f05bbf300de85343cbdca455..01259f55f200b1e0888e4bd14a80e9e2d6a50b1e 100644 (file)
@@ -12,6 +12,7 @@ ifneq ($(CONFIG_LTT),)
 endif
 #      obj-m += test-async-tsc.o
        obj-m += test-tsc-sync.o
+       obj-m += test-tsc.o
 #      obj-m += test-hpet.o
        #obj-m += test-debugfs.o
 #      obj-m += test-mod.o
index 200839abb7226cf24a17f175f9f4ae51ae4730ba..14cd008b3c59372acad35148ad88fa706bbbe79f 100644 (file)
@@ -24,7 +24,7 @@ static void test_each(void *info)
        atomic_dec(&kernel_threads_to_run);
        while(atomic_read(&kernel_threads_to_run))
                cpu_relax();
-       __get_cpu_var(count) = get_cycles();
+       __get_cpu_var(count) = get_cycles_sync();
        local_irq_restore(flags);
 }
 
diff --git a/tests/kernel/test-tsc.c b/tests/kernel/test-tsc.c
new file mode 100644 (file)
index 0000000..8a3991f
--- /dev/null
@@ -0,0 +1,107 @@
+/* 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");
+
This page took 0.038162 seconds and 4 git commands to generate.