Merged Michael's fixatomiclinkage branch

This commit is contained in:
Andrew Johnson
2015-03-09 17:43:44 -05:00
27 changed files with 469 additions and 187 deletions

View File

@@ -20,6 +20,12 @@
# error compiler/clang/compilerSpecific.h is only for use with the clang compiler
#endif
#if __has_attribute(always_inline)
#define EPICS_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
#define EPICS_ALWAYS_INLINE __inline__
#endif
#ifdef __cplusplus
/*

View File

@@ -16,16 +16,8 @@
#ifndef epicsAtomicCD_h
#define epicsAtomicCD_h
#if defined ( __cplusplus )
# define EPICS_ATOMIC_INLINE inline
#else
# define EPICS_ATOMIC_INLINE __inline__
#endif
#define EPICS_ATOMIC_CMPLR_NAME "CLANG"
/*
* we have an inline keyword so we can proceed
* with an os specific inline instantiation
*/
#include "epicsAtomicOSD.h"
#endif /* epicsAtomicCD_h */

View File

@@ -15,6 +15,14 @@
#ifndef compilerSpecific_h
#define compilerSpecific_h
/* The 'inline' key work, possibily with compiler
* dependent flags to force inlineing where it would
* otherwise not be done.
*
* Warning: Second guessing the compiler may result in larger code size
*/
#define EPICS_ALWAYS_INLINE inline
#ifdef __cplusplus

View File

@@ -16,15 +16,8 @@
#ifndef epicsAtomicCD_h
#define epicsAtomicCD_h
#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus )
# define EPICS_ATOMIC_INLINE inline
/*
* We have already defined the public interface in epicsAtomic.h
* so there is nothing more to implement if there isnt an inline
* keyword available. Otherwise, if we have an inline keyword
* we will proceed with an os specific inline implementation.
*/
# include "epicsAtomicOSD.h"
#endif
#define EPICS_ATOMIC_CMPLR_NAME "DEFAULT"
#include "epicsAtomicOSD.h"
#endif /* epicsAtomicCD_h */

View File

@@ -23,6 +23,12 @@
#ifdef __clang__
# error compiler/gcc/compilerSpecific.h is not for use with the clang compiler
#endif
#if __GNUC__ > 2
# define EPICS_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
# define EPICS_ALWAYS_INLINE __inline__
#endif
#ifdef __cplusplus

View File

@@ -20,7 +20,7 @@
# error this header is only for use with the gnu compiler
#endif
#define EPICS_ATOMIC_INLINE __inline__
#define EPICS_ATOMIC_CMPLR_NAME "GCC"
#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
@@ -69,7 +69,7 @@ extern "C" {
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
#define EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
__sync_synchronize ();
}
@@ -77,7 +77,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
__sync_synchronize ();
}
@@ -88,7 +88,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
#if GCC_ATOMIC_INTRINSICS_MIN_X86
#define EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
asm("mfence;");
}
@@ -98,7 +98,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
#if GCC_ATOMIC_INTRINSICS_MIN_X86
#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
asm("mfence;");
}

View File

