[PATCH] automatic initcalls

From: Roman Zippel (zippel@linux-m68k.org)
Date: Sat Jul 27 2002 - 15:22:59 EST


Hi,

This patch is based on Rusty's patch, I did these changes to get it
working:
- I only look at modules which contain an initcall
- I only order initcalls of level 6 and 7
This makes the problem managable, so that everything what can be built
as module is also correctly initialized when compiled in. Other
initcalls still have to be ordered manually, but these are the minority
and so easier to manage.
I had to push up a few initcall levels and fix a bug in the IDE driver,
but otherwise it seems to work fine.
I also included my version of KBUILD_MODNAME (IMO my version should be a
bit faster :) ).

bye, Roman

Index: Makefile
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/Makefile,v
retrieving revision 1.1.1.30
diff -u -p -r1.1.1.30 Makefile
--- Makefile 27 Jul 2002 12:34:13 -0000 1.1.1.30
+++ Makefile 27 Jul 2002 13:19:29 -0000
@@ -268,6 +268,7 @@ cmd_link_vmlinux = $(LD) $(LDFLAGS) $(LD
                 $(DRIVERS) \
                 $(NETWORKS) \
                 --end-group \
+ init/generated-initcalls.o \
                 -o vmlinux
 
 # set -e makes the rule exit immediately on error
@@ -284,9 +285,25 @@ define rule_link_vmlinux
         $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
 endef
 
-vmlinux: $(vmlinux-objs) FORCE
+init/generated-initcalls.c: .allinit.defs
+ set -e; echo '#include <linux/init.h>' > $@; \
+ sed -n < $< "s,^T ,,p" | sort > .defined.all; \
+ sed -n < $< "s,^U ,,p" | sort > .undefined.all; \
+ join -o "1.2 2.2" .defined.all .undefined.all | sort -u | tsort > .sorted.all; \
+ cut -d ' ' -f 3 < .allinit.defs | sort -u | grep -v -f .sorted.all > .other.all; \
+ cat .other.all >> .sorted.all; \
+ while read obj; do objdump -t $$obj | awk '/F \.initcall\.test/ { print "extern int " $$6 "(void);" }'; done < .other.all >> $@; \
+ echo 'initcall_t generated_initcalls[] = {' >> $@; \
+ while read obj; do objdump -t $$obj | awk '/F \.initcall\.test/ { print $$6 "," }'; done < .other.all >> $@; \
+ echo '0 };' >> $@
+
+vmlinux: $(vmlinux-objs) init/generated-initcalls.o FORCE
         $(call if_changed_rule,link_vmlinux)
 
+.allinit.defs: $(CORE_FILES) $(LIBS) $(DRIVERS) $(NETWORKS)
+ rm -f $@; \
+ for s in $(dir $^); do ls -ld $$s; awk "{ print \$$1 \" \" \$$2 \" $$s\" \$$3 }" < $${s}.all_defs >> $@; done
+
 # The actual objects are generated when descending,
 # make sure no implicit rule kicks in
 
@@ -586,6 +603,7 @@ defconfig:
 
 # files removed with 'make clean'
 CLEAN_FILES += \
+ init/generated-initcalls.c .allinit.defs .defined.all .undefined.all .other.all .sorted.all \
         include/linux/compile.h \
         vmlinux System.map \
         drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
@@ -647,7 +665,7 @@ clean: archclean
         @echo 'Cleaning up'
         @find . -name SCCS -prune -o -name BitKeeper -prune -o \
                 \( -name \*.[oas] -o -name core -o -name .\*.cmd -o \
- -name .\*.tmp -o -name .\*.d \) -type f -print \
+ -name .\*.tmp -o -name .\*.d -o -name .\*[._]defs \) -type f -print \
                 | grep -v lxdialog/ | xargs rm -f
         @rm -f $(CLEAN_FILES)
         @$(MAKE) -f Documentation/DocBook/Makefile clean
