0

Upgraded the gcc version from 4.6.3 to 8.2.0. The following function doesn't work without the memory barrier.

static u32 checksumPsedoHeader(u16 size, u32 src_addr, u32 dest_addr)
{
    const u16 protocol_udp = 17;
    u32 checksum = 0;
    // Add UDP pseudo header.
    struct PseudoHeader
    {
         unsigned int src;
         unsigned int dst;
         unsigned char zero;
         unsigned char proto;
         u16 length;
    } pseudoHeader;

    // Initalize the array. Using an uninitialized
    // array is not acceptable by newer compiler versions.
    memset((void*)&pseudoHeader, 0, sizeof(pseudoHeader));

    pseudoHeader.dst = htonl(dest_addr);
    pseudoHeader.src = htonl(src_addr);
    pseudoHeader.zero = 0;
    pseudoHeader.proto = protocol_udp;
    pseudoHeader.length = htons(size);

    u16 *pseudo_header_p = (u16*)&pseudoHeader;

    asm volatile("" ::: "memory");  // The function doesn't work without this line after GCC upgration.

    for (u32 i = 0; i < sizeof(pseudoHeader); i += 2)
    {
        checksum = checksum + *pseudo_header_p;
        pseudo_header_p++;
    }

    return checksum;
}

Why does it need a memory barrier here? The pointer type conversion make the compiler did the wrong optimization(after the memory barrier, the for loop fetch the values from memories but all the values have not been flushed to the memories)?

0 Answers0