Linker functions
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 22 Jan 2014 20:56:54 +0000 (12:56 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 22 Jan 2014 20:56:54 +0000 (12:56 -0800)
We can run functions automatically during kernel initialization.  If you
want a void foo(void) func to run, write it like this:

linker_func_2(foo)
{
bar();
}

The functions will run in any order within a level, and lower levels
will run before higher levels.

kern/include/linker_func.h [new file with mode: 0644]
kern/include/ns.h
kern/linker_tables.ld
kern/src/init.c
kern/src/testing.c

diff --git a/kern/include/linker_func.h b/kern/include/linker_func.h
new file mode 100644 (file)
index 0000000..81c6c05
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2014 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Linker functions.  These are functions of type void func(void) that are
+ * automatically run during the kernel initialization.
+ *
+ * There are different levels; the functions of lower levels are run before
+ * higher levels.  There is no guarantee of ordering of functions within a
+ * level.
+ *
+ * To use, change your function definition to use the appropriate macro, e.g.
+ *
+ *             void foo(void)
+ *             {
+ *                     bar();
+ *             }
+ *
+ * becomes
+ *
+ *             linker_func_3(foo)
+ *             {
+ *                     bar();
+ *             }
+ *
+ * And foo() will run during the third level of functions.
+ *
+ * For now, all levels are run sequentially, and with interrupts enabled. */
+
+#ifndef ROS_KERN_LINKER_FUNC_H
+#define ROS_KERN_LINKER_FUNC_H
+
+#define __linkerfunc1  __attribute__((__section__(".linkerfunc1")))
+#define __linkerfunc2  __attribute__((__section__(".linkerfunc2")))
+#define __linkerfunc3  __attribute__((__section__(".linkerfunc3")))
+#define __linkerfunc4  __attribute__((__section__(".linkerfunc4")))
+
+typedef void (*linker_func_t)(void);
+
+#define linker_func_1(x)                                                       \
+       void (x)(void);                                                            \
+       linker_func_t __linkerfunc1 __##x = (x);                                   \
+       void (x)(void)
+
+#define linker_func_2(x)                                                       \
+       void (x)(void);                                                            \
+       linker_func_t __linkerfunc2 __##x = (x);                                   \
+       void (x)(void)
+
+#define linker_func_3(x)                                                       \
+       void (x)(void);                                                            \
+       linker_func_t __linkerfunc3 __##x = (x);                                   \
+       void (x)(void)
+
+#define linker_func_4(x)                                                       \
+       void (x)(void);                                                            \
+       linker_func_t __linkerfunc4 __##x = (x);                                   \
+       void (x)(void)
+
+extern linker_func_t __linkerfunc1start[];
+extern linker_func_t __linkerfunc1end[];
+extern linker_func_t __linkerfunc2start[];
+extern linker_func_t __linkerfunc2end[];
+extern linker_func_t __linkerfunc3start[];
+extern linker_func_t __linkerfunc3end[];
+extern linker_func_t __linkerfunc4start[];
+extern linker_func_t __linkerfunc4end[];
+
+#endif /* ROS_KERN_LINKER_FUNC_H */
index 080f06c..17accae 100644 (file)
@@ -6,6 +6,8 @@
 #include <err.h>
 #include <rendez.h>
 #include <rwlock.h>
+#include <linker_func.h>
+
 /*
  * functions (possibly) linked in, complete, from libc.
  */
@@ -1029,8 +1031,5 @@ extern unsigned int       qiomaxatomic;
 
 /* special sections */
 #define __devtab  __attribute__((__section__(".devtab")))
-#define __devlink  __attribute__((__section__(".devlink")))
-#define __etherlink  __attribute__((__section__(".etherlink")))
-#define __media  __attribute__((__section__(".media")))
 
 #endif /* ROS_KERN_NS_H */
index 1c258a4..8701179 100644 (file)
        PROVIDE(__devtabend = .);
 
        . = ALIGN(32);
-       PROVIDE(__devlinkstart = .);
-       .devlink : {
-               *(.devlink)
+       PROVIDE(__linkerfunc1start = .);
+       .linkerfunc1 : {
+               *(.linkerfunc1)
        }
-       PROVIDE(__devlinkend = .);
+       PROVIDE(__linkerfunc1end = .);
 
        . = ALIGN(32);
-       PROVIDE(__etherlinkstart = .);
-       .etherlink : {
-               *(.etherlink)
+       PROVIDE(__linkerfunc2start = .);
+       .linkerfunc2 : {
+               *(.linkerfunc2)
        }
-       PROVIDE(__etherlinkend = .);
+       PROVIDE(__linkerfunc2end = .);
 
        . = ALIGN(32);
-       PROVIDE(__mediastart = .);
-       .media : {
-               *(.media)
+       PROVIDE(__linkerfunc3start = .);
+       .linkerfunc3 : {
+               *(.linkerfunc3)
        }
-       PROVIDE(__mediaend = .);
+       PROVIDE(__linkerfunc3end = .);
+
+       . = ALIGN(32);
+       PROVIDE(__linkerfunc4start = .);
+       .linkerfunc4 : {
+               *(.linkerfunc4)
+       }
+       PROVIDE(__linkerfunc4end = .);
index eec798e..b58d899 100644 (file)
 #include <ext2fs.h>
 #include <kthread.h>
 #include <console.h>
+#include <linker_func.h>
 
 // zra: flag for Ivy
 int booting = 1;
 
+static void run_linker_funcs(void);
+
 void kernel_init(multiboot_info_t *mboot_info)
 {
        extern char (RO BND(__this, end) edata)[], (RO SNT end)[];
@@ -85,6 +88,7 @@ void kernel_init(multiboot_info_t *mboot_info)
        enable_irq();
        void ether8139link(void);
        ether8139link();
+       run_linker_funcs();
 /*
        void ether8169link(void);
        ether8169link();
@@ -149,27 +153,43 @@ void _warn(const char *file, int line, const char *fmt,...)
        va_end(ap);
 }
 
+static void run_links(linker_func_t *linkstart, linker_func_t *linkend)
+{
+       /* Unlike with devtab, our linker sections for the function pointers are
+        * 8 byte aligned (4 on 32 bit) (done by the linker/compiler), so we don't
+        * have to worry about that.  */
+       printd("linkstart %p, linkend %p\n", linkstart, linkend);
+       for (int i = 0; &linkstart[i] < linkend; i++) {
+               printd("i %d, linkfunc %p\n", i, linkstart[i]);
+               linkstart[i]();
+       }
+}
+
+static void run_linker_funcs(void)
+{
+       run_links(__linkerfunc1start, __linkerfunc1end);
+       run_links(__linkerfunc2start, __linkerfunc2end);
+       run_links(__linkerfunc3start, __linkerfunc3end);
+       run_links(__linkerfunc4start, __linkerfunc4end);
+}
+
 /* You need to reference PROVIDE symbols somewhere, or they won't be included.
  * Only really a problem for debugging. */
 void debug_linker_tables(void)
 {
        extern struct dev __devtabstart[];
        extern struct dev __devtabend[];
-       extern char __devlinkstart[];
-       extern char __devlinkend[];
-       extern char __etherlinkstart[];
-       extern char __etherlinkend[];
-       extern char __mediastart[];
-       extern char __mediaend[];
-       printk("devtab %p %p\ndevlink %p %p\netherlink %p %p\nmedia %p %p\n", 
+       printk("devtab %p %p\nlink1 %p %p\nlink2 %p %p\nlink3 %p %p\nlink4 %p %p\n",
               __devtabstart,
               __devtabend,
-              __devlinkstart,
-              __devlinkend,
-              __etherlinkstart,
-              __etherlinkend,
-              __mediastart,
-              __mediaend);
+                  __linkerfunc1start,
+                  __linkerfunc1end,
+                  __linkerfunc2start,
+                  __linkerfunc2end,
+                  __linkerfunc3start,
+                  __linkerfunc3end,
+                  __linkerfunc4start,
+                  __linkerfunc4end);
 }
 
 #endif //Everything For Free
index 7894bf3..44d9f69 100644 (file)
@@ -1883,3 +1883,106 @@ void test_alarm(void)
 
        printk("%s complete\n", __FUNCTION__);
 }
+
+/* Linker function tests.  Keep them commented, etc. */
+#if 0
+linker_func_1(xme11)
+{
+       printk("xme11\n");
+}
+
+linker_func_1(xme12)
+{
+       printk("xme12\n");
+}
+
+linker_func_1(xme13)
+{
+       printk("xme13\n");
+}
+
+linker_func_1(xme14)
+{
+       printk("xme14\n");
+}
+
+linker_func_1(xme15)
+{
+       printk("xme15\n");
+}
+
+linker_func_2(xme21)
+{
+       printk("xme21\n");
+}
+
+linker_func_2(xme22)
+{
+       printk("xme22\n");
+}
+
+linker_func_2(xme23)
+{
+       printk("xme23\n");
+}
+
+linker_func_2(xme24)
+{
+       printk("xme24\n");
+}
+
+linker_func_2(xme25)
+{
+       printk("xme25\n");
+}
+
+linker_func_3(xme31)
+{
+       printk("xme31\n");
+}
+
+linker_func_3(xme32)
+{
+       printk("xme32\n");
+}
+
+linker_func_3(xme33)
+{
+       printk("xme33\n");
+}
+
+linker_func_3(xme34)
+{
+       printk("xme34\n");
+}
+
+linker_func_3(xme35)
+{
+       printk("xme35\n");
+}
+
+linker_func_4(xme41)
+{
+       printk("xme41\n");
+}
+
+linker_func_4(xme42)
+{
+       printk("xme42\n");
+}
+
+linker_func_4(xme43)
+{
+       printk("xme43\n");
+}
+
+linker_func_4(xme44)
+{
+       printk("xme44\n");
+}
+
+linker_func_4(xme45)
+{
+       printk("xme45\n");
+}
+#endif /* linker func tests */