2 * \brief DDE for Linux 2.6 Unit tests
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/cunit/CUnit.h>
25 #include <l4/cunit/Basic.h>
26 #include <l4/util/parse_cmd.h>
27 #include <l4/util/util.h>
28 #include <l4/log/l4log.h>
30 /* We define 4 initcalls and see if these are executed
31 * in the beginning and in the right order. Expecations:
33 * - After running the init calls, _init_count == 4
34 * - {_foo, _bar, _bla, _blub}_count carry numbers from 0 through 3
35 * giving their execution order. These need to be:
41 static unsigned _init_count = 0;
42 static unsigned _foo_count = 0;
43 static unsigned _bar_count = 0;
44 static unsigned _bla_count = 0;
45 static unsigned _blub_count = 0;
47 /** Test checking whether the initcalls have been executed correctly. */
48 static int test_initcalls(void)
50 CU_ASSERT(_init_count == 4);
51 CU_ASSERT(_foo_count == 3);
52 CU_ASSERT(_bar_count == 2);
53 CU_ASSERT(_blub_count == 1);
54 CU_ASSERT(_bla_count == 0);
61 _foo_count = _init_count++;
67 _bar_count = _init_count++;
73 _bla_count = _init_count++;
77 static void blub(void)
79 _blub_count = _init_count++;
81 subsys_initcall(blub);
83 /***********************************************************************
84 ** Test 1: Check whether the current() macro works. **
85 ***********************************************************************/
86 static int current_test(void)
88 struct task_struct *t = current;
94 /***********************************************************************
95 ** Test 2: Getting complicated. Test startup of some kernel threads **
96 ** and wait for them to finish using completions. **
97 ***********************************************************************/
98 #define NUM_KTHREADS 5
99 static struct completion _kthread_completions_[NUM_KTHREADS];
101 static int kernel_thread_func(void *arg)
103 CU_ASSERT((int)arg >= 0);
104 CU_ASSERT((int)arg < NUM_KTHREADS);
105 CU_ASSERT(current != NULL);
110 complete_and_exit( &_kthread_completions_[(int)arg], 0 );
115 static int kernel_thread_test(void)
119 for (i=0; i < NUM_KTHREADS; i++) {
121 // initialize completion event
122 init_completion(&_kthread_completions_[i]);
123 // start kernel thread
124 j = kernel_thread(kernel_thread_func, (void *)i, 0);
128 for (i=0; i < NUM_KTHREADS; i++) {
130 wait_for_completion(&_kthread_completions_[i]);
132 CU_ASSERT(i==NUM_KTHREADS);
138 /******************************************************************************
139 ** Test 3: Test kernel wait queues: start a thread incrementing wait_value, **
140 ** and sleep until wait_value is larger than 6 for the first time. **
141 ******************************************************************************/
142 static DECLARE_WAIT_QUEUE_HEAD(_wq_head);
143 static unsigned wait_value = 0;
144 static struct completion wq_completion;
146 static int inc_func(void *arg)
156 CU_ASSERT(wait_value == 10);
158 complete_and_exit(&wq_completion, 0);
162 static int wq_test(void)
166 init_completion(&wq_completion);
167 // start a thread incrementing wait_value
168 pid = kernel_thread(inc_func, 0, 0);
171 // wait until wait_value > 6
172 wait_event(_wq_head, wait_value > 6);
173 CU_ASSERT(wait_value > 6);
175 // wait for inc_thread to exit
176 wait_for_completion(&wq_completion);
177 CU_ASSERT(wait_value == 10);
183 /****************************************************************************
184 ** Test 4: Tasklets **
185 ****************************************************************************/
186 static unsigned _low_count = 0;
187 static unsigned _high_count = 0;
189 static void tasklet_low_func(unsigned long i)
194 static void tasklet_high_func(unsigned long i)
199 static DECLARE_TASKLET(low0, tasklet_low_func, 0);
200 static DECLARE_TASKLET(low1, tasklet_low_func, 1);
201 static DECLARE_TASKLET(low2, tasklet_low_func, 2);
202 static DECLARE_TASKLET_DISABLED(low3, tasklet_low_func, 3);
204 static DECLARE_TASKLET(hi0, tasklet_high_func, 10);
205 static DECLARE_TASKLET(hi1, tasklet_high_func, 11);
206 static DECLARE_TASKLET_DISABLED(hi2, tasklet_high_func, 12);
209 static int tasklet_test(void)
211 l4dde26_softirq_init();
213 // schedule tasklets 0-3, 3 disabled
214 tasklet_schedule(&low0);
215 tasklet_schedule(&low1);
216 tasklet_schedule(&low2);
217 tasklet_schedule(&low3);
220 // 0-2 should have executed by now
221 CU_ASSERT(_low_count == 3);
222 tasklet_enable(&low3);
224 // 3 should be ready, too
225 CU_ASSERT(_low_count == 4);
227 // schedule hi and low tasklets, hi2 is disabled
228 tasklet_hi_schedule(&hi0);
229 tasklet_hi_schedule(&hi1);
230 tasklet_hi_schedule(&hi2);
231 tasklet_schedule(&low0);
232 tasklet_schedule(&low1);
233 tasklet_schedule(&low2);
235 CU_ASSERT(_high_count == 2);
236 CU_ASSERT(_low_count == 7);
239 tasklet_enable(&hi2);
240 // schedule low3 2 times, should only run once
241 tasklet_schedule(&low3);
242 tasklet_schedule(&low3);
244 CU_ASSERT(_high_count == 3);
245 CU_ASSERT(_low_count == 8);
252 /******************************************************************************
255 ** Schedule a periodic timer printing "tick" every second. Additionally, **
256 ** schedule timers for 5, 10, 15, 20, and 25 seconds. Timer at 15s will **
257 ** deactivate the 20s timer. **
258 ******************************************************************************/
260 static struct timer_list _timer;
261 static struct timer_list _timer5;
262 static struct timer_list _timer10;
263 static struct timer_list _timer15;
264 static struct timer_list _timer20;
265 static struct timer_list _timer25;
267 static void tick_func(unsigned long d)
269 printk("tick (%ld)\n", jiffies);
270 _timer.expires = jiffies + HZ;
275 static void timer_func(unsigned long d)
277 printk("timer_func: %lu\n", d);
280 printk("De-scheduling 20s timer.\n");
281 del_timer(&_timer20);
284 if (timer_pending(&_timer20))
285 printk("timer for 20s still pending.\n");
287 printk("timer for 20s has been disabled.\n");
291 static void timer_test(void)
293 l4dde26_init_timers();
295 printk("BEGIN TIMER TEST\n");
296 printk("jiffies(%p): %ld, HZ(%p): %ld\n", &jiffies, jiffies, &HZ, HZ);
298 setup_timer(&_timer, tick_func, 0);
299 _timer.expires = jiffies + HZ;
302 setup_timer(&_timer5, timer_func, 5);
303 _timer5.expires = jiffies + 5*HZ;
304 setup_timer(&_timer10, timer_func, 10);
305 _timer10.expires = jiffies + 10*HZ;
306 setup_timer(&_timer15, timer_func, 15);
307 _timer15.expires = jiffies + 15*HZ;
308 setup_timer(&_timer20, timer_func, 20);
309 _timer20.expires = jiffies + 20*HZ;
310 setup_timer(&_timer25, timer_func, 25);
311 _timer25.expires = jiffies + 25*HZ;
314 add_timer(&_timer10);
315 add_timer(&_timer15);
316 add_timer(&_timer20);
317 add_timer(&_timer25);
320 printk("END TIMER TEST\n");
325 /******************************
326 ** Test 6: Memory subsystem **
327 ******************************/
329 static void memory_kmem_cache_test(void)
331 struct kmem_cache *cache0 = NULL;
337 static struct obj0 *p0[1024];
339 struct kmem_cache *cache1 = NULL;
345 static struct obj1 *p1[256];
347 CU_ASSERT(cache0 == NULL);
348 CU_ASSERT(cache1 == NULL);
350 cache0 = kmem_cache_create("obj0", sizeof(*p0[0]), 0, 0, 0);
351 cache1 = kmem_cache_create("obj1", sizeof(*p1[0]), 0, 0, 0);
353 CU_ASSERT(cache0 != NULL);
354 CU_ASSERT(cache1 != NULL);
357 for (i = 0; i < 1024; ++i) {
358 p0[i] = kmem_cache_alloc(cache0, i);
359 CU_ASSERT(p0[i] != NULL);
362 for (i = 0; i < 256; ++i) {
363 p1[i] = kmem_cache_alloc(cache1, i);
364 CU_ASSERT(p1[i] != NULL);
367 for (i = 256; i > 0; --i)
368 kmem_cache_free(cache1, p1[i-1]);
370 for (i = 1024; i > 0; --i)
371 kmem_cache_free(cache0, p0[i-1]);
373 kmem_cache_destroy(cache1);
374 kmem_cache_destroy(cache0);
378 static void memory_page_alloc_test(void)
381 p[0] = __get_free_page(GFP_KERNEL);
382 p[1] = __get_free_pages(GFP_KERNEL, 1);
383 p[2] = __get_free_pages(GFP_KERNEL, 2);
384 p[3] = __get_free_pages(GFP_KERNEL, 3);
386 CU_ASSERT(p[0] != 0);
387 CU_ASSERT(p[1] != 0);
388 CU_ASSERT(p[2] != 0);
389 CU_ASSERT(p[3] != 0);
398 static void memory_kmalloc_test(void)
400 l4dde26_kmalloc_init();
402 const unsigned count = 33;
406 for (i = 0; i < count; ++i) {
407 p[i] = kmalloc(32 + i*15, GFP_KERNEL);
408 CU_ASSERT(p[i] != NULL);
410 CU_ASSERT(*p[i] == i);
413 for (i = count; i > 0; --i)
414 if (p[i-1]) kfree(p[i-1]);
416 for (i = 0; i < count; ++i) {
417 p[i] = kmalloc(3000 + i*20, GFP_KERNEL);
418 CU_ASSERT(p[i] != NULL);
420 CU_ASSERT(*p[i] == i);
423 for (i = count; i > 0; --i)
424 if (p[i-1]) kfree(p[i-1]);
429 static int memory_test(void)
431 if (1) memory_kmem_cache_test();
432 if (1) memory_page_alloc_test();
433 if (1) memory_kmalloc_test();
438 /****************************************************************************
439 ** Test 7: KThreads **
440 ****************************************************************************/
441 void kthread_test(void)
446 /****************************************************************************
447 ** Test 8: Work queues **
448 ****************************************************************************/
449 static void work_queue_func(void *data);
450 static void work_queue_func2(void *data);
451 static struct workqueue_struct *_wq;
452 static DECLARE_WORK(_wobj, work_queue_func, NULL);
453 static DECLARE_WORK(_wobj2, work_queue_func2, NULL);
454 static int wq_cnt = 0;
456 static void work_queue_func(void *data)
458 printk("Work queue function... Do some work here...\n");
460 queue_work(_wq, &_wobj);
464 static void work_queue_func2(void *data)
466 printk("Work queue function 2... Do some work here...\n");
468 schedule_work(&_wobj2);
472 static void work_queue_test(void)
475 printk("BEGIN WQ TEST\n");
476 _wq = create_workqueue("HelloWQ");
478 queue_work(_wq, &_wobj);
479 schedule_work(&_wobj2);
480 printk("END WQ TEST\n");
484 /****************************************************************************
486 ****************************************************************************/
494 /*************************************************
495 ** Main routine (switch on desired tests here) **
496 *************************************************/
498 int main(int argc, const char **argv)
500 int test_current = 0;
501 int test_kernel_thread = 0;
503 int test_tasklet = 0;
506 int test_kthread = 0;
510 if (parse_cmdline(&argc, &argv,
511 'c', "current", "test current() function",
512 PARSE_CMD_SWITCH, 1, &test_current,
513 'k', "kernel-thread", "test startup of kernel threads",
514 PARSE_CMD_SWITCH, 1, &test_kernel_thread,
515 'w', "waitqueue", "test wait queues",
516 PARSE_CMD_SWITCH, 1, &test_wait,
517 't', "tasklet", "test tasklets",
518 PARSE_CMD_SWITCH, 1, &test_tasklet,
519 'T', "timer", "test timers",
520 PARSE_CMD_SWITCH, 1, &test_timer,
521 'm', "memory", "test memory management",
522 PARSE_CMD_SWITCH, 1, &test_memory,
523 'K', "kthread", "test kthreads",
524 PARSE_CMD_SWITCH, 1, &test_kthread,
525 'W', "workqueue", "test work queues",
526 PARSE_CMD_SWITCH, 1, &test_work,
527 'p', "pci", "test PCI stuff",
528 PARSE_CMD_SWITCH, 1, &test_pci,
532 LOG("DDEKit test. Carrying out tests:");
533 LOGd(test_current, "\t* current()");
534 LOGd(test_kernel_thread, "\t* kernel_thread()");
535 LOGd(test_wait, "\t* wait queues");
536 LOGd(test_tasklet, "\t* tasklets");
537 LOGd(test_timer, "\t* timers");
538 LOGd(test_memory, "\t* memory management");
539 LOGd(test_kthread, "\t* kthreads");
540 LOGd(test_work, "\t* work queues");
541 LOGd(test_pci, "\t* PCI subsystem");
544 l4dde26_process_init();
545 l4dde26_do_initcalls();
547 if (test_current) current_test();
548 if (test_kernel_thread) kernel_thread_test();
549 if (test_wait) wq_test();
550 if (test_tasklet) tasklet_test();
551 if (test_timer) timer_test();
552 if (test_memory) memory_test();
553 /* if (1) kthread_test(); */
554 if (test_work) work_queue_test();
555 if (test_pci) pci_test();
561 static int dde26_ts_init(void)
564 l4dde26_process_init();
565 l4dde26_do_initcalls();
570 static int dde26_ts_cleanup(void)
576 int main(int argc, char **argv)
578 CU_pSuite dde_testsuite = NULL;
580 int err = CU_initialize_registry();
581 if (err == CUE_SUCCESS)
582 printk("Initialized CUnit registry.\n");
584 printk("Could not initialize CUnit registry.\n");
588 dde_testsuite = CU_add_suite("DDE2.6 test suite", dde26_ts_init, dde26_ts_cleanup);
590 printk("Added DDE2.6 test suite.\n");
592 printk("Could not add DDE2.6 test suite.\n");
596 CU_ADD_TEST(dde_testsuite, test_initcalls);
597 CU_ADD_TEST(dde_testsuite, current_test);
598 CU_ADD_TEST(dde_testsuite, kernel_thread_test);
599 CU_ADD_TEST(dde_testsuite, wq_test);
600 CU_ADD_TEST(dde_testsuite, tasklet_test);
601 CU_ADD_TEST(dde_testsuite, memory_test);
603 CU_basic_set_mode(CU_BRM_VERBOSE);
604 CU_basic_run_tests();
606 CU_cleanup_registry();