Index: Rules.make
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/Rules.make,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 Rules.make
--- Rules.make 6 Jul 2002 00:33:37 -0000 1.1.1.17
+++ Rules.make 27 Jul 2002 18:56:39 -0000
@@ -105,9 +105,16 @@ multi-objs-m := $(foreach m, $(multi-use
 subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))
 
 # Replace multi-part objects by their individual parts, look at local dir only
-real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m))) $(EXTRA_TARGETS)
+mod-objs-y := $(filter-out $(subdir-obj-y), $(obj-y))
+real-objs-y := $(foreach m, $(mod-objs-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m))) $(EXTRA_TARGETS)
 real-objs-m := $(foreach m, $(obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(m)))
 
+modnames := $(foreach m, $(sort $(mod-objs-y) $(objs-m)), $(if $($(m:.o=-objs)),$(foreach mm,$($(m:.o=-objs)),.$(mm).$(m))))
+
+modname = $(*F)
+
+$(multi-objs-y) $(multi-objs-m) : modname = $(patsubst .$@.%,%,$(filter .$@.%,$(modnames)))
+
 # Only build module versions for files which are selected to be built
 export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))
 
@@ -168,6 +175,7 @@ $(addprefix $(MODVERDIR)/,$(export-objs:
 c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
           $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
           -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
+ -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname:.o=))) \
           $(export_flags)
 
 # Our objects only depend on modversions.h, not on the individual .ver
@@ -248,7 +256,7 @@ endif
 # The echo suppresses the "Nothing to be done for first_rule"
 first_rule: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
             $(if $(KBUILD_MODULES),$(obj-m)) \
- sub_dirs
+ sub_dirs .all_defs
         @echo -n
 
 # Compile C sources (.c)
@@ -269,6 +277,7 @@ $(export-objs:.o=.lst): export_flags :
 c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
           $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
           -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) \
+ -DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname:.o=))) \
           $(export_flags)
 
 quiet_cmd_cc_s_c = CC $(echo_target)
@@ -294,6 +303,17 @@ cmd_cc_lst_c = $(CC) $(c_flags) -g -
 
 %.lst: %.c FORCE
         $(call if_changed_dep,cc_lst_c)
+
+.%.defs: %.o
+ if [ -n "$$(objdump -h $< | egrep '^[ ]*[0-9]+ \.initcall\.test')" ]; then \
+ nm $< | sed -n "s,^[0-9a-f ]*\([TU].*\),\1 $<,p" > $@; \
+ else > $@; fi
+
+$(subdir-y:%=%/.all_defs): sub_dirs
+
+.all_defs: $(mod-objs-y:%.o=.%.defs) $(subdir-y:%=%/.all_defs)
+ cat $(mod-objs-y:%.o=.%.defs) /dev/null > $@; \
+ for s in $(subdir-y); do awk "{ print \$$1 \" \" \$$2 \" $$s/\" \$$3 }" < $$s/.all_defs; done >> $@
 
 # Compile assembler sources (.S)
 # ---------------------------------------------------------------------------
Index: drivers/ide/main.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/drivers/ide/main.c,v
retrieving revision 1.1.1.7
diff -u -p -r1.1.1.7 main.c
--- drivers/ide/main.c 27 Jul 2002 12:40:01 -0000 1.1.1.7
+++ drivers/ide/main.c 27 Jul 2002 13:19:30 -0000
@@ -1401,12 +1401,6 @@ static int __init ata_module_init(void)
         /*
          * Initialize all device type driver modules.
          */
-#ifdef CONFIG_BLK_DEV_IDEDISK
- idedisk_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDECD
- ide_cdrom_init();
-#endif
 #ifdef CONFIG_BLK_DEV_IDETAPE
         idetape_init();
 #endif
Index: fs/dnotify.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/dnotify.c,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 dnotify.c
--- fs/dnotify.c 27 Jul 2002 12:34:15 -0000 1.1.1.5
+++ fs/dnotify.c 27 Jul 2002 13:19:30 -0000
@@ -155,4 +155,4 @@ static int __init dnotify_init(void)
         return 0;
 }
 
