1 #include <libcflat.h> 2 #include <asm/smp.h> 3 #include <asm/cpumask.h> 4 #include <asm/barrier.h> 5 6 #define LOOP_SIZE 10000000 7 8 struct lock_ops { 9 void (*lock)(int *v); 10 void (*unlock)(int *v); 11 }; 12 static struct lock_ops lock_ops; 13 14 static void gcc_builtin_lock(int *lock_var) 15 { 16 while (__sync_lock_test_and_set(lock_var, 1)); 17 } 18 static void gcc_builtin_unlock(int *lock_var) 19 { 20 __sync_lock_release(lock_var); 21 } 22 static void none_lock(int *lock_var) 23 { 24 while (*(volatile int *)lock_var != 0); 25 *(volatile int *)lock_var = 1; 26 } 27 static void none_unlock(int *lock_var) 28 { 29 *(volatile int *)lock_var = 0; 30 } 31 32 static int global_a, global_b; 33 static int global_lock; 34 35 static cpumask_t smp_test_complete; 36 37 static void test_spinlock(void) 38 { 39 int i, errors = 0; 40 int cpu = smp_processor_id(); 41 42 printf("CPU%d online\n", cpu); 43 44 for (i = 0; i < LOOP_SIZE; i++) { 45 46 lock_ops.lock(&global_lock); 47 48 if (global_a == (cpu + 1) % 2) { 49 global_a = 1; 50 global_b = 0; 51 } else { 52 global_a = 0; 53 global_b = 1; 54 } 55 56 if (global_a == global_b) 57 errors++; 58 59 lock_ops.unlock(&global_lock); 60 } 61 report("CPU%d: Done - Errors: %d", errors == 0, cpu, errors); 62 63 cpumask_set_cpu(cpu, &smp_test_complete); 64 if (cpu != 0) 65 halt(); 66 } 67 68 int main(int argc, char **argv) 69 { 70 int cpu; 71 72 if (argc > 1 && strcmp(argv[1], "bad") != 0) { 73 lock_ops.lock = gcc_builtin_lock; 74 lock_ops.unlock = gcc_builtin_unlock; 75 } else { 76 lock_ops.lock = none_lock; 77 lock_ops.unlock = none_unlock; 78 } 79 80 for_each_present_cpu(cpu) { 81 if (cpu == 0) 82 continue; 83 smp_boot_secondary(cpu, test_spinlock); 84 } 85 86 test_spinlock(); 87 88 while (!cpumask_full(&smp_test_complete)) 89 cpu_relax(); 90 91 return report_summary(); 92 } 93