EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  <20112012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  <20112012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: [Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base
From: Jeff Hill <[email protected]>
To: [email protected]
Date: Wed, 31 Aug 2011 22:29:27 -0000
Jeff Hill has proposed merging lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base.

Requested reviews:
  EPICS Core Developers (epics-core)

For more details, see:
https://code.launchpad.net/~johill-lanl/epics-base/epicsThreadOnce-atomics-based/+merge/73605

o added new epicsAtomics based, and OS independent, implementation of epicsThreadOnce in epicsThreadOnce.cpp
o changed type of epicsThreadOnceId from epicsThreadId to void *
o fixed once flag isnt initialized with EPICSTHREAD_ONCE_INIT in ipAddrToAsciiAsynchronous.cpp
o removed OS dependent implementations of epicsThreadOnce from {posix, RTEMS, vxWorks, win32}

-- 
https://code.launchpad.net/~johill-lanl/epics-base/epicsThreadOnce-atomics-based/+merge/73605
Your team EPICS Core Developers is requested to review the proposed merge of lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base.
=== modified file 'configure/CONFIG.gnuCommon'
--- configure/CONFIG.gnuCommon	2009-11-25 17:15:47 +0000
+++ configure/CONFIG.gnuCommon	2011-08-31 22:29:24 +0000
@@ -12,6 +12,8 @@
 
 GNU = YES
 
+CMPLR_CLASS = gcc
+
 GNU_BIN = $(GNU_DIR)/bin
 GNU_LIB = $(GNU_DIR)/lib
 

=== modified file 'configure/CONFIG_COMMON'
--- configure/CONFIG_COMMON	2011-08-17 21:36:38 +0000
+++ configure/CONFIG_COMMON	2011-08-31 22:29:24 +0000
@@ -133,11 +133,14 @@
 GENERIC_SRC_DIRS = .. $(SRC_DIRS)
 OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
        $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))
-ALL_SRC_DIRS = $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
+CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
+       $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default ))
+ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
 
 #--------------------------------------------------
 # compile line include directories
 INSTALL_INCLUDES += \
+       -I$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) \
        -I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \
        -I$(INSTALL_INCLUDE)
 SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS)))
@@ -379,25 +382,36 @@
 #
 # auto determine the directory paths that things are installed to
 # RULES:
-# 1) found in any one of several os specific area
+# 0) found in any one of several compiler specific paths
+#       => install to $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)
+# 1) not found in (0) and found in any one of several OS specific paths
 #       => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS)
-# 2) not foundin (1) and found in generic area
+# 2) not found in (1) and found in generic paths
 #       => install to $(INSTALL_INCLUDE)
 # 3) not found in (1) or (2) then may be (not yet) computer generated
 #       => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let
 #       build rules work on vpath
 #
 # These rules guarantee that the users include from
-# no more than two directories
+# no more than three directories
 #
 INSTALL_INC += $(foreach inc, $(INC), \
     $(firstword \
+        $(CMPLR_INSTALL_INC) \
         $(OS_INSTALL_INC) \
         $(GENERIC_INSTALL_INC) \
         $(GENERATED_INSTALL_INC) ) )
 INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) )
 
 #
+# Rule 0
+#
+CMPLR_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/, $(INSTALL_INC_jjj) )
+INSTALL_INC_jjj = $(foreach dir, $(CMPLR_SRC_DIRS), $(INSTALL_INC_iii)  )
+INSTALL_INC_iii = $(subst $(dir)/, , $(INSTALL_INC_hhh) )
+INSTALL_INC_hhh = $(wildcard $(addsuffix /$(inc), $(dir)) )
+
+#
 # Rule 1
 #
 OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) )

=== modified file 'configure/RULES_BUILD'
--- configure/RULES_BUILD	2010-12-20 15:48:12 +0000
+++ configure/RULES_BUILD	2011-08-31 22:29:24 +0000
@@ -408,7 +408,11 @@
 	@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
 
 $(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : %
-	$(ECHO) "Installing os dependent include file $@"
+	$(ECHO) "Installing OS dependent include file $@"
+	@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
+	
+$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/% : %
+	$(ECHO) "Installing compiler dependent include file $@"
 	@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
 
 $(INSTALL_DOC)/%: %

=== modified file 'configure/os/CONFIG.solarisCommon.solarisCommon'
--- configure/os/CONFIG.solarisCommon.solarisCommon	2010-10-05 19:27:37 +0000
+++ configure/os/CONFIG.solarisCommon.solarisCommon	2011-08-31 22:29:24 +0000
@@ -7,6 +7,8 @@
 # Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc
 #-------------------------------------------------------
 
+CMPLR_CLASS = solStudio
+
 SPARCWORKS = /opt/SUNWspro
 GNU = NO
 

=== modified file 'configure/os/CONFIG.win32-x86.win32-x86'
--- configure/os/CONFIG.win32-x86.win32-x86	2011-08-17 21:36:38 +0000
+++ configure/os/CONFIG.win32-x86.win32-x86	2011-08-31 22:29:24 +0000
@@ -11,6 +11,8 @@
 
 VALID_BUILDS = Host Ioc
 
+CMPLR_CLASS = msvc
+
 # convert UNIX path to native path
 PATH_FILTER = $(subst /,\\,$(1))
 
@@ -122,7 +124,7 @@
 # /D_CRTDBG_MAP_ALLOC
 # /RTCsu catch bugs occurring only in optimized code
 # /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs
-OPT_CXXFLAGS_NO = /RTCsu /Zi 
+OPT_CXXFLAGS_NO = /RTCsu /Zi
 
 # specify object file name and location
 OBJ_CXXFLAG = /Fo

=== modified file 'src/libCom/Makefile'
--- src/libCom/Makefile	2011-08-23 22:28:20 +0000
+++ src/libCom/Makefile	2011-08-31 22:29:24 +0000
@@ -9,6 +9,7 @@
 TOP = ../..
 include $(TOP)/configure/CONFIG
 
+<<<<<<< TREE
 SRC = $(TOP)/src
 LIBCOM = $(SRC)/libCom
 
@@ -38,6 +39,288 @@
 include $(LIBCOM)/yacc/Makefile
 
 # Library to build:
+=======
+LIBCOM = $(TOP)/src/libCom
+
+# Command-line input support
+epicsReadline_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY)
+epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY))
+
+#POSIX thread priority scheduling flag
+THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
+osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
+
+#epicsVersion is created by this Makefile
+INC += epicsVersion.h
+
+SRC_DIRS += $(LIBCOM)/bucketLib
+INC += bucketLib.h
+SRCS += bucketLib.c
+
+SRC_DIRS += $(LIBCOM)/ring
+#following needed for locating epicsRingPointer.h and epicsRingBytes.h
+INC += epicsRingPointer.h
+INC += epicsRingBytes.h
+SRCS += epicsRingPointer.cpp
+SRCS += epicsRingBytes.c
+
+SRC_DIRS += $(LIBCOM)/calc
+INC += postfix.h
+SRCS += postfix.c
+SRCS += calcPerform.c
+
+SRC_DIRS += $(LIBCOM)/cvtFast
+INC += cvtFast.h
+SRCS += cvtFast.c
+
+# From cppStd
+SRC_DIRS += $(LIBCOM)/cppStd
+INC += epicsAlgorithm.h
+INC += epicsExcept.h
+INC += epicsMemory.h
+
+# From cxxTemplates
+SRC_DIRS += $(LIBCOM)/cxxTemplates
+INC += resourceLib.h
+INC += tsDLList.h
+INC += tsSLList.h
+INC += tsMinMax.h
+INC += tsBTree.h
+INC += tsFreeList.h
+INC += epicsSingleton.h
+INC += epicsGuard.h
+INC += epicsOnce.h
+SRCS += resourceLib.cpp
+SRCS += epicsOnce.cpp
+SRCS += epicsSingletonMutex.cpp
+
+SRC_DIRS += $(LIBCOM)/dbmf
+INC += dbmf.h
+SRCS += dbmf.c
+
+SRC_DIRS += $(LIBCOM)/ellLib
+INC += ellLib.h
+SRCS += ellLib.c
+
+SRC_DIRS += $(LIBCOM)/env
+INC += envDefs.h
+SRCS += envSubr.c
+SRCS += envData.c
+
+SRC_DIRS += $(LIBCOM)/error
+INC += epicsPrint.h
+INC += errMdef.h
+INC += errSymTbl.h
+INC += errlog.h
+INC += error.h
+SRCS += errlog.c
+SRCS += errSymLib.c
+SRCS += errSymTbl.c
+
+SRC_DIRS += $(LIBCOM)/fdmgr
+INC += fdManager.h
+INC += fdmgr.h
+SRCS += fdmgr.cpp
+SRCS += fdManager.cpp
+
+SRC_DIRS += $(LIBCOM)/freeList
+INC += freeList.h
+SRCS += freeListLib.c
+HTMLS += freeList/freeList.html
+
+SRC_DIRS += $(LIBCOM)/gpHash
+INC += gpHash.h
+SRCS += gpHashLib.c
+HTMLS += gpHash/gpHash.html
+
+SRC_DIRS += $(LIBCOM)/iocsh
+INC += iocsh.h
+INC += registry.h
+INC += libComRegister.h
+SRCS += iocsh.cpp
+SRCS += registry.c
+SRCS += libComRegister.c
+
+SRC_DIRS += $(LIBCOM)/logClient
+INC += iocLog.h
+INC += logClient.h
+SRCS += iocLog.c
+SRCS += logClient.c
+
+SRC_DIRS += $(LIBCOM)/macLib
+INC += macLib.h
+SRCS += macCore.c
+SRCS += macEnv.c
+SRCS += macUtil.c
+
+SRC_DIRS += $(LIBCOM)/misc
+INC += adjustment.h
+INC += cantProceed.h
+INC += dbDefs.h
+INC += epicsConvert.h
+INC += epicsExit.h
+INC += epicsStdlib.h
+INC += epicsString.h
+INC += epicsTypes.h
+INC += shareLib.h
+INC += epicsExport.h
+INC += unixFileName.h
+INC += locationException.h
+INC += ipAddrToAsciiAsynchronous.h
+INC += epicsUnitTest.h
+INC += testMain.h
+SRCS += aToIPAddr.c
+SRCS += adjustment.c
+SRCS += cantProceed.c
+SRCS += epicsConvert.c
+SRCS += epicsExit.c
+SRCS += epicsStdlib.c
+SRCS += epicsString.c
+SRCS += truncateFile.c
+SRCS += ipAddrToAsciiAsynchronous.cpp
+SRCS += epicsUnitTest.c
+
+# From osi
+SRC_DIRS += $(LIBCOM)/osi
+INC += osiFileName.h
+INC += osiSock.h
+INC += osdSock.h
+INC += epicsInterrupt.h
+INC += osdInterrupt.h
+
+INC += epicsMutex.h
+INC += osdMutex.h
+INC += epicsEvent.h
+INC += osdEvent.h
+INC += epicsMath.h
+INC += osdMessageQueue.h
+INC += osdStrtod.h
+
+INC += epicsAssert.h
+INC += epicsFindSymbol.h
+INC += osiPoolStatus.h
+INC += osdPoolStatus.h
+INC += osdThread.h
+
+INC += epicsThread.h
+INC += epicsTime.h
+INC += epicsGeneralTime.h
+INC += osdTime.h
+INC += generalTimeSup.h
+INC += osiClockTime.h
+INC += epicsSignal.h
+INC += osiProcess.h
+INC += osiUnistd.h
+INC += osiWireFormat.h
+INC += osdWireFormat.h
+INC += osdWireConfig.h
+INC += epicsAtomic.h
+INC += epicsAtomicCD.h
+INC += epicsAtomicOSD.h
+INC += epicsAtomicDefault.h
+INC += epicsEndian.h
+INC += epicsReadline.h
+INC += epicsMessageQueue.h
+INC += epicsStdio.h
+INC += epicsStdioRedirect.h
+INC += epicsGetopt.h
+
+INC += devLib.h
+INC += devLibVME.h
+INC += devLibVMEImpl.h
+INC += osdVME.h
+INC += compilerDependencies.h
+INC += compilerSpecific.h
+
+SRCS += epicsThread.cpp
+SRCS += epicsMutex.cpp
+SRCS += epicsEvent.cpp
+SRCS += epicsTime.cpp
+SRCS += epicsMessageQueue.cpp
+SRCS += epicsMath.cpp
+SRCS += epicsAtomicOSD.cpp
+
+SRCS += epicsGeneralTime.c
+SRCS += osiClockTime.c
+
+SRCS += osdSock.c
+SRCS += osdSockAddrReuse.cpp
+SRCS += osiSock.c
+SRCS += systemCallIntMech.cpp
+SRCS += epicsSocketConvertErrnoToString.cpp
+SRCS += osdAssert.c
+SRCS += osdFindSymbol.c
+SRCS += osdInterrupt.c
+SRCS += osdPoolStatus.c
+SRCS += osdSignal.cpp
+SRCS += osdEnv.c
+SRCS += epicsReadline.c
+SRCS += epicsTempFile.cpp
+SRCS += epicsThreadOnce.cpp
+SRCS += epicsStdio.c
+SRCS += osdStdio.c
+
+osdEnv_CFLAGS_WIN32= -U__STDC__
+
+SRCS += osdThread.c
+SRCS += osdMutex.c
+SRCS += osdEvent.c
+SRCS += osdTime.cpp
+SRCS += osdProcess.c
+SRCS += osdNetIntf.c
+SRCS += osdMessageQueue.c
+
+SRCS += devLibVME.c
+SRCS += devLibVMEOSD.c
+
+SRC_DIRS += $(LIBCOM)/taskwd
+INC += taskwd.h
+SRCS += taskwd.c
+
+SRC_DIRS += $(LIBCOM)/timer
+INC += epicsTimer.h
+SRCS += epicsTimer.cpp
+SRCS += timer.cpp
+SRCS += timerQueue.cpp
+SRCS += timerQueueActive.cpp
+SRCS += timerQueueActiveMgr.cpp
+SRCS += timerQueuePassive.cpp
+
+#tsDefs contains R3.13 compatibility tsStamp code
+SRC_DIRS += $(LIBCOM)/tsDefs
+INC += tsDefs.h
+SRCS += tsDefs.c
+
+# Time providers, in osi
+SRCS_vxWorks += osiNTPTime.c
+SRCS_RTEMS += osiNTPTime.c
+
+# These files are in osi/os/vxWorks
+# Special reboot hook
+SRCS_vxWorks += atReboot.cpp
+# For old vxWorks applications
+INC_vxWorks += camacLib.h
+INC_vxWorks += epicsDynLink.h
+INC_vxWorks += module_types.h
+INC_vxWorks += task_params.h
+SRCS_vxWorks += epicsDynLink.c
+SRCS_vxWorks += veclist.c
+SRCS_vxWorks += logMsgToErrlog.cpp
+
+#This forces the vxWorks compatibility stuff to be loaded
+OBJS_vxWorks = vxComLibrary
+
+# These files are in osi/os/WIN32
+INC_WIN32 += epicsAtomicMS.h
+SRCS_WIN32 += epicsGetopt.c 
+SRCS_WIN32 += setThreadName.cpp
+#SRCS_WIN32 += dllmain.cpp
+SRCS_WIN32 += forceBadAllocException.cpp
+
+#       Library to build:
+#       lib$(LIBRARY).a  or   ..dll/..exp/..lib
+#
+>>>>>>> MERGE-SOURCE
 LIBRARY=Com
 
 Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32