@@ -20,6 +20,12 @@
# error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler
#endif
#if _MSC_VER >= 1200
#define EPICS_ALWAYS_INLINE __forceinline
#else
#define EPICS_ALWAYS_INLINE __inline
#endif
#ifdef __cplusplus
/*

View File

@@ -24,18 +24,14 @@
#ifdef _MSC_EXTENSIONS
#include <intrin.h>
#define EPICS_ATOMIC_CMPLR_NAME "MSVC-INTRINSIC"
#if _MSC_VER >= 1200
# define EPICS_ATOMIC_INLINE __forceinline
#else
# define EPICS_ATOMIC_INLINE __inline
#endif
#include <intrin.h>
#if defined ( _M_IX86 )
# pragma warning( push )
# pragma warning( disable : 4793 )
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void)
{
long fence;
__asm { xchg fence, eax }
@@ -44,14 +40,14 @@
#elif defined ( _M_X64 )
# define MS_ATOMIC_64
# pragma intrinsic ( __faststorefence )
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void)
{
__faststorefence ();
}
#elif defined ( _M_IA64 )
# define MS_ATOMIC_64
# pragma intrinsic ( __mf )
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void)
{
__mf ();
}
@@ -88,13 +84,13 @@ extern "C" {
#endif /* __cplusplus */
#define EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
epicsAtomicMemoryBarrier ();
}
#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
epicsAtomicMemoryBarrier ();
}
@@ -108,9 +104,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
#else /* ifdef _MSC_EXTENSIONS */
#if defined ( __cplusplus )
# define EPICS_ATOMIC_INLINE inline
#endif
#define EPICS_ATOMIC_CMPLR_NAME "MSVC-DIRECT"
/*
* if unavailable as an intrinsic we will try

View File

@@ -0,0 +1,44 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author:
* Jeffrey O. Hill
* johill@lanl.gov
*/
#ifndef compilerSpecific_h
#define compilerSpecific_h
#if !defined(__SUNPRO_C) && !defined (__SUNPRO_CC)
# error Not Solaris Studio
#endif
#if (defined(__SUNPRO_C) && __SUNPRO_C < 0x590) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
# define EPICS_ALWAYS_INLINE inline
#else
# define EPICS_ALWAYS_INLINE inline __attribute__((always_inline))
#endif
#ifdef __cplusplus
/*
* CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
* CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
*
* (our default guess is that the compiler implements the C++ 97 standard)
*/
#define CXX_THROW_SPECIFICATION
#define CXX_PLACEMENT_DELETE
#endif /* __cplusplus */
#endif /* ifndef compilerSpecific_h */

View File

@@ -16,16 +16,8 @@
#ifndef epicsAtomicCD_h
#define epicsAtomicCD_h
#if defined ( __cplusplus )
# define EPICS_ATOMIC_INLINE inline
#else
# define EPICS_ATOMIC_INLINE __inline
#endif
#define EPICS_ATOMIC_CMPLR_NAME "SOLSTUDIO"
/*
* we have an inline keyword so we can proceed
* with an os specific inline instantiation
*/
#include "epicsAtomicOSD.h"
#endif /* epicsAtomicCD_h */

View File

