Format string space reclamation

From: Mark Rustad
Date: Thu Dec 09 2004 - 15:24:28 EST


Folks,

Has anyone considered reclaiming the memory occupied by format string in initialization code? Below I have a patch that adds macro functions pkinit, pkdevinit and pkdevexit into init.h. These functions create their format strings into special sections so that they can be reclaimed along .init.data. Additional changes were needed in the linker script to use new sections so that a const could be applied to the declared character arrays - without the "const" the compiler would not do type checking on the arguments to printk.

This kind of thing can save some run-time memory in embedded systems. I have used the printk in my own stuff for some time, but only recently enhanced this to allow the format strings and arguments to be checked by the compiler. That held me up from passing it along until now.

Obviously this does not do everything to allow all architectures to use it, but it does not seem to cause any trouble in architectures that have not made the linker script changes to take advantage of it.

Is anyone else interested in this?

--- a/include/linux/init.h 2004-04-03 21:36:16.000000000 -0600
+++ obj/include/linux/init.h 2004-12-09 11:38:29.000000000 -0600
@@ -43,7 +43,9 @@
discard it in modules) */
#define __init __attribute__ ((__section__ (".init.text")))
#define __initdata __attribute__ ((__section__ (".init.data")))
+#define __initrodata __attribute__ ((__section__ (".ro.init.data")))
#define __exitdata __attribute__ ((__section__(".exit.data")))
+#define __exitrodata __attribute__ ((__section__(".ro.exit.data")))
#define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))

#ifdef MODULE
@@ -208,8 +210,9 @@
#else
#define __devinit __init
#define __devinitdata __initdata
+#define __devinitrodata __initrodata
#define __devexit __exit
-#define __devexitdata __exitdata
+#define __devexitrodata __exitrodata
#endif

/* Functions marked as __devexit may be discarded at kernel link time, depending
@@ -230,4 +233,29 @@
#define __exit_p(x) NULL
#endif

+#ifndef __ASSEMBLY__
+/*
+ * The pkinit function can be used in place of printk in __init functions,
+ * and the pkdevinit function can be used in __devinit and pkdevexit can
+ * be used in __devexit functions in order to place the format string into
+ * the appripriate section so they can be reclaimed or discarded as
+ * appropriate.
+ *
+ * Be careful not to use this in any other type of function and do not
+ * use it unless the format string is a literal string.
+ */
+
+#define _pk(typ, fstr, x...) do { static const char _f[] typ = fstr; \
+ printk(_f, ## x); } while (0)
+#define pkinit(f, x...) _pk(__initrodata, f, ## x)
+
+#if defined(CONFIG_HOTPLUG)
+#define pkdevinit(f, x...) printk(f, ## x);
+#define pkdevexit(f, x...) printk(f, ## x);
+#else
+#define pkdevinit(f, x...) _pk(__devinitrodata, f, ## x)
+#define pkdevexit(f, x...) _pk(__devexitrodata, f, ## x)
+#endif /* CONFIG_HOTPLUG */
+#endif /* __ASSEMBLY__ */
+
#endif /* _LINUX_INIT_H */
--- a/arch/i386/kernel/vmlinux.lds.S 2004-11-17 13:41:53.000000000 -0600
+++ obj/arch/i386/kernel/vmlinux.lds.S 2004-12-09 13:17:25.000000000 -0600
@@ -60,7 +60,7 @@
*(.init.text)
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { *(.init.data) *(.ro.init.data) }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -94,7 +94,7 @@
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ .exit.data : { *(.exit.data) *(.ro.exit.data) }
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }

--
Mark Rustad, MRustad@xxxxxxx

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/