2 * Copyright 2007 John Birrell <jb@FreeBSD.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
33 #include <sys/kthread.h>
34 #include <sys/module.h>
35 #include <sys/sysctl.h>
36 #include <sys/cyclic.h>
39 static struct timespec test_001_start;
42 cyclic_test_001_func(void *arg)
47 timespecsub(&ts,&test_001_start);
48 printf("%s: called after %lu.%09lu on curcpu %d\n",__func__,(u_long) ts.tv_sec,(u_long) ts.tv_nsec, curcpu);
59 printf("%s: starting\n",__func__);
61 hdlr.cyh_func = (cyc_func_t) cyclic_test_001_func;
65 when.cyt_interval = 1000000000;
67 nanotime(&test_001_start);
69 mutex_enter(&cpu_lock);
71 id = cyclic_add(&hdlr, &when);
73 mutex_exit(&cpu_lock);
77 mutex_enter(&cpu_lock);
81 mutex_exit(&cpu_lock);
83 printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
86 static struct timespec test_002_start;
89 cyclic_test_002_func(void *arg)
94 timespecsub(&ts,&test_002_start);
95 printf("%s: called after %lu.%09lu on curcpu %d\n",__func__,(u_long) ts.tv_sec,(u_long) ts.tv_nsec, curcpu);
99 cyclic_test_002_online(void *arg, cpu_t *c, cyc_handler_t *hdlr, cyc_time_t *t)
101 printf("%s: online on curcpu %d\n",__func__, curcpu);
102 hdlr->cyh_func = cyclic_test_002_func;
103 hdlr->cyh_arg = NULL;
105 t->cyt_interval = 1000000000;
109 cyclic_test_002_offline(void *arg, cpu_t *c, void *arg1)
111 printf("%s: offline on curcpu %d\n",__func__, curcpu);
115 cyclic_test_002(void)
118 cyc_omni_handler_t hdlr;
121 printf("%s: starting\n",__func__);
123 hdlr.cyo_online = cyclic_test_002_online;
124 hdlr.cyo_offline = cyclic_test_002_offline;
127 nanotime(&test_002_start);
129 mutex_enter(&cpu_lock);
131 id = cyclic_add_omni(&hdlr);
133 mutex_exit(&cpu_lock);
137 mutex_enter(&cpu_lock);
141 mutex_exit(&cpu_lock);
143 printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
146 static struct timespec test_003_start;
149 cyclic_test_003_func(void *arg)
154 timespecsub(&ts,&test_003_start);
155 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);
159 cyclic_test_003(void)
169 printf("%s: starting\n",__func__);
171 hdlr.cyh_func = (cyc_func_t) cyclic_test_003_func;
175 nanotime(&test_003_start);
177 mutex_enter(&cpu_lock);
179 when.cyt_interval = 200000000;
180 hdlr.cyh_arg = (void *) 0UL;
181 id = cyclic_add(&hdlr, &when);
183 when.cyt_interval = 400000000;
184 hdlr.cyh_arg = (void *) 1UL;
185 id1 = cyclic_add(&hdlr, &when);
187 hdlr.cyh_arg = (void *) 2UL;
188 when.cyt_interval = 1000000000;
189 id2 = cyclic_add(&hdlr, &when);
191 hdlr.cyh_arg = (void *) 3UL;
192 when.cyt_interval = 1300000000;
193 id3 = cyclic_add(&hdlr, &when);
195 mutex_exit(&cpu_lock);
199 mutex_enter(&cpu_lock);
206 mutex_exit(&cpu_lock);
208 printf("%s: %s\n",__func__, error == 0 ? "passed":"failed");
211 /* Kernel thread command routine. */
213 cyclic_run_tests(void *arg)
215 intptr_t cmd = (intptr_t) arg;
234 printf("%s: finished\n",__func__);
240 cyclic_test(SYSCTL_HANDLER_ARGS)
244 error = sysctl_wire_old_buffer(req, sizeof(int));
246 error = sysctl_handle_int(oidp, &cmd, 0, req);
247 if (error != 0 || req->newptr == NULL)
250 /* Check for command validity. */
256 * Execute the tests in a kernel thread to avoid blocking
257 * the sysctl. Look for the results in the syslog.
259 error = kthread_add(cyclic_run_tests, (void *)(uintptr_t) cmd,
260 NULL, NULL, 0, 0, "cyctest%d", cmd);
263 printf("Usage: debug.cyclic.test=(1..9) or -1 for all tests\n");
271 SYSCTL_NODE(_debug, OID_AUTO, cyclic, CTLFLAG_RW, NULL, "Cyclic nodes");
272 SYSCTL_PROC(_debug_cyclic, OID_AUTO, test, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
273 cyclic_test, "I", "Enables a cyclic test. Use -1 for all tests.");
276 cyclic_test_modevent(module_t mod, int type, void *data)
298 DEV_MODULE(cyclic_test, cyclic_test_modevent, NULL);
299 MODULE_VERSION(cyclic_test, 1);
300 MODULE_DEPEND(cyclic_test, cyclic, 1, 1, 1);
301 MODULE_DEPEND(cyclic_test, opensolaris, 1, 1, 1);