@@ -17,7 +17,9 @@
#include <stdlib.h> /* define size_t */
#include "shareLib.h"
#include "compilerSpecific.h"
#define EPICS_ATOMIC_INLINE static EPICS_ALWAYS_INLINE
#ifdef __cplusplus
extern "C" {
@@ -26,10 +28,10 @@ extern "C" {
typedef void * EpicsAtomicPtrT;
/* load target into cache */
epicsShareFunc void epicsAtomicReadMemoryBarrier ();
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void);
/* push cache version of target into target */
epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void);
/*
* lock out other smp processors from accessing the target,
@@ -37,8 +39,8 @@ epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
* to target, allow other smp processors to access the target,
* return new value of target as modified by this operation
*/
epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget );
epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget );
EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget );
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget );
/*
* lock out other smp processors from accessing the target,
@@ -46,8 +48,8 @@ epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget );
* to target, allow out other smp processors to access the target,
* return new value of target as modified by this operation
*/
epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget );
epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget );
EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget );
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget );
/*
* lock out other smp processors from accessing the target,
@@ -55,23 +57,23 @@ epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget );
* to target, allow other smp processors to access the target,
* return new value of target as modified by this operation
*/
epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta );
epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta );
epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta );
EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta );
EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta );
EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta );
/*
* set cache version of target, flush cache to target
*/
epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue );
epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue );
epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue );
EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue );
EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newValue );
EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue );
/*
* fetch target into cache, return new value of target
*/
epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget );
epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget );
epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget );
EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget );
EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget );
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget );
/*
* lock out other smp processors from accessing the target,
@@ -80,11 +82,11 @@ epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTar
* to access the target, return the original value stored in the
* target
*/
epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
size_t oldVal, size_t newVal );
epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget,
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
int oldVal, int newVal );
epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
EpicsAtomicPtrT * pTarget,
EpicsAtomicPtrT oldVal,
EpicsAtomicPtrT newVal );
@@ -111,119 +113,98 @@ namespace atomic {
/*
* overloaded c++ interface
*/
epicsShareFunc size_t increment ( size_t & v );
epicsShareFunc int increment ( int & v );
epicsShareFunc size_t decrement ( size_t & v );
epicsShareFunc int decrement ( int & v );
epicsShareFunc size_t add ( size_t & v, size_t delta );
epicsShareFunc int add ( int & v, int delta );
epicsShareFunc size_t subtract ( size_t & v, size_t delta );
epicsShareFunc int subtract ( int & v, int delta );
epicsShareFunc void set ( size_t & v , size_t newValue );
epicsShareFunc void set ( int & v, int newValue );
epicsShareFunc void set ( EpicsAtomicPtrT & v,
EpicsAtomicPtrT newValue );
epicsShareFunc size_t get ( const size_t & v );
epicsShareFunc int get ( const int & v );
epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v );
epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal,
size_t newVal );
epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal );
epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
EpicsAtomicPtrT oldVal,
EpicsAtomicPtrT newVal );
/************* incr ***************/
inline size_t increment ( size_t & v )
EPICS_ATOMIC_INLINE size_t increment ( size_t & v )
{
return epicsAtomicIncrSizeT ( & v );
}
inline int increment ( int & v )
EPICS_ATOMIC_INLINE int increment ( int & v )
{
return epicsAtomicIncrIntT ( & v );
}
/************* decr ***************/
inline size_t decrement ( size_t & v )
EPICS_ATOMIC_INLINE size_t decrement ( size_t & v )
{
return epicsAtomicDecrSizeT ( & v );
}
inline int decrement ( int & v )
EPICS_ATOMIC_INLINE int decrement ( int & v )
{
return epicsAtomicDecrIntT ( & v );
}
/************* add ***************/
inline size_t add ( size_t & v, size_t delta )
EPICS_ATOMIC_INLINE size_t add ( size_t & v, size_t delta )
{
return epicsAtomicAddSizeT ( & v, delta );
}
inline int add ( int & v, int delta )
EPICS_ATOMIC_INLINE int add ( int & v, int delta )
{
return epicsAtomicAddIntT ( & v, delta );
}
/************* sub ***************/
inline size_t subtract ( size_t & v, size_t delta )
EPICS_ATOMIC_INLINE size_t subtract ( size_t & v, size_t delta )
{
return epicsAtomicSubSizeT ( & v, delta );
}
inline int subtract ( int & v, int delta )
EPICS_ATOMIC_INLINE int subtract ( int & v, int delta )
{
return epicsAtomicAddIntT ( & v, -delta );
}
/************* set ***************/
inline void set ( size_t & v , size_t newValue )
EPICS_ATOMIC_INLINE void set ( size_t & v , size_t newValue )
{
epicsAtomicSetSizeT ( & v, newValue );
}
inline void set ( int & v, int newValue )
EPICS_ATOMIC_INLINE void set ( int & v, int newValue )
{
epicsAtomicSetIntT ( & v, newValue );
}
inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
EPICS_ATOMIC_INLINE void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
{
epicsAtomicSetPtrT ( & v, newValue );
}
/************* get ***************/
inline size_t get ( const size_t & v )
EPICS_ATOMIC_INLINE size_t get ( const size_t & v )
{
return epicsAtomicGetSizeT ( & v );
}
inline int get ( const int & v )
EPICS_ATOMIC_INLINE int get ( const int & v )
{
return epicsAtomicGetIntT ( & v );
}
inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
EPICS_ATOMIC_INLINE EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
{
return epicsAtomicGetPtrT ( & v );
}
/************* cas ***************/
inline size_t compareAndSwap ( size_t & v,
size_t oldVal, size_t newVal )
EPICS_ATOMIC_INLINE size_t compareAndSwap ( size_t & v,
size_t oldVal, size_t newVal )
{
return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal );
}
inline int compareAndSwap ( int & v, int oldVal, int newVal )
EPICS_ATOMIC_INLINE int compareAndSwap ( int & v, int oldVal, int newVal )
{
return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal );
}
inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
EpicsAtomicPtrT oldVal,
EpicsAtomicPtrT newVal )
EPICS_ATOMIC_INLINE EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
EpicsAtomicPtrT oldVal,
EpicsAtomicPtrT newVal )
{
return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal );
}

