Add another mutex tester for Jeff's spinlock code w/ the refcount
[dragonfly.git] / test / sysperf / mutex3.c
1 /*
2  * mutex3.c
3  *
4  * $DragonFly: src/test/sysperf/mutex3.c,v 1.1 2006/05/18 02:22:46 dillon Exp $
5  */
6
7 #include "blib.h"
8
9 #include <sys/types.h>
10 #include <machine/atomic.h>
11 #include <machine/cpufunc.h>
12
13 int *mtx;
14 int refcnt;
15
16 static void
17 spin_lock_contested(void)
18 {
19         int i;
20         int j;
21
22         j = 1;
23         while (atomic_swap_int(mtx, 1) != 0) {
24                 for (i = 0; i < j; ++i)
25                         __asm __volatile("pause"::);
26                 j <<= 1;
27         }
28 }
29
30 static __inline void
31 spin_lock(void)
32 {
33         if (refcnt == 1) {
34                 if (*mtx == 0)
35                         *mtx = 1;
36                 else
37                         spin_lock_contested();
38         } else if (atomic_swap_int(mtx, 1) != 0) {
39                 spin_lock_contested();
40         }
41 }
42
43 static __inline void
44 spin_unlock(void)
45 {
46         cpu_sfence();
47         *mtx = 0;
48 }
49
50 int
51 main(int ac, char **av)
52 {
53     long long count = 0;
54     long long max;
55     int j;
56     int *counter;
57     pid_t pid;
58
59     printf("Test simple locked bus cycle mutex latency\n");
60     printf("auto-forks two processes for the test with shared memory\n");
61     printf("This test is only useful on a SMP box\n");
62
63     start_timing();
64     mtx = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
65     counter = mtx + 64;
66     while (stop_timing(0, NULL) == 0) {
67         for (j = 0; j < 100; ++j) {
68             spin_lock();
69             spin_unlock();
70         }
71         count += 100;
72     }
73     max = count;
74     *mtx = 0;
75
76     refcnt = 1;
77     start_timing();
78     for (count = 0; count < max; count += 100) {
79         for (j = 0; j < 100; ++j) {
80             spin_lock();
81             spin_unlock();      /* release */
82             ++counter[64];
83         }
84     }
85     stop_timing(count, "complex_mtx(uncontested/1cpu)");
86     refcnt = 2;
87
88     if ((pid = fork()) == 0) {
89         for (;;) {
90             for (j = 0; j < 100; ++j) {
91                 spin_lock();
92                 spin_unlock();  /* release */
93                 ++counter[128];
94             }
95         }
96     } else {
97         start_timing();
98         for (count = 0; count < max; count += 100) {
99             for (j = 0; j < 100; ++j) {
100                 spin_lock();
101                 spin_unlock();  /* release */
102                 ++counter[64];
103             }
104         }
105         stop_timing(count, "complex_mtx");
106         printf("proc1=%d proc2=%d\n", counter[64], counter[128]);
107         kill(pid, 9);
108     }
109     return(0);
110 }
111