#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.
This code is using a variant of the 'struct hack', which was later replaced by 'flexible array members'. Neither
memregnorpis 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
sets
pb->dma_buf_addrpoint to the start of astruct pkt_buf, then after the assignment:the
pb->dma_buf_addrpoints to the address of thedma_bufarray within the packet. Thei * 2048used suggests thatpis a contiguous block of memory split into 2 KiB pages, and the DMA buffer is immediately after the ID field.