View File

@@ -0,0 +1,65 @@
/*************************************************************************\
* Copyright (c) 2011 LANS LLC, as Operator of
* Los Alamos National Laboratory.
* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
*/
#ifndef epicsAtomicOSD_h
#define epicsAtomicOSD_h
#include <shareLib.h>
#include "epicsMMIO.h"
#include "compilerSpecific.h"
#include "epicsInterrupt.h"
#define EPICS_ATOMIC_OS_NAME "RTEMS"
typedef struct EpicsAtomicLockKey {
int key;
} EpicsAtomicLockKey;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
epicsAtomicMemoryBarrierFallback();
}
#endif
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
rwbarr();
}
#endif
EPICS_ATOMIC_INLINE void epicsAtomicLock ( struct EpicsAtomicLockKey * pkey )
{
pkey->key = epicsInterruptLock();
}
EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( struct EpicsAtomicLockKey * pkey )
{
epicsInterruptUnlock(pkey->key);
}
#ifdef __cplusplus
} /* end of extern "C" */
#endif /* __cplusplus */
#include "epicsAtomicDefault.h"
#endif /* epicsAtomicOSD_h */

View File

@@ -1,22 +0,0 @@
/*************************************************************************\
* Copyright (c) 2011 LANS LLC, as Operator of
* Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
*/
#define epicsExportSharedSymbols
#include "epicsAtomic.h"
// if the compiler is unable to inline then instantiate out-of-line
#ifndef EPICS_ATOMIC_INLINE
# define EPICS_ATOMIC_INLINE
# include "epicsAtomicOSD.h"
#endif

View File

@@ -16,6 +16,8 @@
#ifndef epicsAtomicOSD_h
#define epicsAtomicOSD_h
#define EPICS_ATOMIC_OS_NAME "WIN32"
#ifdef VC_EXTRALEAN
# define VC_EXTRALEAN_DETECTED_epicsAtomicOSD_h
#else

View File

@@ -19,14 +19,6 @@
#include "epicsAssert.h"
#include "epicsAtomic.h"
// if the compiler is unable to inline then instantiate out-of-line
#ifndef EPICS_ATOMIC_INLINE
# define EPICS_ATOMIC_INLINE
# include "epicsAtomicOSD.h"
#endif
#ifndef EPICS_ATOMIC_LOCK
/*
* Slow, but probably correct on all systems.
* Useful only if something more efficient isn`t
@@ -69,31 +61,14 @@ void epicsAtomicUnlock ( EpicsAtomicLockKey * )
assert ( status == 0 );
}
#endif // ifndef EPICS_ATOMIC_LOCK
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
// Slow, but probably correct on all systems.
// Useful only if something more efficient isn`t
// provided based on knowledge of the compiler
// or OS
void epicsAtomicReadMemoryBarrier ()
void epicsAtomicMemoryBarrierFallback (void)
{
EpicsAtomicLockKey key;
epicsAtomicLock ( & key );
epicsAtomicUnlock ( & key );
}
#endif
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
// Slow, but probably correct on all systems.
// Useful only if something more efficient isn`t
// provided based on knowledge of the compiler
// or OS
void epicsAtomicWriteMemoryBarrier ()
{
EpicsAtomicLockKey key;
epicsAtomicLock ( & key );
epicsAtomicUnlock ( & key );
}
#endif

View File

@@ -16,14 +16,33 @@
#ifndef epicsAtomicOSD_h
#define epicsAtomicOSD_h
#include <shareLib.h>
#define EPICS_ATOMIC_OS_NAME "POSIX"
typedef struct EpicsAtomicLockKey {} EpicsAtomicLockKey;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
epicsAtomicMemoryBarrierFallback();
}
#endif
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
epicsAtomicMemoryBarrierFallback();
}
#endif
epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * );
epicsShareFunc void epicsAtomicMemoryBarrierFallback ( void );
#ifdef __cplusplus
} /* end of extern "C" */

