选定的处理器不支持"SWP X1,X1,[X0]"
selected processor does not support `swp x1,x1,[x0]'
我尝试使用swp指令来实现原子交换。
asm volatile ("swp %[newval], %[newval], [%[oldval]]"
: [newval] "+r" (newval), [oldval] "+p" (oldval)
:
: "memory");
当我编译代码时(使用g++ main.cpp -o main -march=armv8-a
(。我收到以下错误消息。
/tmp/cc0MHTHA.s: Assembler messages:
/tmp/cc0MHTHA.s:20: Error: selected processor does not support `swp x1,x1,[x0]'
我使用的ARM机器是armv8的,/proc/cpuinfo是这样的(这是一台16核的SMP机器,除了第一行之外,其他处理器的信息是一样的。
processor : 0
model name : phytium FT1500a
flags : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x70
CPU architecture: 8
CPU variant : 0x1
CPU part : 0x660
bogomips : 3590.55
CPU revision : 1
g++ --version
输出
g++ (Ubuntu/Linaro 4.9.1-16kord6) 4.9.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我在使用 ldrex/strex 指令时收到以下错误
/tmp/ccXxJgQH.s: Assembler messages:
/tmp/ccXxJgQH.s:19: Error: unknown mnemonic `ldrex' -- `ldrex x0,[x0]'
谁能解释我为什么以及在哪里出现此错误以及如何处理此错误?机器不支持SWP,或者我应该在编译命令上添加一些参数(也许是-march(来指示CPU架构?
您不需要(也不应该使用(内联程序集。
为此,请使用内置的 gcc:type __atomic_exchange_n (type *ptr, type val, int memorder)
或 C++11std::atomic
,因此编译器可以根据-mcpu=
命令行选项以及您是针对 64 位还是 32 位 ARM(或 x86(等构建目标 CPU 的最佳指令序列。 此外,编译器了解您在做什么,并可以相应地进行优化。
// static inline
int xchg_gcc(int *p, int newval) {
int oldval = __atomic_exchange_n(p, newval, __ATOMIC_SEQ_CST);
//__atomic_signal_fence ( __ATOMIC_SEQ_CST);
return oldval;
}
对于带有 gcc5.4 的 ARM64 和 ARM(带-mcpu=cortex-a72
的 32 位(,这可以编译到您想要的(Godbolt 编译器资源管理器(:
.L2: ## This is the ARM64 version.
ldaxr w2, [x0]
stlxr w3, w1, [x0]
cbnz w3, .L2
mov w0, w2 # This insn will optimize away after inlining, leaving just the retry loop
ret
或者,如果您只想要原子性,但不需要对其他操作进行排序,请使用__ATOMIC_RELAXED
而不是__ATOMIC_SEQ_CST
。 然后它编译为ldxr
/stxr
,而不是 LL/SC 指令的获取/发布版本。
对于 32 位版本,如果未指定-mcpu
或-march
,它将调用库函数,因为它不知道用于交换的内容。
我不确定SEQ_CST
asm volatile("":::"memory")
方式用于非原子事物的__atomic_exchange
内置命令; 如果不是,您可能需要如下所述的围栏 C++11atomic_signal_fence
.
或者使用此可移植的 C++11 版本,该版本编译为相同的 ASM:
#include <atomic>
// static inline
int xchg_stdatomic(std::atomic<int> *p, int newval) {
atomic_signal_fence(std::memory_order_seq_cst);
int oldval = p->exchange(newval, std::memory_order_seq_cst);
atomic_signal_fence(std::memory_order_seq_cst); // order WRT. non-atomic variables (on gcc/clang at least).
return oldval;
}
atomic_signal_fence
被用作asm("":::"memory")
的等价物,以阻止使用非atomic
加载/存储(但不发出任何指令(的编译时重新排序。 这就是 gcc 实现它的方式,但如果 gcc 中只是一个实现细节的标准要求这样做,IDK。
至少在 gcc 中,atomic_signal_fence
对"正常"变量的操作进行排序,但atomic_thread_fence
只对atomic
变量的操作进行排序。 (从多个线程共享对非atomic
变量的访问将是一场未定义行为的数据竞赛,因此 gcc 假设它不会发生。 这里的问题是,该标准是否要求signal_fence
订购非atomic
操作以及atomic
和volatile
访问,因为关于信号处理程序中可以安全访问的内容的保证非常弱。
无论如何,由于signal_fence编译为没有指令,并且只是阻止我们希望exchange()
阻止的重新排序,因此没有害处。 (除非您不希望exchange()
对非共享变量进行排序,在这种情况下,您不应该使用 signal_fence(。
swp
受支持,但在 ARMv6 和 ARMv7 中已弃用。 ARM的文档说它增加了中断延迟(因为swp
本身是不可中断的(。 也
多核系统中,在交换指令期间阻止所有处理器访问主内存会降低整体系统性能。
- 如何修复此错误"the value of 'x1' is not usable in a constant expression"?static_assert
- 选定的处理器不支持"SWP X1,X1,[X0]"
- 在GLFW中,哪个按钮定义了X1和X2按钮?
- Vector.push_back(pair<int,int>(x1,x2 )));不起作用
- 类型(x0 = y0,x1 = y1,x2 = x0,..)的括号和逗号表达中的评估顺序
- 使用C 在范围x1和x2中删除值的节点
- 给定许多垂直或水平段及其终点的坐标(x1,x2,y1,y2),我们有多少个相交
- 如何按距点的距离(x1,y1)升序对一组坐标进行排序
- 对抛物线的坐标 (x,y) 进行排序 y=ax^2+bx+c x=x1,x2,x3, x4.根据 y 坐标
- C++字符变量值'x1'
- 如果我有一条从点x1,y1到x2,y2的线,我怎么能画出两条从点x2,y2成45度角的线来画箭头呢