=== removed file 'src/libCom/misc/compilerDependencies.h'
--- src/libCom/misc/compilerDependencies.h	2011-06-20 18:52:32 +0000
+++ src/libCom/misc/compilerDependencies.h	1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
-
-/*************************************************************************\
-* 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
- * [email protected]
- */
-
-#ifndef compilerDependencies_h
-#define compilerDependencies_h
-
-/*
- * This is an attempt to move all tests identifying what features a 
- * compiler supports into one file.
- *
- * Since this is a compiler, and not os dependent, issue then ifdefs 
- * are used. The ifdefs allow us to make the default assumption that 
- * standards incompliance issues will be fixed by future compiler 
- * releases.
- */
-
-#ifdef __cplusplus
-
-/*
- * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
- * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
- */
-
-#if defined ( _MSC_VER )
-#   if _MSC_VER >= 1200  /* visual studio 6.0 or later */
-#       define CXX_PLACEMENT_DELETE
-#   endif
-#   if _MSC_VER > 1300  /* some release after visual studio 7 we hope */
-#       define CXX_THROW_SPECIFICATION
-#   endif
-#elif defined ( __HP_aCC ) 
-#   if _HP_aCC > 33300
-#       define CXX_PLACEMENT_DELETE
-#   endif
-#   define CXX_THROW_SPECIFICATION
-#elif defined ( __BORLANDC__ ) 
-#   if __BORLANDC__ >= 0x600
-#       define CXX_PLACEMENT_DELETE
-#   endif
-#   define CXX_THROW_SPECIFICATION
-#elif defined ( __GNUC__ ) 
-#   if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
-#       define CXX_THROW_SPECIFICATION
-#   endif
-#   if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
-#       define CXX_PLACEMENT_DELETE
-#   endif
-#else
-#   define CXX_PLACEMENT_DELETE
-#   define CXX_THROW_SPECIFICATION
-#endif
-
-/*
- * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
- */
-#if defined ( CXX_THROW_SPECIFICATION )
-#   define epicsThrows(X) throw X
-#else
-#   define epicsThrows(X)
-#endif
-
-/*
- * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
- */
-#if defined ( CXX_PLACEMENT_DELETE )
-#   define epicsPlacementDeleteOperator(X) void operator delete X;
-#else
-#   define epicsPlacementDeleteOperator(X)
-#endif
-
-#endif /* __cplusplus */
-
-/*
- * Enable format-string checking if possible
- */
-#ifdef __GNUC__
-# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
-#else
-# define EPICS_PRINTF_STYLE(f,a)
-#endif
-
-/*
- * Deprecation marker
- */
-#if defined( __GNUC__ ) && (__GNUC__ > 2)
-# define EPICS_DEPRECATED __attribute__((deprecated))
-#else
-# define EPICS_DEPRECATED
-#endif
-
-#endif  /* ifndef compilerDependencies_h */

=== modified file 'src/libCom/misc/ipAddrToAsciiAsynchronous.cpp'
--- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp	2008-10-21 20:26:48 +0000
+++ src/libCom/misc/ipAddrToAsciiAsynchronous.cpp	2011-08-31 22:29:24 +0000
@@ -127,7 +127,7 @@
 ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
 unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
 bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
-static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;
+static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
 
 // the users are not required to supply a show routine
 // for there transaction callback class

=== added directory 'src/libCom/osi/compiler'
=== added directory 'src/libCom/osi/compiler/borland'
=== added file 'src/libCom/osi/compiler/borland/compilerSpecific.h'
--- src/libCom/osi/compiler/borland/compilerSpecific.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/borland/compilerSpecific.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,55 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerSpecific_h
+#define compilerSpecific_h
+ 
+#ifndef __BORLANDC__
+#   error compiler/borland/compilerSpecific.h is only for use with the Borland compiler
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * in general we dont like ifdefs but they do allow us to check the
+ * compiler version and make the optimistic assumption that 
+ * standards incompliance issues will be fixed by future compiler 
+ * releases
+ */
+ 
+/*
+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
+ */
+#if __BORLANDC__ >= 0x600
+#    define CXX_PLACEMENT_DELETE
+#endif
+
+#define CXX_THROW_SPECIFICATION
+
+#endif /* __cplusplus */
+
+/*
+ * Enable format-string checking if possible
+ */
+#define EPICS_PRINTF_STYLE(f,a)
+
+/*
+ * Deprecation marker
+ */
+#define EPICS_DEPRECATED
+
+#endif  /* ifndef compilerSpecific_h */

=== added directory 'src/libCom/osi/compiler/clang'
=== added file 'src/libCom/osi/compiler/clang/compilerSpecific.h'
--- src/libCom/osi/compiler/clang/compilerSpecific.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/clang/compilerSpecific.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,59 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerSpecific_h
+#define compilerSpecific_h
+ 
+#ifndef __clang__
+#   error compiler/clang/compilerSpecific.h is only for use with the clang compiler
+#endif
+
+/*
+ * WARNING: the current state of this file is only based on reading clang manuals
+ * and has not actually been tested with the compiler
+ */
+#pragma warning compiler/clang/compilerSpecific.h is based on reading the manual, but hasnt been tested with the clang compiler
+
+#ifdef __cplusplus
+
+/*
+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
+ */
+#define CXX_PLACEMENT_DELETE
+#define CXX_THROW_SPECIFICATION
+
+#endif /* __cplusplus */
+
+/*
+ * Enable format-string checking if possible
+ */
+#if __has_attribute(format)
+#   define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
+#else
+#   define EPICS_PRINTF_STYLE
+#endif
+
+/*
+ * Deprecation marker if possible
+ */
+#if __has_attribute(deprecated)
+#   define EPICS_DEPRECATED __attribute__((deprecated))
+#else
+#   define EPICS_DEPRECATED
+#endif
+
+#endif  /* ifndef compilerSpecific_h */

=== added file 'src/libCom/osi/compiler/clang/epicsAtomicCD.h'
--- src/libCom/osi/compiler/clang/epicsAtomicCD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/clang/epicsAtomicCD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,27 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if defined ( __cplusplus )
+#   define EPICS_ATOMIC_INLINE inline
+#else
+#   define EPICS_ATOMIC_INLINE __inline__
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */

=== added directory 'src/libCom/osi/compiler/default'
=== added file 'src/libCom/osi/compiler/default/compilerSpecific.h'
--- src/libCom/osi/compiler/default/compilerSpecific.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/default/compilerSpecific.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,45 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerSpecific_h
+#define compilerSpecific_h
+ 
+#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 */
+
+/*
+ * Enable format-string checking if possible
+ * (our default guess is that the compiler doesnt implement non-standard extensions)
+ */
+#define EPICS_PRINTF_STYLE(f,a)
+
+/*
+ * Deprecation marker
+ * (our default guess is that the compiler doesnt implement non-standard extensions)
+ */
+#define EPICS_DEPRECATED
+
+#endif  /* ifndef compilerSpecific_h */

=== added file 'src/libCom/osi/compiler/default/epicsAtomicCD.h'
--- src/libCom/osi/compiler/default/epicsAtomicCD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/default/epicsAtomicCD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,25 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus )
+#   define EPICS_ATOMIC_INLINE inline
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */

=== added directory 'src/libCom/osi/compiler/gcc'
=== added file 'src/libCom/osi/compiler/gcc/compilerSpecific.h'
--- src/libCom/osi/compiler/gcc/compilerSpecific.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/gcc/compilerSpecific.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,62 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerSpecific_h
+#define compilerSpecific_h
+
+#ifndef __GNUC__
+#   error compiler/gcc/compilerSpecific.h is only for use with the gnu compiler
+#endif
+ 
+#ifdef __cplusplus
+
+/*
+ * in general we dont like ifdefs but they do allow us to check the
+ * compiler version and make the optimistic assumption that 
+ * standards incompliance issues will be fixed by future compiler 
+ * releases
+ */
+
+/*
+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
+ */
+
+#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
+#   define CXX_THROW_SPECIFICATION
+#endif
+
+#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
+#   define CXX_PLACEMENT_DELETE
+#endif
+
+#endif /* __cplusplus */
+
+/*
+ * Enable format-string checking if possible
+ */
+#define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
+
+/*
+ * Deprecation marker if possible
+ */
+#if  (__GNUC__ > 2)
+#   define EPICS_DEPRECATED __attribute__((deprecated))
+#else
+#   define EPICS_DEPRECATED
+#endif
+
+#endif  /* ifndef compilerSpecific_h */

=== added file 'src/libCom/osi/compiler/gcc/epicsAtomicCD.h'
--- src/libCom/osi/compiler/gcc/epicsAtomicCD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/gcc/epicsAtomicCD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,172 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#ifndef __GNUC__
+#   error this header is only for use with the gnu compiler
+#endif
+
+#define EPICS_ATOMIC_INLINE __inline__
+
+#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
+#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
+    GCC_ATOMIC_CONCAT ( \
+        __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
+        __SIZEOF_INT__ )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
+    GCC_ATOMIC_CONCAT ( \
+        __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
+        __SIZEOF_SIZE_T__ )
+        
+#define GCC_ATOMIC_INTRINSICS_MIN_X86 \
+    ( defined ( __i486 ) || defined ( __pentium ) || \
+    defined ( __pentiumpro ) || defined ( __MMX__ ) )
+    
+#define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \
+    ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \
+    ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \
+    GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+ * We are optimistic that __sync_synchronize is implemented
+ * in all version four gcc invarient of target. The gnu doc 
+ * seems to say that when not supported by architecture a call
+ * to an external function is generated but in practice
+ * this isnt the case for some of the atomic intrinsics, and 
+ * so there is an undefined symbol. So far we have not seen 
+ * that with __sync_synchronize, but we can only guess based
+ * on experimental evidence.
+ *
+ * For example we know that when generating object code for
+ * 386 most of the atomic instrinsics are not present and
+ * we see undefined symbols with mingw, but we dont have
+ * troubles with __sync_synchronize.
+ */
+#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
+{
+    __sync_synchronize ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
+{
+    __sync_synchronize ();
+}
+#endif
+
+#endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */
+
+#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
+    || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER 
+
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+    return __sync_add_and_fetch ( pTarget, 1 );
+}
+
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+    return __sync_sub_and_fetch ( pTarget, 1 );
+}
+
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+    return __sync_add_and_fetch ( pTarget, delta ); 
+}
+
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, 
+                                        int oldVal, int newVal )
+{
+    return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */
+
+#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
+    || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER 
+
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    return __sync_add_and_fetch ( pTarget, 1u );
+}
+
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    return __sync_sub_and_fetch ( pTarget, 1u );
+}
+
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+    return __sync_add_and_fetch ( pTarget, delta ); 
+}
+
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+    return __sync_sub_and_fetch ( pTarget, delta ); 
+}
+
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, 
+                                        size_t oldVal, size_t newVal )
+{
+    return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                            EpicsAtomicPtrT * pTarget, 
+                            EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+    return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+/*
+ * if currently unavailable as gcc intrinsics we
+ * will try for an os specific inline solution
+ */
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */

=== added directory 'src/libCom/osi/compiler/msvc'
=== added file 'src/libCom/osi/compiler/msvc/compilerSpecific.h'
--- src/libCom/osi/compiler/msvc/compilerSpecific.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/msvc/compilerSpecific.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,57 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerSpecific_h
+#define compilerSpecific_h
+ 
+#ifndef _MSC_VER
+#   error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * in general we dont like ifdefs but they do allow us to check the
+ * compiler version and make the optimistic assumption that 
+ * standards incompliance issues will be fixed by future compiler 
+ * releases
+ */
+ 
+/*
+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
+ */
+#if _MSC_VER >= 1200  /* visual studio 6.0 or later */
+#    define CXX_PLACEMENT_DELETE
+#endif
+
+#if _MSC_VER > 1300  /* some release after visual studio 7 we hope */
+#    define CXX_THROW_SPECIFICATION
+#endif
+
+#endif /* __cplusplus */
+
+/*
+ * Enable format-string checking if possible
+ */
+#define EPICS_PRINTF_STYLE(f,a)
+
+/*
+ * Deprecation marker
+ */
+#define EPICS_DEPRECATED
+
+#endif  /* ifndef compilerSpecific_h */

=== added file 'src/libCom/osi/compiler/msvc/epicsAtomicCD.h'
--- src/libCom/osi/compiler/msvc/epicsAtomicCD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/msvc/epicsAtomicCD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,124 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#include "epicsAssert.h"
+
+#ifndef _MSC_VER
+#   error this header file is only for use with with the Microsoft Compiler
+#endif
+
+#ifdef _MSC_EXTENSIONS
+
+#include <intrin.h>
+
+#if _MSC_VER >= 1200
+#   define EPICS_ATOMIC_INLINE __forceinline
+#else
+#   define EPICS_ATOMIC_INLINE __inline
+#endif
+
+#if defined ( _M_IX86 )
+#   pragma warning( push )
+#   pragma warning( disable : 4793 )
+    EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
+    {
+        long fence;
+        __asm { xchg fence, eax }
+    }
+#   pragma warning( pop )
+#elif defined ( _M_X64 )
+#   define MS_ATOMIC_64
+#   pragma intrinsic ( __faststorefence )
+    EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () 
+    { 
+        __faststorefence ();
+    }
+#elif defined ( _M_IA64 )
+#   define MS_ATOMIC_64
+#   pragma intrinsic ( __mf )
+    EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () 
+    { 
+        __mf (); 
+    }
+#else
+#   error unexpected target architecture, msvc version of epicsAtomicCD.h
+#endif
+
+/*
+ * The windows doc appears to recommend defining InterlockedExchange
+ * to be _InterlockedExchange to cause it to be an intrinsic, but that
+ * creates issues when later, in a windows os specific header, we include
+ * windows.h. Therefore, we except some code duplication between the msvc 
+ * csAtomic.h and win32 osdAtomic.h to avoid problems, and to keep the 
+ * os specific windows.h header file out of the msvc cdAtomic.h
+ */
+#define MS_LONG long
+#define MS_InterlockedExchange _InterlockedExchange
+#define MS_InterlockedCompareExchange _InterlockedCompareExchange
+#define MS_InterlockedIncrement _InterlockedIncrement 
+#define MS_InterlockedDecrement _InterlockedDecrement 
+#define MS_InterlockedExchange _InterlockedExchange
+#define MS_InterlockedExchangeAdd _InterlockedExchangeAdd
+#if defined ( MS_ATOMIC_64 ) 
+#   define MS_LONGLONG long long
+#   define MS_InterlockedIncrement64 _InterlockedIncrement64
+#   define MS_InterlockedDecrement64 _InterlockedDecrement64 
+#   define MS_InterlockedExchange64 _InterlockedExchange64 
+#   define MS_InterlockedExchangeAdd64 _InterlockedExchangeAdd64 
+#   define MS_InterlockedCompareExchange64 _InterlockedCompareExchange64
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
+{
+    epicsAtomicMemoryBarrier ();
+}
+
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
+{
+    epicsAtomicMemoryBarrier ();
+}
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#include "epicsAtomicMS.h"
+#include "epicsAtomicDefault.h"
+
+#else /* ifdef _MSC_EXTENSIONS */
+
+#if defined ( __cplusplus )
+#   define EPICS_ATOMIC_INLINE inline
+#endif
+
+/* 
+ * if unavailable as an intrinsic we will try
+ * for os specific solution
+ */
+#include "epicsAtomicOSD.h"
+
+#endif /* ifdef _MSC_EXTENSIONS */
+
+#endif /* epicsAtomicCD_h */
+

=== added directory 'src/libCom/osi/compiler/solStudio'
=== added file 'src/libCom/osi/compiler/solStudio/epicsAtomicCD.h'
--- src/libCom/osi/compiler/solStudio/epicsAtomicCD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/solStudio/epicsAtomicCD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,27 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if defined ( __cplusplus )
+#   define EPICS_ATOMIC_INLINE inline
+#else
+#   define EPICS_ATOMIC_INLINE __inline
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */

=== added file 'src/libCom/osi/compilerDependencies.h'
--- src/libCom/osi/compilerDependencies.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compilerDependencies.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,47 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef compilerDependencies_h
+#define compilerDependencies_h
+
+#include "compilerSpecific.h"
+
+#ifdef __cplusplus
+
+/*
+ * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
+ *
+ * Note: now a widely accepted concensus (ref Meyers and C++ faq) is that 
+ * one should avoid using throw specifications in C++ code
+ */
+#if defined ( CXX_THROW_SPECIFICATION )
+#   define epicsThrows(X) throw X
+#else
+#   define epicsThrows(X)
+#endif
+
+/*
+ * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
+ */
+#if defined ( CXX_PLACEMENT_DELETE )
+#   define epicsPlacementDeleteOperator(X) void operator delete X;
+#else
+#   define epicsPlacementDeleteOperator(X)
+#endif
+
+#endif /* __cplusplus */
+
+#endif  /* ifndef compilerDependencies_h */

=== added file 'src/libCom/osi/epicsAtomic.h'
--- src/libCom/osi/epicsAtomic.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsAtomic.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,237 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomic_h
+#define epicsAtomic_h
+
+#include <stdlib.h> /* define size_t */
+
+#include "shareLib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void * EpicsAtomicPtrT;
+
+/* load target into cache */
+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+
+/* push cache version of target into target */
+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, add one to target, flush cache 
+ * 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 );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, subtract one from target, flush cache 
+ * 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 );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, add/sub delta to/from target, flush cache 
+ * 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 );
+
+/*
+ * 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 );
+
+/*
+ * 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 );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, if target is equal to oldVal set target 
+ * to newVal, flush cache to target, allow other smp processors 
+ * to access the target, return the original value stored in the
+ * target
+ */
+epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, 
+                                            size_t oldVal, size_t newVal );
+epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget, 
+                                            int oldVal, int newVal );
+epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                                            EpicsAtomicPtrT * pTarget, 
+                                            EpicsAtomicPtrT oldVal, 
+                                            EpicsAtomicPtrT newVal );
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+/*
+ * options for inline compiler instrinsic or os specific 
+ * implementations of the above function prototypes
+ *
+ * its importnat for certaiin compiler to define the
+ * inline functions before they get used in the c++ 
+ * code below
+ */
+#include "epicsAtomicCD.h"
+
+#ifdef __cplusplus
+
+namespace epics {
+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 )
+{
+    return epicsAtomicIncrSizeT ( & v );
+}
+
+inline int increment ( int & v )
+{
+    return epicsAtomicIncrIntT ( & v );
+}
+
+/************* decr ***************/
+inline size_t decrement ( size_t & v )
+{
+    return epicsAtomicDecrSizeT ( & v );
+}
+
+inline int decrement ( int & v )
+{
+    return epicsAtomicDecrIntT ( & v );
+}
+
+/************* add ***************/
+inline size_t add ( size_t & v, size_t delta )
+{
+    return epicsAtomicAddSizeT ( & v, delta );
+}
+
+inline int add ( int & v, int delta )
+{
+    return epicsAtomicAddIntT ( & v, delta );
+}
+
+/************* sub ***************/
+inline size_t subtract ( size_t & v, size_t delta )
+{
+    return epicsAtomicSubSizeT ( & v, delta );
+}
+
+inline int subtract ( int & v, int delta )
+{
+    return epicsAtomicAddIntT ( & v, -delta );
+}
+
+/************* set ***************/
+inline void set ( size_t & v , size_t newValue ) 
+{ 
+    epicsAtomicSetSizeT  ( & v, newValue ); 
+}
+
+inline void set ( int & v, int newValue )
+{
+    epicsAtomicSetIntT ( & v, newValue );
+}
+
+inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
+{
+    epicsAtomicSetPtrT ( & v, newValue );
+}
+
+/************* get ***************/
+inline size_t get ( const size_t & v )
+{
+    return epicsAtomicGetSizeT ( & v );
+}
+
+inline int get ( const int & v )
+{
+    return epicsAtomicGetIntT ( & v );
+}
+
+inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
+{
+    return epicsAtomicGetPtrT ( & v );
+}
+
+/************* cas ***************/
+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 )
+{
+    return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal );
+}
+
+inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, 
+                                            EpicsAtomicPtrT oldVal, 
+                                            EpicsAtomicPtrT newVal )
+{
+    return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal );
+}
+
+} /* end of namespace atomic */
+} /* end of namespace epics */ 
+
+#endif /* ifdef __cplusplus */
+
+#endif /* epicsAtomic_h */

