如何在Linux,x86,arm,GCC和icc上执行primefaces操作?
每一个现代操作系统都提供了一些primefaces操作
- Windows有
Interlocked*
API - FreeBSD有
<machine/atomic.h>
- Solaris有
<atomic.h>
- Mac OS X有
<libkern/OSAtomic.h>
任何这样的Linux?
- 我需要它在大多数Linux支持的平台上工作,包括:x86,x86_64和arm 。
- 我需要它在至lessGCC和英特尔编译器上工作。
- 我不需要像glib或qt那样使用第三个库文件。
- 我需要它在C ++中工作(C不需要)
问题:
- 所有平台(ARM)均不支持GCCprimefaces内置
__sync_*
,英特尔编译器不支持。 - AFAIK
<asm/atomic.h>
不应该在用户空间中使用,我没有成功地使用它。 另外,我不确定它是否会与英特尔编译器一起工作。
有什么build议么?
我知道有很多相关的问题,但其中一些指向__sync*
,这对我来说是不可行的(ARM),有些则指向asm/atomic.h
。
也许有一个内联汇编库为GCC做这个(ICC支持gcc汇编)?
编辑:
有一个非常局部的解决scheme,只允许添加操作(允许实现primefaces计数器但不locking需要CAS的自由结构):
如果使用libstc++
(Intel编译器使用libstdc++
),则可以使用在<ext/atomicity.h>
或<bits/atomicity.h>
中定义的__gnu_cxx::__exchange_and_add
。 取决于编译器版本。
不过,我仍然希望看到支持CAS的东西。
项目正在使用这个:
http://packages.debian.org/source/sid/libatomic-ops
如果你想要简单的操作,如CAS,你不能只使用特定于内核的特定实现,并用autotools / cmake在用户空间中进行检查吗? 就许可证而言,尽pipe内核是GPL,但我认为这是由Intel / AMD提供的内联程序集,而不是内核拥有许可证。 它们恰好在内核源代码中以易于访问的forms出现。
C&C ++最近的标准(从2011年开始)现在指定了primefaces操作:
- C11:
stdatomic.h
- C ++ 11:
std::atomic
无论如何,您的平台或编译器可能不支持这些较新的标题和function。
该死。 我会build议海湾合作委员会的原语,然后你说他们是没有限制的。 🙂
在这种情况下,我会为每个您关心的架构/编译器组合编写一个#ifdef
,并对内联asm进行编码。 也许检查__GNUC__
或者一些类似的macros,如果它们可用,就使用GCC原语,因为它感觉使用这些更为正确。 🙂
你会有很多的重复,并且可能很难validation正确性,但是这似乎是很多项目做这个的方式,而且我已经有了很好的结果。
过去有些陷阱:在使用GCC的时候,不要忘记“ asm volatile
”和"memory"
, "cc"
等等。
具有非侵入性许可的Boost和其他框架已经提供了便携式primefaces计数器 – 只要它们在目标平台上得到支持即可。
第三方库对我们有好处。 如果由于奇怪的原因你的公司禁止你使用它们,你仍然可以看看它们如何继续(只要许可证允许它使用)来实现你正在寻找的东西。
我最近做了一个这样的事情,我遇到了和你一样的困难。 我的解决scheme基本如下:
- 尝试使用特征macros来检测gcc内置函数
- 如果不可用的话,只需用
cmpxch
和__asm__
来实现其他体系结构(ARM比这更复杂一点)。 只要做一个可能的大小,例如sizeof(int)
。 - 使用
inline
函数在一个或两个基元上实现所有其他function
GCC有一个补丁来支持ARMprimefaces操作。 在英特尔上不会帮助你,但是你可以检查代码 – 最近有一些内核支持旧的ARM体系结构,而新的内核支持内置的指令,所以你应该能够构build一些可行的方法。
__sync*
当然是(已经)被英特尔编译器支持,因为GCC从那里采用了这些插件。 阅读本页面的第一段。 另请参阅“ 用于Linux * Intrinsics参考的英特尔®C ++编译器参考 ”(第198页)。它是从2006年开始的 ,详细描述了这些内置的function。
对于ARM的支持,对于以前的ARM CPU来说:它不能完全在用户空间中完成,但可以在内核空间中完成(通过在操作期间禁止中断),我想我已经在某个地方读了一段时间的支持。
根据__sync_*
年10月8日这个PHP错误 , __sync_*
将只能失败
- PA-RISC与Linux以外的其他产品兼容
- SPARCv7和更低
- ARM与GCC <4.3
- ARMv5以及Linux以外的版本
- MIPS1
所以在GCC> 4.3(现在是4.7)的情况下,ARMv6和更新版本不应该有问题。 只要为Linux编译,就不应该对ARMv5有任何问题。
在Debian / Ubuntu推荐…
sudo apt-get install libatomic-ops-dev
示例: http : //www.hpl.hp.com/research/linux/atomic_ops/example.php4
GCC和ICC兼容。
与使用primefaces<T>的英特尔线程构build模块(TBB)相比,libatomic-ops-dev速度提高了一倍! (英特尔编译器)
在Ubuntu i7生产者 – 消费者线程上testing在0.5secs下环形缓冲区连接1000万英寸而不是TBE的1.2secs
和易于使用,例如
不稳定的AO_t头;
AO_fetch_and_add1(头);
请参阅: kernel_user_helpers.txt或entry-arm.c并查找__kuser_cmpxchg
。 从其他ARM Linux版本的评论中可以看出,
kuser_cmpxchg
位置:0xffff0fc0 参考原型: int __kuser_cmpxchg(int32_t oldval,int32_t newval,volatile int32_t * ptr); input: r0 = oldval r1 = newval r2 = ptr lr =返回地址 输出: r0 =成功代码(零或非零) C标志=如果r0 == 0则设置,如果r0!= 0则清除 Clobbered寄存器: r3,ip,标志 定义: 只有在* ptr等于oldval的情况下,才会在* ptr中存储newval。 如果* ptr更改则返回零,如果不发生交换则返回非零。 如果* ptr被改变以允许组装,C标志也被设置 调用代码中的优化。 用法示例:
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr); #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0) int atomic_add(volatile int *ptr, int val) { int old, new; do { old = *ptr; new = old + val; } while(__kuser_cmpxchg(old, new, ptr)); return new; }
笔记:
- 这个例程已经包含了需要的内存障碍。
- 仅当__kuser_helper_version> = 2(来自内核版本2.6.12)时才有效。
这是使用Linux与ARMv3使用swp
原语。 你必须有一个非常古老的ARM来支持这个。 只有数据中止或中断可能导致旋转失败,所以内核监视这个地址〜0xffff0fc0,并在数据中止或中断发生时执行用户空间 PC
修复。 所有支持ARMv5及更低版本的用户空间库都将使用此工具。
例如, QtConcurrent使用这个。