View File

@@ -13,9 +13,13 @@
* johill@lanl.gov
*/
#include "shareLib.h"
#ifndef epicsAtomicOSD_h
#define epicsAtomicOSD_h
#define EPICS_ATOMIC_OS_NAME "Solaris"
#if defined ( __SunOS_5_10 )
/*
@@ -31,7 +35,7 @@ extern "C" {
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
#define EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
membar_consumer ();
}
@@ -39,7 +43,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
membar_producer ();
}
@@ -47,7 +51,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
#ifndef EPICS_ATOMIC_CAS_INTT
#define EPICS_ATOMIC_CAS_INTT
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
int oldVal, int newVal )
{
STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) );
@@ -59,7 +63,7 @@ EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
#ifndef EPICS_ATOMIC_CAS_SIZET
#define EPICS_ATOMIC_CAS_SIZET
EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
size_t * pTarget,
size_t oldVal, size_t newVal )
{
@@ -71,7 +75,7 @@ EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
#ifndef EPICS_ATOMIC_CAS_PTRT
#define EPICS_ATOMIC_CAS_PTRT
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
EpicsAtomicPtrT * pTarget,
EpicsAtomicPtrT oldVal,
EpicsAtomicPtrT newVal )
@@ -132,7 +136,7 @@ EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
#ifndef EPICS_ATOMIC_ADD_SIZET
#define EPICS_ATOMIC_ADD_SIZET
EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
size_t delta )
{
STATIC_ASSERT ( sizeof ( ulong_t ) == sizeof ( size_t ) );
@@ -143,7 +147,7 @@ EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
#ifndef EPICS_ATOMIC_SUB_SIZET
#define EPICS_ATOMIC_SUB_SIZET
EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget,
EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget,
size_t delta )
{
STATIC_ASSERT ( sizeof ( ulong_t ) == sizeof ( size_t ) );

View File

@@ -1,21 +0,0 @@
/*************************************************************************\
* Copyright (c) 2011 LANS LLC, as Operator of
* Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
*/
#define epicsExportSharedSymbols
#include "epicsAtomic.h"
// if the compiler is unable to inline then instantiate out-of-line
#ifndef EPICS_ATOMIC_INLINE
# define EPICS_ATOMIC_INLINE
# include "epicsAtomicOSD.h"
#endif

View File

@@ -32,13 +32,15 @@
#include <limits.h>
#include <vxAtomicLib.h>
#define EPICS_ATOMIC_OS_NAME "VX-ATOMICLIB"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
#define EPICS_ATOMIC_READ_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
{
VX_MEM_BARRIER_R ();
}
@@ -46,7 +48,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
{
VX_MEM_BARRIER_W ();
}
@@ -206,6 +208,8 @@ EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
#include "vxLib.h"
#include "intLib.h"
#define EPICS_ATOMIC_OS_NAME "VX-INTLIB"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -232,7 +236,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey )
* no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
* (we are not protecting against multiple access to memory mapped IO)
*/
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {}
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) {}
#endif
#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
@@ -241,7 +245,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {}
* no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
* (we are not protecting against multiple access to memory mapped IO)
*/
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {}
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) {}
#endif
#ifdef __cplusplus

