------- Comment #5 from anders at kaseorg dot com 2009-10-09 16:12 ------- As Nelson pointed out, the subsequent commit to that macro <http://git.kernel.org/linus/0b1c723d0bd199300a1a2de57a46000d17577498> cannot be done with C. In any event, while it may also be useful to add extensions like nobits to C, adding enough extensions to subsume all conceivable uses of inline assembly clearly isnÂ’t a sustainable solution.
A more fundamental source of ugliness in the Linux kernel is that many functions which are written entirely in assembly (and must be, because they have special calling conventions dictated by the hardware, or are involved in setting up the appropriate environment for executing C code, or must be hand-optimized for performance, etc.) need to access members of a C struct. Since there is no way to get the offset of a C struct member from assembly, the kernelÂ’s current solution is to compile (but not assemble) a special file named asm-offsets.c: #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) int main(void) { #define ENTRY(entry) DEFINE(tsk_ ## entry, offsetof(struct task_struct, entry)) ENTRY(state); ENTRY(flags); ENTRY(pid); Â… } resulting in asm-offsets.s: main: pushq %rbp # movq %rsp, %rbp #, #APP ->tsk_state $0 offsetof(struct task_struct, state) # ->tsk_flags $20 offsetof(struct task_struct, flags) # ->tsk_pid $680 offsetof(struct task_struct, pid) # Â… which is post-processed with sed into a header asm-offsets.h that consists of a long list of definitions for assembly code: #define tsk_state 0 /* offsetof(struct task_struct, state) # */ #define tsk_flags 20 /* offsetof(struct task_struct, flags) # */ #define tsk_pid 680 /* offsetof(struct task_struct, pid) # */ Â… If toplevel extended asm was available, this entire mechanism could have been unnecessary, because one could write this directly: asm("kernel_thread:\n" Â… "movl %c[tsk_pid](%%rax),%%eax\n" : : [tsk_pid] "n" (offsetof(struct task_struct, pid))); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41045