【问题标题】:InterlockedOr8 on gcc MinGWgcc MinGW 上的 InterlockedOr8
【发布时间】: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。

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

【问题讨论】:

    标签: c++ windows gcc mingw interlocked


    【解决方案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”变量线程安全,而不是它所引用的地址。
    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2012-11-10
    • 2017-01-14
    相关资源
    最近更新 更多