summaryrefslogtreecommitdiff
path: root/dde26_test
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2012-02-19 05:56:38 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2012-02-19 05:56:38 +0100
commit19796a75ab8ba43b31e230ea169d5383c6392bfc (patch)
tree3041c5678e06133dd7fcbf2ebf34b6506334f677 /dde26_test
parent6b2e5e0d91823c2a6ce5a5cb12ae3d00b82adae7 (diff)
parent8df772b3c665e663f6f9d2a70f9c691590bd3f91 (diff)
Merge branch 'dde' into upstream-merged
Diffstat (limited to 'dde26_test')
-rw-r--r--dde26_test/Makeconf.local10
-rw-r--r--dde26_test/Makefile20
-rw-r--r--dde26_test/default.ld213
-rw-r--r--dde26_test/main.c481
4 files changed, 724 insertions, 0 deletions
diff --git a/dde26_test/Makeconf.local b/dde26_test/Makeconf.local
new file mode 100644
index 00000000..d6594dc7
--- /dev/null
+++ b/dde26_test/Makeconf.local
@@ -0,0 +1,10 @@
+SYSTEMS = x86-l4v2
+ARCH = x86
+SYSTEM = x86-l4v2
+
+DDEKITLIBDIR = /root/hurd/libddekit/
+DDEKITINCDIR = /root/hurd/libddekit/include
+DDE26LIBDIR = /root/hurd/libdde_linux26/lib/src
+OBJ_BASE = /root/hurd/libdde_linux26/build
+
+L4LIBDIR = .
diff --git a/dde26_test/Makefile b/dde26_test/Makefile
new file mode 100644
index 00000000..0ccbf521
--- /dev/null
+++ b/dde26_test/Makefile
@@ -0,0 +1,20 @@
+PKGDIR ?= ../libdde_linux26
+L4DIR ?= $(PKGDIR)
+
+SYSTEMS = x86-l4v2
+
+DEFAULT_RELOC = 0x00a00000
+
+include Makeconf.local
+
+TARGET = dde26_test
+
+SRC_C = main.c
+
+LIBS += -ldde_linux26.o -ldde_linux26_block -ldde_linux26_char -ldde_linux26_net /root/hurd/libddekit/libddekit.a -lpciaccess -lthreads -lshouldbeinlibc
+CFLAGS += -g
+
+# DDE configuration
+include $(L4DIR)/Makeconf
+
+include $(L4DIR)/mk/prog.mk
diff --git a/dde26_test/default.ld b/dde26_test/default.ld
new file mode 100644
index 00000000..f8e4e28d
--- /dev/null
+++ b/dde26_test/default.ld
@@ -0,0 +1,213 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SEARCH_DIR("/usr/i486-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.dyn :
+ {
+ *(.rel.init)
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+ *(.rel.fini)
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+ *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+ *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+ *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+ *(.rel.ctors)
+ *(.rel.dtors)
+ *(.rel.got)
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+ }
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x90909090
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+
+ KEEP (*(.mark_beg_l4dde_ctors))
+ KEEP (*(SORT(.l4dde_ctors.?)))
+ KEEP (*(SORT(.l4dde_ctors.??)))
+ KEEP (*(SORT(.l4dde_ctors.???)))
+ KEEP (*(SORT(.l4dde_ctors.????)))
+ KEEP (*(SORT(.l4dde_ctors.?????)))
+ KEEP (*(.l4dde_ctors))
+ KEEP (*(.mark_end_l4dde_ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ . = DATA_SEGMENT_RELRO_END (12, .);
+ .got.plt : { *(.got.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ }
+ . = ALIGN(32 / 8);
+ . = ALIGN(32 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }
+}
+
diff --git a/dde26_test/main.c b/dde26_test/main.c
new file mode 100644
index 00000000..f96a212b
--- /dev/null
+++ b/dde26_test/main.c
@@ -0,0 +1,481 @@
+/*
+ * \brief DDE for Linux 2.6 test program
+ * \author Bjoern Doebel <doebel@os.inf.tu-dresden.de>
+ * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
+ * \date 2007-01-22
+ */
+
+#include <asm/current.h>
+
+#include <linux/kernel.h>
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+//#include <linux/kthread.h>
+
+#include <dde.h>
+//#include <ddekit/initcall.h>
+#include <dde26.h>
+#include <ddekit/timer.h>
+
+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;
+}