Вопрос

I had no problems with the shipped version of MinGW that comes with CodeBlocks 12.11. But now I tried to compile SyncSys. Compiling enet was no problem but compiling SyncSys itself with gcc/MinGW brings the errors, that I can't use the function _InterlockedOr8 because it is not declared. Research lead to the fact that _InterlockedOr8 is defined in intrin.h. intrin.h is not included and I searched for the equivalent for it on MinGW/gcc: x86intrin.h. But this still does not work. InterlockedOr8 would be the "real" function to call but this is could not be found either by the compiler although winbase.h and windows.h are included.

While researching this problem there where very few hits I could not learn from. How can I fix this?

Это было полезно?

Решение

_InterlockedOr8 is an intrinsic compiler function unique to the Microsoft compiler - meaning that the compiler automatically inlines an implementation into the code instead of linking with a library. <intr.h> is a header file distributed with Visual Studio, separate from the Windows SDK.

If you can't switch to Visual Studio (free download, btw), then you could define your own replacement version of this function:

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
    }
}

Notice that this function differs from _InterlockedOr8 in the fact that it doesn't return the original value of *dst. The implementation gets a more complicated if you need the return value. I took a quick look at SyncSys source. The two places that need that function don't need the return value. So all you have to do is convert the above code to use the gcc style of inline assembly.

Update

Here's a version that correctly returns the original value within the destination address before the OR operation. It could probably use a little code review scrutiny...

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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top