gcc MinGW 上的 InterlockedOr8

Posted

技术标签:

【中文标题】gcc MinGW 上的 InterlockedOr8【英文标题】:InterlockedOr8 on gcc MinGW 【发布时间】:2014-01-05 04:50:25 【问题描述】:

我对 CodeBlocks 12.11 随附的 MinGW 版本没有任何问题。但现在我尝试编译SyncSys。编译 enet 没问题,但是用 gcc/MinGW 编译 SyncSys 本身会带来错误,我不能使用函数 _InterlockedOr8 因为它没有声明。研究表明 _InterlockedOr8 是在 intrin.h 中定义的。 intrin.h 不包括在内,我在 MinGW/gcc 上搜索了它的等效项:x86intrin.h。但这仍然行不通。 InterlockedOr8 将是要调用的“真实”函数,但编译器也找不到此函数,尽管包含 winbase.h 和 windows.h。

在研究这个问题时,我无法从中吸取教训。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

_InterlockedOr8 是 Microsoft 编译器独有的内在编译器函数 - 这意味着编译器会自动将实现内联到代码中,而不是与库链接。 <intr.h> 是随 Visual Studio 分发的头文件,独立于 Windows SDK。

如果你不能切换到 Visual Studio (free download, btw),那么你可以定义你自己的这个函数的替换版本:

void InterlockedOr8(char* dst, char src)

    __asm
    
        mov eax, dst       ; EAX = dst
        mov cl, src        ; ECX = src
        lock or [eax], cl  ; *dst = src | *dst; // this is the actual interlocked-or op
    

请注意,此函数与 _InterlockedOr8 的不同之处在于它不返回 *dst 的原始值。如果您需要返回值,实现会变得更加复杂。我快速浏览了 SyncSys 源代码。需要那个函数的两个地方不需要返回值。所以你所要做的就是将上面的代码转换为使用内联汇编的gcc风格。

更新

这是一个在 OR 操作之前正确返回目标地址内原始值的版本。它可能需要一些代码审查审查......

char MyInterlockedOr8(char* dst, char src)

    char result = 0;
    const size_t ptr_size = sizeof(dst);

    _asm
    
        mov esi, dst    ; esi = dst
        mov cl, src     ; cl = src // keep "src" cached in a register
        mov al, [esi]   ; al = *dst
start:
        mov bl, cl      ; bl = src
        or bl, al       ; bl = src | *dst

        lock cmpxchg [esi], bl;   // if (*dst == eax)  *dst=bl ; else al = *dst;
        jne start

        mov result, al  ; result = al
    

    return result;

【讨论】:

我可以切换到 VS,我已经安装了 VS,但我不喜欢 IDE,如果我将 CodeBlocks 中的编译器设置为 MSVC10,我没有调试器,并且 cl.exe 总是抛出 D8003-Errors。我从来没有看过汇编程序,所以我不知道你的代码中发生了什么,所以如果你能添加一些提示/cmets 会很酷,感谢你的帮助。 我也看过代码,你说得对,它不关心返回值,但 _InterlockedAnd8 必须返回正确的值,因为它被使用了。我只是猜测 _InterlockedAnd8 的代码必须是: void _InterlockedAnd8( volatile char* dst, char src ) asm( "mov eax, dst;mov cl, src; lock and [eax], cl;" ); 我说的对吗? 或多或少。但是如果代码实际上使用了 InterlockedOr8 的返回值(这是交换前 dst 指向的值),生成的汇编代码会变得更多,并使用 interlocked-compare-exchange 调用。 我不能把 dst 的值复制到另一个变量中然后返回这个变量吗?诸如此类: char _InterlockedAnd8( volatile char dst, char src ) char ret( *dst ); asm("mov eax, dst;mov cl, src; lock and [eax], cl;");返回 ret; ? @JoshuaBehrens - 如您所见,如果 dst 的内容在您分配“ret”和“或”操作码之间被另一个线程更改,则返回值将不正确。 volatile 关键字最多只会使“dst”变量线程安全,而不是它所引用的地址。

以上是关于gcc MinGW 上的 InterlockedOr8的主要内容,如果未能解决你的问题,请参考以下文章

如何将使用sysioctl.h的代码移植到MinGW gcc中?

Windows 上的 GCC 设备上没有剩余空间

mingw32位下载以及windows下安装

Windows 8 上的 MinGW

mingw和gcc的关系?mingw具有gcc的全部核心编译功能吗

在windows下使用GNU工具-gcc编译器