lkml.org 
[lkml]   [2005]   [Aug]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: question on memory barrier
    Date
    From

    On Wed, 24 Aug 2005, moreau francis wrote:

    >
    > --- "linux-os (Dick Johnson)" <linux-os@analogic.com> a écrit :
    >
    >>
    >> On Wed, 24 Aug 2005, moreau francis wrote:
    >>
    >>> Hi,
    >>>
    >>> I'm currently trying to write a USB driver for Linux. The device must be
    >>> configured by writing some values into the same register but I want to be
    >>> sure that the writing order is respected by either the compiler and the
    >> cpu.
    >>>
    >>> For example, here is a bit of driver's code:
    >>>
    >>> """
    >>> #include <asm/io.h>
    >>>
    >>> static inline void dev_out(u32 *reg, u32 value)
    >>> {
    >>> writel(value, regs);
    >>> }
    >>>
    >>> void config_dev(void)
    >>> {
    >>> dev_out(reg_a, 0x0); /* first io */
    >>> dev_out(reg_a, 0xA); /* second io */
    >>> }
    >>>
    >>
    >> This should be fine. The effect of the first bit of code
    >> plus all side-effects (if any) should be complete at the
    >> first effective sequence-point (;) but you need to
    >
    > sorry but I'm not sure to understand you...Do you mean that the first write
    > into reg_a pointer will be completed before the second write because they're
    > separated by a (;) ?

    Yes. The compiler must make sure that every effect of all previous
    code and all side-effects are complete at a "sequence-point". There
    are several sequence-points and the most obvious is a ";".

    The compiler is free to reorder anything in a compound statement
    as long as it complies with presidence rules, but it can't re-order
    the statements themselves.

    In other words:

    volatile unsigned int *hardware = virtual(MY_DEVICE);

    *hardware = 1;
    *hardware = 2;
    *hardware = 4;
    *hardware = 8;

    .. happens exactly as shown above. If it didn't, you couldn't
    write device drivers. An example of the code above:

    .file "xxx.c"
    .text
    .globl foo
    .type foo, @function
    foo:
    pushl %ebp
    movl %esp, %ebp
    subl $4, %esp
    movl $305419896, -4(%ebp) // init the pointer
    movl -4(%ebp), %eax // Get pointer
    movl $1, (%eax) // *hardware = 1;
    movl -4(%ebp), %eax // Get pointer
    movl $2, (%eax) // *hardware = 2;
    movl -4(%ebp), %eax // Get pointer
    movl $4, (%eax) // *hardware = 4;
    movl -4(%ebp), %eax // Get pointer
    movl $8, (%eax) // *hardware = 8;
    movl $0, %eax
    leave
    ret
    .size foo, .-foo
    .section .note.GNU-stack,"",@progbits
    .ident "GCC: (GNU) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)"

    Because of the necessary 'volatile' keyword, even the pointer is
    obtained over again each time. This wastes CPU cycles. One
    could do:

    movl $1, (%eax)
    movl $2, (%eax)
    movl $4, (%eax)
    movl $8, (%eax)

    .. after the pointer is loaded. Unfortunately, 'C' doesn't have
    a keyword that would accommodate that.

    When communicating across a PCI/Bus, the writes are cached.
    They don't necessarily occur __now__. It will take a (perhaps
    dummy) read of the PCI/Bus to make them get to the hardware
    now. Even then, they will still get there in order, all 4 writes,
    because the interface is a FIFO. A read on the PCI/Bus will force
    all pending writes to be written).

    Some arcitectures do write-combining which means that, for instance
    on an Intel Pentium P6, it's possible for all writes of adjacent
    words may be condensed into a single quadword write. This may not be
    what you want. If you have such a situation, one would execute
    WBINVD after the critical writes. No not do this just to "make sure".
    It wastes a lot of bandwidth.

    See http://developer.intel.com/design/PentiumII/applnots/24442201.pdf



    > Or because writes are encapsulated inside an inline function, therefore
    > compiler
    > must execute every single writes before returning from the inline function ?
    >

    In-line doesn't care. It's not as complicated as many expect.

    > Thanks.
    >
    > Francis
    >

    Cheers,
    Dick Johnson
    Penguin : Linux version 2.6.12.5 on an i686 machine (5537.79 BogoMips).
    Warning : 98.36% of all statistics are fiction.

    ****************************************************************
    The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them.

    Thank you.
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-08-24 20:26    [W:2.129 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site