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 112