-module_init(dnotify_init)
+fs_initcall(dnotify_init);
Index: fs/fcntl.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/fcntl.c,v
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.8 fcntl.c
--- fs/fcntl.c 27 Jul 2002 12:34:14 -0000 1.1.1.8
+++ fs/fcntl.c 27 Jul 2002 13:19:30 -0000
@@ -568,4 +568,4 @@ static int __init fasync_init(void)
         return 0;
 }
 
-module_init(fasync_init)
+fs_initcall(fasync_init);
Index: fs/locks.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/fs/locks.c,v
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.9 locks.c
--- fs/locks.c 27 Jul 2002 12:34:14 -0000 1.1.1.9
+++ fs/locks.c 27 Jul 2002 13:19:30 -0000
@@ -1936,4 +1936,4 @@ static int __init filelock_init(void)
         return 0;
 }
 
-module_init(filelock_init)
+fs_initcall(filelock_init);
Index: include/linux/init.h
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/include/linux/init.h,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 init.h
--- include/linux/init.h 13 Jun 2002 00:22:57 -0000 1.1.1.6
+++ include/linux/init.h 27 Jul 2002 13:19:30 -0000
@@ -65,10 +65,16 @@ extern initcall_t __initcall_start, __in
 #define arch_initcall(fn) __define_initcall("3",fn)
 #define subsys_initcall(fn) __define_initcall("4",fn)
 #define fs_initcall(fn) __define_initcall("5",fn)
-#define device_initcall(fn) __define_initcall("6",fn)
-#define late_initcall(fn) __define_initcall("7",fn)
 
-#define __initcall(fn) device_initcall(fn)
+#define device_initcall(fn) __initcall(fn)
+#define late_initcall(fn) __initcall(fn)
+
+#define __CAT3(a,b,c) a##b##c
+#define _CAT3(a,b,c) __CAT3(a,b,c)
+
+#define __initcall(fn) \
+ int __attribute__((__section__ (".initcall.test"))) _CAT3(fn,_,KBUILD_MODNAME)(void) \
+ { return fn(); }
 
 #define __exitcall(fn) \
         static exitcall_t __exitcall_##fn __exit_call = fn
Index: init/main.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/init/main.c,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 main.c
--- init/main.c 27 Jul 2002 12:34:42 -0000 1.1.1.17
+++ init/main.c 27 Jul 2002 13:19:31 -0000
@@ -464,6 +464,8 @@ asmlinkage void __init start_kernel(void
 
 struct task_struct *child_reaper = &init_task;
 
+extern initcall_t generated_initcalls[];
+
 static void __init do_initcalls(void)
 {
         initcall_t *call;
@@ -473,6 +475,9 @@ static void __init do_initcalls(void)
                 (*call)();
                 call++;
         } while (call < &__initcall_end);
+
+ for (call = generated_initcalls; *call; call++)
+ (*call)();
 
         /* Make sure there is no pending stuff from the initcall sequence */
         flush_scheduled_tasks();
Index: kernel/sched.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/kernel/sched.c,v
retrieving revision 1.1.1.22
diff -u -p -r1.1.1.22 sched.c
--- kernel/sched.c 27 Jul 2002 12:34:42 -0000 1.1.1.22
+++ kernel/sched.c 27 Jul 2002 15:50:14 -0000
@@ -1910,7 +1910,7 @@ int __init migration_init(void)
         return 0;
 }
 
-__initcall(migration_init);
+fs_initcall(migration_init);
 #endif
 
 extern void init_timervecs(void);
Index: kernel/softirq.c
===================================================================
RCS file: /usr/src/cvsroot/linux-2.5/kernel/softirq.c,v
retrieving revision 1.1.1.12
diff -u -p -r1.1.1.12 softirq.c
--- kernel/softirq.c 27 Jul 2002 12:34:43 -0000 1.1.1.12
+++ kernel/softirq.c 27 Jul 2002 15:50:14 -0000
@@ -417,4 +417,4 @@ static __init int spawn_ksoftirqd(void)
         return 0;
 }
 
-__initcall(spawn_ksoftirqd);
+fs_initcall(spawn_ksoftirqd);

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



This archive was generated by hypermail 2b29 : Tue Jul 30 2002 - 14:00:27 EST