View File

@@ -22,6 +22,14 @@ epicsTypesTest_SRCS += epicsTypesTest.cpp
testHarness_SRCS += epicsTypesTest.cpp
TESTS += epicsTypesTest
TESTPROD_HOST += epicsInlineTest
epicsInlineTest_SRCS += epicsInlineTest1.c
epicsInlineTest_SRCS += epicsInlineTest2.c
epicsInlineTest_SRCS += epicsInlineTest3.cpp
epicsInlineTest_SRCS += epicsInlineTest4.cpp
testHarness_SRCS += $(epicsInlineTest_SRCS)
TESTS += epicsInlineTest
TESTPROD_HOST += epicsCalcTest
epicsCalcTest_SRCS += epicsCalcTest.cpp
testHarness_SRCS += epicsCalcTest.cpp

View File

@@ -248,11 +248,89 @@ template void testCAS < EpicsAtomicPtrT > (void);
# pragma warning ( pop )
#endif
static void testClassify()
{
testDiag("Classify Build conditions");
#ifdef EPICS_ATOMIC_CMPLR_NAME
testDiag("Compiler dependent impl name %s", EPICS_ATOMIC_CMPLR_NAME);
#else
testDiag("Compiler dependent impl name undefined");
#endif
#ifdef EPICS_ATOMIC_OS_NAME
testDiag("OS dependent impl name %s", EPICS_ATOMIC_OS_NAME);
#else
testDiag("OS dependent impl name undefined");
#endif
#ifdef __GNUC__
#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
testDiag("GCC using atomic builtin memory barrier");
#else
testDiag("GCC using asm memory barrier");
#endif
#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
testDiag("GCC use builtin for int");
#endif
#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
testDiag("GCC use builtin for size_t");
#endif
#ifndef EPICS_ATOMIC_INCR_INTT
testDiag("Use default epicsAtomicIncrIntT()");
#endif
#ifndef EPICS_ATOMIC_INCR_SIZET
testDiag("Use default epicsAtomicIncrSizeT()");
#endif
#ifndef EPICS_ATOMIC_DECR_INTT
testDiag("Use default epicsAtomicDecrIntT()");
#endif
#ifndef EPICS_ATOMIC_DECR_SIZET
testDiag("Use default epicsAtomicDecrSizeT()");
#endif
#ifndef EPICS_ATOMIC_ADD_INTT
testDiag("Use default epicsAtomicAddIntT()");
#endif
#ifndef EPICS_ATOMIC_ADD_SIZET
testDiag("Use default epicsAtomicAddSizeT()");
#endif
#ifndef EPICS_ATOMIC_SUB_SIZET
testDiag("Use default epicsAtomicSubSizeT()");
#endif
#ifndef EPICS_ATOMIC_SET_INTT
testDiag("Use default epicsAtomicSetIntT()");
#endif
#ifndef EPICS_ATOMIC_SET_SIZET
testDiag("Use default epicsAtomicSetSizeT()");
#endif
#ifndef EPICS_ATOMIC_SET_PTRT
testDiag("Use default epicsAtomicSetPtrT()");
#endif
#ifndef EPICS_ATOMIC_GET_INTT
testDiag("Use default epicsAtomicGetIntT()");
#endif
#ifndef EPICS_ATOMIC_GET_SIZET
testDiag("Use default epicsAtomicGetSizeT()");
#endif
#ifndef EPICS_ATOMIC_GET_PTRT
testDiag("Use default epicsAtomicGetPtrT()");
#endif
#ifndef EPICS_ATOMIC_CAS_INTT
testDiag("Use default epicsAtomicCmpAndSwapIntT()");
#endif
#ifndef EPICS_ATOMIC_CAS_SIZET
testDiag("Use default epicsAtomicCmpAndSwapSizeT()");
#endif
#ifndef EPICS_ATOMIC_CAS_PTRT
testDiag("Use default epicsAtomicCmpAndSwapPtrT()");
#endif
#endif /* __GNUC__ */
}
MAIN ( epicsAtomicTest )
{
testPlan ( 31 );
testClassify ();
testIncrDecr < int > ();
testIncrDecr < size_t > ();

View File

@@ -0,0 +1,64 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* This test checks the variations on inline function defintions.
*
* "static inline int func(void) {...}"
*
* Consistent meaning in C89, C99, and C++ (98 and 11).
* If not inline'd results in a private symbol in each compilation unit.
* Thus the non-inline'd version is duplicated in each compilation unit.
* However, definitions in different compilation units may be different.
*
* "inline int func(void) {...}"
* Warning: Not consistent, avoid use in headers meant for C or C++
*
* In C++ this may be safely defined in more than one compilation unit.
* Where not inlined it will result in a weak public symbol.
* Thus non-inline'd version isn't duplicated, but must be the same
* in all compilation units.
*
*/
#include "compilerSpecific.h"
#include "epicsUnitTest.h"
#include "testMain.h"
static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void)
{
return 1;
}
/* Fails to link in C99
inline int epicsInlineTestFn2(void)
{
return 42;
}
*/
void epicsInlineTest1(void)
{
testDiag("epicsInlineTest1()");
testOk1(epicsInlineTestFn1()==1);
/*testOk1(epicsInlineTestFn2()==42);*/
}
void epicsInlineTest2(void);
void epicsInlineTest3(void);
void epicsInlineTest4(void);
MAIN(epicsInlineTest)
{
testPlan(6);
testDiag("Test variation on inline int func()");
epicsInlineTest1();
epicsInlineTest2();
epicsInlineTest3();
epicsInlineTest4();
return testDone();
}

