2 * \brief DDE for Linux 2.6 test program
3 * \author Bjoern Doebel <doebel@os.inf.tu-dresden.de>
4 * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
8 #include <asm/current.h>
10 #include <linux/kernel.h>
11 #include <linux/completion.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/wait.h>
15 #include <linux/sched.h>
16 #include <linux/workqueue.h>
17 #include <linux/interrupt.h>
18 //#include <linux/kthread.h>
20 #include <l4/dde/dde.h>
21 #include <l4/dde/ddekit/initcall.h>
22 #include <l4/dde/linux26/dde26.h>
24 #include <l4/util/parse_cmd.h>
25 #include <l4/util/util.h>
26 #include <l4/log/log.h>
28 /* We define 4 initcalls and see if these are executed
31 static __init void foo(void) { printk("foo module_init\n"); }
32 static __init void bar(void) { printk("bar device_initcall\n"); }
33 static __init void bla(void) { printk("bla arch_initcall\n"); }
34 static __init void blub(void) { printk("blub subsys_initcall\n"); }
38 subsys_initcall(blub);
40 /***********************************************************************
41 ** Test 1: Check whether the current() macro works. **
42 ***********************************************************************/
43 static void current_test(void)
45 struct task_struct *t = NULL;
47 printk("Current() test.\n");
50 printk("\tt = %p\n", t);
54 /***********************************************************************
55 ** Test 2: Getting complicated. Test startup of some kernel threads **
56 ** and wait for them to finish using completions. **
57 ***********************************************************************/
58 #define NUM_KTHREADS 5
59 static struct completion _kthread_completions_[NUM_KTHREADS];
61 static int kernel_thread_func(void *arg)
63 printk("\t\tKernel thread %d\n", (int)arg);
64 printk("\t\tcurrent = %p\n", current);
69 complete_and_exit( &_kthread_completions_[(int)arg], 0 );
74 static void kernel_thread_test(void)
77 printk("Testing kernel_thread()\n");
78 for (i=0; i < NUM_KTHREADS; i++) {
80 printk("\tInitializing completion for kernel thread.%x\n", i+1);
81 init_completion(&_kthread_completions_[i]);
82 printk("\tStarting kthread.%x\n", i+1);
83 j = kernel_thread(kernel_thread_func, (void *)i, 0);
84 printk("\treturn: %d\n", j);
87 for (i=0; i < NUM_KTHREADS; i++) {
88 printk("\tWaiting for kthread.%x to complete.\n", i+1);
89 wait_for_completion(&_kthread_completions_[i]);
90 printk("\tkthread.%x has exited.\n", i+1);
95 /******************************************************************************
96 ** Test 3: Test kernel wait queues: start a thread incrementing wait_value, **
97 ** and sleep until wait_value is larger than 6 for the first time. **
98 ******************************************************************************/
99 static DECLARE_WAIT_QUEUE_HEAD(_wq_head);
100 static int wait_value = 0;
101 static struct completion wq_completion;
103 static int inc_func(void *arg)
107 printk("\033[33mI am counting up wait_value.\033[0m\n");
110 printk("\033[33mwait_value: %d\033[0m\n", ++wait_value);
114 complete_and_exit(&wq_completion, 0);
118 static void wq_test(void)
121 printk("\033[32mWait_queue test. I'm waiting vor wait_value to become >6.\033[0m\n");
123 init_completion(&wq_completion);
124 pid = kernel_thread(inc_func, 0, 0);
126 wait_event(_wq_head, wait_value > 6);
127 printk("\033[32;1mwait_value > 6 occured!\033[0m\n");
129 wait_for_completion(&wq_completion);
130 printk("\033[32mtest done.\033[0m\n");
134 /****************************************************************************
135 ** Test 4: Tasklets **
136 ****************************************************************************/
137 static void tasklet_func(unsigned long i)
139 printk("TASKLET: %d\n", i);
143 static DECLARE_TASKLET(low0, tasklet_func, 0);
144 static DECLARE_TASKLET(low1, tasklet_func, 1);
145 static DECLARE_TASKLET(low2, tasklet_func, 2);
146 static DECLARE_TASKLET_DISABLED(low3, tasklet_func, 3);
148 static DECLARE_TASKLET(hi0, tasklet_func, 10);
149 static DECLARE_TASKLET(hi1, tasklet_func, 11);
150 static DECLARE_TASKLET_DISABLED(hi2, tasklet_func, 12);
153 static void tasklet_test(void)
155 printk("BEGIN TASKLET TEST\n");
157 l4dde26_softirq_init();
159 printk("sleep 1000 msec\n");
162 printk("Scheduling tasklets 0-2 immediately. 3 is disabled for 2 seconds.\n");
163 tasklet_schedule(&low0);
165 tasklet_schedule(&low1);
166 tasklet_schedule(&low2);
167 tasklet_schedule(&low3);
169 tasklet_enable(&low3);
173 printk("Scheduling hi_tasklets 10-12, and tasklets 0-2\n");
174 tasklet_hi_schedule(&hi0);
175 tasklet_hi_schedule(&hi1);
176 tasklet_hi_schedule(&hi2);
177 tasklet_schedule(&low0);
178 tasklet_schedule(&low1);
179 tasklet_schedule(&low2);
180 tasklet_enable(&hi2);
183 printk("Scheduling (disabled) tasklet 3 twice - should only run once after enabling.\n");
184 tasklet_disable(&low3);
185 tasklet_schedule(&low3);
186 tasklet_schedule(&low3);
187 tasklet_enable(&low3);
191 printk("END TASKLET TEST\n");
195 /******************************************************************************
198 ** Schedule a periodic timer printing "tick" every second. Additionally, **
199 ** schedule timers for 5, 10, 15, 20, and 25 seconds. Timer at 15s will **
200 ** deactivate the 20s timer. **
201 ******************************************************************************/
203 static struct timer_list _timer;
204 static struct timer_list _timer5;
205 static struct timer_list _timer10;
206 static struct timer_list _timer15;
207 static struct timer_list _timer20;
208 static struct timer_list _timer25;
210 static void tick_func(unsigned long d)
212 printk("tick (%ld)\n", jiffies);
213 _timer.expires = jiffies + HZ;
218 static void timer_func(unsigned long d)
220 printk("timer_func: %lu\n", d);
223 printk("De-scheduling 20s timer.\n");
224 del_timer(&_timer20);
227 if (timer_pending(&_timer20))
228 printk("timer for 20s still pending.\n");
230 printk("timer for 20s has been disabled.\n");
234 static void timer_test(void)
236 l4dde26_init_timers();
238 printk("BEGIN TIMER TEST\n");
240 printk("jiffies: %ld, HZ: %ld\n", jiffies, HZ);
242 printk("jiffies(%p): %ld, HZ(%p): %ld\n", &jiffies, jiffies, &HZ, HZ);
245 setup_timer(&_timer, tick_func, 0);
246 _timer.expires = jiffies + HZ;
249 setup_timer(&_timer5, timer_func, 5);
250 _timer5.expires = jiffies + 5*HZ;
251 setup_timer(&_timer10, timer_func, 10);
252 _timer10.expires = jiffies + 10*HZ;
253 setup_timer(&_timer15, timer_func, 15);
254 _timer15.expires = jiffies + 15*HZ;
255 setup_timer(&_timer20, timer_func, 20);
256 _timer20.expires = jiffies + 20*HZ;
257 setup_timer(&_timer25, timer_func, 25);
258 _timer25.expires = jiffies + 25*HZ;
261 add_timer(&_timer10);
262 add_timer(&_timer15);
263 add_timer(&_timer20);
264 add_timer(&_timer25);
269 printk("END TIMER TEST\n");
273 /******************************
274 ** Test 6: Memory subsystem **
275 ******************************/
277 static void memory_kmem_cache_test(void)
279 struct kmem_cache *cache0;
285 static struct obj0 *p0[1024];
287 struct kmem_cache *cache1;
293 static struct obj1 *p1[256];
295 cache0 = kmem_cache_create("obj0", sizeof(*p0[0]), 0, 0, 0);
296 cache1 = kmem_cache_create("obj1", sizeof(*p1[0]), 0, 0, 0);
297 printk("kmem caches: %p %p\n", cache0, cache1);
300 for (i = 0; i < 1024; ++i)
301 p0[i] = kmem_cache_alloc(cache0, i);
303 for (i = 0; i < 256; ++i)
304 p1[i] = kmem_cache_alloc(cache1, i);
306 for (i = 256; i > 0; --i)
307 kmem_cache_free(cache1, p1[i-1]);
309 for (i = 1024; i > 0; --i)
310 kmem_cache_free(cache0, p0[i-1]);
312 kmem_cache_destroy(cache1);
313 kmem_cache_destroy(cache0);
314 printk("Done testing kmem_cache_alloc() & co.\n");
318 static void memory_page_alloc_test(void)
321 p[0] = __get_free_page(GFP_KERNEL);
322 p[1] = __get_free_pages(GFP_KERNEL, 1);
323 p[2] = __get_free_pages(GFP_KERNEL, 2);
324 p[3] = __get_free_pages(GFP_KERNEL, 3);
325 printk("pages: %p %p %p %p\n", p[0], p[1], p[2], p[3]);
331 printk("Freed pages\n");
335 static void memory_kmalloc_test(void)
337 // XXX initialized by dde26_init()!
338 // l4dde26_kmalloc_init();
340 const unsigned count = 33;
344 for (i = 0; i < count; ++i) {
345 p[i] = kmalloc(32 + i*15, GFP_KERNEL);
347 printk("p[%d] = %p\n", i, p[i]);
350 for (i = count; i > 0; --i)
351 if (p[i-1]) kfree(p[i-1]);
353 for (i = 0; i < count; ++i) {
354 p[i] = kmalloc(3000 + i*20, GFP_KERNEL);
356 printk("p[%d] = %p\n", i, p[i]);
359 for (i = count; i > 0; --i)
360 if (p[i-1]) kfree(p[i-1]);
365 static void memory_test(void)
367 printk("memory test\n");
368 if (1) memory_kmem_cache_test();
369 if (1) memory_page_alloc_test();
370 if (1) memory_kmalloc_test();
371 printk("End of memory test\n");
375 /****************************************************************************
376 ** Test 7: KThreads **
377 ****************************************************************************/
378 void kthread_test(void)
383 /****************************************************************************
384 ** Test 8: Work queues **
385 ****************************************************************************/
386 static void work_queue_func(struct work_struct *data);
387 static void work_queue_func2(struct work_struct *data);
388 static struct workqueue_struct *_wq;
389 static DECLARE_WORK(_wobj, work_queue_func);
390 static DECLARE_WORK(_wobj2, work_queue_func2);
391 static int wq_cnt = 0;
393 static void work_queue_func(struct work_struct *data)
395 printk("(1) Work queue function... Do some work here...\n");
397 queue_work(_wq, &_wobj);
401 static void work_queue_func2(struct work_struct *data)
403 printk("(2) Work queue function 2... Do some work here...\n");
405 schedule_work(&_wobj2);
409 static void work_queue_test(void)
412 printk("BEGIN WQ TEST\n");
413 _wq = create_workqueue("HelloWQ");
415 queue_work(_wq, &_wobj);
416 schedule_work(&_wobj2);
417 printk("END WQ TEST\n");
421 /****************************************************************************
423 ****************************************************************************/
431 /*************************************************
432 ** Main routine (switch on desired tests here) **
433 *************************************************/
435 int main(int argc, const char **argv)
437 int test_current = 1;
438 int test_kernel_thread = 1;
440 int test_tasklet = 1;
443 int test_kthread = 1;
449 if (parse_cmdline(&argc, &argv,
450 'c', "current", "test current() function",
451 PARSE_CMD_SWITCH, 1, &test_current,
452 'k', "kernel-thread", "test startup of kernel threads",
453 PARSE_CMD_SWITCH, 1, &test_kernel_thread,
454 'w', "waitqueue", "test wait queues",
455 PARSE_CMD_SWITCH, 1, &test_wait,
456 't', "tasklet", "test tasklets",
457 PARSE_CMD_SWITCH, 1, &test_tasklet,
458 'T', "timer", "test timers",
459 PARSE_CMD_SWITCH, 1, &test_timer,
460 'm', "memory", "test memory management",
461 PARSE_CMD_SWITCH, 1, &test_memory,
462 'K', "kthread", "test kthreads",
463 PARSE_CMD_SWITCH, 1, &test_kthread,
464 'W', "workqueue", "test work queues",
465 PARSE_CMD_SWITCH, 1, &test_work,
466 'p', "pci", "test PCI stuff",
467 PARSE_CMD_SWITCH, 1, &test_pci,
471 printk("DDEKit test. Carrying out tests:\n");
472 printk("\t* current()\n");
473 printk("\t* kernel_thread()\n");
474 printk("\t* wait queues\n");
475 printk("\t* tasklets\n");
476 printk("\t* timers\n");
477 printk("\t* memory management\n");
478 printk("\t* kthreads\n");
479 printk("\t* work queues\n");
480 printk("\t* PCI subsystem\n");
483 printk("l4dde26_init()\n");
485 printk("l4dde26_process_init()\n");
486 l4dde26_process_init();
487 printk("l4dde26_do_initcalls()\n");
488 l4dde26_do_initcalls();
491 printk("Init done. Running tests.\n");
492 if (test_current) current_test();
493 if (test_kernel_thread) kernel_thread_test();
494 if (test_wait) wq_test();
495 if (test_tasklet) tasklet_test();
496 if (test_timer) timer_test();
497 if (test_memory) memory_test();
498 if (1) kthread_test();
499 if (test_work) work_queue_test();
500 // if (test_pci) pci_test();
501 printk("Test done.\n");