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
========================================================================