Changeset 9059

Show
Ignore:
Timestamp:
10/27/08 11:42:58 (6 years ago)
Author:
robert
Message:

From Blasius Czink, "Among other things I added support for atomic operations on BSD-like systems and additional methods (for "and", "or", "xor").
"

and a later post the same osg-submissions thread:

"it's been a while since I have made the changes but I think it was due to problems with static builds of OpenThreads? on windows. I was using
OpenThreads? in a communication/synchronisation library (without
OpenSceneGraph). It seems I forgot to post a small change in the CMakeLists file of OpenThreads?. If a user turns DYNAMIC_OPENTHREADS to OFF (static build) OT_LIBRARY_STATIC will be defined in the Config.
Without these changes a windows user will always end up with a "declspec(dllexport)" or "declspec(dllimport)" which is a problem for static builds."

And another post from Blasius on this topic:

"I tested with VS2005 and VS2008. For 32 bit everything works as expected. For x64 and VS2008 I could successfully do the cmake-configure and then the compilation but I had occasional crashes of cmTryCompileExec.exe (during the cmake-configure phase) which seems to be a cmake bug. With VS2005 and 64bit cmake does not set _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED although the interlocked functionality should be there. If I place the source snippet from the CHECK_CXX_SOURCE_RUNS macro to a separate sourcefile I can compile and run the resulting executable successfully. Forcing OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED (on VS2005/x64) reveals a bug in "intrin.h" which seems to be fixed in VS2008 but not in VS2005.

In case anyone is interested the lines:
MACHINEI(unsigned char _interlockedbittestandset(long *a, long b))
MACHINEI(unsigned char _interlockedbittestandreset(long *a, long b))
MACHINEX64(unsigned char _interlockedbittestandset64(int64 *a, int64 b))
MACHINEX64(unsigned char _interlockedbittestandreset64(int64 *a, int64 b))

should be changed to:
MACHINEI(unsigned char _interlockedbittestandset(long volatile *a, long b))
MACHINEI(unsigned char _interlockedbittestandreset(long volatile *a, long b))
MACHINEX64(unsigned char _interlockedbittestandset64(int64 volatile *a, int64 b))
MACHINEX64(unsigned char _interlockedbittestandreset64(int64 volatile *a, int64 b))

The worst thing that can happen is that interlocked funtionality is not detected during cmake-configure and the mutex fallback is used.
Which reminds me another small glitch in the Atomic header so I attached a corrected version.

Why is the OT_LIBRARY_STATIC added to the config file? It is not needed anywhere.

OT_LIBRARY_STATIC is needed if you are doing static-builds on Windows. See my previous post on that.
"