=== added file 'src/libCom/osi/epicsAtomicDefault.h'
--- src/libCom/osi/epicsAtomicDefault.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsAtomicDefault.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,235 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+ 
+#ifndef epicsAtomicDefault_h
+#define epicsAtomicDefault_h
+
+/* 
+ * EPICS_ATOMIC_INLINE might be defined, but empty for an out-of-line 
+ * instantiation
+ */
+#ifdef EPICS_ATOMIC_INLINE 
+
+#ifdef __cpluplus
+extern "C" {
+#endif
+
+/*
+ * struct EpicsAtomicLockKey;
+ * epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+ * epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+ * epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
+ * epicsShareFunc void epicsAtomicUnock ( struct EpicsAtomicLockKey * );
+ */
+
+/*
+ * incr 
+ */
+#ifndef EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+    EpicsAtomicLockKey key; 
+    epicsAtomicLock ( & key );
+    const int result = ++(*pTarget);
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const size_t result = ++(*pTarget);
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+/*
+ * decr 
+ */
+#ifndef EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const int result = --(*pTarget);
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const size_t result = --(*pTarget);
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+/*
+ * add/sub 
+ */
+#ifndef EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const int result = *pTarget += delta;
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const size_t result = *pTarget += delta;
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const size_t result = *pTarget -= delta;
+    epicsAtomicUnlock ( & key );
+    return result;
+}
+#endif
+
+/*
+ * set
+ */
+#ifndef EPICS_ATOMIC_SET_INTT
+EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newVal )
+{
+    *pTarget = newVal;
+    epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SET_SIZET
+EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal )
+{
+    *pTarget = newVal;
+    epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SET_PTRT
+EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, 
+						EpicsAtomicPtrT newVal )
+{
+    *pTarget = newVal;
+    epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+/*
+ * get 
+ */
+#ifndef EPICS_ATOMIC_GET_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget )
+{
+    epicsAtomicReadMemoryBarrier ();
+    return *pTarget;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_GET_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget )
+{
+    epicsAtomicReadMemoryBarrier ();
+    return *pTarget;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_GET_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT 
+        epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget )
+{
+    epicsAtomicReadMemoryBarrier ();
+    return *pTarget;
+}
+#endif
+
+/*
+ * cmp and swap 
+ */
+#ifndef EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldval, int newval )
+{
+    EpicsAtomicLockKey key; 
+    epicsAtomicLock ( & key );
+    const int cur = *pTarget;
+    if ( cur == oldval ) {
+        *pTarget = newval;
+    }
+    epicsAtomicUnlock ( & key );
+    return cur;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, 
+				size_t oldval, size_t newval )
+{
+    EpicsAtomicLockKey key; 
+    epicsAtomicLock ( & key );
+    const size_t cur = *pTarget;
+    if ( cur == oldval ) {
+        *pTarget = newval;
+    }
+    epicsAtomicUnlock ( & key );
+    return cur;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                            EpicsAtomicPtrT * pTarget, 
+                            EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval )
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key );
+    const EpicsAtomicPtrT cur = *pTarget;
+    if ( cur == oldval ) {
+        *pTarget = newval;
+    }
+    epicsAtomicUnlock ( & key );
+    return cur;
+}
+#endif
+
+#ifdef __cpluplus
+} /* end of extern "C" */
+#endif
+
+#endif /* EPICS_ATOMIC_INLINE */
+
+#endif /* epicsAtomicDefault_h */
+
+

=== modified file 'src/libCom/osi/epicsThread.h'
--- src/libCom/osi/epicsThread.h	2010-04-26 20:38:11 +0000
+++ src/libCom/osi/epicsThread.h	2011-08-31 22:29:24 +0000
@@ -51,7 +51,7 @@
 /* (epicsThreadId)0 is guaranteed to be an invalid thread id */
 typedef struct epicsThreadOSD *epicsThreadId;
 
