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

Reply via email to