如何在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一些可行的方法。

http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00050.html

__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使用这个。