The do_initcalls() Function

Do_initcalls() is located in init/main.c.

Do_initcalls() runs the list of functions registered with the __initcall attribute, which usually only applies to compiled-in kernel modules and device drivers. The __initcall attribute eliminates the need for a hand-maintained list of device driver initialization functions.

The __initcall mechanism works by creating a constant function pointer in a memory section called .initcall.init, that points to the initialization function itself. When the kernel image is linked, the linker organizes all of these function pointers into a single memory section, and do_initcalls() invokes them in the order they appear there.

The macros and type definitions that implement the __initcall attribute are shown in Figure 9; the code for do_initcalls() is shown in Figure 10.

typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);

#define __initcall(fn)  \
    static initcall_t __initcall_##fn __init_call = fn

#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))

Figure 9. The __initcall macros and typedefs.

extern initcall_t __initcall_start, __initcall_end;

static void __init do_initcalls(void)
{
    initcall_t *call;

    call = &__initcall_start;
    do {
        (*call)();
        call++;
    } while (call < &__initcall_end);

    flush_scheduled_tasks();
}

Figure 10. The do_initcalls() function.