xref: /kvm-unit-tests/arm/spinlock-test.c (revision 3c13c64209599d16c1b04655144af5097aabb857)
1 /*
2  * Spinlock test
3  *
4  * This code is based on code from the tcg_baremetal_tests.
5  *
6  * Copyright (C) 2015 Virtual Open Systems SAS
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <libcflat.h>
14 #include <asm/smp.h>
15 #include <asm/barrier.h>
16 
17 #define LOOP_SIZE 10000000
18 
19 struct lock_ops {
20 	void (*lock)(int *v);
21 	void (*unlock)(int *v);
22 };
23 static struct lock_ops lock_ops;
24 
gcc_builtin_lock(int * lock_var)25 static void gcc_builtin_lock(int *lock_var)
26 {
27 	while (__sync_lock_test_and_set(lock_var, 1));
28 }
gcc_builtin_unlock(int * lock_var)29 static void gcc_builtin_unlock(int *lock_var)
30 {
31 	__sync_lock_release(lock_var);
32 }
none_lock(int * lock_var)33 static void none_lock(int *lock_var)
34 {
35 	while (*(volatile int *)lock_var != 0);
36 	*(volatile int *)lock_var = 1;
37 }
none_unlock(int * lock_var)38 static void none_unlock(int *lock_var)
39 {
40 	*(volatile int *)lock_var = 0;
41 }
42 
43 static int global_a, global_b;
44 static int global_lock;
45 
test_spinlock(void * data __unused)46 static void test_spinlock(void *data __unused)
47 {
48 	int i, errors = 0;
49 	int cpu = smp_processor_id();
50 
51 	printf("CPU%d online\n", cpu);
52 
53 	for (i = 0; i < LOOP_SIZE; i++) {
54 
55 		lock_ops.lock(&global_lock);
56 
57 		if (global_a == (cpu + 1) % 2) {
58 			global_a = 1;
59 			global_b = 0;
60 		} else {
61 			global_a = 0;
62 			global_b = 1;
63 		}
64 
65 		if (global_a == global_b)
66 			errors++;
67 
68 		lock_ops.unlock(&global_lock);
69 	}
70 	report(errors == 0, "CPU%d: Done - Errors: %d", cpu, errors);
71 }
72 
main(int argc,char ** argv)73 int main(int argc, char **argv)
74 {
75 	report_prefix_push("spinlock");
76 	if (argc > 1 && strcmp(argv[1], "bad") != 0) {
77 		lock_ops.lock = gcc_builtin_lock;
78 		lock_ops.unlock = gcc_builtin_unlock;
79 	} else {
80 		lock_ops.lock = none_lock;
81 		lock_ops.unlock = none_unlock;
82 	}
83 
84 	on_cpus(test_spinlock, NULL);
85 
86 	return report_summary();
87 }
88