zoukankan      html  css  js  c++  java
  • good explanation of __read_mostly, __init, __exit macros


    http://stackoverflow.com/questions/11505681/good-explanation-of-read-mostly-init-exit-macros


    The macro expansion of __read_mostly :

    #define __read_mostly __attribute__((__section__(".data..read_mostly"))

    This one is from cache.h

    __init:

    #define __init          __section(.init.text) __cold notrace

    from init.h

    __exit:

    #define __exit          __section(.exit.text) __exitused __cold notrace

    After searching through net i have not found any good explanation ofwhat is happening there.

    Additonal question : I have heard about various "linker magic"employed in kernel development. Any informationregarding this will be wonderful.

    I have some ideas about these macros about what they do. Like __init supposed to indicate that the function code can be removed after initialization. __read_mostly is for indicating that the data is seldom written and by this it minimizes cache misses. But i have not idea about How they do it. I mean they are gcc extensions. So in theory they can be demonstrated by small userland c code.

    UPDATE 1:

    I have tried to test the __section__ with arbitrary section name. the test code :

    #include <stdio.h>
    
    #define __read_mostly __attribute__((__section__("MY_DATA")))
    
    struct ro {
        char a;
        int b;
        char * c;
    };
    
    struct ro my_ro  __read_mostly = {
        .a = 'a',
        .b = 3,
        .c = NULL,
    };
    
    
    int main(int argc, char **argv) {
        printf("hello");
        printf("my ro %c %d %p 
    ", my_ro.a, my_ro.b, my_ro.c);
        return 0;
    }

    Now with __read_mostly the generated assembly code :

        .file   "ro.c"
    .globl my_ro
        .section    MY_DATA,"aw",@progbits
        .align 16
        .type   my_ro, @object
        .size   my_ro, 16
    my_ro:
        .byte   97
        .zero   3
        .long   3
        .quad   0
        .section    .rodata
    .LC0:
        .string "hello"
    .LC1:
        .string "my ro %c %d %p 
    "
        .text
    .globl main
        .type   main, @function
    main:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        pushq   %rbx
        subq    $24, %rsp
        movl    %edi, -20(%rbp)
        movq    %rsi, -32(%rbp)
        movl    $.LC0, %eax
        movq    %rax, %rdi
        movl    $0, %eax
        .cfi_offset 3, -24
        call    printf
        movq    my_ro+8(%rip), %rcx
        movl    my_ro+4(%rip), %edx
        movzbl  my_ro(%rip), %eax
        movsbl  %al, %ebx
        movl    $.LC1, %eax
        movl    %ebx, %esi
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        addq    $24, %rsp
        popq    %rbx
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)"
        .section    .note.GNU-stack,"",@progbits

    Now without the __read_mostly macro the assembly code remains more or less the same.

    this is the diff

    --- rm.S    2012-07-17 16:17:05.795771270 +0600
    +++ rw.S    2012-07-17 16:19:08.633895693 +0600
    @@ -1,6 +1,6 @@
        .file   "ro.c"
     .globl my_ro
    -   .section    MY_DATA,"aw",@progbits
    +   .data
        .align 16
        .type   my_ro, @object
        .size   my_ro, 16

    So essentially only the a subsection is created, nothing fancy.

    Even the objdump disassmbly does not show any difference.

    So my final conclusion about them, its the linker's job do something for data section marked with a special name. I think linux kernel uses some kind of custom linker script do achieve these things.

    One of the thing about __read_mostly, data which were put there can be grouped and managed in a way so that cache misses can be reduced.

    Someone at lkml submitted a patch to remove __read_mostly. Which spawned a fascinated discussion on the merits and demerits of __read_mostly.

    here is the link : https://lkml.org/lkml/2007/12/13/477

    I will post further update on __init and __exit.

    UPDATE 2

    These macros __init , __exit and __read_mostly put the contents of data(in case of __read_mostly) and text(in cases of __init and __exit) are put into custom named sections. These sections are utilized by the linker. Now as linker is not used as its default behaviour for various reasons, A linker script is employed to achieve the purposes of these macros.

    A background may be found how a custom linker script can be used to eliminate dead code(code which is linked to by linker but never executed). This issue is of very high importance in embedded scenarios. This document discusses how a linker script can be fine tuned to remove dead code : elinux.org/images/2/2d/ELC2010-gc-sections_Denys_Vlasenko.pdf

    In case kernel the initial linker script can be found include/asm-generic/vmlinux.lds.h. This is not the final script. This is kind of starting point, the linker script is further modified for different platforms.

    A quick look at this file the portions of interest can immediately found:

    #define READ_MOSTLY_DATA(align)                     
        . = ALIGN(align);                       
        *(.data..read_mostly)                       
        . = ALIGN(align);

    It seems this section is using the ".data..readmostly" section.

    Also you can find __init and __exit section related linker commands :

    #define INIT_TEXT                           
        *(.init.text)                           
        DEV_DISCARD(init.text)                      
        CPU_DISCARD(init.text)                      
        MEM_DISCARD(init.text)
    
    #define EXIT_TEXT                           
        *(.exit.text)                           
        DEV_DISCARD(exit.text)                      
        CPU_DISCARD(exit.text)                      
        MEM_DISCARD(exit.text)

    Linking seems pretty complex thing to do :)


  • 相关阅读:
    (七)android开发中两种方式监听短信的原理和实现
    (三)android中Toast的使用
    (二)、Android ListView滑动过程中图片显示重复错位闪烁问题解决
    (一)PagerAdapter、FragmentPagerAdapter、FragmentStatePagerAdapter的区别
    (六)Android中使用CountDownTimer实现倒计时功能
    (五)在android 4.4上设置手机状态栏的背景
    (四)使用PagerSlidingTabStrip和ViewPager实现可左右滑动和点击效果功能
    devexpress表格gridcontrol实现列统计,总计,平均,求和等。
    常用GDB命令行调试命令
    新浪微博SSO授权后回调客户端没有执行sinaweiboDidLogIn&无法返回应用
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645631.html
Copyright © 2011-2022 走看看