我试图在我的软件中计时一些函数调用来比较不同的实现。
为了获得所需的时序,我正在使用 RAII 结构在函数的开头和结尾读取我的 ARM A9 处理器的 PCCNTR 寄存器。
问题是编译器不尊重我的对象的构造破坏顺序。这是编译器中的错误还是允许的优化?
编译器是一个arm-none-eabi-g++ (Sourcery CodeBench Lite 2012.03-56) 4.6.3
#define GET_TICK(var) \
asm volatile (\
"mrc p15, 0, %0, c9, c13, 0;"\
: "=r" (var)\
);
struct tick{
uint32_t &start;
uint32_t &end;
tick(uint32_t& s, uint32_t &e)
:start(s)
, end(e)
{
GET_TICK(start);
}
~tick(){
GET_TICK(end);
}
};
bool mailbox::send(uint32_t &start, uint32_t &end, uint32_t msg){
tick t(start, end);
/* now start should have the current timestamp */
{
Spinlocker lock(SPINLOCK_LOCK_REG_0); // RAII mutex locker
uint32_t cnt = mb_msg_max_count + 1;
do{
cnt = count();
if(cnt >= mb_msg_max_count){
lock.release();
lock.get();
}
}while(cnt >= mb_msg_max_count);
*(first_message + cnt) = msg;
inc_counter(); // free function
MEM_BARRIER; // #define asm volatile("dsb st;")
/* spinlock should be destroyed but it is only after t */
}
return true;
/* now end should have the current timestamp */
}
生成的汇编代码:
83000a64 <mailbox::get(unsigned long&, unsigned long&)>:
83000a64: b530 push {r4, r5, lr}
83000a66: 4604 mov r4, r0
83000a68: 680b ldr r3, [r1, #0]
83000a6a: b083 sub sp, #12
83000a6c: 4615 mov r5, r2
83000a6e: ee19 2f1d mrc 15, 0, r2, cr9, cr13, {0}
83000a72: f44f 41d0 mov.w r1, #26624 ; 0x6800
83000a76: 601a str r2, [r3, #0]
83000a78: a801 add r0, sp, #4
83000a7a: f6c4 210f movt r1, #18959 ; 0x4a0f
83000a7e: f000 f871 bl 83000b64 <Spinlocker::Spinlocker(unsigned long volatile*)>
83000a82: 6823 ldr r3, [r4, #0]
83000a84: 681a ldr r2, [r3, #0]
83000a86: b18a cbz r2, 83000aac <mailbox::get(unsigned long&, unsigned long&)+0x48>
83000a88: 6819 ldr r1, [r3, #0]
83000a8a: 1e48 subs r0, r1, #1
83000a8c: 6018 str r0, [r3, #0]
83000a8e: f3bf 8f4e dsb st
83000a92: 6864 ldr r4, [r4, #4]
83000a94: 1e51 subs r1, r2, #1
83000a96: f854 4021 ldr.w r4, [r4, r1, lsl #2]
83000a9a: ee19 0f1d mrc 15, 0, r0, cr9, cr13, {0} <- timer is read before Spinlock is destroyed. Is this allowed?
83000a9e: 6028 str r0, [r5, #0]
83000aa0: a801 add r0, sp, #4
83000aa2: f000 f885 bl 83000bb0 <Spinlocker::~Spinlocker()> <- Shouldn't this be done before issuing the MCR assembly?
83000aa6: 4620 mov r0, r4
83000aa8: b003 add sp, #12
83000aaa: bd30 pop {r4, r5, pc}
83000aac: a801 add r0, sp, #4
83000aae: f000 f86b bl 83000b88 <Spinlocker::release()>
83000ab2: a801 add r0, sp, #4
83000ab4: f000 f86e bl 83000b94 <Spinlocker::get()>
83000ab8: 6823 ldr r3, [r4, #0]
83000aba: 681a ldr r2, [r3, #0]
83000abc: 2a00 cmp r2, #0
83000abe: d1e3 bne.n 83000a88 <mailbox::get(unsigned long&, unsigned long&)+0x24>
83000ac0: e7f4 b.n 83000aac <mailbox::get(unsigned long&, unsigned long&)+0x48>
83000ac2: bf00 nop