xref: /netbsd-src/external/cddl/osnet/dev/cyclic/cyclic_test.c (revision 4817a0b0b8fe9612e8ebe21a9bf2d97b95038a97)
1 /*	$NetBSD: cyclic_test.c,v 1.2 2010/02/21 01:46:33 darran Exp $	*/
2 
3 /*-
4  * Copyright 2007 John Birrell <jb@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/cddl/dev/cyclic/cyclic_test.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/conf.h>
35 #include <sys/kthread.h>
36 #include <sys/module.h>
37 #include <sys/sysctl.h>
38 #include <sys/cyclic.h>
39 #include <sys/time.h>
40 
41 static struct timespec test_001_start;
42 
43 static void
44 cyclic_test_001_func(void *arg)
45 {
46 	struct timespec ts;
47 
48 	nanotime(&ts);
49 	timespecsub(&ts,&test_001_start);
50 	printf("%s: called after %lu.%09lu on curcpu %d\n",__func__,(u_long) ts.tv_sec,(u_long) ts.tv_nsec, curcpu);
51 }
52 
53 static void
54 cyclic_test_001(void)
55 {
56 	int error = 0;
57 	cyc_handler_t hdlr;
58 	cyc_time_t when;
59 	cyclic_id_t id;
60 
61 	printf("%s: starting\n",__func__);
62 
63 	hdlr.cyh_func = (cyc_func_t) cyclic_test_001_func;
64         hdlr.cyh_arg = 0;
65 
66         when.cyt_when = 0;
67         when.cyt_interval = 1000000000;
68 
69 	nanotime(&test_001_start);
70 
71 	mutex_enter(&cpu_lock);
72 
73         id = cyclic_add(&hdlr, &when);
74 
75 	mutex_exit(&cpu_lock);
76 
77 	DELAY(1200000);
78 
79 	mutex_enter(&cpu_lock);
80 
81 	cyclic_remove(id);
82 
83 	mutex_exit(&cpu_lock);
84 
85 	printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
86 }
87 
88 static struct timespec test_002_start;
89 
90 static void
91 cyclic_test_002_func(void *arg)
92 {
93 	struct timespec ts;
94 
95 	nanotime(&ts);
96 	timespecsub(&ts,&test_002_start);
97 	printf("%s: called after %lu.%09lu on curcpu %d\n",__func__,(u_long) ts.tv_sec,(u_long) ts.tv_nsec, curcpu);
98 }
99 
100 static void
101 cyclic_test_002_online(void *arg, cpu_t *c, cyc_handler_t *hdlr, cyc_time_t *t)
102 {
103 	printf("%s: online on curcpu %d\n",__func__, curcpu);
104 	hdlr->cyh_func = cyclic_test_002_func;
105 	hdlr->cyh_arg = NULL;
106 	t->cyt_when = 0;
107 	t->cyt_interval = 1000000000;
108 }
109 
110 static void
111 cyclic_test_002_offline(void *arg, cpu_t *c, void *arg1)
112 {
113 	printf("%s: offline on curcpu %d\n",__func__, curcpu);
114 }
115 
116 static void
117 cyclic_test_002(void)
118 {
119 	int error = 0;
120 	cyc_omni_handler_t hdlr;
121 	cyclic_id_t id;
122 
123 	printf("%s: starting\n",__func__);
124 
125 	hdlr.cyo_online = cyclic_test_002_online;
126 	hdlr.cyo_offline = cyclic_test_002_offline;
127 	hdlr.cyo_arg = NULL;
128 
129 	nanotime(&test_002_start);
130 
131 	mutex_enter(&cpu_lock);
132 
133         id = cyclic_add_omni(&hdlr);
134 
135 	mutex_exit(&cpu_lock);
136 
137 	DELAY(1200000);
138 
139 	mutex_enter(&cpu_lock);
140 
141 	cyclic_remove(id);
142 
143 	mutex_exit(&cpu_lock);
144 
145 	printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
146 }
147 
148 static struct timespec test_003_start;
149 
150 static void
151 cyclic_test_003_func(void *arg)
152 {
153 	struct timespec ts;
154 
155 	nanotime(&ts);
156 	timespecsub(&ts,&test_003_start);
157 	printf("%s: called after %lu.%09lu on curcpu %d id %ju\n",__func__,(u_long) ts.tv_sec,(u_long) ts.tv_nsec, curcpu, (uintmax_t)(uintptr_t) arg);
158 }
159 
160 static void
161 cyclic_test_003(void)
162 {
163 	int error = 0;
164 	cyc_handler_t hdlr;
165 	cyc_time_t when;
166 	cyclic_id_t id;
167 	cyclic_id_t id1;
168 	cyclic_id_t id2;
169 	cyclic_id_t id3;
170 
171 	printf("%s: starting\n",__func__);
172 
173 	hdlr.cyh_func = (cyc_func_t) cyclic_test_003_func;
174 
175         when.cyt_when = 0;
176 
177 	nanotime(&test_003_start);
178 
179 	mutex_enter(&cpu_lock);
180 
181         when.cyt_interval = 200000000;
182         hdlr.cyh_arg = (void *) 0UL;
183         id = cyclic_add(&hdlr, &when);
184 
185         when.cyt_interval = 400000000;
186         hdlr.cyh_arg = (void *) 1UL;
187         id1 = cyclic_add(&hdlr, &when);
188 
189         hdlr.cyh_arg = (void *) 2UL;
190         when.cyt_interval = 1000000000;
191         id2 = cyclic_add(&hdlr, &when);
192 
193         hdlr.cyh_arg = (void *) 3UL;
194         when.cyt_interval = 1300000000;
195         id3 = cyclic_add(&hdlr, &when);
196 
197 	mutex_exit(&cpu_lock);
198 
199 	DELAY(1200000);
200 
201 	mutex_enter(&cpu_lock);
202 
203 	cyclic_remove(id);
204 	cyclic_remove(id1);
205 	cyclic_remove(id2);
206 	cyclic_remove(id3);
207 
208 	mutex_exit(&cpu_lock);
209 
210 	printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
211 }
212 
213 /* Kernel thread command routine. */
214 static void
215 cyclic_run_tests(void *arg)
216 {
217 	intptr_t cmd = (intptr_t) arg;
218 
219 	switch (cmd) {
220 	case 1:
221 		cyclic_test_001();
222 		break;
223 	case 2:
224 		cyclic_test_002();
225 		break;
226 	case 3:
227 		cyclic_test_003();
228 		break;
229 	default:
230 		cyclic_test_001();
231 		cyclic_test_002();
232 		cyclic_test_003();
233 		break;
234 	}
235 
236 	printf("%s: finished\n",__func__);
237 
238 	kthread_exit();
239 }
240 
241 static int
242 cyclic_test(SYSCTL_HANDLER_ARGS)
243 {
244 	int error, cmd = 0;
245 
246 	error = sysctl_wire_old_buffer(req, sizeof(int));
247 	if (error == 0)
248 		error = sysctl_handle_int(oidp, &cmd, 0, req);
249 	if (error != 0 || req->newptr == NULL)
250 		return (error);
251 
252 	/* Check for command validity. */
253 	switch (cmd) {
254 	case 1:
255 	case 2:
256 	case -1:
257 		/*
258 		 * Execute the tests in a kernel thread to avoid blocking
259 		 * the sysctl. Look for the results in the syslog.
260 		 */
261 		error = kthread_add(cyclic_run_tests, (void *)(uintptr_t) cmd,
262 		    NULL, NULL, 0, 0, "cyctest%d", cmd);
263 		break;
264 	default:
265 		printf("Usage: debug.cyclic.test=(1..9) or -1 for all tests\n");
266 		error = EINVAL;
267 		break;
268 	}
269 
270 	return (error);
271 }
272 
273 SYSCTL_NODE(_debug, OID_AUTO, cyclic, CTLFLAG_RW, NULL, "Cyclic nodes");
274 SYSCTL_PROC(_debug_cyclic, OID_AUTO, test, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
275     cyclic_test, "I", "Enables a cyclic test. Use -1 for all tests.");
276 
277 static int
278 cyclic_test_modevent(module_t mod, int type, void *data)
279 {
280 	int error = 0;
281 
282 	switch (type) {
283 	case MOD_LOAD:
284 		break;
285 
286 	case MOD_UNLOAD:
287 		break;
288 
289 	case MOD_SHUTDOWN:
290 		break;
291 
292 	default:
293 		error = EOPNOTSUPP;
294 		break;
295 
296 	}
297 	return (error);
298 }
299 
300 DEV_MODULE(cyclic_test, cyclic_test_modevent, NULL);
301 MODULE_VERSION(cyclic_test, 1);
302 MODULE_DEPEND(cyclic_test, cyclic, 1, 1, 1);
303 MODULE_DEPEND(cyclic_test, opensolaris, 1, 1, 1);
304