Author Topic: MSVC or non-GCC Porting  (Read 14006 times)

d3x0r

  • Jr. Member
  • **
  • Posts: 75
    • View Profile
MSVC or non-GCC Porting
« on: November 08, 2014, 06:15:32 am »
Specific to using MSVC instead of GCC to build (or OpenWatcom; although doesn't solve OpenWatcom on Linux)

Code: [Select]
#ifndef __GCC__
#    ifdef __64__
#          define __sync_bool_compare_and_swap(a,b,c) InterlockedCompareExchange64((__int64*)a,(__int64)b,(__int64)c)
#    else
#          define __sync_bool_compare_and_swap(a,b,c) InterlockedCompareExchange(a,b,c)
#   endif
#endif

although as a quick and dirty hack the following code works
Code: [Select]
// in src\z\ZMemPool_Optimized.cpp
#ifdef __GCC__
      if (__sync_bool_compare_and_swap(&MemTable[BitPosition],NewBlock,NewBlock->Next))
#else
if( (MemTable[BitPosition] == NewBlock) ? (MemTable[BitPosition]=NewBlock->Next),1:0)
#endif

which does the same job, but without lock.....

d3x0r

  • Jr. Member
  • **
  • Posts: 75
    • View Profile
Re: MSVC or non-GCC Porting
« Reply #1 on: November 08, 2014, 07:42:57 am »

Code: [Select]
// in ZTypes.h
#ifdef _WIN32
#    define MANUAL_BREAKPOINT  DebugBreak()
#else
#    define MANUAL_BREAKPOINT  asm volatile ("int3;")
#endif
// #define MANUAL_BREAKPOINT  asm volatile ("int3;")

d3x0r

  • Jr. Member
  • **
  • Posts: 75
    • View Profile
Re: MSVC or non-GCC Porting
« Reply #2 on: November 08, 2014, 10:26:58 am »
Sorry, should be Pointer not 32/64 bit switch...
needed to reverse b and c params and add test if result is the assigned value... not exactly the intrinsic.
Code: [Select]
#ifndef __GNUC__
#    define __sync_bool_compare_and_swap(a,b,c) (InterlockedCompareExchangePointer((void*volatile*)a,c,b), (*a)==(c))
#endif

olive

  • Administrator
  • Full Member
  • *****
  • Posts: 149
    • View Profile
Re: MSVC or non-GCC Porting
« Reply #3 on: November 09, 2014, 10:56:47 pm »
...
Code: [Select]
// in src\z\ZMemPool_Optimized.cpp
#ifdef __GCC__
      if (__sync_bool_compare_and_swap(&MemTable[BitPosition],NewBlock,NewBlock->Next))
#else
        if( (MemTable[BitPosition] == NewBlock) ? (MemTable[BitPosition]=NewBlock->Next),1:0)
#endif

which does the same job, but without lock.....

During development, we forgotten the atomic instructions here. It seemed to work. But when trying to track weird and inexplicable crash, we finally found it was this.

So, it won't work correctly without the atomic instruction at this particular place.

Because the comparison and the assignation are not atomic, something can happens between. The tread can be interrupted or another thread can execute the same code at the same time.

As unlikely it might sound statistically, it happens more often one could believe.

The weird about this kind of issue is that the occurrence may vary between machines from rare to frequent depending on a lot of parameters involving scheduler algorithm, number of cores.

Stabilizing the Blackvoxel core took a long time and involved many tests on a lot of machines, graphic cards (some remains to do...). Even with the powerful tools like valgrind we have on linux, some issues was long to track.

Sorry, should be Pointer not 32/64 bit switch...
needed to reverse b and c params and add test if result is the assigned value... not exactly the intrinsic.
Code: [Select]
#ifndef __GNUC__
#    define __sync_bool_compare_and_swap(a,b,c) (InterlockedCompareExchangePointer((void*volatile*)a,c,b), (*a)==(c))
#endif

We suggest you to change the test on define because testing for gcc could trigger on some wrong case, as an example on a future MacOS port with LLVM toolchain.

So we recommend applying compiler/platform specific patch with testing for compiler and (when pertinent) to platform.

But our goal is primarily to support well Blackvoxel on one "official" compiler.

As we are only two in the team to do everything, we prefer to focus on doing one thing very well rather than several poorly.  :)

The Blackvoxel Team

d3x0r

  • Jr. Member
  • **
  • Posts: 75
    • View Profile
Re: MSVC or non-GCC Porting
« Reply #4 on: November 10, 2014, 11:24:25 am »

Stack overflow 'compare and swap atomics...'
Quote from: StackOverflow

On Mac OS X and Windows there are builtin CompareAndSwap functions you should be using anyway (InterlockedCompareExchange() and OSAtomicCompareAndSwapPtrBarrier() respectively). Thus will work regardless of the compilers on those platforms.

How to get predefined macros...
Quote
Code: [Select]

Command lines
Compiler C macros C++ macros
Clang/LLVM clang -dM -E -x c /dev/null clang++ -dM -E -x c++ /dev/null
GNU GCC/G++        gcc   -dM -E -x c /dev/null g++     -dM -E -x c++ /dev/null
Hewlett-Packard C/aC++ cc    -dM -E -x c /dev/null aCC     -dM -E -x c++ /dev/null
IBM XL C/C++     xlc   -qshowmacros -E /dev/null xlc++   -qshowmacros -E /dev/null
Intel ICC/ICPC icc   -dM -E -x c /dev/null icpc    -dM -E -x c++ /dev/null
Microsoft Visual Studio (none) (none)
Oracle Solaris Studio cc    -xdumpmacros -E /dev/null CC      -xdumpmacros -E /dev/null
Portland Group PGCC/PGCPP pgcc  -dM -E (none)
looks to me like also ICC is a gcc variant that might (and on further research it does....)  and maybe that hewlett-packard version...


Modified location to "ZOs_Specific_Various.h"
modified define test to #if defined( _MSC_VER ) || defined( __WATCOMC__ )
for known exceptions.


olive

  • Administrator
  • Full Member
  • *****
  • Posts: 149
    • View Profile
Re: MSVC or non-GCC Porting
« Reply #5 on: November 10, 2014, 09:18:50 pm »
That's very interesting informations. And it will be useful for the mac os port.

We never had a mac. But as a BSD derivative, we suppose it shouldn’t be too far from linux for system base application calls.

The Blackvoxel Team