1
#define MEMBER_OFFSET(c_type, mbr_name) ((uint32_t) (uintptr_t)(&((c_type*)0)->mbr_name))
#define CACHE_ALIGN __attribute__((aligned(EF_VI_DMA_ALIGN)))

struct pkt_buf {
    struct pkt_buf* next;
    ef_addr dma_buf_addr;
    int id;
    uint8_t dma_buf[1] CACHE_ALIGN;
};


struct pkt_buf* pkt_bufs [N_BUFS];

for( i = 0; i < N_BUFS; ++i ) {
    struct pkt_buf* pb = (struct pkt_buf*) ((char*) p + i * 2048);
    pb->id = i;
    pb->dma_buf_addr = ef_memreg_dma_addr(&memreg, i * 2048);
    pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf); // why do this?
    pkt_bufs[i] = pb;
}

Question> I understand the meaning of MEMBER_OFFSET. However, I didn't get the meaning of the following line:

pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf)

Basically, the value of MEMBER_OFFSET(struct pkt_buf, dma_buf) is the offset value in byte for member variable dma_buf in struct pkt_buf.

q0987
  • 34,938
  • 69
  • 242
  • 387

1 Answers1

0

This code is using a variant of the 'struct hack', which was later replaced by 'flexible array members'. Neither memreg nor p is defined in the code shown, nor is the function (macro?) ef_memreg_dma_addr(), so there are elements of speculation here.

However, it is doing calculations such that if

pb->dma_buf_addr = ef_memreg_dma_addr(&memreg, i * 2048);

sets pb->dma_buf_addr point to the start of a struct pkt_buf, then after the assignment:

pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf);

the pb->dma_buf_addr points to the address of the dma_buf array within the packet. The i * 2048 used suggests that p is a contiguous block of memory split into 2 KiB pages, and the DMA buffer is immediately after the ID field.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278