/* * \brief DDE for Linux 2.6 test program * \author Bjoern Doebel * \author Christian Helmuth * \date 2007-01-22 */ #include #include #include #include #include #include #include #include #include //#include #include //#include #include #include int using_std = 1; /* We define 4 initcalls and see if these are executed * in the beginning. */ static __init void foo(void) { printk("foo module_init\n"); } static __init void bar(void) { printk("bar device_initcall\n"); } static __init void bla(void) { printk("bla arch_initcall\n"); } static __init void blub(void) { printk("blub subsys_initcall\n"); } //module_init(foo); //device_initcall(bar); //arch_initcall(bla); //subsys_initcall(blub); /*********************************************************************** ** Test 1: Check whether the current() macro works. ** ***********************************************************************/ static void current_test(void) { struct task_struct *t = NULL; printk("Current() test.\n"); t = current; printk("\tt = %p\n", t); } /*********************************************************************** ** Test 2: Getting complicated. Test startup of some kernel threads ** ** and wait for them to finish using completions. ** ***********************************************************************/ #define NUM_KTHREADS 5 static struct completion _kthread_completions_[NUM_KTHREADS]; static int kernel_thread_func(void *arg) { printk("\t\tKernel thread %d\n", (int)arg); printk("\t\tcurrent = %p\n", current); /* do some work */ msleep(200); complete_and_exit( &_kthread_completions_[(int)arg], 0 ); return 0; } static void kernel_thread_test(void) { int i; printk("Testing kernel_thread()\n"); for (i=0; i < NUM_KTHREADS; i++) { int j; printk("\tInitializing completion for kernel thread.%x\n", i+1); init_completion(&_kthread_completions_[i]); printk("\tStarting kthread.%x\n", i+1); j = kernel_thread(kernel_thread_func, (void *)i, 0); printk("\treturn: %d\n", j); } for (i=0; i < NUM_KTHREADS; i++) { printk("\tWaiting for kthread.%x to complete.\n", i+1); wait_for_completion(&_kthread_completions_[i]); printk("\tkthread.%x has exited.\n", i+1); } } /****************************************************************************** ** Test 3: Test kernel wait queues: start a thread incrementing wait_value, ** ** and sleep until wait_value is larger than 6 for the first time. ** ******************************************************************************/ static DECLARE_WAIT_QUEUE_HEAD(_wq_head); static int wait_value = 0; static struct completion wq_completion; static int inc_func(void *arg) { int i = 0; printk("\033[33mI am counting up wait_value.\033[0m\n"); for (i=0; i<10; i++) { printk("\033[33mwait_value: %d\033[0m\n", ++wait_value); wake_up(&_wq_head); msleep(500); } complete_and_exit(&wq_completion, 0); } static void wq_test(void) { int pid; printk("\033[32mWait_queue test. I'm waiting vor wait_value to become >6.\033[0m\n"); init_completion(&wq_completion); pid = kernel_thread(inc_func, 0, 0); wait_event(_wq_head, wait_value > 6); printk("\033[32;1mwait_value > 6 occured!\033[0m\n"); wait_for_completion(&wq_completion); printk("\033[32mtest done.\033[0m\n"); } /**************************************************************************** ** Test 4: Tasklets ** ****************************************************************************/ static void tasklet_func(unsigned long i) { printk("TASKLET: %d\n", i); } static DECLARE_TASKLET(low0, tasklet_func, 0); static DECLARE_TASKLET(low1, tasklet_func, 1); static DECLARE_TASKLET(low2, tasklet_func, 2); static DECLARE_TASKLET_DISABLED(low3, tasklet_func, 3); static DECLARE_TASKLET(hi0, tasklet_func, 10); static DECLARE_TASKLET(hi1, tasklet_func, 11); static DECLARE_TASKLET_DISABLED(hi2, tasklet_func, 12); static void tasklet_test(void) { printk("BEGIN TASKLET TEST\n"); l4dde26_softirq_init(); printk("sleep 1000 msec\n"); msleep(1000); printk("Scheduling tasklets 0-2 immediately. 3 is disabled for 2 seconds.\n"); tasklet_schedule(&low0); tasklet_schedule(&low1); tasklet_schedule(&low2); tasklet_schedule(&low3); msleep(2000); tasklet_enable(&low3); msleep(1000); printk("Scheduling hi_tasklets 10-12, and tasklets 0-2\n"); tasklet_hi_schedule(&hi0); tasklet_hi_schedule(&hi1); tasklet_hi_schedule(&hi2); tasklet_schedule(&low0); tasklet_schedule(&low1); tasklet_schedule(&low2); tasklet_enable(&hi2); msleep(1000); printk("Scheduling (disabled) tasklet 3 twice - should only run once after enabling.\n"); tasklet_disable(&low3); tasklet_schedule(&low3); tasklet_schedule(&low3); tasklet_enable(&low3); msleep(1000); printk("END TASKLET TEST\n"); } /****************************************************************************** ** Test 5: Timers ** ** ** ** Schedule a periodic timer printing "tick" every second. Additionally, ** ** schedule timers for 5, 10, 15, 20, and 25 seconds. Timer at 15s will ** ** deactivate the 20s timer. ** ******************************************************************************/ static struct timer_list _timer; static struct timer_list _timer5; static struct timer_list _timer10; static struct timer_list _timer15; static struct timer_list _timer20; static struct timer_list _timer25; static void tick_func(unsigned long d) { printk("tick (%ld)\n", jiffies); _timer.expires = jiffies + HZ; add_timer(&_timer); } static void timer_func(unsigned long d) { printk("timer_func: %lu\n", d); if (d == 15) { printk("De-scheduling 20s timer.\n"); del_timer(&_timer20); } if (timer_pending(&_timer20)) printk("timer for 20s still pending.\n"); else printk("timer for 20s has been disabled.\n"); } static void timer_test(void) { l4dde26_init_timers(); printk("BEGIN TIMER TEST\n"); printk("jiffies: %ld, HZ: %ld\n", jiffies, HZ); setup_timer(&_timer, tick_func, 0); _timer.expires = jiffies + HZ; add_timer(&_timer); setup_timer(&_timer5, timer_func, 5); _timer5.expires = jiffies + 5*HZ; setup_timer(&_timer10, timer_func, 10); _timer10.expires = jiffies + 10*HZ; setup_timer(&_timer15, timer_func, 15); _timer15.expires = jiffies + 15*HZ; setup_timer(&_timer20, timer_func, 20); _timer20.expires = jiffies + 20*HZ; setup_timer(&_timer25, timer_func, 25); _timer25.expires = jiffies + 25*HZ; add_timer(&_timer5); add_timer(&_timer10); add_timer(&_timer15); add_timer(&_timer20); add_timer(&_timer25); msleep(30000); del_timer(&_timer); printk("END TIMER TEST\n"); } /****************************** ** Test 6: Memory subsystem ** ******************************/ static void memory_kmem_cache_test(void) { struct kmem_cache *cache0; struct obj0 { unsigned foo; unsigned bar; }; static struct obj0 *p0[1024]; struct kmem_cache *cache1; struct obj1 { char foo[50]; unsigned *bar; }; static struct obj1 *p1[256]; cache0 = kmem_cache_create("obj0", sizeof(*p0[0]), 0, 0, 0); cache1 = kmem_cache_create("obj1", sizeof(*p1[0]), 0, 0, 0); printk("kmem caches: %p %p\n", cache0, cache1); unsigned i; for (i = 0; i < 1024; ++i) p0[i] = kmem_cache_alloc(cache0, i); for (i = 0; i < 256; ++i) p1[i] = kmem_cache_alloc(cache1, i); for (i = 256; i > 0; --i) kmem_cache_free(cache1, p1[i-1]); for (i = 1024; i > 0; --i) kmem_cache_free(cache0, p0[i-1]); kmem_cache_destroy(cache1); kmem_cache_destroy(cache0); printk("Done testing kmem_cache_alloc() & co.\n"); } static void memory_page_alloc_test(void) { unsigned long p[4]; p[0] = __get_free_page(GFP_KERNEL); p[1] = __get_free_pages(GFP_KERNEL, 1); p[2] = __get_free_pages(GFP_KERNEL, 2); p[3] = __get_free_pages(GFP_KERNEL, 3); printk("pages: %p %p %p %p\n", p[0], p[1], p[2], p[3]); free_pages(p[0], 0); free_pages(p[1], 1); free_pages(p[2], 2); free_pages(p[3], 3); printk("Freed pages\n"); } static void memory_kmalloc_test(void) { // XXX initialized by dde26_init()! // l4dde26_kmalloc_init(); const unsigned count = 33; char *p[count]; int i; for (i = 0; i < count; ++i) { p[i] = kmalloc(32 + i*15, GFP_KERNEL); *p[i] = i; printk("p[%d] = %p\n", i, p[i]); } for (i = count; i > 0; --i) if (p[i-1]) kfree(p[i-1]); for (i = 0; i < count; ++i) { p[i] = kmalloc(3000 + i*20, GFP_KERNEL); *p[i] = i; printk("p[%d] = %p\n", i, p[i]); } for (i = count; i > 0; --i) if (p[i-1]) kfree(p[i-1]); } static void memory_test(void) { printk("memory test\n"); if (1) memory_kmem_cache_test(); if (1) memory_page_alloc_test(); if (1) memory_kmalloc_test(); printk("End of memory test\n"); } /**************************************************************************** ** Test 7: KThreads ** ****************************************************************************/ void kthread_test(void) { } /**************************************************************************** ** Test 8: Work queues ** ****************************************************************************/ static void work_queue_func(struct work_struct *data); static void work_queue_func2(struct work_struct *data); static struct workqueue_struct *_wq; static DECLARE_WORK(_wobj, work_queue_func); static DECLARE_WORK(_wobj2, work_queue_func2); static int wq_cnt = 0; static void work_queue_func(struct work_struct *data) { printk("(1) Work queue function... Do some work here...\n"); if (++wq_cnt < 5) queue_work(_wq, &_wobj); } static void work_queue_func2(struct work_struct *data) { printk("(2) Work queue function 2... Do some work here...\n"); if (++wq_cnt < 10) schedule_work(&_wobj2); } static void work_queue_test(void) { int i; printk("BEGIN WQ TEST\n"); _wq = create_workqueue("HelloWQ"); BUG_ON(_wq == NULL); queue_work(_wq, &_wobj); schedule_work(&_wobj2); printk("END WQ TEST\n"); } /**************************************************************************** ** Test 9: PCI ** ****************************************************************************/ void pci_test(void) { l4dde26_init_pci(); } /************************************************* ** Main routine (switch on desired tests here) ** *************************************************/ int main(int argc, const char **argv) { int test_current = 1; int test_kernel_thread = 1; int test_wait = 1; int test_tasklet = 1; int test_timer = 1; int test_memory = 1; int test_kthread = 1; int test_work = 1; int test_pci = 1; msleep(1000); l4dde26_init (); l4dde26_process_init (); l4dde26_do_initcalls (); printk("DDEKit test. Carrying out tests:\n"); printk("\t* current()\n"); printk("\t* kernel_thread()\n"); printk("\t* wait queues\n"); printk("\t* tasklets\n"); printk("\t* timers\n"); printk("\t* memory management\n"); printk("\t* kthreads\n"); printk("\t* work queues\n"); printk("\t* PCI subsystem\n"); #if 0 printk("l4dde26_init()\n"); l4dde26_init(); printk("l4dde26_process_init()\n"); l4dde26_process_init(); printk("l4dde26_do_initcalls()\n"); l4dde26_do_initcalls(); #endif printk("Init done. Running tests.\n"); if (test_current) current_test(); if (test_kernel_thread) kernel_thread_test(); if (test_wait) wq_test(); if (test_tasklet) tasklet_test(); if (test_timer) timer_test(); if (test_memory) memory_test(); if (1) kthread_test(); if (test_work) work_queue_test(); // if (test_pci) pci_test(); printk("Test done.\n"); return 0; }