xref: /netbsd-src/regress/sys/kern/latency1/latency1.c (revision f82d7874c259b2a6cc59b714f844919f32bf7b51)
1 /*	$NetBSD: latency1.c,v 1.1 2008/05/23 22:22:36 ad Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * THIS IS NOT A GOOD TEST OF REALTIME DISPATCH LATENCY AND SHOULD NOT
31  * BE USED AS ONE.
32  *
33  * Two threads are involved in the test.  Every 100ms the first thread
34  * writes a byte down a pipe.  The second thread waits to read it.  The
35  * time taken for the byte to move between threads is measured.  With
36  * no arguments, it uses timeshared threads.  When given any argument
37  * (junk will do) it uses realtime threads.  Ctrl-C ends the test.
38  */
39 
40 #include <sys/mman.h>
41 #include <sys/resource.h>
42 
43 #include <pthread.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <sched.h>
48 #include <limits.h>
49 #include <signal.h>
50 #include <err.h>
51 
52 pthread_barrier_t	barrier;
53 struct timespec		start;
54 int			fds[2];
55 int 			done;
56 long			max = 0;
57 long			min = LONG_MAX;
58 
59 static void
sigint(int junk)60 sigint(int junk)
61 {
62 
63 	done = 1;
64 }
65 
66 static void *
reader(void * cookie)67 reader(void *cookie)
68 {
69 	struct timespec end;
70 	char buf[1];
71 	long val;
72 
73 	for (;;) {
74 		(void)pthread_barrier_wait(&barrier);
75 		if (read(fds[0], buf, sizeof(buf)) == -1) {
76 			err(1, "read");
77 		}
78 		clock_gettime(CLOCK_MONOTONIC, &end);
79 		timespecsub(&end, &start, &end);
80 		val = (long)end.tv_sec * 1000000000 + (long)end.tv_nsec;
81 		printf("%ld\n", val);
82 		if (val > max)
83 			max = val;
84 		if (val < min)
85 			min = val;
86 	}
87 }
88 
89 int
main(int argc,char * argv[])90 main(int argc, char *argv[])
91 {
92 	static struct timespec delay = { 0, 100000000 };	/* 100ms */
93 	struct sched_param sp;
94 	pthread_t pt;
95 	char buf[1];
96 
97 	if (geteuid() != 0) {
98 		errx(1, "run me as root");
99 	}
100 	if (pipe(fds)) {
101 		err(1, "pipe");
102 	}
103 	pthread_barrier_init(&barrier, NULL, 2);
104 	if (pthread_create(&pt, NULL, reader, NULL)) {
105 		errx(1, "pthread_create failed");
106 	}
107 	if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
108 		err(1, "mlockall");
109 	}
110 	if (signal(SIGINT, sigint)) {
111 		err(1, "siginal");
112 	}
113 	if (argc != 1) {
114 		/* Have an argument, use realtime priorities. */
115 		sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 2;
116 		if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) {
117 			errx(1, "pthread_setschedparam");
118 		}
119 		sp.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
120 		if (pthread_setschedparam(pt, SCHED_FIFO, &sp)) {
121 			errx(1, "pthread_setschedparam");
122 		}
123 	} else {
124 		/* Not realtime, set the maximum timeshared priority. */
125 		if (setpriority(PRIO_PROCESS, 0, -20)) {
126 			err(1, "setpriority");
127 		}
128 	}
129 
130 	do {
131 		(void)pthread_barrier_wait(&barrier);
132 		while (nanosleep(&delay, NULL) != 0) {
133 			/* nothing */
134 		}
135 		clock_gettime(CLOCK_MONOTONIC, &start);
136 		if (write(fds[1], buf, sizeof(buf)) == -1) {
137 			err(1, "write");
138 		}
139 	} while (!done);
140 
141 	printf("\nmin %ldns, max=%ldns\n", min, max);
142 	return 0;
143 }
144