Name: local_t test code. Author: Rusty Russell Status: Booted on 2.6.0-test1 Depends: Depends: Depends: Misc/qemu-page-offset.patch.gz D: Test code for local_t implementations. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10321-2.6.0-test1-local_t-test.pre/init/main.c .10321-2.6.0-test1-local_t-test/init/main.c --- .10321-2.6.0-test1-local_t-test.pre/init/main.c 2003-06-17 16:57:33.000000000 +1000 +++ .10321-2.6.0-test1-local_t-test/init/main.c 2003-07-15 09:35:55.000000000 +1000 @@ -548,6 +548,90 @@ static void do_pre_smp_initcalls(void) extern void prepare_namespace(void); +#include + +struct test_stats +{ + atomic_t test_hardirq; + atomic_t test_softirq; + atomic_t test_user; + + local_t test_var; +}; + +static DEFINE_PER_CPU(struct test_stats, test_stats) += { ATOMIC_INIT(0), ATOMIC_INIT(0), ATOMIC_INIT(0), LOCAL_INIT(0) }; + +static int test_running; + +void test_code_hardirq(void) +{ + if (test_running) { + atomic_inc(&__get_cpu_var(test_stats).test_hardirq); + cpu_local_inc(test_stats.test_var); + } +} + +static void test_code_softirq(unsigned long data) +{ + if (test_running) { + atomic_inc(&__get_cpu_var(test_stats).test_softirq); + cpu_local_inc(test_stats.test_var); + } +} + +/* A timer, a hard interrupt and a kernel thread walk into bar... */ +static void test_code(void) +{ + struct timer_list timer; + unsigned int i; + + init_timer(&timer); + timer.function = test_code_softirq; + timer.data = 0; + + test_running = 1; + mb(); + + for (i = 0; i < 1000; i++) { + timer.expires = jiffies + 5; + add_timer(&timer); + + /* Do ten at a time to increase chance of race. */ + do { + atomic_add(10, &get_cpu_var(test_stats).test_user); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + cpu_local_inc(test_stats.test_var); + put_cpu_var(test_stats); + } while (timer_pending(&timer)); + } + test_running = 0; + mb(); + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + printk("local_test %i: %i %i %i %li\n", + i, atomic_read(&per_cpu(test_stats, i).test_hardirq), + atomic_read(&per_cpu(test_stats, i).test_softirq), + atomic_read(&per_cpu(test_stats, i).test_user), + local_read(&per_cpu(test_stats, i).test_var)); + if (local_read(&per_cpu(test_stats, i).test_var) + != (atomic_read(&per_cpu(test_stats, i).test_hardirq) + + atomic_read(&per_cpu(test_stats, i).test_softirq) + + atomic_read(&per_cpu(test_stats, i).test_user))) + panic("Amounts not equal on cpu %i\n", i); + } +} + static int init(void * unused) { static char * argv_sh[] = { "sh", NULL, }; @@ -582,6 +666,8 @@ static int init(void * unused) unlock_kernel(); system_running = 1; + test_code(); + if (open("/dev/console", O_RDWR, 0) < 0) printk("Warning: unable to open an initial console.\n"); diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10321-2.6.0-test1-local_t-test.pre/kernel/sched.c .10321-2.6.0-test1-local_t-test/kernel/sched.c --- .10321-2.6.0-test1-local_t-test.pre/kernel/sched.c 2003-07-14 16:58:38.000000000 +1000 +++ .10321-2.6.0-test1-local_t-test/kernel/sched.c 2003-07-15 09:35:55.000000000 +1000 @@ -1165,6 +1165,8 @@ DEFINE_PER_CPU(struct kernel_stat, kstat (jiffies - (rq)->expired_timestamp >= \ STARVATION_LIMIT * ((rq)->nr_running) + 1))) +extern void test_code_hardirq(void); + /* * This function gets called by the timer code, with HZ frequency. * We call it with interrupts disabled. @@ -1179,6 +1181,8 @@ void scheduler_tick(int user_ticks, int runqueue_t *rq = this_rq(); task_t *p = current; + test_code_hardirq(); + if (rcu_pending(cpu)) rcu_check_callbacks(cpu, user_ticks);