如果我有一个整数x,以下哪些语句在iPhone上的ARM体系结构中是原子的?
int x;
int y;
x = 92; // . . . . . . A
x++; // . . . . . . B
y = ++x; // . . . . . . C
printf("x = %d\n", x); // D
我知道,在i386平台上,语句A,B和D是原子的,而C则不是。我很确定C在iOS中不是原子的。我怀疑基本的加载和存储操作(D和A)在iOS中也是原子的,但我不确定。有谁知道更多?
16位和8位值如何?或iPhone 6S上的64位值以及iPhone 5及以下的64位值?
(如果答案是我怀疑的......有没有基本的加载和存储操作不是原子的平台?)
答案 0 :(得分:2)
您没有就x
和y
的声明提供足够的背景信息。如果函数中有本地,则它们将被分配给寄存器,而其他线程不能触及它们。所以我认为你的意思是他们是全球性的(或者至少是静态的)。
ARM 是一种加载存储架构。它没有内存到内存指令。所以实际上只有 A / D 的行是原子的。你无条件地写了这个值。与其他线程无关。如果一个线程写入92
而另一个写入29
,则没有办法知道没有某种互斥量的内容。
早期 ARM cpus有swp
;但大多数iOS产品将使用ldrex
和strex
。您必须使用这些说明进行任何类型的原子更新。
ARM 可以一次写入8/16/32/64位,大多数系统设计都会使高速缓存同步,以便另一个CPU看到一个CPU的写入。环形缓冲区结构可以与生产者/消费者一起使用,其中只有一个CPU写入环头,另一个CPU写入环尾;即,这将是一个原子结构,您可以在没有swp
或ldrex
和strex
的情况下使用。
如果您手动分配64位值,可能会搞砸。你必须努力做到这一点。例如,如果在64位值的上/下32位之间发生页面错误。显然,取决于CPU类型,未对齐的值也可能存在问题。如果你正常地声明它们,它们应该由编译器很好地对齐。使用未对齐 32位和16位值也可以实现这一点。 iOS 可能会使这些访问看起来像用户空间。通常,如果您依赖原子行为,则不应进行任何奇怪的转换,并正常声明变量。
修改强>
(如果答案是我怀疑的......有没有基本的加载和存储操作不是原子的平台?)
是的,有许多平台,其中较大的值加载/存储不是原子的;特别适用于所有数据类型。实际上,大多数CPU至少为8位(尽管存在4位CPU),因此char
加载和存储通常是原子的。对于较小的CPU,较大值的加载/存储可能需要几个周期。在这些情况下,编译器将花费多个周期来更新值。这是sig_atomic_t
背后的想法;它是一个可变大小,可以原子方式更新。所有Posix systems都应提供sig_atomic_t
,但普通 C99 没有一般保证。 C11添加了_Atomic
类型限定符。