我想知道是否有可能确保line被原子地执行,因为它可以由ISR和主上下文执行。我正在开发一个ARM9 (LPC313x),并使用RealView 4 (armcc)。
foo() {
..
stack_var = ++volatile_var; // line
..
}我正在寻找任何例程,如_atomic_ for C166,直接汇编代码等。我希望不必禁用中断。
非常感谢。
发布于 2011-03-26 11:24:33
快速地看,C166 _atomic_宏似乎利用了一条指令,在指定数量的指令的持续时间内有效地屏蔽中断。在ARM架构中没有任何与之直接对应的东西。
当然,您可以使用swp指令(或__swp内部的RealView工具链)来实现关键部分周围的锁。另一个答案中提到的ldrex/strex并不存在于包含ARM9处理器的ARM体系结构版本5中。分别为http://infocenter.arm.com/help/topic/com.arm.doc.dui0491c/CJAHDCHB.html和http://infocenter.arm.com/help/topic/com.arm.doc.dui0489c/Chdbbbai.html。
围绕这个(使用RealView工具链)的一个简单的锁实现是:
{
/* Loop until lock acquired */
while (__swp(LOCKED, &lockvar) == LOCKED);
..
/* Critical section */
..
lockvar = UNLOCKED;
}但是,当主线程持有锁时,这将导致ISR上下文中的死锁。
我认为屏蔽操作周围的中断可能是最不容易的解决方案,尽管如果您的主上下文是在用户模式下执行的,那么它需要一个系统调用来实现。
发布于 2011-03-24 12:48:38
不,我不认为你可以期望++volatile_var是原子的,即使你没有这个任务。为此使用适当的原子原语。如果您的编译器没有提供这样的扩展,您很容易在web上找到用于该扩展的短内联汇编程序。我认为,汇编程序指令是调用ldrex和strex,用于arm上的原子交换。
编辑:问题中要求的特定处理器类型似乎没有实现这些指令。
编辑:下面的代码应该与gcc一起工作,因为另一个编译器可能需要修改__asm__部件。
inline
size_t arm_ldrex(size_t volatile*ptr) {
size_t ret;
__asm__ volatile ("ldrex %0,[%1]\t@ load exclusive\n"
: "=&r" (ret)
: "r" (ptr)
: "cc", "memory"
);
return ret;
}
inline
_Bool arm_strex(size_t volatile*ptr, size_t val) {
size_t error;
__asm__ volatile ("strex %0,%1,[%2]\t@ store exclusive\n"
: "=&r" (error)
: "r" (val), "r" (ptr)
: "cc", "memory"
);
return !error;
}
inline
size_t atomic_add_fetch(size_t volatile *object, size_t operand) {
for (;;) {
size_t oldval = arm_ldrex(object);
size_t newval = oldval + operand;
if (arm_strex(object, newval)) return newval;
}
}https://stackoverflow.com/questions/5418621
复制相似问题