在c中包装读取宏

时间:2014-11-27 01:36:57

标签: c linux kernel

有一个读取宏如下:

#define I915_READ16(reg)        i915_read16(dev_priv, (reg))
#define I915_WRITE16(reg)       i915_write16(dev_priv, (reg))

我想测量每个读/写命令所经过的时间。 我可以很容易地写如下

#define I915_WRITE_NOTRACE(reg, val)    \
do {                                    \
        __start_mmio();                 \
        writel(val, dev_priv->regs + (reg));\
        _end_mmio();                    \
} while(0)

其中__start_mmio和__end_mmio是衡量时间的函数。 但是对于读取,如果我这样做,这个宏给我一个编译错误,因为宏使用如下:

val = I915_READ16(reg)

将被解码为

val = do {                              
        __start_mmio();                 
        readl(dev_priv->regs + (reg));
        _end_mmio();                    
} while(0)

绝对是编译错误。

4 个答案:

答案 0 :(得分:2)

创建内联函数而不是宏;

inline int I915_READ16_NOTRACE(int reg) {
    __start_mmio();  
    int result = readl(dev_priv->regs + (reg));
    _end_mmio();
    return result;
};

或者如果你必须使它成为宏,请使用逗号表示法,例如;

#define I915_READ16_NOTRACE(reg) \ 
    ((__start_mmio(),0) + readl(dev_priv->regs + (reg)) + (_end_mmio(),0))

答案 1 :(得分:2)

使用此宏:

#define I915_READ_NOTRACE(reg) \
    (start_mmio2() + readl(dev_priv->regs + (reg)) + end_mmio2())

您可以将start_mmio2end_mmio2定义为返回0的函数。例如:

static inline int start_mmio2(void)
{
    __start_mmio();
    return 0;
}

答案 2 :(得分:1)

由于这似乎是针对Linux内核的,我们可以使用像statement expressions这样的gcc扩展:

#define I915_READ_NOTRACE(reg) ({     \
    __start_mmio();                   \
    uint16_t val = I915_READ16(val);  \
    __end_mmio();                     \
    val;                              \
})

答案 3 :(得分:0)

将val作为参数传递给读包装宏。

#define I915_READ16_NOTRACE(reg, val)   \
do {                                    \
        __start_mmio();                 \
        (val) = i915_read16(dev_priv, (reg)); \
        _end_mmio();                    \
} while(0)