xref: /dragonfly/test/sysperf/umtx1.c (revision 65cc0652)
1 /*
2  * umtx1.c
3  */
4 
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <sys/errno.h>
8 #include <pthread.h>
9 #include <machine/cpufunc.h>
10 #include <machine/atomic.h>
11 #include "blib.h"
12 
13 static void *do_child(void *arg);
14 static void *do_parent(void *arg);
15 
16 u_int mtx;
17 u_long total;
18 
19 int
20 main(int ac, char **av)
21 {
22 	pthread_t td1;
23 	pthread_t td2;
24 	int n;
25 	int k;
26 	int status;
27 
28 	printf("tests umtx hand-off loop\n");
29 	for (n = 1; n; --n) {
30 		if (fork() == 0) {
31 			start_timing();
32 			for (k = 0; k < 10; ++k) {
33 				pthread_create(&td1, NULL, do_child, NULL);
34 				pthread_create(&td2, NULL, do_parent, NULL);
35 				pthread_join(td2, NULL);
36 				pthread_join(td1, NULL);
37 			}
38 			stop_timing(total, "total");
39 			_exit(0);
40 		}
41 	}
42 	while (wait3(&status, 0, NULL) <= 0 || errno == EINTR)
43 		;
44 
45 	return 0;
46 }
47 
48 static
49 void *
50 do_child(void *arg __unused)
51 {
52 	for (;;) {
53 		while (mtx == 0)
54 			umtx_sleep(&mtx, 0, 0);
55 		if (atomic_swap_int(&mtx, 0) == 2) {
56 			umtx_wakeup(&mtx, 0);
57 			pthread_yield();
58 			break;
59 		}
60 		umtx_wakeup(&mtx, 0);
61 	}
62 	return NULL;
63 }
64 
65 static
66 void *
67 do_parent(void *arg __unused)
68 {
69 	int j;
70 	int loops;
71 
72 	for (j = 0; j < 1000000; ++j) {
73 		atomic_swap_int(&mtx, 1);
74 		umtx_wakeup(&mtx, 0);
75 		pthread_yield();
76 		while (mtx == 1)
77 			umtx_sleep(&mtx, 1, 0);
78 	}
79 	start_timing();
80 	for (j = 0; j < 1000000; ++j) {
81 		atomic_swap_int(&mtx, 1);
82 		umtx_wakeup(&mtx, 0);
83 		while (mtx == 1)
84 			umtx_sleep(&mtx, 1, 0);
85 	}
86 	stop_timing(j, "mtx1");
87 	atomic_add_long(&total, j * 2);
88 
89 	atomic_swap_int(&mtx, 2);
90 	umtx_wakeup(&mtx, 0);
91 	while (mtx == 2)
92 		umtx_sleep(&mtx, 2, 0);
93 
94 	return NULL;
95 }
96