Location:
OpenSceneGraph/trunk
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/CMakeModules/CheckAtomicOps.cmake

    r8519 r9059  
    9191" _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    9292 
    93 IF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     93CHECK_CXX_SOURCE_RUNS(" 
     94#include <libkern/OSAtomic.h> 
     95 
     96int main() 
     97{ 
     98  volatile int32_t value = 0; 
     99  long data = 0; 
     100  long * volatile ptr = &data; 
     101   
     102  OSAtomicIncrement32(&value); 
     103  OSMemoryBarrier(); 
     104  OSAtomicDecrement32(&value); 
     105  OSAtomicCompareAndSwapInt(value, 1, &value); 
     106  OSAtomicCompareAndSwapPtr(ptr, ptr, (void * volatile *)&ptr); 
     107} 
     108" _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     109 
     110 
     111IF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED AND NOT _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
    94112  SET(_OPENTHREADS_ATOMIC_USE_MUTEX 1) 
    95 ENDIF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     113ENDIF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED AND NOT _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
  • OpenSceneGraph/trunk/include/OpenThreads/Atomic

    r8493 r9059  
    2424#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    2525# include <atomic.h> 
     26#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     27# include <libkern/OSAtomic.h> 
     28# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES 
    2629#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    2730# include "Mutex" 
     
    4750    _OPENTHREADS_ATOMIC_INLINE unsigned operator++(); 
    4851    _OPENTHREADS_ATOMIC_INLINE unsigned operator--(); 
     52    _OPENTHREADS_ATOMIC_INLINE unsigned AND(unsigned value); 
     53    _OPENTHREADS_ATOMIC_INLINE unsigned OR(unsigned value); 
     54    _OPENTHREADS_ATOMIC_INLINE unsigned XOR(unsigned value); 
     55    _OPENTHREADS_ATOMIC_INLINE unsigned exchange(unsigned value = 0); 
    4956    _OPENTHREADS_ATOMIC_INLINE operator unsigned() const; 
    5057 private: 
     
    5865#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    5966    volatile long _value; 
     67#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     68    volatile int32_t _value; 
    6069#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    6170    volatile uint_t _value; 
     
    126135} 
    127136 
     137_OPENTHREADS_ATOMIC_INLINE unsigned 
     138Atomic::AND(unsigned value) 
     139{ 
     140#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     141    return __sync_fetch_and_and(&_value, value); 
     142#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     143    return __and_and_fetch(&_value, value); 
     144#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     145    return atomic_and_uint_nv(&_value, value); 
     146#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     147    ScopedLock<Mutex> lock(_mutex); 
     148    _value &= value; 
     149    return _value; 
     150#else 
     151    _value &= value; 
     152    return _value; 
     153#endif 
     154} 
     155 
     156_OPENTHREADS_ATOMIC_INLINE unsigned 
     157Atomic::OR(unsigned value) 
     158{ 
     159#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     160    return __sync_fetch_and_or(&_value, value); 
     161#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     162    return __or_and_fetch(&_value, value); 
     163#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     164    return atomic_or_uint_nv(&_value, value); 
     165#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     166    ScopedLock<Mutex> lock(_mutex); 
     167    _value |= value;  
     168    return _value; 
     169#else 
     170    _value |= value; 
     171    return _value; 
     172#endif 
     173} 
     174 
     175_OPENTHREADS_ATOMIC_INLINE unsigned 
     176Atomic::XOR(unsigned value) 
     177{ 
     178#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     179    return __sync_fetch_and_xor(&_value, value); 
     180#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     181    return __xor_and_fetch(&_value, value); 
     182#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     183    return atomic_xor_uint_nv(&_value, value); 
     184#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     185    ScopedLock<Mutex> lock(_mutex); 
     186    _value ^= value; 
     187    return _value; 
     188#else 
     189    _value ^= value; 
     190    return _value; 
     191#endif 
     192} 
     193 
     194_OPENTHREADS_ATOMIC_INLINE unsigned 
     195Atomic::exchange(unsigned value) 
     196{ 
     197#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     198    return __sync_lock_test_and_set(&_value, value); 
     199#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     200    return __compare_and_swap(&_value, _value, value); 
     201#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     202    return atomic_cas_uint(&_value, _value, value); 
     203#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     204    ScopedLock<Mutex> lock(_mutex); 
     205    unsigned oldval = _value; 
     206    _value = value; 
     207    return oldval; 
     208#else 
     209    unsigned oldval = _value; 
     210    _value = value; 
     211    return oldval; 
     212#endif 
     213} 
     214 
    128215_OPENTHREADS_ATOMIC_INLINE 
    129216Atomic::operator unsigned() const 
  • OpenSceneGraph/trunk/include/OpenThreads/Exports

    r6096 r9059  
    1515#define _OPENTHREAD_EXPORTS_H_ 
    1616 
     17#include <OpenThreads/Config> 
    1718 
    1819#ifndef WIN32 
  • OpenSceneGraph/trunk/src/OpenThreads/CMakeLists.txt

    r8488 r9059  
    1111 
    1212INCLUDE(CheckAtomicOps) 
     13 
     14# User Options 
     15OPTION(DYNAMIC_OPENTHREADS "Set to ON to build OpenThreads for dynamic linking.  Use OFF for static." ON) 
     16IF (DYNAMIC_OPENTHREADS) 
     17    SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED") 
     18ELSE (DYNAMIC_OPENTHREADS) 
     19    SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "STATIC") 
     20    SET(OT_LIBRARY_STATIC 1) 
     21ENDIF (DYNAMIC_OPENTHREADS) 
    1322 
    1423################################################################################ 
     
    3847    ${OPENTHREADS_CONFIG_HEADER} 
    3948) 
    40  
    41 # User Options 
    42 OPTION(DYNAMIC_OPENTHREADS "Set to ON to build OpenThreads for dynamic linking.  Use OFF for static." ON) 
    43 IF   (DYNAMIC_OPENTHREADS) 
    44     SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED") 
    45 ELSE (DYNAMIC_OPENTHREADS) 
    46     SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "STATIC") 
    47 ENDIF(DYNAMIC_OPENTHREADS) 
    4849 
    4950# Use our modified version of FindThreads.cmake which has Sproc hacks. 
  • OpenSceneGraph/trunk/src/OpenThreads/common/Atomic.cpp

    r8493 r9059  
    1515 
    1616#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    17 # include <windows.h> 
     17#include <windows.h> 
     18#include <intrin.h> 
     19#pragma intrinsic(_InterlockedAnd) 
     20#pragma intrinsic(_InterlockedOr) 
     21#pragma intrinsic(_InterlockedXor) 
    1822#endif 
    1923 
     
    4145#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    4246    return InterlockedIncrement(&_value); 
     47#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     48    return OSAtomicIncrement32(&_value); 
    4349#else 
    4450# error This implementation should happen inline in the include file 
     
    5359#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    5460    return InterlockedDecrement(&_value); 
     61#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     62    return OSAtomicDecrement32(&_value); 
    5563#else 
    5664# error This implementation should happen inline in the include file 
    5765#endif 
    5866} 
     67 
     68unsigned 
     69Atomic::AND(unsigned value) 
     70{ 
     71#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     72    return __sync_fetch_and_and(&_value, value); 
     73#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     74    return _InterlockedAnd(&_value, value); 
     75#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     76    return OSAtomicAnd32((uint32_t)value, (uint32_t *)&_value); 
     77#else 
     78# error This implementation should happen inline in the include file 
     79#endif 
     80} 
     81 
     82unsigned 
     83Atomic::OR(unsigned value) 
     84{ 
     85#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     86    return __sync_fetch_and_or(&_value, value); 
     87#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     88    return _InterlockedOr(&_value, value); 
     89#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     90    return OSAtomicOr32((uint32_t)value, (uint32_t *)&_value); 
     91#else 
     92# error This implementation should happen inline in the include file 
     93#endif 
     94} 
     95 
     96unsigned 
     97Atomic::XOR(unsigned value) 
     98{ 
     99#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     100    return __sync_fetch_and_xor(&_value, value); 
     101#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     102    return _InterlockedXor(&_value, value); 
     103#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     104    return OSAtomicXor32((uint32_t)value, (uint32_t *)&_value); 
     105#else 
     106# error This implementation should happen inline in the include file 
     107#endif 
     108} 
     109 
     110 
     111unsigned 
     112Atomic::exchange(unsigned value) 
     113{ 
     114#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     115    return __sync_lock_test_and_set(&_value, value); 
     116#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     117    return InterlockedExchange(&_value, value); 
     118#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     119    return OSAtomicCompareAndSwap32(_value, value, &_value); 
     120#else 
     121# error This implementation should happen inline in the include file 
     122#endif 
     123} 
     124 
    59125 
    60126Atomic::operator unsigned() const 
     
    66132    MemoryBarrier(); 
    67133    return static_cast<unsigned const volatile &>(_value); 
     134#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     135    OSMemoryBarrier(); 
     136    return static_cast<unsigned const volatile>(_value); 
    68137#else 
    69138# error This implementation should happen inline in the include file 
     
    78147#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    79148    return ptrOld == InterlockedCompareExchangePointer((PVOID volatile*)&_ptr, (PVOID)ptrNew, (PVOID)ptrOld); 
     149#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     150    return OSAtomicCompareAndSwapPtr((void *)ptrOld, (void *)ptrNew, (void* volatile *)&_ptr); 
    80151#else 
    81152# error This implementation should happen inline in the include file 
     
    92163    MemoryBarrier(); 
    93164    return _ptr; 
     165#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC) 
     166    OSMemoryBarrier(); 
     167    return _ptr; 
    94168#else 
    95169# error This implementation should happen inline in the include file 
  • OpenSceneGraph/trunk/src/OpenThreads/common/Config.in

    r8494 r9059  
    2828#cmakedefine _OPENTHREADS_ATOMIC_USE_SUN 
    2929#cmakedefine _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED 
     30#cmakedefine _OPENTHREADS_ATOMIC_USE_BSD_ATOMIC 
    3031#cmakedefine _OPENTHREADS_ATOMIC_USE_MUTEX 
     32#cmakedefine OT_LIBRARY_STATIC 
    3133 
    3234#endif 
  • OpenSceneGraph/trunk/src/OpenThreads/win32/Win32BarrierPrivateData.h

    r6584 r9059  
    2121#ifndef _WINDOWS_ 
    2222#define WIN32_LEAN_AND_MEAN 
     23#define _WIN32_WINNT 0x0400 
    2324#include <windows.h> 
    2425#endif 
  • OpenSceneGraph/trunk/src/OpenThreads/win32/Win32ConditionPrivateData.h

    r8708 r9059  
    4545    Win32ConditionPrivateData () 
    4646        :waiters_(0),  
     47         was_broadcast_(0), 
    4748         sema_(CreateSemaphore(NULL,0,0x7fffffff,NULL)), 
    4849         waiters_done_(CreateEvent(NULL,FALSE,FALSE,NULL)) 
     
    7071            ReleaseSemaphore(sema_.get(),waiters_,NULL); 
    7172 
    72                         cooperativeWait(waiters_done_.get(), INFINITE); 
     73            cooperativeWait(waiters_done_.get(), INFINITE); 
    7374 
    7475            //end of broadcasting 
     
    105106        // wait in timeslices, giving testCancel() a change to 
    106107        // exit the thread if requested. 
    107                 try { 
    108                         DWORD dwResult =        cooperativeWait(sema_.get(), timeout_ms); 
    109                     if(dwResult != WAIT_OBJECT_0) 
    110                                 result = (int)dwResult; 
    111                 } 
    112                 catch(...){ 
    113                         // thread is canceled in cooperative wait , do cleanup 
    114                     InterlockedDecrement(&waiters_); 
    115                         long w = InterlockedGet(&waiters_); 
    116                         int last_waiter = was_broadcast_ && w == 0; 
     108        try { 
     109              DWORD dwResult = cooperativeWait(sema_.get(), timeout_ms); 
     110            if(dwResult != WAIT_OBJECT_0) 
     111                result = (int)dwResult; 
     112        } 
     113        catch(...){ 
     114            // thread is canceled in cooperative wait , do cleanup 
     115            InterlockedDecrement(&waiters_); 
     116            long w = InterlockedGet(&waiters_); 
     117            int last_waiter = was_broadcast_ && w == 0; 
    117118 
    118                         if (last_waiter)  SetEvent(waiters_done_.get()); 
    119                         // rethrow 
    120                         throw; 
    121                 } 
     119            if (last_waiter)  SetEvent(waiters_done_.get()); 
     120            // rethrow 
     121            throw; 
     122        } 
    122123 
    123                  
     124         
    124125        // We're ready to return, so there's one less waiter. 
    125126        InterlockedDecrement(&waiters_);