gpt4 book ai didi

multithreading - 处理 __sync_add_and_fetch 未定义

转载 作者:行者123 更新时间:2023-12-03 13:05:10 29 4
gpt4 key购买 nike

在我的开源软件项目中,我调用了 gcc atomic builtins : __sync_add_and_fetch 和 __sync_sub_and_fetch 实现对某些变量的原子增量和减量。我定期收到试图编译我的代码的人的电子邮件,但他们收到以下链接器错误:

refcountobject.cpp:(.text+0xb5): undefined reference to `__sync_sub_and_fetch_4'
refcountobject.cpp:(.text+0x115): undefined reference to `__sync_add_and_fetch_4'

经过一番挖掘,我将根本原因缩小到他们的旧版本 gcc (4.1) 默认为 i386 的目标架构这一事实。显然,gcc 实际上并没有在 80386 上进行原子加法的内在函数,因此它隐式地在其中注入(inject)了一个未定义的 __sync_add_and_fetch_4 调用。 here 对它的工作原理进行了很好的描述。 .

简单的解决方法,如 here 所述,就是告诉他们修改Makefile来追加 -march=奔腾作为编译器标志之一。一切都很好。

那么什么是长期修复,所以用户不必手动修复 Makefile?

我正在考虑一些想法:

我不想将 -march=pentium 作为编译器标志硬编码到 Makefile 中。我猜这会破坏任何不是基于英特尔的东西。但是如果 Makefile 有一个规则来检测默认目标是 i386,我当然可以添加它。我正在考虑在 Makefile 中有一个规则,它是一个调用 gcc -dumpmachine 并解析出第一个三元组的脚本。如果字符串是 i386,它将添加编译器标志。我假设没有人会真正为 80386 机器构建。

另一种选择是实际提供 __sync_add_and_fetch_4 的实现,以供链接器使用。它甚至可以根据定义的 GCC_HAVE_SYNC_COMPARE_AND_SWAP 宏的存在有条件地编译。我使用全局 pthread_mutex 对实现进行了原型(prototype)设计。可能不是最好的性能,但它可以很好地解决问题。如果为 x86 编译,一个更好的想法可能是自己编写内联程序集以调用“lock xadd”来实现。

最佳答案

这是我的另一个工作解决方案。它可能在某些情况下存在,但我选择了上面的 makefile+script 解决方案。

此解决方案是在单独的源文件中提供 _sync_add_and_fetch_4、_sync_fetch_and_add_4、_sync_sub_and_fetch_4 和 _sync_fetch_and_sub_4 的本地定义。只有当编译器无法本地生成它们时,它们才会被链接。需要一些组装,但是 Wikipedia所有地方都有一个我可以引用的合理实现。 (我还反汇编了编译器通常生成的内容,以推断其他一切是否正确)。

#if defined(__i386) || defined(i386) || defined(__i386__)
extern "C" unsigned int xadd_4(volatile void* pVal, unsigned int inc)
{

unsigned int result;
unsigned int* pValInt = (unsigned int*)pVal;

asm volatile(
"lock; xaddl %%eax, %2;"
:"=a" (result)
: "a" (inc), "m" (*pValInt)
:"memory" );

return (result);

}

extern "C" unsigned int __sync_add_and_fetch_4(volatile void* pVal, unsigned int inc)
{
return (xadd_4(pVal, inc) + inc);
}

extern "C" unsigned int __sync_sub_and_fetch_4(volatile void* pVal, unsigned int inc)
{
return (xadd_4(pVal, -inc) - inc);
}

extern "C" unsigned int __sync_fetch_and_add_4(volatile void* pVal, unsigned int inc)
{
return xadd_4(pVal, inc);
}

extern "C" unsigned int __sync_fetch_and_sub_4(volatile void* pVal, unsigned int inc)
{
return xadd_4(pVal, -inc);
}

#endif

关于multithreading - 处理 __sync_add_and_fetch 未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15014417/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com