-typedef epicsThreadId epicsThreadOnceId;
+typedef void * epicsThreadOnceId;
 #define EPICS_THREAD_ONCE_INIT 0
 
 epicsShareFunc void epicsShareAPI epicsThreadOnce(

=== added file 'src/libCom/osi/epicsThreadOnce.cpp'
--- src/libCom/osi/epicsThreadOnce.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsThreadOnce.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,129 @@
+
+/*************************************************************************\
+* Copyright (c) 2011 LANS LLC, as Operator of
+*     Los Alamos National Laboratory.
+* Copyright (c) 2011 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 [email protected]
+ *  Original Authors (before converting to operating system independent code): 
+ *                      Jeff Hill, Andrew Johnson, Marty Kraimer, Eric Norum
+ */
+
+#include <cstdlib>
+
+#define epicsExportSharedSymbols
+#include "errlog.h"
+#include "cantProceed.h"
+#include "epicsThread.h"
+#include "epicsAtomic.h"
+#include "epicsAssert.h"
+
+namespace {
+    
+struct ThreadID {
+public:
+    ThreadID ();
+    ThreadID ( epicsThreadId id );
+    bool operator == ( const ThreadID & ) const;
+private:
+    epicsThreadId m_threadId;
+    ThreadID ( const ThreadID & ); // disabled
+    ThreadID & operator = ( const ThreadID & ); // disabled
+};
+
+inline ThreadID :: ThreadID ( epicsThreadId id ) : 
+    m_threadId ( id ) 
+{
+}
+
+inline ThreadID :: ThreadID () : m_threadId ( 0 ) 
+{
+}
+
+inline bool ThreadID :: operator == ( const ThreadID & ctrl ) const
+{
+    return ctrl.m_threadId == m_threadId;
+}
+
+static ThreadID done;
+
+} // end of namespace annonymous
+
+using namespace epics;
+using namespace atomic;
+
+/*
+ * epicsThreadOnceOnly ()
+ */
+static void epicsShareAPI epicsThreadOnceOnly ( epicsThreadOnceId * pId, 
+                                                    void ( * pFunc )( void * ), 
+                                                    void * pArg )
+{
+    static const epicsThreadOnceId idStartup = EPICS_THREAD_ONCE_INIT;
+    ThreadID self ( epicsThreadGetIdSelf () );
+    epicsThreadOnceId pCurrent = compareAndSwap ( *pId, idStartup, & self );
+    if ( pCurrent != & done ) {
+        if ( pCurrent == idStartup ) {
+            ( *pFunc ) ( pArg );
+            set ( *pId, & done );
+        }
+        else {
+            {
+                ThreadID & initID = 
+                        * reinterpret_cast < ThreadID * > ( pCurrent );
+                if ( initID == self ) {
+                    cantProceed( "epicsThreadOnce() once was called "
+                                "recursively from the user's once fuction\n" );
+                }
+            }
+            static const std :: size_t spinDownInit = 1000u;
+            static const std :: size_t spinCount = 10u;
+            STATIC_ASSERT ( spinDownInit > spinCount );
+            static const std :: size_t spinThresh = spinDownInit - spinCount;
+            std :: size_t spinDown = spinDownInit;
+            do {
+                if ( spinDown <= spinThresh ) {
+                    epicsThreadSleep ( epicsThreadSleepQuantum () );
+                }
+                if ( spinDown > 0u ) {
+                    spinDown--;
+                }
+                else {
+                    errlogPrintf ( "epicsThreadOnce: waiting for another "
+                            "thread to finish calling the once function\n" );
+                    spinDown = spinThresh;
+                }
+                pCurrent = get ( *pId );
+            } while ( pCurrent != & done );
+        }
+    }
+}
+
+//
+// we implement this as a separate function so that it is easy to see
+// that the performance impact of the primary (most commonly used) path  
+// and that options for inlining this function are available (based on 
+// source code organization)
+//
+// performance might be slightly better if this were implemented as an inline
+// function, but that would pull epicsAtomic.h into epicsThread.h, and on
+// windows this includes (the lean and mean version of) windows.h, so perhaps 
+// its best to make this an out-of-line function as that type of instantiation 
+// will probably have only a small negative impact on performance
+//
+extern "C" void epicsShareAPI epicsThreadOnce ( epicsThreadOnceId * pId, 
+                                                void ( * pFunc )( void * ), 
+                                                void * pArg )
+{
+    const epicsThreadOnceId pCurrent = get ( *pId );
+    if ( pCurrent != & done ) {
+        epicsThreadOnceOnly ( pId, pFunc, pArg );
+    }
+}

=== modified file 'src/libCom/osi/os/RTEMS/osdThread.c'
--- src/libCom/osi/os/RTEMS/osdThread.c	2010-10-05 19:27:37 +0000
+++ src/libCom/osi/os/RTEMS/osdThread.c	2011-08-31 22:29:24 +0000
@@ -60,7 +60,6 @@
  * Support for `once-only' execution
  */
 static int initialized = 0;
-static epicsMutexId onceMutex;
 
 /*
  * Just map osi 0 to 99 into RTEMS 199 to 100
@@ -231,7 +230,6 @@
         rtems_task_priority old;
 
         rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
-        onceMutex = epicsMutexMustCreate();
         taskVarMutex = epicsMutexMustCreate ();
         rtems_task_ident (RTEMS_SELF, 0, &tid);
         setThreadInfo (tid, "_main_", NULL, NULL);
@@ -471,36 +469,6 @@
 }
 
 /*
- * Ensure func() is run only once.
- */
-void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
-{
-    #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
-
-    if (!initialized) epicsThreadInit();
-    epicsMutexMustLock(onceMutex);
-    if (*id != EPICS_THREAD_ONCE_DONE) {
-        if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
-            *id = epicsThreadGetIdSelf();    /* mark active */
-            epicsMutexUnlock(onceMutex);
-            func(arg);
-            epicsMutexMustLock(onceMutex);
-            *id = EPICS_THREAD_ONCE_DONE;    /* mark done */
-        } else if (*id == epicsThreadGetIdSelf()) {
-            epicsMutexUnlock(onceMutex);
-            cantProceed("Recursive epicsThreadOnce() initialization\n");
-        } else
-            while (*id != EPICS_THREAD_ONCE_DONE) {
-                /* Another thread is in the above func(arg) call. */
-                epicsMutexUnlock(onceMutex);
-                epicsThreadSleep(epicsThreadSleepQuantum());
-                epicsMutexMustLock(onceMutex);
-            }
-    }
-    epicsMutexUnlock(onceMutex);
-}
-
-/*
  * Thread private storage implementation based on the vxWorks
  * implementation by Andrew Johnson APS/ASD.
  */

=== added file 'src/libCom/osi/os/WIN32/epicsAtomicMS.h'
--- src/libCom/osi/os/WIN32/epicsAtomicMS.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicMS.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,222 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicMS_h
+#define epicsAtomicMS_h
+
+#include "epicsAssert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+    MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
+    return MS_InterlockedIncrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    return MS_InterlockedDecrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+    STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    /* we dont use InterlockedAdd because only latest windows is supported */
+    return delta + ( int ) MS_InterlockedExchangeAdd ( pTarg, 
+                                            ( MS_LONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, 
+                                            int oldVal, int newVal )
+{
+    STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    return (int) MS_InterlockedCompareExchange ( pTarg, 
+                                    (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#if ! defined ( MS_ATOMIC_64 )
+
+/*
+ * necessary for next three functions 
+ *
+ * looking at the MS documentation it appears that they will
+ * keep type long the same size as an int on 64 bit builds
+ */
+STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( size_t ) );
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
+    return MS_InterlockedIncrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    return MS_InterlockedDecrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, 
+                                                    size_t delta )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    /* we dont use InterlockedAdd because only latest windows is supported */
+    return delta + ( size_t ) MS_InterlockedExchangeAdd ( pTarg, 
+                                                 ( MS_LONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    MS_LONG ldelta = (MS_LONG) delta;
+    /* we dont use InterlockedAdd because only latest windows is supported */
+    return ( ( size_t ) MS_InterlockedExchangeAdd ( pTarg, -ldelta ) ) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( 
+                                    size_t * pTarget, 
+                                    size_t oldVal, size_t newVal )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    return (size_t) MS_InterlockedCompareExchange ( pTarg, 
+                                    (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                                    EpicsAtomicPtrT * pTarget, 
+                                    EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+    MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+    return (EpicsAtomicPtrT) MS_InterlockedCompareExchange ( pTarg, 
+                                    (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#else /* ! MS_ATOMIC_64 */
+
+/*
+ * necessary for next three functions 
+ */
+STATIC_ASSERT ( sizeof ( MS_LONGLONG ) == sizeof ( size_t ) );
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) pTarget;
+    return ( size_t ) MS_InterlockedIncrement64 ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+    return ( size_t ) MS_InterlockedDecrement64 ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+    /* we dont use InterlockedAdd64 because only latest windows is supported */
+    return delta + ( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, 
+                                        ( MS_LONGLONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+    MS_LONGLONG ldelta = (MS_LONGLONG) delta;
+    /* we dont use InterlockedAdd64 because only latest windows is supported */
+    return (( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, -ldelta )) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, 
+                                    size_t oldVal, size_t newVal )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+    return (size_t) MS_InterlockedCompareExchange64 ( pTarg, 
+                                    (MS_LONGLONG) newVal, 
+                                    (MS_LONGLONG) oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                            EpicsAtomicPtrT * pTarget, 
+                            EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+    MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+    return (EpicsAtomicPtrT) MS_InterlockedCompareExchange64 ( pTarg, 
+                                    (MS_LONGLONG) newVal, (MS_LONGLONG) oldVal );
+}
+#endif
+
+#endif /* ! MS_ATOMIC_64 */
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* ifdef epicsAtomicMS_h */
+

=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,22 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#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 "epicsAtomic.h"
+#endif
+

=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.h'
--- src/libCom/osi/os/WIN32/epicsAtomicOSD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,49 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#define VC_EXTRALEAN
+#define STRICT
+#include "windows.h"
+
+#if defined ( _WIN64 )
+#    define MS_ATOMIC_64
+#endif
+
+#define MS_LONG LONG 
+#define MS_InterlockedExchange InterlockedExchange
+#define MS_InterlockedCompareExchange InterlockedCompareExchange
+#define MS_InterlockedIncrement InterlockedIncrement 
+#define MS_InterlockedDecrement InterlockedDecrement 
+#define MS_InterlockedExchange InterlockedExchange
+#define MS_InterlockedExchangeAdd InterlockedExchangeAdd
+#if defined ( MS_ATOMIC_64 )
+#   define MS_LONGLONG LONGLONG 
+#   define MS_InterlockedIncrement64 InterlockedIncrement64
+#   define MS_InterlockedDecrement64 InterlockedDecrement64 
+#   define MS_InterlockedExchange64 InterlockedExchange64 
+#   define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64 
+#   define MS_InterlockedCompareExchange InterlockedCompareExchange64
+#endif
+
+#ifdef EPICS_ATOMIC_INLINE
+#    include "epicsAtomicMS.h"
+#    include "epicsAtomicDefault.h"
+#endif
+
+#endif /* epicsAtomicOSD_h */
+

=== modified file 'src/libCom/osi/os/WIN32/osdThread.c'
--- src/libCom/osi/os/WIN32/osdThread.c	2011-02-11 22:33:58 +0000
+++ src/libCom/osi/os/WIN32/osdThread.c	2011-08-31 22:29:24 +0000
@@ -1008,41 +1008,6 @@
 }
 
 /*
- * epicsThreadOnce ()
- */
-epicsShareFunc void epicsShareAPI epicsThreadOnce (
-    epicsThreadOnceId *id, void (*func)(void *), void *arg )
-{
-    static struct epicsThreadOSD threadOnceComplete;
-    #define EPICS_THREAD_ONCE_DONE & threadOnceComplete
-    win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
-
-    assert ( pGbl );
-    
-    EnterCriticalSection ( & pGbl->mutex );
-
-    if ( *id != EPICS_THREAD_ONCE_DONE ) {
-        if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */
-            *id = epicsThreadGetIdSelf();      /* mark active */
-            LeaveCriticalSection ( & pGbl->mutex );
-            func ( arg );
-            EnterCriticalSection ( & pGbl->mutex );
-            *id = EPICS_THREAD_ONCE_DONE;      /* mark done */
-        } else if ( *id == epicsThreadGetIdSelf() ) {
-            LeaveCriticalSection ( & pGbl->mutex );
-            cantProceed( "Recursive epicsThreadOnce() initialization\n" );
-        } else
-            while ( *id != EPICS_THREAD_ONCE_DONE ) {
-                /* Another thread is in the above func(arg) call. */
-                LeaveCriticalSection ( & pGbl->mutex );
-                epicsThreadSleep ( epicsThreadSleepQuantum() );
-                EnterCriticalSection ( & pGbl->mutex );
-            }
-    }
-    LeaveCriticalSection ( & pGbl->mutex );
-}
-
-/*
  * epicsThreadPrivateCreate ()
  */
 epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate ()

=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/posix/epicsAtomicOSD.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/posix/epicsAtomicOSD.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,108 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#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 "epicsAtomic.h"
+#endif
+
+/* Authors: Jeffrey O. Hill */
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#define epicsExportSharedSymbols
+#include "epicsAssert.h"
+
+// if the compiler is unable to inline then instantiate out-of-line
+#ifndef EPICS_ATOMIC_INLINE
+#define EPICS_ATOMIC_INLINE
+#include "epicsAtomic.h"
+#endif
+
+#ifndef EPICS_ATOMIC_LOCK
+
+/*
+ * Slow, but probably correct on all systems.
+ * Useful only if something more efficent isnt 
+ * provided based on knowledge of the compiler 
+ * or OS 
+ *
+ * A statically initialized pthread mutex doesnt 
+ * need to be destroyed 
+ * 
+ * !!!!!
+ * !!!!! WARNING 
+ * !!!!!
+ * !!!!! Do not use this implementation on systems where
+ * !!!!! code runs at interrupt context. If so, then 
+ * !!!!! an implementation must be provided that is based
+ * !!!!! on a compiler intrinsic or an interrpt lock and or
+ * !!!!! a spin lock primitive
+ * !!!!!
+ */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void epicsAtomicLock ( EpicsAtomicLockKey * )
+{
+    unsigned countDown = 1000u;
+    int status;
+    while ( true ) {
+        status = pthread_mutex_lock ( & mutex );
+        if ( status == 0 ) return;
+        assert ( status == EINTR );
+        static const useconds_t retryDelayUSec = 100000;
+        usleep ( retryDelayUSec );
+        countDown--;
+        assert ( countDown );
+    }
+}
+
+void epicsAtomicUnlock ( EpicsAtomicLockKey * )
+{
+    const int status = pthread_mutex_unlock ( & mutex );
+    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 efficent isnt 
+// provided based on knowledge of the compiler 
+// or OS 
+void epicsAtomicReadMemoryBarrier ()
+{
+    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 efficent isnt 
+// provided based on knowledge of the compiler 
+// or OS 
+void epicsAtomicWriteMemoryBarrier ()
+{
+    EpicsAtomicLockKey key;
+    epicsAtomicLock ( & key  );
+    epicsAtomicUnlock ( & key  );
+}
+#endif
+

=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.h'
--- src/libCom/osi/os/posix/epicsAtomicOSD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/posix/epicsAtomicOSD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,32 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+struct EpicsAtomicLockKey {};
+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
+epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * );
+
+#ifdef EPICS_ATOMIC_INLINE
+
+#include "epicsAtomicDefault.h"
+
+#endif /* ifdef EPICS_ATOMIC_INLINE */
+
+#endif /* epicsAtomicOSD_h */
+

=== modified file 'src/libCom/osi/os/posix/osdThread.c'
--- src/libCom/osi/os/posix/osdThread.c	2010-05-14 22:26:54 +0000
+++ src/libCom/osi/os/posix/osdThread.c	2011-08-31 22:29:24 +0000
@@ -76,7 +76,6 @@
 } epicsThreadOSD;
 
 static pthread_key_t getpthreadInfo;
-static pthread_mutex_t onceLock;
 static pthread_mutex_t listLock;
 static ELLLIST pthreadList = ELLLIST_INIT;
 static commonAttr *pcommonAttr = 0;
@@ -207,8 +206,6 @@
     int status;
 
     pthread_key_create(&getpthreadInfo,0);
-    status = pthread_mutex_init(&onceLock,0);
-    checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
     status = pthread_mutex_init(&listLock,0);
     checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
     pcommonAttr = calloc(1,sizeof(commonAttr));
@@ -321,47 +318,6 @@
 #endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
 }
 
-epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
-{
-    static struct epicsThreadOSD threadOnceComplete;
-    #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
-    int status;
-
-    epicsThreadInit();
-    status = mutexLock(&onceLock);
-    if(status) {
-        fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
-            strerror(status));
-        exit(-1);
-    }
-
-    if (*id != EPICS_THREAD_ONCE_DONE) {
-        if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
-            *id = epicsThreadGetIdSelf();    /* mark active */
-            status = pthread_mutex_unlock(&onceLock);
-            checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
-            func(arg);
-            status = mutexLock(&onceLock);
-            checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
-            *id = EPICS_THREAD_ONCE_DONE;    /* mark done */
-        } else if (*id == epicsThreadGetIdSelf()) {
-            status = pthread_mutex_unlock(&onceLock);
-            checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
-            cantProceed("Recursive epicsThreadOnce() initialization\n");
-        } else
-            while (*id != EPICS_THREAD_ONCE_DONE) {
-                /* Another thread is in the above func(arg) call. */
-                status = pthread_mutex_unlock(&onceLock);
-                checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
-                epicsThreadSleep(epicsThreadSleepQuantum());
-                status = mutexLock(&onceLock);
-                checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
-            }
-    }
-    status = pthread_mutex_unlock(&onceLock);
-    checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
-}
-
 epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
     unsigned int priority, unsigned int stackSize,
     EPICSTHREADFUNC funptr,void *parm)

=== added file 'src/libCom/osi/os/solaris/epicsAtomicOSD.h'
--- src/libCom/osi/os/solaris/epicsAtomicOSD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/solaris/epicsAtomicOSD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,166 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#if defined ( EPICS_ATOMIC_INLINE )
+
+/* 
+ * atomic.h exists only in Solaris 10 or higher
+ */
+#if defined ( __SunOS_5_10 )
+
+#include <atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE int epicsAtomicReadMemoryBarrier ()  
+{
+    membar_consumer ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE int epicsAtomicWriteMemoryBarrier ()  
+{
+    membar_producer ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, 
+                                               int oldVal, int newVal )
+{
+    STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) );
+    return ( int ) atomic_cas_uint ( pTarget, ( unsigned ) oldVal, 
+                                        ( unsigned ) newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapSizeT ( 
+                                                  size_t * pTarget,
+                                                  size_t oldVal, size_t newVal )
+{
+    STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+    void ** ppPtr = (void **) pTarget;
+    return ( size_t ) atomic_cas_ptr ( ppPtr, ( void * )oldVal, ( void * )newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( 
+                                       EpicsAtomicPtrT * pTarget, 
+                                       EpicsAtomicPtrT oldVal, 
+                                       EpicsAtomicPtrT newVal )
+{
+    return atomic_cas_ptr ( pTarget, oldVal, newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+    unsigned * const pTarg = ( unsigned * ) ( pTarget );
+    return ( int ) atomic_inc_uint_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+    void ** const ppTarg = ( void ** ) ( pTarget );
+    return ( size_t ) atomic_inc_ptr_nv ( ppTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+    unsigned * const pTarg = ( unsigned * ) ( pTarget );
+    return ( int ) atomic_dec_uint_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+    void ** const pTarg = ( void ** ) ( pTarget );
+    return ( size_t ) atomic_dec_ptr_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+    STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+    unsigned * const pTarg = ( unsigned * ) ( pTarget );
+    return ( int ) atomic_add_int_nv ( pTarg, delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, 
+                                                 size_t delta )
+{
+    STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+    void ** const pTarg = ( void ** ) ( pTarget );
+    return ( size_t ) atomic_add_ptr_nv ( pTarg, ( ssize_t ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, 
+                                                 size_t delta )
+{
+    STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+    void ** const pTarg = ( void ** ) ( pTarget );
+    ssize_t = sdelta = ( ssize_t ) delta;
+    return ( size_t ) atomic_add_ptr_nv ( pTarg, -sdelta );
+}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* ifdef __SunOS_5_10 */
+
+#include "epicsAtomicDefault.h"
+
+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
+
+#endif /* epicsAtomicOSD_h */
+

=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,22 @@
+
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#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 "epicsAtomic.h"
+#endif
+

=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.h'
--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.h	1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.h	2011-08-31 22:29:24 +0000
@@ -0,0 +1,255 @@
+/*************************************************************************\
+* 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
+ *  [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#if defined ( EPICS_ATOMIC_INLINE )
+
+#include "vxWorks.h" /* obtain the version of vxWorks */
+#include "epicsAssert.h"
+
+/*
+ * With vxWorks 6.6 and later we need to use vxAtomicLib
+ * to implement this functionality correctly on SMP systems
+ */
+#if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606
+
+#include <limits.h>
+#include <vxAtomicLib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () 
+{
+    VX_MEM_BARRIER_R ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () 
+{
+    VX_MEM_BARRIER_W ();
+}
+#endif
+
+/*
+ * we make the probably correct guess that if ULONG_MAX 
+ * is the same as UINT_MAX then sizeof ( atomic_t )
+ * will be the same as sizeof ( size_t )
+ *
+ * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and
+ * WRS doesnt not supply at this time the atomic interface 
+ * for 8 byte integers that is needed - so that architecture 
+ * receives the lock synchronized version
+ */
+#if ULONG_MAX == UINT_MAX
+
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) );
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) );
+
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicInc ( pTarg );
+    return 1 + ( size_t ) ( oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicDec ( pTarg );
+    return ( ( size_t ) oldVal ) - 1u;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+    /* 
+     * vxAtomicLib doc indicates that vxAtomicAdd is 
+     * implemented using signed arithmetic, but it
+     * does not change the end result because twos
+     * complement addition is used in either case
+     */
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
+    return delta + ( size_t ) oldVal;
+} 
+#endif 
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+    /* 
+     * vxAtomicLib doc indicates that vxAtomicSub is 
+     * implemented using signed arithmetic, but it
+     * does not change the end result because twos
+     * complement subtraction is used in either case
+     */
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta );
+    return ( ( size_t ) oldVal ) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, 
+                            size_t oldVal, size_t newVal )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, 
+                            EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#else /* ULONG_MAX == UINT_MAX */
+
+/*
+ * if its 64 bit SMP vxWorks and the compiler doesnt
+ * have an intrinsic then maybe there isnt any way to 
+ * implement these without using a global lock because 
+ * size_t is maybe bigger than atomic_t
+ *
+ * I dont yet have access to vxWorks manuals for 
+ * 64 bit systems so this is still undecided, but is
+ * defaulting now to a global lock
+ */
+
+#endif /* ULONG_MAX == UINT_MAX */
+
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) );
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicInc ( pTarg );
+    return 1 + ( int ) oldVal;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicDec ( pTarg );
+    return ( ( int ) oldVal ) - 1;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
+    return delta + ( int ) oldVal;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, 
+                                            int oldVal, int newVal )
+{
+    atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+    return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
+
+#include "vxLib.h"
+#include "intLib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_LOCK
+#define EPICS_ATOMIC_LOCK
+
+typedef struct EpicsAtomicLockKey { int m_key; } EpicsAtomicLockKey;
+
+EPICS_ATOMIC_INLINE void epicsAtomicLock ( EpicsAtomicLockKey * pKey )
+{
+    pKey->m_key = intLock ();
+}
+
+EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey )
+{
+    intUnlock ( pKey->m_key );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+/* 
+ * 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 () {}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+/* 
+ * 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 () {}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
+
+#include "epicsAtomicDefault.h"
+
+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
+
+#endif /* epicsAtomicOSD_h */
+

=== modified file 'src/libCom/osi/os/vxWorks/osdThread.c'
--- src/libCom/osi/os/vxWorks/osdThread.c	2010-08-11 15:45:17 +0000
+++ src/libCom/osi/os/vxWorks/osdThread.c	2011-08-31 22:29:24 +0000
@@ -53,7 +53,6 @@
 static void **papTSD = 0;
 static int nepicsThreadPrivate = 0;
 
-static SEM_ID epicsThreadOnceMutex = 0;
 
 /* Just map osi 0 to 99 into vx 100 to 199 */
 /* remember that for vxWorks lower number means higher priority */
@@ -83,19 +82,6 @@
     }
 }
 
-static void epicsThreadInit(void)
-{
-    static int lock = 0;
-
-    while(!vxTas(&lock)) taskDelay(1);
-    if(epicsThreadOnceMutex==0) {
-        epicsThreadOnceMutex = semMCreate(
-                SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
-        assert(epicsThreadOnceMutex);
-    }
-    lock = 0;
-}
-
 unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) 
 {
 
@@ -112,43 +98,6 @@
     return stackSizeTable[stackSizeClass];
 }
 
-struct epicsThreadOSD {};
-    /* Strictly speaking this should be a WIND_TCB, but we only need it to
-     * be able to create an epicsThreadId that is guaranteed never to be
-     * the same as any current TID, and since TIDs are pointers this works.
-     */
-
-void epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
-{
-    static struct epicsThreadOSD threadOnceComplete;
-    #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
-    int result;
-
-    epicsThreadInit();
-    result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
-    assert(result == OK);
-    if (*id != EPICS_THREAD_ONCE_DONE) {
-        if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
-            *id = epicsThreadGetIdSelf();    /* mark active */
-            semGive(epicsThreadOnceMutex);
-            func(arg);
-            result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
-            assert(result == OK);
-            *id = EPICS_THREAD_ONCE_DONE;    /* mark done */
-        } else if (*id == epicsThreadGetIdSelf()) {
-            semGive(epicsThreadOnceMutex);
-            cantProceed("Recursive epicsThreadOnce() initialization\n");
-        } else
-            while (*id != EPICS_THREAD_ONCE_DONE) {
-                /* Another thread is in the above func(arg) call. */
-                semGive(epicsThreadOnceMutex);
-                epicsThreadSleep(epicsThreadSleepQuantum());
-                result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
-                assert(result == OK);
-            }
-    }
-    semGive(epicsThreadOnceMutex);
-}
 
 static void createFunction(EPICSTHREADFUNC func, void *parm)
 {
@@ -173,7 +122,6 @@
     EPICSTHREADFUNC funptr,void *parm)
 {
     int tid;
-    if(epicsThreadOnceMutex==0) epicsThreadInit();
     if(stackSize<100) {
         errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);
         return(0);
@@ -343,7 +291,6 @@
     static int lock = 0;
     epicsThreadPrivateId id;
 
-    epicsThreadInit();
     /*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/
     while(!vxTas(&lock)) taskDelay(1);
     id = (epicsThreadPrivateId)++nepicsThreadPrivate;

=== modified file 'src/libCom/test/Makefile'
--- src/libCom/test/Makefile	2011-08-30 23:09:11 +0000
+++ src/libCom/test/Makefile	2011-08-31 22:29:24 +0000
@@ -108,6 +108,11 @@
 testHarness_SRCS += epicsMutexTest.cpp
 TESTS += epicsMutexTest
 
+TESTPROD_HOST += epicsAtomicTest
+epicsAtomicTest_SRCS += epicsAtomicTest.c
+testHarness_SRCS += epicsAtomicTest.c
+TESTS += epicsAtomicTest
+
 TESTPROD_HOST += epicsExceptionTest
 epicsExceptionTest_SRCS += epicsExceptionTest.cpp
 testHarness_SRCS += epicsExceptionTest.cpp
@@ -178,6 +183,10 @@
 fdmgrTest_LIBS += ca
 # FIXME: program never exits.
 
+TESTPROD_HOST += epicsAtomicPerform
+epicsAtomicPerform_SRCS += epicsAtomicPerform.cpp
+testHarness_SRCS += epicsAtomicPerform.cpp
+
 TESTPROD_HOST += cvtFastPerform
 cvtFastPerform_SRCS += cvtFastPerform.cpp
 testHarness_SRCS += cvtFastPerform.cpp

=== added file 'src/libCom/test/epicsAtomicPerform.cpp'
--- src/libCom/test/epicsAtomicPerform.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/test/epicsAtomicPerform.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,506 @@
+
+#include <cstdlib>
+#include <cstdio>
+#include <cassert>
+#include <typeinfo>
+
+#include "epicsInterrupt.h"
+#include "epicsAtomic.h"
+#include "epicsTime.h"
+#include "epicsUnitTest.h"
+#include "testMain.h"
+
+using std :: size_t;
+using namespace epics; 
+using namespace atomic;
+
+class RefCtr {
+public:
+    RefCtr ();
+    ~RefCtr ();
+    void reference ();
+    void unreference ();
+private:
+    size_t m_cnt;
+};
+
+class Ownership {
+public:
+    Ownership ();
+    Ownership ( RefCtr & refCtr );
+    Ownership ( const Ownership & );
+    ~Ownership ();
+    Ownership & operator = ( const Ownership & );
+private:
+    RefCtr * _pRefCtr;
+    static RefCtr m_noOwnership;
+};
+
+inline RefCtr :: RefCtr () 
+{
+    epicsAtomicSetSizeT ( & m_cnt, 0 );
+}
+
+inline RefCtr :: ~RefCtr () 
+{ 
+    unsigned cnt = epicsAtomicGetSizeT ( & m_cnt );
+    assert ( cnt == 0u ); 
+}
+
+inline void RefCtr :: reference () 
+{ 
+    epicsAtomicIncrSizeT ( & m_cnt ); 
+}
+
+inline void RefCtr :: unreference () 
+{ 
+    epicsAtomicDecrSizeT ( & m_cnt ); 
+}
+
+RefCtr Ownership :: m_noOwnership;
+
+inline Ownership :: Ownership () : 
+    _pRefCtr ( & m_noOwnership ) 
+{
+    m_noOwnership.reference ();
+}
+
+inline Ownership :: Ownership ( RefCtr & refCtr ) : 
+    _pRefCtr ( & refCtr ) 
+{ 
+    refCtr.reference (); 
+} 
+
+inline Ownership :: Ownership ( const Ownership & ownership ) : 
+    _pRefCtr ( ownership._pRefCtr ) 
+{ 
+    _pRefCtr->reference (); 
+} 
+
+inline Ownership :: ~Ownership () 
+{ 
+    _pRefCtr->unreference (); 
+} 
+
+inline Ownership & Ownership ::
+    operator = ( const Ownership & ownership )
+{
+    RefCtr * const pOldRefCtr = _pRefCtr;
+    _pRefCtr = ownership._pRefCtr;
+    _pRefCtr->reference (); 
+    pOldRefCtr->unreference (); 
+    return *this;
+}
+
+inline Ownership retOwnership ( const Ownership & ownership )
+{
+    return Ownership ( ownership );
+}
+
+inline Ownership recurRetOwner10 ( const Ownership & ownershipIn )
+{
+    Ownership ownership = 
+        retOwnership ( 
+            retOwnership ( 
+                retOwnership ( 
+                    retOwnership ( 
+                        retOwnership ( ownershipIn ) ) ) ) );
+    return retOwnership ( 
+                retOwnership ( 
+                    retOwnership ( 
+                        retOwnership ( 
+                            retOwnership ( ownership ) ) ) ) );
+}
+
+inline Ownership recurRetOwner100 ( const Ownership & ownershipIn )
+{
+    Ownership ownership = 
+            recurRetOwner10 ( 
+                recurRetOwner10 ( 
+                    recurRetOwner10 ( 
+                        recurRetOwner10 ( 
+                            recurRetOwner10 ( ownershipIn ) ) ) ) );
+    return recurRetOwner10 ( 
+            recurRetOwner10 ( 
+                recurRetOwner10 ( 
+                    recurRetOwner10 ( 
+                        recurRetOwner10 ( ownership ) ) ) ) );
+}
+
+inline Ownership recurRetOwner1000 ( const Ownership & ownershipIn )
+{
+    Ownership ownership = 
+            recurRetOwner100 ( 
+                recurRetOwner100 ( 
+                    recurRetOwner100 ( 
+                        recurRetOwner100 ( 
+                            recurRetOwner100 ( ownershipIn ) ) ) ) );
+    return recurRetOwner100 ( 
+            recurRetOwner100 ( 
+                recurRetOwner100 (
+                    recurRetOwner100 ( 
+                        recurRetOwner100 ( ownership ) ) ) ) );
+}
+
+inline void passRefOwnership ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+    ownershipOut = ownershipIn;
+}
+
+inline void passRefOwnership10 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+    Ownership ownershipTmp0;
+    passRefOwnership ( ownershipIn,  ownershipTmp0 );
+    Ownership ownershipTmp1;
+    passRefOwnership ( ownershipTmp0, ownershipTmp1 );
+    Ownership ownershipTmp2;
+    passRefOwnership ( ownershipTmp1, ownershipTmp2 );
+    Ownership ownershipTmp3; 
+    passRefOwnership ( ownershipTmp2, ownershipTmp3 );
+    Ownership ownershipTmp4;
+    passRefOwnership ( ownershipTmp3, ownershipTmp4 );
+    Ownership ownershipTmp5;
+    passRefOwnership ( ownershipTmp4, ownershipTmp5 );
+    Ownership ownershipTmp6; 
+    passRefOwnership ( ownershipTmp5, ownershipTmp6 );
+    Ownership ownershipTmp7;
+    passRefOwnership ( ownershipTmp6, ownershipTmp7 );
+    Ownership ownershipTmp8;
+    passRefOwnership ( ownershipTmp7, ownershipTmp8 );
+    passRefOwnership ( ownershipTmp8, ownershipOut );
+}
+
+inline void passRefOwnership100 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+    Ownership ownershipTmp0;
+    passRefOwnership10 ( ownershipIn,  ownershipTmp0 );
+    Ownership ownershipTmp1;
+    passRefOwnership10 ( ownershipTmp0, ownershipTmp1 );
+    Ownership ownershipTmp2;
+    passRefOwnership10 ( ownershipTmp1, ownershipTmp2 );
+    Ownership ownershipTmp3; 
+    passRefOwnership10 ( ownershipTmp2, ownershipTmp3 );
+    Ownership ownershipTmp4;
+    passRefOwnership10 ( ownershipTmp3, ownershipTmp4 );
+    Ownership ownershipTmp5;
+    passRefOwnership10 ( ownershipTmp4, ownershipTmp5 );
+    Ownership ownershipTmp6; 
+    passRefOwnership10 ( ownershipTmp5, ownershipTmp6 );
+    Ownership ownershipTmp7;
+    passRefOwnership10 ( ownershipTmp6, ownershipTmp7 );
+    Ownership ownershipTmp8;
+    passRefOwnership10 ( ownershipTmp7, ownershipTmp8 );
+    passRefOwnership10 ( ownershipTmp8, ownershipOut );
+}
+
+inline void passRefOwnership1000 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+    Ownership ownershipTmp0;
+    passRefOwnership100 ( ownershipIn,  ownershipTmp0 );
+    Ownership ownershipTmp1;
+    passRefOwnership100 ( ownershipTmp0, ownershipTmp1 );
+    Ownership ownershipTmp2;
+    passRefOwnership100 ( ownershipTmp1, ownershipTmp2 );
+    Ownership ownershipTmp3; 
+    passRefOwnership100 ( ownershipTmp2, ownershipTmp3 );
+    Ownership ownershipTmp4;
+    passRefOwnership100 ( ownershipTmp3, ownershipTmp4 );
+    Ownership ownershipTmp5;
+    passRefOwnership100 ( ownershipTmp4, ownershipTmp5 );
+    Ownership ownershipTmp6; 
+    passRefOwnership100 ( ownershipTmp5, ownershipTmp6 );
+    Ownership ownershipTmp7;
+    passRefOwnership100 ( ownershipTmp6, ownershipTmp7 );
+    Ownership ownershipTmp8;
+    passRefOwnership100 ( ownershipTmp7, ownershipTmp8 );
+    passRefOwnership100 ( ownershipTmp8, ownershipOut );
+}
+
+time_t extTime = 0;
+
+template < class T >
+class OrdinaryIncr {
+public:
+    OrdinaryIncr () : m_target ( 0 ) {}
+    void run ();
+    void diagnostic ( double delay );
+private:	
+    T m_target;
+};
+
+// tests the time it takes to perform a call to an external 
+// function and also increment an integer word. The 
+// epicsInterruptIsInterruptContext function is an 
+// out-of-line function implemented in a sharable library 
+// so hopefully it wont be optimized away.
+template < class T >
+inline void OrdinaryIncr < T > :: run ()
+{
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+    m_target += epicsInterruptIsInterruptContext ();
+}
+
+template < class T >
+void OrdinaryIncr < T > :: diagnostic ( double delay )
+{
+    delay /= 10.0;
+    delay *= 1e6;
+    const char * const pName = typeid ( T ) . name ();
+    testDiag ( "raw incr of \"%s\" and a NOOP function call takes %f microseconds", 
+                         pName, delay );
+}
+
+template < class T >
+class AtomicIncr {
+public:
+    AtomicIncr () : m_target ( 0 ) {}
+    void run ();
+    void diagnostic ( double delay );
+private:	
+    T m_target;
+};
+
+template < class T >
+inline void AtomicIncr < T > :: run ()
+{
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+    increment ( m_target );
+}
+
+template < class T >
+void AtomicIncr < T > :: diagnostic ( double delay )
+{
+    delay /= 10.0;
+    delay *= 1e6;
+    const char * const pName = typeid ( T ) . name ();
+    testDiag ( "epicsAtomicIncr \"%s\" takes %f microseconds", 
+                        pName, delay );
+}
+
+template < class T > T trueValue ();
+template < class T > T falseValue ();
+
+// int
+template <>
+inline int trueValue < int > () { return 1; }
+
+template <>
+inline int falseValue < int > () { return 0; }
+
+// size_t 
+template <>
+inline size_t trueValue < size_t > () { return 1u; }
+
+template <>
+inline size_t falseValue < size_t > () { return 0u; }
+
+// EpicsAtomicPtrT
+template <>
+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > () 
+{ static char c; return & c; }
+
+template <>
+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > () 
+{ return 0u; }
+
+template < class T >
+class AtomicCmpAndSwap {
+public:
+    AtomicCmpAndSwap () : m_target ( 0 ) {}
+    void run ();
+    void diagnostic ( double delay );
+private:	
+    T m_target;
+};
+
+template < class T >
+inline void AtomicCmpAndSwap < T > :: run ()
+{
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+    compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+}
+
+template < class T >
+void AtomicCmpAndSwap < T > :: diagnostic ( double delay )
+{
+    delay /= 10.0;
+    delay *= 1e6;
+    const char * const pName = typeid ( T ) . name ();
+    testDiag ( "epicsAtomicCmpAndSwap of \"%s\" takes %f microseconds", 
+                         pName, delay );
+}
+
+template < class T >
+class AtomicSet {
+public:
+    AtomicSet () : m_target ( 0 ) {}
+    void run ();
+    void diagnostic ( double delay );
+private:	
+    T m_target;
+};
+
+template < class T >
+inline void AtomicSet < T > :: run ()
+{
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+    set ( m_target, 0 );
+}
+
+template < class T >
+void AtomicSet < T > :: diagnostic ( double delay )
+{
+    delay /= 10.0;
+    delay *= 1e6;
+    const char * const pName = typeid ( T ) . name ();
+    testDiag ( "epicsAtomicSet of \"%s\" takes %f microseconds", 
+		    pName, delay );
+}
+
+static const unsigned N = 10000;
+
+void recursiveOwnershipRetPerformance ()
+{
+    RefCtr refCtr;
+    epicsTime begin = epicsTime::getCurrent ();
+    for ( size_t i = 0; i < N; i++ ) {
+        Ownership ownership ( refCtr );
+        recurRetOwner1000 ( ownership );
+    }
+    double delay = epicsTime::getCurrent () -  begin;
+    delay /= N * 1000u; // convert to delay per call
+    delay *= 1e6; // convert to micro seconds
+    testDiag ( "retOwnership() takes %f microseconds", delay );
+}
+
+void ownershipPassRefPerformance ()
+{
+    RefCtr refCtr;
+    epicsTime begin = epicsTime::getCurrent ();
+    for ( size_t i = 0; i < N; i++ ) {
+        Ownership ownershipSrc ( refCtr );
+        Ownership ownershipDest;
+        passRefOwnership1000 ( ownershipSrc, ownershipDest );
+    }
+    double delay = epicsTime::getCurrent () -  begin;
+    delay /= N * 1000u; // convert to delay per call
+    delay *= 1e6; // convert to micro seconds
+    testDiag ( "passRefOwnership() takes %f microseconds", delay );
+}
+
+template < class T >
+class Ten 
+{
+public:
+    void run ();
+    void diagnostic ( double delay );
+    typedef Ten < Ten < T > > Hundred;
+    typedef Ten < Hundred > Thousand;
+private:
+    T m_target;
+};
+
+template < class T >
+inline void Ten < T > :: run ()
+{
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+    m_target.run ();
+}
+
+template < class T >
+void Ten < T > :: diagnostic ( double delay )
+{
+    m_target.diagnostic ( delay / 10.0 );
+}
+
+template < class T >
+void measurePerformance ()
+{
+    epicsTime begin = epicsTime::getCurrent ();
+    T target;
+    for ( size_t i = 0; i < N; i++ ) {
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+        target.run ();
+    }
+    double delay = epicsTime::getCurrent () -  begin;
+    delay /= ( N * 10u ); // convert to delay per call
+    target.diagnostic ( delay );
+}
+
+template < class T > 
+void measure ()
+{
+    measurePerformance < typename Ten < T > :: Hundred > ();
+}
+
+MAIN ( epicsAtomicPerform )
+{
+    testPlan ( 0 );
+    //
+    // The tests running here are measuring fast
+    // functions so they tend to be impacted
+    // by where the cache lines are wrt to the
+    // virtual pages perhap
+    //
+    measure < AtomicSet < int > > ();
+    measure < AtomicSet < size_t > > ();
+    measure < AtomicSet < void * > > ();
+    measure < OrdinaryIncr < int > > ();
+    measure < OrdinaryIncr < size_t > > ();
+    measure < AtomicIncr < int > > ();
+    measure < AtomicIncr < size_t > > ();
+    measure < AtomicCmpAndSwap < int > > ();
+    measure < AtomicCmpAndSwap < size_t > > ();
+    measure < AtomicCmpAndSwap < void * > > ();
+    recursiveOwnershipRetPerformance ();
+    ownershipPassRefPerformance ();
+    return testDone();
+}

=== added file 'src/libCom/test/epicsAtomicTest.cpp'
--- src/libCom/test/epicsAtomicTest.cpp	1970-01-01 00:00:00 +0000
+++ src/libCom/test/epicsAtomicTest.cpp	2011-08-31 22:29:24 +0000
@@ -0,0 +1,238 @@
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "epicsAtomic.h"
+#include "epicsTime.h"
+#include "epicsThread.h"
+#include "epicsUnitTest.h"
+#include "testMain.h"
+
+using namespace epics;
+using namespace atomic;
+
+template < class T >
+struct TestDataIncrDecr {
+    T m_testValue;
+    size_t m_testIterations;
+};
+
+template < class T >
+struct TestDataAddSub {
+    T m_testValue;
+    size_t m_testIterations;
+    static const T delta = 17;
+};
+
+template < class T >
+static void incr ( void *arg )
+{
+    TestDataIncrDecr < T > * const pTestData = 
+	    reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
+    increment ( pTestData->m_testValue );
+    increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+static void decr ( void *arg )
+{
+    TestDataIncrDecr < T > * const pTestData = 
+	    reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
+    decrement ( pTestData->m_testValue );
+    increment ( pTestData->m_testIterations );
+}
+
+
+template < class T >
+static void add ( void *arg )
+{
+    TestDataAddSub < T > * const pTestData = 
+	    reinterpret_cast < TestDataAddSub < T > * > ( arg );
+    add ( pTestData->m_testValue, TestDataAddSub < T > :: delta  );
+    increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+static void sub ( void *arg )
+{
+    TestDataAddSub < T > * const pTestData = 
+	    reinterpret_cast < TestDataAddSub < T > * > ( arg );
+    subtract ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
+    increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+struct TestDataCAS {
+    T m_testValue;
+    size_t m_testIterationsSet;
+    size_t m_testIterationsNotSet;
+};
+
+int isModulo ( size_t N, size_t n ) 
+{
+    return ( n % N ) == 0u;
+}
+
+template < class T >
+static T trueValue ();
+template < class T >
+static T falseValue ();
+
+// int
+template <>
+inline int trueValue < int > () { return 1; }
+
+template <>
+inline int falseValue < int > () { return 0; }
+
+// size_t 
+template <>
+inline size_t trueValue < size_t > () { return 1u; }
+
+template <>
+inline size_t falseValue < size_t > () { return 0u; }
+
+// EpicsAtomicPtrT
+template <>
+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > () 
+{ static char c; return & c; }
+
+template <>
+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > () 
+{ return 0u; }
+
+template < class T >
+static void cas ( void *arg )
+{
+    TestDataCAS < T > * const pTestData = 
+	    reinterpret_cast < TestDataCAS < T > * > ( arg );
+    /*
+     * intentionally waste cpu and maximize
+     * contention for the shared data
+     */
+    increment ( pTestData->m_testIterationsNotSet );
+    while ( ! compareAndSwap ( pTestData->m_testValue, 
+                                        falseValue < T > (), 
+                                        trueValue < T > () ) ) {
+    }
+    decrement ( pTestData->m_testIterationsNotSet );
+    set ( pTestData->m_testValue, falseValue < T > () );
+    increment ( pTestData->m_testIterationsSet );
+}
+
+template < class T >
+void testIncrDecr ()
+{
+    static const size_t N = 100;
+    static const T NT = static_cast < T > ( N );
+
+    const unsigned int stackSize = 
+        epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+    TestDataIncrDecr < T > testData = { 0, N };
+    set ( testData.m_testValue, NT  );
+    testOk ( get ( testData.m_testValue ) == NT,
+	    "set/get %u", testData.m_testValue );
+    set ( testData.m_testIterations, 0u );
+    testOk ( get ( testData.m_testIterations ) == 0u,
+	    "set/get %u", testData.m_testIterations );
+    for ( size_t i = 0u; i < N; i++ ) {
+        epicsThreadCreate ( "incr",
+		    50, stackSize, incr < T >, & testData );
+        epicsThreadCreate ( "decr",
+		    50, stackSize, decr < T >, & testData );
+    }
+    while ( testData.m_testIterations < 2 * N ) {
+        epicsThreadSleep ( 0.01 );
+    }
+    testOk ( get ( testData.m_testIterations ) == 2 * N,
+	    "incr/decr iterations %u", 
+	    testData.m_testIterations );
+    testOk ( get ( testData.m_testValue ) == NT, 
+	    "incr/decr final value %u", 
+	    testData.m_testValue );
+}
+
+template < class T >
+void testAddSub ()
+{
+    static const size_t N = 100;
+    static const T NDT = TestDataAddSub < T > :: delta *
+	    				static_cast < T > ( N );
+
+    const unsigned int stackSize = 
+        epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+    TestDataIncrDecr < T > testData = { 0, N };
+    set ( testData.m_testValue, NDT  );
+    testOk ( get ( testData.m_testValue ) == NDT,
+	    "set/get %u", testData.m_testValue );
+    set ( testData.m_testIterations, 0u );
+    testOk ( get ( testData.m_testIterations ) == 0u,
+	    "set/get %u", testData.m_testIterations );
+    for ( size_t i = 0u; i < N; i++ ) {
+        epicsThreadCreate ( "add",
+		    50, stackSize, add < T >, & testData );
+        epicsThreadCreate ( "sub",
+		    50, stackSize, sub < T >, & testData );
+    }
+    while ( testData.m_testIterations < 2 * N ) {
+        epicsThreadSleep ( 0.01 );
+    }
+    testOk ( get ( testData.m_testIterations ) == 2 * N,
+	    "add/sub iterations %u", 
+	    testData.m_testIterations );
+    testOk ( get ( testData.m_testValue ) == NDT, 
+	    "add/sub final value %u", 
+	    testData.m_testValue );
+}
+
+template < class T >
+void testCAS ()
+{
+	static const size_t N = 10;
+
+    const unsigned int stackSize = 
+        epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+	TestDataCAS < T > testData = { 0, N, N };
+	set ( testData.m_testIterationsSet, 0 );
+	testOk ( get ( testData.m_testIterationsSet ) == 0u,
+				"set/get %u", testData.m_testIterationsSet );
+	set ( testData.m_testIterationsNotSet, 0 );
+	testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
+				"set/get %u", testData.m_testIterationsNotSet );
+	set ( testData.m_testValue, trueValue < T > () );
+	testOk ( get ( testData.m_testValue ) == trueValue < T > (),
+				"set/get a true value" );
+	for ( size_t i = 0u; i < N; i++ ) {
+		epicsThreadCreate ( "tns",
+					50, stackSize, cas < T >, & testData );
+	}
+	set ( testData.m_testValue, falseValue < T > () );
+	while ( testData.m_testIterationsSet < N ) {
+		epicsThreadSleep ( 0.01 );
+	}
+	testOk ( get ( testData.m_testIterationsSet ) == N,
+				"test and set iterations %u", 
+				testData.m_testIterationsSet );
+	testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
+				"test and set not-set tracking = %u", 
+				testData.m_testIterationsNotSet );
+}
+
+MAIN ( epicsAtomicTest )
+{
+
+    testPlan ( 31 );
+
+    testIncrDecr < int > ();
+    testIncrDecr < size_t > ();
+    testAddSub < int > ();
+    testAddSub < size_t > ();
+    testCAS < int > ();
+    testCAS < size_t > ();
+    testCAS < EpicsAtomicPtrT > ();
+
+    return testDone ();
+}


Navigate by Date:
Prev: Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
Next: [Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base Jeff Hill
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  <20112012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: [Merge] lp:~mshankar/epics-base/softioclogging into lp:epics-base noreply
Next: [Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base Jeff Hill
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  <20112012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·