View File

@@ -0,0 +1,28 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "compilerSpecific.h"
#include "epicsUnitTest.h"
static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void)
{
return 2;
}
/* Fails to link in C99
inline int epicsInlineTestFn2(void)
{
return 42;
}
*/
void epicsInlineTest2(void)
{
testDiag("epicsInlineTest2()");
testOk1(epicsInlineTestFn1()==2);
/*testOk1(epicsInlineTestFn2()==42);*/
}

View File

@@ -0,0 +1,27 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "compilerSpecific.h"
#include "epicsUnitTest.h"
static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void)
{
return 3;
}
inline int epicsInlineTestFn2(void)
{
return 42;
}
extern "C"
void epicsInlineTest3(void)
{
testDiag("epicsInlineTest3()");
testOk1(epicsInlineTestFn1()==3);
testOk1(epicsInlineTestFn2()==42);
}

View File

@@ -0,0 +1,27 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "compilerSpecific.h"
#include "epicsUnitTest.h"
static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void)
{
return 4;
}
inline int epicsInlineTestFn2(void)
{
return 42;
}
extern "C"
void epicsInlineTest4(void)
{
testDiag("epicsInlineTest4()");
testOk1(epicsInlineTestFn1()==4);
testOk1(epicsInlineTestFn2()==42);
}

View File

@@ -44,6 +44,7 @@ int epicsThreadTest(void);
int epicsTimerTest(void);
int epicsTimeTest(void);
int epicsTypesTest(void);
int epicsInlineTest(void);
int macDefExpandTest(void);
int macLibTest(void);
int ringBytesTest(void);
@@ -92,6 +93,7 @@ void epicsRunLibComTests(void)
runTest(epicsThreadPrivateTest);
runTest(epicsTimeTest);
runTest(epicsTypesTest);
runTest(epicsInlineTest);
runTest(macDefExpandTest);
runTest(macLibTest);
runTest(ringBytesTest);