just ran into an interesting circular header file issue. first, from <linux/timer.h>: ===== struct timer_list { struct list_head entry; unsigned long expires; void (*function)(unsigned long); unsigned long data; struct tvec_base *base; #ifdef CONFIG_TIMER_STATS void *start_site; char start_comm[16]; <--- note hard-coded "16" int start_pid; #endif ===== now pop over to kernel/timer.c: ===== void init_timer(struct timer_list *timer) { timer->entry.next = NULL; timer->base = __raw_get_cpu_var(tvec_bases); #ifdef CONFIG_TIMER_STATS timer->start_site = NULL; timer->start_pid = -1; memset(timer->start_comm, 0, TASK_COMM_LEN); ^^^^^^^^^^^^^ ??? #endif } ===== it certainly seems that calling init_timer() will clear that array of 16 bytes, but timer.c uses the flexible macro definition TASK_COMM_LEN. why doesn't timer.h? so let's make that change to timer.h and, to get the macro definition of TASK_COMM_LEN in timer.h, we need to include <linux/sched.h> where it's defined: /* Task command name length */ #define TASK_COMM_LEN 16 then try to "make": ... CC arch/x86/kernel/asm-offsets.s In file included from include/linux/sched.h:341, from include/linux/timer.h:7, from include/linux/workqueue.h:8, from include/linux/slub_def.h:11, from include/linux/slab.h:118, from include/linux/percpu.h:5, from include/asm/local.h:4, from include/linux/module.h:19, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets_32.c:7, from arch/x86/kernel/asm-offsets.c:2: include/linux/aio.h:202: error: field ʽwqʼ has incomplete type In file included from include/linux/timer.h:7, from include/linux/workqueue.h:8, from include/linux/slub_def.h:11, from include/linux/slab.h:118, from include/linux/percpu.h:5, from include/asm/local.h:4, from include/linux/module.h:19, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets_32.c:7, from arch/x86/kernel/asm-offsets.c:2: include/linux/sched.h:598: error: field ʽworkʼ has incomplete type make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1 make: *** [prepare0] Error 2 $ the problem appears to be that timer.h includes sched.h, but sched.h conversely includes timer.h. so timer.h includes sched.h early (before the definition of "struct timer_list" can be defined). sched.h then tries to include timer.h, but can't since multiple inclusion protection of timer.h prevents that. at which point, later on in sched.h, *something* badly needs the definition of struct timer_list but doesn't have it. whoops. thoughts? it would seem that, for cleanliness, if timer.h and timer.c really should match in that array length, then they *both* should be using the more general "TASK_COMM_LEN". but, under the circumstances, that can't be done as long as that macro is defined in sched.h. thoughts? rday -- ======================================================================== Robert P. J. Day Linux Consulting, Training and Annoying Kernel Pedantry: Have classroom, will lecture. http://crashcourse.ca Waterloo, Ontario, CANADA ========================================================================