Merge lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:~epics-core/epics-base/3.15

Proposed by Jeff Hill
Status: Superseded
Proposed branch: lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based
Merge into: lp:~epics-core/epics-base/3.15
Diff against target: 3899 lines (+3245/-276) (has conflicts)
38 files modified
configure/CONFIG.gnuCommon (+2/-0)
configure/CONFIG_COMMON (+18/-4)
configure/RULES_BUILD (+5/-1)
configure/os/CONFIG.solarisCommon.solarisCommon (+2/-0)
configure/os/CONFIG.win32-x86.win32-x86 (+3/-1)
src/libCom/Makefile (+283/-0)
src/libCom/misc/compilerDependencies.h (+0/-104)
src/libCom/misc/ipAddrToAsciiAsynchronous.cpp (+1/-1)
src/libCom/osi/compiler/borland/compilerSpecific.h (+55/-0)
src/libCom/osi/compiler/clang/compilerSpecific.h (+59/-0)
src/libCom/osi/compiler/clang/epicsAtomicCD.h (+27/-0)
src/libCom/osi/compiler/default/compilerSpecific.h (+45/-0)
src/libCom/osi/compiler/default/epicsAtomicCD.h (+25/-0)
src/libCom/osi/compiler/gcc/compilerSpecific.h (+62/-0)
src/libCom/osi/compiler/gcc/epicsAtomicCD.h (+172/-0)
src/libCom/osi/compiler/msvc/compilerSpecific.h (+57/-0)
src/libCom/osi/compiler/msvc/epicsAtomicCD.h (+124/-0)
src/libCom/osi/compiler/solStudio/epicsAtomicCD.h (+27/-0)
src/libCom/osi/compilerDependencies.h (+47/-0)
src/libCom/osi/epicsAtomic.h (+237/-0)
src/libCom/osi/epicsAtomicDefault.h (+235/-0)
src/libCom/osi/epicsThread.h (+1/-1)
src/libCom/osi/epicsThreadOnce.cpp (+129/-0)
src/libCom/osi/os/RTEMS/osdThread.c (+0/-32)
src/libCom/osi/os/WIN32/epicsAtomicMS.h (+222/-0)
src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp (+22/-0)
src/libCom/osi/os/WIN32/epicsAtomicOSD.h (+49/-0)
src/libCom/osi/os/WIN32/osdThread.c (+0/-35)
src/libCom/osi/os/posix/epicsAtomicOSD.cpp (+108/-0)
src/libCom/osi/os/posix/epicsAtomicOSD.h (+32/-0)
src/libCom/osi/os/posix/osdThread.c (+0/-44)
src/libCom/osi/os/solaris/epicsAtomicOSD.h (+166/-0)
src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp (+22/-0)
src/libCom/osi/os/vxWorks/epicsAtomicOSD.h (+255/-0)
src/libCom/osi/os/vxWorks/osdThread.c (+0/-53)
src/libCom/test/Makefile (+9/-0)
src/libCom/test/epicsAtomicPerform.cpp (+506/-0)
src/libCom/test/epicsAtomicTest.cpp (+238/-0)
Text conflict in src/libCom/Makefile
To merge this branch: bzr merge lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based
Reviewer Review Type Date Requested Status
EPICS Core Developers Pending
Review via email: mp+73605@code.launchpad.net

This proposal has been superseded by a proposal from 2011-08-31.

Description of the change

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}

To post a comment you must log in.
12261. By Jeff Hill

fixed spelling in comment

Unmerged revisions

12261. By Jeff Hill

fixed spelling in comment

12260. By Jeff Hill

o moved epicsThreadOnce impl details to anonymous namespace
o fixed recursion sanity test is too agressive
o added some comments

12259. By Jeff Hill

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}

12258. By Jeff Hill <email address hidden>

fixed names on redefinition protection macros for vxWorks

12257. By Jeff Hill

fixed epics atomic read memory barrier name - old versions of vxWorks

12256. By Jeff Hill

fixed word missing from vxWorks specific read and write memory barrier functions

12255. By Jeff Hill <email address hidden>

fixed vxWorks name for epicsAtomicTest

12254. By Jeff Hill <email address hidden>

fixed wrong return type old vxWorks epicsAtomicUnlock

12253. By Jeff Hill

fixed test count

12252. By Jeff Hill

fixed vxWorks jumbled ifdef

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure/CONFIG.gnuCommon'
2--- configure/CONFIG.gnuCommon 2009-11-25 17:15:47 +0000
3+++ configure/CONFIG.gnuCommon 2011-08-31 22:29:24 +0000
4@@ -12,6 +12,8 @@
5
6 GNU = YES
7
8+CMPLR_CLASS = gcc
9+
10 GNU_BIN = $(GNU_DIR)/bin
11 GNU_LIB = $(GNU_DIR)/lib
12
13
14=== modified file 'configure/CONFIG_COMMON'
15--- configure/CONFIG_COMMON 2011-08-17 21:36:38 +0000
16+++ configure/CONFIG_COMMON 2011-08-31 22:29:24 +0000
17@@ -133,11 +133,14 @@
18 GENERIC_SRC_DIRS = .. $(SRC_DIRS)
19 OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
20 $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))
21-ALL_SRC_DIRS = $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
22+CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
23+ $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default ))
24+ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
25
26 #--------------------------------------------------
27 # compile line include directories
28 INSTALL_INCLUDES += \
29+ -I$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) \
30 -I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \
31 -I$(INSTALL_INCLUDE)
32 SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS)))
33@@ -379,25 +382,36 @@
34 #
35 # auto determine the directory paths that things are installed to
36 # RULES:
37-# 1) found in any one of several os specific area
38+# 0) found in any one of several compiler specific paths
39+# => install to $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)
40+# 1) not found in (0) and found in any one of several OS specific paths
41 # => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS)
42-# 2) not foundin (1) and found in generic area
43+# 2) not found in (1) and found in generic paths
44 # => install to $(INSTALL_INCLUDE)
45 # 3) not found in (1) or (2) then may be (not yet) computer generated
46 # => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let
47 # build rules work on vpath
48 #
49 # These rules guarantee that the users include from
50-# no more than two directories
51+# no more than three directories
52 #
53 INSTALL_INC += $(foreach inc, $(INC), \
54 $(firstword \
55+ $(CMPLR_INSTALL_INC) \
56 $(OS_INSTALL_INC) \
57 $(GENERIC_INSTALL_INC) \
58 $(GENERATED_INSTALL_INC) ) )
59 INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) )
60
61 #
62+# Rule 0
63+#
64+CMPLR_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/, $(INSTALL_INC_jjj) )
65+INSTALL_INC_jjj = $(foreach dir, $(CMPLR_SRC_DIRS), $(INSTALL_INC_iii) )
66+INSTALL_INC_iii = $(subst $(dir)/, , $(INSTALL_INC_hhh) )
67+INSTALL_INC_hhh = $(wildcard $(addsuffix /$(inc), $(dir)) )
68+
69+#
70 # Rule 1
71 #
72 OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) )
73
74=== modified file 'configure/RULES_BUILD'
75--- configure/RULES_BUILD 2010-12-20 15:48:12 +0000
76+++ configure/RULES_BUILD 2011-08-31 22:29:24 +0000
77@@ -408,7 +408,11 @@
78 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
79
80 $(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : %
81- $(ECHO) "Installing os dependent include file $@"
82+ $(ECHO) "Installing OS dependent include file $@"
83+ @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
84+
85+$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/% : %
86+ $(ECHO) "Installing compiler dependent include file $@"
87 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
88
89 $(INSTALL_DOC)/%: %
90
91=== modified file 'configure/os/CONFIG.solarisCommon.solarisCommon'
92--- configure/os/CONFIG.solarisCommon.solarisCommon 2010-10-05 19:27:37 +0000
93+++ configure/os/CONFIG.solarisCommon.solarisCommon 2011-08-31 22:29:24 +0000
94@@ -7,6 +7,8 @@
95 # Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc
96 #-------------------------------------------------------
97
98+CMPLR_CLASS = solStudio
99+
100 SPARCWORKS = /opt/SUNWspro
101 GNU = NO
102
103
104=== modified file 'configure/os/CONFIG.win32-x86.win32-x86'
105--- configure/os/CONFIG.win32-x86.win32-x86 2011-08-17 21:36:38 +0000
106+++ configure/os/CONFIG.win32-x86.win32-x86 2011-08-31 22:29:24 +0000
107@@ -11,6 +11,8 @@
108
109 VALID_BUILDS = Host Ioc
110
111+CMPLR_CLASS = msvc
112+
113 # convert UNIX path to native path
114 PATH_FILTER = $(subst /,\\,$(1))
115
116@@ -122,7 +124,7 @@
117 # /D_CRTDBG_MAP_ALLOC
118 # /RTCsu catch bugs occurring only in optimized code
119 # /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs
120-OPT_CXXFLAGS_NO = /RTCsu /Zi
121+OPT_CXXFLAGS_NO = /RTCsu /Zi
122
123 # specify object file name and location
124 OBJ_CXXFLAG = /Fo
125
126=== modified file 'src/libCom/Makefile'
127--- src/libCom/Makefile 2011-08-23 22:28:20 +0000
128+++ src/libCom/Makefile 2011-08-31 22:29:24 +0000
129@@ -9,6 +9,7 @@
130 TOP = ../..
131 include $(TOP)/configure/CONFIG
132
133+<<<<<<< TREE
134 SRC = $(TOP)/src
135 LIBCOM = $(SRC)/libCom
136
137@@ -38,6 +39,288 @@
138 include $(LIBCOM)/yacc/Makefile
139
140 # Library to build:
141+=======
142+LIBCOM = $(TOP)/src/libCom
143+
144+# Command-line input support
145+epicsReadline_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY)
146+epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY))
147+
148+#POSIX thread priority scheduling flag
149+THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
150+osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
151+
152+#epicsVersion is created by this Makefile
153+INC += epicsVersion.h
154+
155+SRC_DIRS += $(LIBCOM)/bucketLib
156+INC += bucketLib.h
157+SRCS += bucketLib.c
158+
159+SRC_DIRS += $(LIBCOM)/ring
160+#following needed for locating epicsRingPointer.h and epicsRingBytes.h
161+INC += epicsRingPointer.h
162+INC += epicsRingBytes.h
163+SRCS += epicsRingPointer.cpp
164+SRCS += epicsRingBytes.c
165+
166+SRC_DIRS += $(LIBCOM)/calc
167+INC += postfix.h
168+SRCS += postfix.c
169+SRCS += calcPerform.c
170+
171+SRC_DIRS += $(LIBCOM)/cvtFast
172+INC += cvtFast.h
173+SRCS += cvtFast.c
174+
175+# From cppStd
176+SRC_DIRS += $(LIBCOM)/cppStd
177+INC += epicsAlgorithm.h
178+INC += epicsExcept.h
179+INC += epicsMemory.h
180+
181+# From cxxTemplates
182+SRC_DIRS += $(LIBCOM)/cxxTemplates
183+INC += resourceLib.h
184+INC += tsDLList.h
185+INC += tsSLList.h
186+INC += tsMinMax.h
187+INC += tsBTree.h
188+INC += tsFreeList.h
189+INC += epicsSingleton.h
190+INC += epicsGuard.h
191+INC += epicsOnce.h
192+SRCS += resourceLib.cpp
193+SRCS += epicsOnce.cpp
194+SRCS += epicsSingletonMutex.cpp
195+
196+SRC_DIRS += $(LIBCOM)/dbmf
197+INC += dbmf.h
198+SRCS += dbmf.c
199+
200+SRC_DIRS += $(LIBCOM)/ellLib
201+INC += ellLib.h
202+SRCS += ellLib.c
203+
204+SRC_DIRS += $(LIBCOM)/env
205+INC += envDefs.h
206+SRCS += envSubr.c
207+SRCS += envData.c
208+
209+SRC_DIRS += $(LIBCOM)/error
210+INC += epicsPrint.h
211+INC += errMdef.h
212+INC += errSymTbl.h
213+INC += errlog.h
214+INC += error.h
215+SRCS += errlog.c
216+SRCS += errSymLib.c
217+SRCS += errSymTbl.c
218+
219+SRC_DIRS += $(LIBCOM)/fdmgr
220+INC += fdManager.h
221+INC += fdmgr.h
222+SRCS += fdmgr.cpp
223+SRCS += fdManager.cpp
224+
225+SRC_DIRS += $(LIBCOM)/freeList
226+INC += freeList.h
227+SRCS += freeListLib.c
228+HTMLS += freeList/freeList.html
229+
230+SRC_DIRS += $(LIBCOM)/gpHash
231+INC += gpHash.h
232+SRCS += gpHashLib.c
233+HTMLS += gpHash/gpHash.html
234+
235+SRC_DIRS += $(LIBCOM)/iocsh
236+INC += iocsh.h
237+INC += registry.h
238+INC += libComRegister.h
239+SRCS += iocsh.cpp
240+SRCS += registry.c
241+SRCS += libComRegister.c
242+
243+SRC_DIRS += $(LIBCOM)/logClient
244+INC += iocLog.h
245+INC += logClient.h
246+SRCS += iocLog.c
247+SRCS += logClient.c
248+
249+SRC_DIRS += $(LIBCOM)/macLib
250+INC += macLib.h
251+SRCS += macCore.c
252+SRCS += macEnv.c
253+SRCS += macUtil.c
254+
255+SRC_DIRS += $(LIBCOM)/misc
256+INC += adjustment.h
257+INC += cantProceed.h
258+INC += dbDefs.h
259+INC += epicsConvert.h
260+INC += epicsExit.h
261+INC += epicsStdlib.h
262+INC += epicsString.h
263+INC += epicsTypes.h
264+INC += shareLib.h
265+INC += epicsExport.h
266+INC += unixFileName.h
267+INC += locationException.h
268+INC += ipAddrToAsciiAsynchronous.h
269+INC += epicsUnitTest.h
270+INC += testMain.h
271+SRCS += aToIPAddr.c
272+SRCS += adjustment.c
273+SRCS += cantProceed.c
274+SRCS += epicsConvert.c
275+SRCS += epicsExit.c
276+SRCS += epicsStdlib.c
277+SRCS += epicsString.c
278+SRCS += truncateFile.c
279+SRCS += ipAddrToAsciiAsynchronous.cpp
280+SRCS += epicsUnitTest.c
281+
282+# From osi
283+SRC_DIRS += $(LIBCOM)/osi
284+INC += osiFileName.h
285+INC += osiSock.h
286+INC += osdSock.h
287+INC += epicsInterrupt.h
288+INC += osdInterrupt.h
289+
290+INC += epicsMutex.h
291+INC += osdMutex.h
292+INC += epicsEvent.h
293+INC += osdEvent.h
294+INC += epicsMath.h
295+INC += osdMessageQueue.h
296+INC += osdStrtod.h
297+
298+INC += epicsAssert.h
299+INC += epicsFindSymbol.h
300+INC += osiPoolStatus.h
301+INC += osdPoolStatus.h
302+INC += osdThread.h
303+
304+INC += epicsThread.h
305+INC += epicsTime.h
306+INC += epicsGeneralTime.h
307+INC += osdTime.h
308+INC += generalTimeSup.h
309+INC += osiClockTime.h
310+INC += epicsSignal.h
311+INC += osiProcess.h
312+INC += osiUnistd.h
313+INC += osiWireFormat.h
314+INC += osdWireFormat.h
315+INC += osdWireConfig.h
316+INC += epicsAtomic.h
317+INC += epicsAtomicCD.h
318+INC += epicsAtomicOSD.h
319+INC += epicsAtomicDefault.h
320+INC += epicsEndian.h
321+INC += epicsReadline.h
322+INC += epicsMessageQueue.h
323+INC += epicsStdio.h
324+INC += epicsStdioRedirect.h
325+INC += epicsGetopt.h
326+
327+INC += devLib.h
328+INC += devLibVME.h
329+INC += devLibVMEImpl.h
330+INC += osdVME.h
331+INC += compilerDependencies.h
332+INC += compilerSpecific.h
333+
334+SRCS += epicsThread.cpp
335+SRCS += epicsMutex.cpp
336+SRCS += epicsEvent.cpp
337+SRCS += epicsTime.cpp
338+SRCS += epicsMessageQueue.cpp
339+SRCS += epicsMath.cpp
340+SRCS += epicsAtomicOSD.cpp
341+
342+SRCS += epicsGeneralTime.c
343+SRCS += osiClockTime.c
344+
345+SRCS += osdSock.c
346+SRCS += osdSockAddrReuse.cpp
347+SRCS += osiSock.c
348+SRCS += systemCallIntMech.cpp
349+SRCS += epicsSocketConvertErrnoToString.cpp
350+SRCS += osdAssert.c
351+SRCS += osdFindSymbol.c
352+SRCS += osdInterrupt.c
353+SRCS += osdPoolStatus.c
354+SRCS += osdSignal.cpp
355+SRCS += osdEnv.c
356+SRCS += epicsReadline.c
357+SRCS += epicsTempFile.cpp
358+SRCS += epicsThreadOnce.cpp
359+SRCS += epicsStdio.c
360+SRCS += osdStdio.c
361+
362+osdEnv_CFLAGS_WIN32= -U__STDC__
363+
364+SRCS += osdThread.c
365+SRCS += osdMutex.c
366+SRCS += osdEvent.c
367+SRCS += osdTime.cpp
368+SRCS += osdProcess.c
369+SRCS += osdNetIntf.c
370+SRCS += osdMessageQueue.c
371+
372+SRCS += devLibVME.c
373+SRCS += devLibVMEOSD.c
374+
375+SRC_DIRS += $(LIBCOM)/taskwd
376+INC += taskwd.h
377+SRCS += taskwd.c
378+
379+SRC_DIRS += $(LIBCOM)/timer
380+INC += epicsTimer.h
381+SRCS += epicsTimer.cpp
382+SRCS += timer.cpp
383+SRCS += timerQueue.cpp
384+SRCS += timerQueueActive.cpp
385+SRCS += timerQueueActiveMgr.cpp
386+SRCS += timerQueuePassive.cpp
387+
388+#tsDefs contains R3.13 compatibility tsStamp code
389+SRC_DIRS += $(LIBCOM)/tsDefs
390+INC += tsDefs.h
391+SRCS += tsDefs.c
392+
393+# Time providers, in osi
394+SRCS_vxWorks += osiNTPTime.c
395+SRCS_RTEMS += osiNTPTime.c
396+
397+# These files are in osi/os/vxWorks
398+# Special reboot hook
399+SRCS_vxWorks += atReboot.cpp
400+# For old vxWorks applications
401+INC_vxWorks += camacLib.h
402+INC_vxWorks += epicsDynLink.h
403+INC_vxWorks += module_types.h
404+INC_vxWorks += task_params.h
405+SRCS_vxWorks += epicsDynLink.c
406+SRCS_vxWorks += veclist.c
407+SRCS_vxWorks += logMsgToErrlog.cpp
408+
409+#This forces the vxWorks compatibility stuff to be loaded
410+OBJS_vxWorks = vxComLibrary
411+
412+# These files are in osi/os/WIN32
413+INC_WIN32 += epicsAtomicMS.h
414+SRCS_WIN32 += epicsGetopt.c
415+SRCS_WIN32 += setThreadName.cpp
416+#SRCS_WIN32 += dllmain.cpp
417+SRCS_WIN32 += forceBadAllocException.cpp
418+
419+# Library to build:
420+# lib$(LIBRARY).a or ..dll/..exp/..lib
421+#
422+>>>>>>> MERGE-SOURCE
423 LIBRARY=Com
424
425 Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
426
427=== removed file 'src/libCom/misc/compilerDependencies.h'
428--- src/libCom/misc/compilerDependencies.h 2011-06-20 18:52:32 +0000
429+++ src/libCom/misc/compilerDependencies.h 1970-01-01 00:00:00 +0000
430@@ -1,104 +0,0 @@
431-
432-/*************************************************************************\
433-* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
434-* National Laboratory.
435-* Copyright (c) 2002 The Regents of the University of California, as
436-* Operator of Los Alamos National Laboratory.
437-* EPICS BASE is distributed subject to a Software License Agreement found
438-* in file LICENSE that is included with this distribution.
439-\*************************************************************************/
440-
441-/*
442- * Author:
443- * Jeffrey O. Hill
444- * johill@lanl.gov
445- */
446-
447-#ifndef compilerDependencies_h
448-#define compilerDependencies_h
449-
450-/*
451- * This is an attempt to move all tests identifying what features a
452- * compiler supports into one file.
453- *
454- * Since this is a compiler, and not os dependent, issue then ifdefs
455- * are used. The ifdefs allow us to make the default assumption that
456- * standards incompliance issues will be fixed by future compiler
457- * releases.
458- */
459-
460-#ifdef __cplusplus
461-
462-/*
463- * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
464- * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
465- */
466-
467-#if defined ( _MSC_VER )
468-# if _MSC_VER >= 1200 /* visual studio 6.0 or later */
469-# define CXX_PLACEMENT_DELETE
470-# endif
471-# if _MSC_VER > 1300 /* some release after visual studio 7 we hope */
472-# define CXX_THROW_SPECIFICATION
473-# endif
474-#elif defined ( __HP_aCC )
475-# if _HP_aCC > 33300
476-# define CXX_PLACEMENT_DELETE
477-# endif
478-# define CXX_THROW_SPECIFICATION
479-#elif defined ( __BORLANDC__ )
480-# if __BORLANDC__ >= 0x600
481-# define CXX_PLACEMENT_DELETE
482-# endif
483-# define CXX_THROW_SPECIFICATION
484-#elif defined ( __GNUC__ )
485-# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
486-# define CXX_THROW_SPECIFICATION
487-# endif
488-# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
489-# define CXX_PLACEMENT_DELETE
490-# endif
491-#else
492-# define CXX_PLACEMENT_DELETE
493-# define CXX_THROW_SPECIFICATION
494-#endif
495-
496-/*
497- * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
498- */
499-#if defined ( CXX_THROW_SPECIFICATION )
500-# define epicsThrows(X) throw X
501-#else
502-# define epicsThrows(X)
503-#endif
504-
505-/*
506- * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
507- */
508-#if defined ( CXX_PLACEMENT_DELETE )
509-# define epicsPlacementDeleteOperator(X) void operator delete X;
510-#else
511-# define epicsPlacementDeleteOperator(X)
512-#endif
513-
514-#endif /* __cplusplus */
515-
516-/*
517- * Enable format-string checking if possible
518- */
519-#ifdef __GNUC__
520-# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
521-#else
522-# define EPICS_PRINTF_STYLE(f,a)
523-#endif
524-
525-/*
526- * Deprecation marker
527- */
528-#if defined( __GNUC__ ) && (__GNUC__ > 2)
529-# define EPICS_DEPRECATED __attribute__((deprecated))
530-#else
531-# define EPICS_DEPRECATED
532-#endif
533-
534-#endif /* ifndef compilerDependencies_h */
535
536=== modified file 'src/libCom/misc/ipAddrToAsciiAsynchronous.cpp'
537--- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2008-10-21 20:26:48 +0000
538+++ src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2011-08-31 22:29:24 +0000
539@@ -127,7 +127,7 @@
540 ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
541 unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
542 bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
543-static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;
544+static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
545
546 // the users are not required to supply a show routine
547 // for there transaction callback class
548
549=== added directory 'src/libCom/osi/compiler'
550=== added directory 'src/libCom/osi/compiler/borland'
551=== added file 'src/libCom/osi/compiler/borland/compilerSpecific.h'
552--- src/libCom/osi/compiler/borland/compilerSpecific.h 1970-01-01 00:00:00 +0000
553+++ src/libCom/osi/compiler/borland/compilerSpecific.h 2011-08-31 22:29:24 +0000
554@@ -0,0 +1,55 @@
555+
556+/*************************************************************************\
557+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
558+* National Laboratory.
559+* Copyright (c) 2002 The Regents of the University of California, as
560+* Operator of Los Alamos National Laboratory.
561+* EPICS BASE is distributed subject to a Software License Agreement found
562+* in file LICENSE that is included with this distribution.
563+\*************************************************************************/
564+
565+/*
566+ * Author:
567+ * Jeffrey O. Hill
568+ * johill@lanl.gov
569+ */
570+
571+#ifndef compilerSpecific_h
572+#define compilerSpecific_h
573+
574+#ifndef __BORLANDC__
575+# error compiler/borland/compilerSpecific.h is only for use with the Borland compiler
576+#endif
577+
578+#ifdef __cplusplus
579+
580+/*
581+ * in general we dont like ifdefs but they do allow us to check the
582+ * compiler version and make the optimistic assumption that
583+ * standards incompliance issues will be fixed by future compiler
584+ * releases
585+ */
586+
587+/*
588+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
589+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
590+ */
591+#if __BORLANDC__ >= 0x600
592+# define CXX_PLACEMENT_DELETE
593+#endif
594+
595+#define CXX_THROW_SPECIFICATION
596+
597+#endif /* __cplusplus */
598+
599+/*
600+ * Enable format-string checking if possible
601+ */
602+#define EPICS_PRINTF_STYLE(f,a)
603+
604+/*
605+ * Deprecation marker
606+ */
607+#define EPICS_DEPRECATED
608+
609+#endif /* ifndef compilerSpecific_h */
610
611=== added directory 'src/libCom/osi/compiler/clang'
612=== added file 'src/libCom/osi/compiler/clang/compilerSpecific.h'
613--- src/libCom/osi/compiler/clang/compilerSpecific.h 1970-01-01 00:00:00 +0000
614+++ src/libCom/osi/compiler/clang/compilerSpecific.h 2011-08-31 22:29:24 +0000
615@@ -0,0 +1,59 @@
616+
617+/*************************************************************************\
618+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
619+* National Laboratory.
620+* Copyright (c) 2002 The Regents of the University of California, as
621+* Operator of Los Alamos National Laboratory.
622+* EPICS BASE is distributed subject to a Software License Agreement found
623+* in file LICENSE that is included with this distribution.
624+\*************************************************************************/
625+
626+/*
627+ * Author:
628+ * Jeffrey O. Hill
629+ * johill@lanl.gov
630+ */
631+
632+#ifndef compilerSpecific_h
633+#define compilerSpecific_h
634+
635+#ifndef __clang__
636+# error compiler/clang/compilerSpecific.h is only for use with the clang compiler
637+#endif
638+
639+/*
640+ * WARNING: the current state of this file is only based on reading clang manuals
641+ * and has not actually been tested with the compiler
642+ */
643+#pragma warning compiler/clang/compilerSpecific.h is based on reading the manual, but hasnt been tested with the clang compiler
644+
645+#ifdef __cplusplus
646+
647+/*
648+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
649+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
650+ */
651+#define CXX_PLACEMENT_DELETE
652+#define CXX_THROW_SPECIFICATION
653+
654+#endif /* __cplusplus */
655+
656+/*
657+ * Enable format-string checking if possible
658+ */
659+#if __has_attribute(format)
660+# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
661+#else
662+# define EPICS_PRINTF_STYLE
663+#endif
664+
665+/*
666+ * Deprecation marker if possible
667+ */
668+#if __has_attribute(deprecated)
669+# define EPICS_DEPRECATED __attribute__((deprecated))
670+#else
671+# define EPICS_DEPRECATED
672+#endif
673+
674+#endif /* ifndef compilerSpecific_h */
675
676=== added file 'src/libCom/osi/compiler/clang/epicsAtomicCD.h'
677--- src/libCom/osi/compiler/clang/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
678+++ src/libCom/osi/compiler/clang/epicsAtomicCD.h 2011-08-31 22:29:24 +0000
679@@ -0,0 +1,27 @@
680+
681+/*************************************************************************\
682+* Copyright (c) 2011 LANS LLC, as Operator of
683+* Los Alamos National Laboratory.
684+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
685+* National Laboratory.
686+* EPICS BASE is distributed subject to a Software License Agreement found
687+* in file LICENSE that is included with this distribution.
688+\*************************************************************************/
689+
690+/*
691+ * Author Jeffrey O. Hill
692+ * johill@lanl.gov
693+ */
694+
695+#ifndef epicsAtomicCD_h
696+#define epicsAtomicCD_h
697+
698+#if defined ( __cplusplus )
699+# define EPICS_ATOMIC_INLINE inline
700+#else
701+# define EPICS_ATOMIC_INLINE __inline__
702+#endif
703+
704+#include "epicsAtomicOSD.h"
705+
706+#endif /* epicsAtomicCD_h */
707
708=== added directory 'src/libCom/osi/compiler/default'
709=== added file 'src/libCom/osi/compiler/default/compilerSpecific.h'
710--- src/libCom/osi/compiler/default/compilerSpecific.h 1970-01-01 00:00:00 +0000
711+++ src/libCom/osi/compiler/default/compilerSpecific.h 2011-08-31 22:29:24 +0000
712@@ -0,0 +1,45 @@
713+
714+/*************************************************************************\
715+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
716+* National Laboratory.
717+* Copyright (c) 2002 The Regents of the University of California, as
718+* Operator of Los Alamos National Laboratory.
719+* EPICS BASE is distributed subject to a Software License Agreement found
720+* in file LICENSE that is included with this distribution.
721+\*************************************************************************/
722+
723+/*
724+ * Author:
725+ * Jeffrey O. Hill
726+ * johill@lanl.gov
727+ */
728+
729+#ifndef compilerSpecific_h
730+#define compilerSpecific_h
731+
732+#ifdef __cplusplus
733+
734+/*
735+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
736+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
737+ *
738+ * (our default guess is that the compiler implements the C++ 97 standard)
739+ */
740+#define CXX_THROW_SPECIFICATION
741+#define CXX_PLACEMENT_DELETE
742+
743+#endif /* __cplusplus */
744+
745+/*
746+ * Enable format-string checking if possible
747+ * (our default guess is that the compiler doesnt implement non-standard extensions)
748+ */
749+#define EPICS_PRINTF_STYLE(f,a)
750+
751+/*
752+ * Deprecation marker
753+ * (our default guess is that the compiler doesnt implement non-standard extensions)
754+ */
755+#define EPICS_DEPRECATED
756+
757+#endif /* ifndef compilerSpecific_h */
758
759=== added file 'src/libCom/osi/compiler/default/epicsAtomicCD.h'
760--- src/libCom/osi/compiler/default/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
761+++ src/libCom/osi/compiler/default/epicsAtomicCD.h 2011-08-31 22:29:24 +0000
762@@ -0,0 +1,25 @@
763+
764+/*************************************************************************\
765+* Copyright (c) 2011 LANS LLC, as Operator of
766+* Los Alamos National Laboratory.
767+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
768+* National Laboratory.
769+* EPICS BASE is distributed subject to a Software License Agreement found
770+* in file LICENSE that is included with this distribution.
771+\*************************************************************************/
772+
773+/*
774+ * Author Jeffrey O. Hill
775+ * johill@lanl.gov
776+ */
777+
778+#ifndef epicsAtomicCD_h
779+#define epicsAtomicCD_h
780+
781+#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus )
782+# define EPICS_ATOMIC_INLINE inline
783+#endif
784+
785+#include "epicsAtomicOSD.h"
786+
787+#endif /* epicsAtomicCD_h */
788
789=== added directory 'src/libCom/osi/compiler/gcc'
790=== added file 'src/libCom/osi/compiler/gcc/compilerSpecific.h'
791--- src/libCom/osi/compiler/gcc/compilerSpecific.h 1970-01-01 00:00:00 +0000
792+++ src/libCom/osi/compiler/gcc/compilerSpecific.h 2011-08-31 22:29:24 +0000
793@@ -0,0 +1,62 @@
794+
795+/*************************************************************************\
796+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
797+* National Laboratory.
798+* Copyright (c) 2002 The Regents of the University of California, as
799+* Operator of Los Alamos National Laboratory.
800+* EPICS BASE is distributed subject to a Software License Agreement found
801+* in file LICENSE that is included with this distribution.
802+\*************************************************************************/
803+
804+/*
805+ * Author:
806+ * Jeffrey O. Hill
807+ * johill@lanl.gov
808+ */
809+
810+#ifndef compilerSpecific_h
811+#define compilerSpecific_h
812+
813+#ifndef __GNUC__
814+# error compiler/gcc/compilerSpecific.h is only for use with the gnu compiler
815+#endif
816+
817+#ifdef __cplusplus
818+
819+/*
820+ * in general we dont like ifdefs but they do allow us to check the
821+ * compiler version and make the optimistic assumption that
822+ * standards incompliance issues will be fixed by future compiler
823+ * releases
824+ */
825+
826+/*
827+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
828+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
829+ */
830+
831+#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
832+# define CXX_THROW_SPECIFICATION
833+#endif
834+
835+#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
836+# define CXX_PLACEMENT_DELETE
837+#endif
838+
839+#endif /* __cplusplus */
840+
841+/*
842+ * Enable format-string checking if possible
843+ */
844+#define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
845+
846+/*
847+ * Deprecation marker if possible
848+ */
849+#if (__GNUC__ > 2)
850+# define EPICS_DEPRECATED __attribute__((deprecated))
851+#else
852+# define EPICS_DEPRECATED
853+#endif
854+
855+#endif /* ifndef compilerSpecific_h */
856
857=== added file 'src/libCom/osi/compiler/gcc/epicsAtomicCD.h'
858--- src/libCom/osi/compiler/gcc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
859+++ src/libCom/osi/compiler/gcc/epicsAtomicCD.h 2011-08-31 22:29:24 +0000
860@@ -0,0 +1,172 @@
861+
862+/*************************************************************************\
863+* Copyright (c) 2011 LANS LLC, as Operator of
864+* Los Alamos National Laboratory.
865+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
866+* National Laboratory.
867+* EPICS BASE is distributed subject to a Software License Agreement found
868+* in file LICENSE that is included with this distribution.
869+\*************************************************************************/
870+
871+/*
872+ * Author Jeffrey O. Hill
873+ * johill@lanl.gov
874+ */
875+
876+#ifndef epicsAtomicCD_h
877+#define epicsAtomicCD_h
878+
879+#ifndef __GNUC__
880+# error this header is only for use with the gnu compiler
881+#endif
882+
883+#define EPICS_ATOMIC_INLINE __inline__
884+
885+#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
886+#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
887+
888+#define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
889+ GCC_ATOMIC_CONCAT ( \
890+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
891+ __SIZEOF_INT__ )
892+
893+#define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
894+ GCC_ATOMIC_CONCAT ( \
895+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
896+ __SIZEOF_SIZE_T__ )
897+
898+#define GCC_ATOMIC_INTRINSICS_MIN_X86 \
899+ ( defined ( __i486 ) || defined ( __pentium ) || \
900+ defined ( __pentiumpro ) || defined ( __MMX__ ) )
901+
902+#define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \
903+ ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 )
904+
905+#define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \
906+ ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \
907+ GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER )
908+
909+#ifdef __cplusplus
910+extern "C" {
911+#endif
912+
913+/*
914+ * We are optimistic that __sync_synchronize is implemented
915+ * in all version four gcc invarient of target. The gnu doc
916+ * seems to say that when not supported by architecture a call
917+ * to an external function is generated but in practice
918+ * this isnt the case for some of the atomic intrinsics, and
919+ * so there is an undefined symbol. So far we have not seen
920+ * that with __sync_synchronize, but we can only guess based
921+ * on experimental evidence.
922+ *
923+ * For example we know that when generating object code for
924+ * 386 most of the atomic instrinsics are not present and
925+ * we see undefined symbols with mingw, but we dont have
926+ * troubles with __sync_synchronize.
927+ */
928+#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
929+
930+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
931+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
932+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
933+{
934+ __sync_synchronize ();
935+}
936+#endif
937+
938+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
939+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
940+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
941+{
942+ __sync_synchronize ();
943+}
944+#endif
945+
946+#endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */
947+
948+#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
949+ || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
950+
951+#define EPICS_ATOMIC_INCR_INTT
952+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
953+{
954+ return __sync_add_and_fetch ( pTarget, 1 );
955+}
956+
957+#define EPICS_ATOMIC_DECR_INTT
958+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
959+{
960+ return __sync_sub_and_fetch ( pTarget, 1 );
961+}
962+
963+#define EPICS_ATOMIC_ADD_INTT
964+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
965+{
966+ return __sync_add_and_fetch ( pTarget, delta );
967+}
968+
969+#define EPICS_ATOMIC_CAS_INTT
970+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
971+ int oldVal, int newVal )
972+{
973+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
974+}
975+
976+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */
977+
978+#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
979+ || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
980+
981+#define EPICS_ATOMIC_INCR_SIZET
982+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
983+{
984+ return __sync_add_and_fetch ( pTarget, 1u );
985+}
986+
987+#define EPICS_ATOMIC_DECR_SIZET
988+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
989+{
990+ return __sync_sub_and_fetch ( pTarget, 1u );
991+}
992+
993+#define EPICS_ATOMIC_ADD_SIZET
994+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
995+{
996+ return __sync_add_and_fetch ( pTarget, delta );
997+}
998+
999+#define EPICS_ATOMIC_SUB_SIZET
1000+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
1001+{
1002+ return __sync_sub_and_fetch ( pTarget, delta );
1003+}
1004+
1005+#define EPICS_ATOMIC_CAS_SIZET
1006+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
1007+ size_t oldVal, size_t newVal )
1008+{
1009+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
1010+}
1011+
1012+#define EPICS_ATOMIC_CAS_PTRT
1013+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
1014+ EpicsAtomicPtrT * pTarget,
1015+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
1016+{
1017+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
1018+}
1019+
1020+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */
1021+
1022+#ifdef __cplusplus
1023+} /* end of extern "C" */
1024+#endif
1025+
1026+/*
1027+ * if currently unavailable as gcc intrinsics we
1028+ * will try for an os specific inline solution
1029+ */
1030+#include "epicsAtomicOSD.h"
1031+
1032+#endif /* epicsAtomicCD_h */
1033
1034=== added directory 'src/libCom/osi/compiler/msvc'
1035=== added file 'src/libCom/osi/compiler/msvc/compilerSpecific.h'
1036--- src/libCom/osi/compiler/msvc/compilerSpecific.h 1970-01-01 00:00:00 +0000
1037+++ src/libCom/osi/compiler/msvc/compilerSpecific.h 2011-08-31 22:29:24 +0000
1038@@ -0,0 +1,57 @@
1039+
1040+/*************************************************************************\
1041+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
1042+* National Laboratory.
1043+* Copyright (c) 2002 The Regents of the University of California, as
1044+* Operator of Los Alamos National Laboratory.
1045+* EPICS BASE is distributed subject to a Software License Agreement found
1046+* in file LICENSE that is included with this distribution.
1047+\*************************************************************************/
1048+
1049+/*
1050+ * Author:
1051+ * Jeffrey O. Hill
1052+ * johill@lanl.gov
1053+ */
1054+
1055+#ifndef compilerSpecific_h
1056+#define compilerSpecific_h
1057+
1058+#ifndef _MSC_VER
1059+# error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler
1060+#endif
1061+
1062+#ifdef __cplusplus
1063+
1064+/*
1065+ * in general we dont like ifdefs but they do allow us to check the
1066+ * compiler version and make the optimistic assumption that
1067+ * standards incompliance issues will be fixed by future compiler
1068+ * releases
1069+ */
1070+
1071+/*
1072+ * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
1073+ * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
1074+ */
1075+#if _MSC_VER >= 1200 /* visual studio 6.0 or later */
1076+# define CXX_PLACEMENT_DELETE
1077+#endif
1078+
1079+#if _MSC_VER > 1300 /* some release after visual studio 7 we hope */
1080+# define CXX_THROW_SPECIFICATION
1081+#endif
1082+
1083+#endif /* __cplusplus */
1084+
1085+/*
1086+ * Enable format-string checking if possible
1087+ */
1088+#define EPICS_PRINTF_STYLE(f,a)
1089+
1090+/*
1091+ * Deprecation marker
1092+ */
1093+#define EPICS_DEPRECATED
1094+
1095+#endif /* ifndef compilerSpecific_h */
1096
1097=== added file 'src/libCom/osi/compiler/msvc/epicsAtomicCD.h'
1098--- src/libCom/osi/compiler/msvc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
1099+++ src/libCom/osi/compiler/msvc/epicsAtomicCD.h 2011-08-31 22:29:24 +0000
1100@@ -0,0 +1,124 @@
1101+
1102+/*************************************************************************\
1103+* Copyright (c) 2011 LANS LLC, as Operator of
1104+* Los Alamos National Laboratory.
1105+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
1106+* National Laboratory.
1107+* EPICS BASE is distributed subject to a Software License Agreement found
1108+* in file LICENSE that is included with this distribution.
1109+\*************************************************************************/
1110+
1111+/*
1112+ * Author Jeffrey O. Hill
1113+ * johill@lanl.gov
1114+ */
1115+
1116+#ifndef epicsAtomicCD_h
1117+#define epicsAtomicCD_h
1118+
1119+#include "epicsAssert.h"
1120+
1121+#ifndef _MSC_VER
1122+# error this header file is only for use with with the Microsoft Compiler
1123+#endif
1124+
1125+#ifdef _MSC_EXTENSIONS
1126+
1127+#include <intrin.h>
1128+
1129+#if _MSC_VER >= 1200
1130+# define EPICS_ATOMIC_INLINE __forceinline
1131+#else
1132+# define EPICS_ATOMIC_INLINE __inline
1133+#endif
1134+
1135+#if defined ( _M_IX86 )
1136+# pragma warning( push )
1137+# pragma warning( disable : 4793 )
1138+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
1139+ {
1140+ long fence;
1141+ __asm { xchg fence, eax }
1142+ }
1143+# pragma warning( pop )
1144+#elif defined ( _M_X64 )
1145+# define MS_ATOMIC_64
1146+# pragma intrinsic ( __faststorefence )
1147+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
1148+ {
1149+ __faststorefence ();
1150+ }
1151+#elif defined ( _M_IA64 )
1152+# define MS_ATOMIC_64
1153+# pragma intrinsic ( __mf )
1154+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
1155+ {
1156+ __mf ();
1157+ }
1158+#else
1159+# error unexpected target architecture, msvc version of epicsAtomicCD.h
1160+#endif
1161+
1162+/*
1163+ * The windows doc appears to recommend defining InterlockedExchange
1164+ * to be _InterlockedExchange to cause it to be an intrinsic, but that
1165+ * creates issues when later, in a windows os specific header, we include
1166+ * windows.h. Therefore, we except some code duplication between the msvc
1167+ * csAtomic.h and win32 osdAtomic.h to avoid problems, and to keep the
1168+ * os specific windows.h header file out of the msvc cdAtomic.h
1169+ */
1170+#define MS_LONG long
1171+#define MS_InterlockedExchange _InterlockedExchange
1172+#define MS_InterlockedCompareExchange _InterlockedCompareExchange
1173+#define MS_InterlockedIncrement _InterlockedIncrement
1174+#define MS_InterlockedDecrement _InterlockedDecrement
1175+#define MS_InterlockedExchange _InterlockedExchange
1176+#define MS_InterlockedExchangeAdd _InterlockedExchangeAdd
1177+#if defined ( MS_ATOMIC_64 )
1178+# define MS_LONGLONG long long
1179+# define MS_InterlockedIncrement64 _InterlockedIncrement64
1180+# define MS_InterlockedDecrement64 _InterlockedDecrement64
1181+# define MS_InterlockedExchange64 _InterlockedExchange64
1182+# define MS_InterlockedExchangeAdd64 _InterlockedExchangeAdd64
1183+# define MS_InterlockedCompareExchange64 _InterlockedCompareExchange64
1184+#endif
1185+
1186+#ifdef __cplusplus
1187+extern "C" {
1188+#endif /* __cplusplus */
1189+
1190+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
1191+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
1192+{
1193+ epicsAtomicMemoryBarrier ();
1194+}
1195+
1196+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
1197+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
1198+{
1199+ epicsAtomicMemoryBarrier ();
1200+}
1201+
1202+#ifdef __cplusplus
1203+} /* end of extern "C" */
1204+#endif /* __cplusplus */
1205+
1206+#include "epicsAtomicMS.h"
1207+#include "epicsAtomicDefault.h"
1208+
1209+#else /* ifdef _MSC_EXTENSIONS */
1210+
1211+#if defined ( __cplusplus )
1212+# define EPICS_ATOMIC_INLINE inline
1213+#endif
1214+
1215+/*
1216+ * if unavailable as an intrinsic we will try
1217+ * for os specific solution
1218+ */
1219+#include "epicsAtomicOSD.h"
1220+
1221+#endif /* ifdef _MSC_EXTENSIONS */
1222+
1223+#endif /* epicsAtomicCD_h */
1224+
1225
1226=== added directory 'src/libCom/osi/compiler/solStudio'
1227=== added file 'src/libCom/osi/compiler/solStudio/epicsAtomicCD.h'
1228--- src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
1229+++ src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 2011-08-31 22:29:24 +0000
1230@@ -0,0 +1,27 @@
1231+
1232+/*************************************************************************\
1233+* Copyright (c) 2011 LANS LLC, as Operator of
1234+* Los Alamos National Laboratory.
1235+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
1236+* National Laboratory.
1237+* EPICS BASE is distributed subject to a Software License Agreement found
1238+* in file LICENSE that is included with this distribution.
1239+\*************************************************************************/
1240+
1241+/*
1242+ * Author Jeffrey O. Hill
1243+ * johill@lanl.gov
1244+ */
1245+
1246+#ifndef epicsAtomicCD_h
1247+#define epicsAtomicCD_h
1248+
1249+#if defined ( __cplusplus )
1250+# define EPICS_ATOMIC_INLINE inline
1251+#else
1252+# define EPICS_ATOMIC_INLINE __inline
1253+#endif
1254+
1255+#include "epicsAtomicOSD.h"
1256+
1257+#endif /* epicsAtomicCD_h */
1258
1259=== added file 'src/libCom/osi/compilerDependencies.h'
1260--- src/libCom/osi/compilerDependencies.h 1970-01-01 00:00:00 +0000
1261+++ src/libCom/osi/compilerDependencies.h 2011-08-31 22:29:24 +0000
1262@@ -0,0 +1,47 @@
1263+
1264+/*************************************************************************\
1265+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
1266+* National Laboratory.
1267+* Copyright (c) 2002 The Regents of the University of California, as
1268+* Operator of Los Alamos National Laboratory.
1269+* EPICS BASE is distributed subject to a Software License Agreement found
1270+* in file LICENSE that is included with this distribution.
1271+\*************************************************************************/
1272+
1273+/*
1274+ * Author:
1275+ * Jeffrey O. Hill
1276+ * johill@lanl.gov
1277+ */
1278+
1279+#ifndef compilerDependencies_h
1280+#define compilerDependencies_h
1281+
1282+#include "compilerSpecific.h"
1283+
1284+#ifdef __cplusplus
1285+
1286+/*
1287+ * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
1288+ *
1289+ * Note: now a widely accepted concensus (ref Meyers and C++ faq) is that
1290+ * one should avoid using throw specifications in C++ code
1291+ */
1292+#if defined ( CXX_THROW_SPECIFICATION )
1293+# define epicsThrows(X) throw X
1294+#else
1295+# define epicsThrows(X)
1296+#endif
1297+
1298+/*
1299+ * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
1300+ */
1301+#if defined ( CXX_PLACEMENT_DELETE )
1302+# define epicsPlacementDeleteOperator(X) void operator delete X;
1303+#else
1304+# define epicsPlacementDeleteOperator(X)
1305+#endif
1306+
1307+#endif /* __cplusplus */
1308+
1309+#endif /* ifndef compilerDependencies_h */
1310
1311=== added file 'src/libCom/osi/epicsAtomic.h'
1312--- src/libCom/osi/epicsAtomic.h 1970-01-01 00:00:00 +0000
1313+++ src/libCom/osi/epicsAtomic.h 2011-08-31 22:29:24 +0000
1314@@ -0,0 +1,237 @@
1315+
1316+/*************************************************************************\
1317+* Copyright (c) 2011 LANS LLC, as Operator of
1318+* Los Alamos National Laboratory.
1319+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
1320+* National Laboratory.
1321+* EPICS BASE is distributed subject to a Software License Agreement found
1322+* in file LICENSE that is included with this distribution.
1323+\*************************************************************************/
1324+
1325+/*
1326+ * Author Jeffrey O. Hill
1327+ * johill@lanl.gov
1328+ */
1329+
1330+#ifndef epicsAtomic_h
1331+#define epicsAtomic_h
1332+
1333+#include <stdlib.h> /* define size_t */
1334+
1335+#include "shareLib.h"
1336+
1337+#ifdef __cplusplus
1338+extern "C" {
1339+#endif
1340+
1341+typedef void * EpicsAtomicPtrT;
1342+
1343+/* load target into cache */
1344+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
1345+
1346+/* push cache version of target into target */
1347+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
1348+
1349+/*
1350+ * lock out other smp processors from accessing the target,
1351+ * load target into cache, add one to target, flush cache
1352+ * to target, allow other smp processors to access the target,
1353+ * return new value of target as modified by this operation
1354+ */
1355+epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget );
1356+epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget );
1357+
1358+/*
1359+ * lock out other smp processors from accessing the target,
1360+ * load target into cache, subtract one from target, flush cache
1361+ * to target, allow out other smp processors to access the target,
1362+ * return new value of target as modified by this operation
1363+ */
1364+epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget );
1365+epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget );
1366+
1367+/*
1368+ * lock out other smp processors from accessing the target,
1369+ * load target into cache, add/sub delta to/from target, flush cache
1370+ * to target, allow other smp processors to access the target,
1371+ * return new value of target as modified by this operation
1372+ */
1373+epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta );
1374+epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta );
1375+epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta );
1376+
1377+/*
1378+ * set cache version of target, flush cache to target
1379+ */
1380+epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue );
1381+epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue );
1382+epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue );
1383+
1384+/*
1385+ * fetch target into cache, return new value of target
1386+ */
1387+epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget );
1388+epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget );
1389+epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget );
1390+
1391+/*
1392+ * lock out other smp processors from accessing the target,
1393+ * load target into cache, if target is equal to oldVal set target
1394+ * to newVal, flush cache to target, allow other smp processors
1395+ * to access the target, return the original value stored in the
1396+ * target
1397+ */
1398+epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
1399+ size_t oldVal, size_t newVal );
1400+epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget,
1401+ int oldVal, int newVal );
1402+epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
1403+ EpicsAtomicPtrT * pTarget,
1404+ EpicsAtomicPtrT oldVal,
1405+ EpicsAtomicPtrT newVal );
1406+
1407+#ifdef __cplusplus
1408+} /* end of extern "C" */
1409+#endif
1410+
1411+/*
1412+ * options for inline compiler instrinsic or os specific
1413+ * implementations of the above function prototypes
1414+ *
1415+ * its importnat for certaiin compiler to define the
1416+ * inline functions before they get used in the c++
1417+ * code below
1418+ */
1419+#include "epicsAtomicCD.h"
1420+
1421+#ifdef __cplusplus
1422+
1423+namespace epics {
1424+namespace atomic {
1425+
1426+/*
1427+ * overloaded c++ interface
1428+ */
1429+epicsShareFunc size_t increment ( size_t & v );
1430+epicsShareFunc int increment ( int & v );
1431+epicsShareFunc size_t decrement ( size_t & v );
1432+epicsShareFunc int decrement ( int & v );
1433+epicsShareFunc size_t add ( size_t & v, size_t delta );
1434+epicsShareFunc int add ( int & v, int delta );
1435+epicsShareFunc size_t subtract ( size_t & v, size_t delta );
1436+epicsShareFunc int subtract ( int & v, int delta );
1437+epicsShareFunc void set ( size_t & v , size_t newValue );
1438+epicsShareFunc void set ( int & v, int newValue );
1439+epicsShareFunc void set ( EpicsAtomicPtrT & v,
1440+ EpicsAtomicPtrT newValue );
1441+epicsShareFunc size_t get ( const size_t & v );
1442+epicsShareFunc int get ( const int & v );
1443+epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v );
1444+epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal,
1445+ size_t newVal );
1446+epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal );
1447+epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
1448+ EpicsAtomicPtrT oldVal,
1449+ EpicsAtomicPtrT newVal );
1450+
1451+/************* incr ***************/
1452+inline size_t increment ( size_t & v )
1453+{
1454+ return epicsAtomicIncrSizeT ( & v );
1455+}
1456+
1457+inline int increment ( int & v )
1458+{
1459+ return epicsAtomicIncrIntT ( & v );
1460+}
1461+
1462+/************* decr ***************/
1463+inline size_t decrement ( size_t & v )
1464+{
1465+ return epicsAtomicDecrSizeT ( & v );
1466+}
1467+
1468+inline int decrement ( int & v )
1469+{
1470+ return epicsAtomicDecrIntT ( & v );
1471+}
1472+
1473+/************* add ***************/
1474+inline size_t add ( size_t & v, size_t delta )
1475+{
1476+ return epicsAtomicAddSizeT ( & v, delta );
1477+}
1478+
1479+inline int add ( int & v, int delta )
1480+{
1481+ return epicsAtomicAddIntT ( & v, delta );
1482+}
1483+
1484+/************* sub ***************/
1485+inline size_t subtract ( size_t & v, size_t delta )
1486+{
1487+ return epicsAtomicSubSizeT ( & v, delta );
1488+}
1489+
1490+inline int subtract ( int & v, int delta )
1491+{
1492+ return epicsAtomicAddIntT ( & v, -delta );
1493+}
1494+
1495+/************* set ***************/
1496+inline void set ( size_t & v , size_t newValue )
1497+{
1498+ epicsAtomicSetSizeT ( & v, newValue );
1499+}
1500+
1501+inline void set ( int & v, int newValue )
1502+{
1503+ epicsAtomicSetIntT ( & v, newValue );
1504+}
1505+
1506+inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
1507+{
1508+ epicsAtomicSetPtrT ( & v, newValue );
1509+}
1510+
1511+/************* get ***************/
1512+inline size_t get ( const size_t & v )
1513+{
1514+ return epicsAtomicGetSizeT ( & v );
1515+}
1516+
1517+inline int get ( const int & v )
1518+{
1519+ return epicsAtomicGetIntT ( & v );
1520+}
1521+
1522+inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
1523+{
1524+ return epicsAtomicGetPtrT ( & v );
1525+}
1526+
1527+/************* cas ***************/
1528+inline size_t compareAndSwap ( size_t & v,
1529+ size_t oldVal, size_t newVal )
1530+{
1531+ return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal );
1532+}
1533+
1534+inline int compareAndSwap ( int & v, int oldVal, int newVal )
1535+{
1536+ return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal );
1537+}
1538+
1539+inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
1540+ EpicsAtomicPtrT oldVal,
1541+ EpicsAtomicPtrT newVal )
1542+{
1543+ return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal );
1544+}
1545+
1546+} /* end of namespace atomic */
1547+} /* end of namespace epics */
1548+
1549+#endif /* ifdef __cplusplus */
1550+
1551+#endif /* epicsAtomic_h */
1552
1553=== added file 'src/libCom/osi/epicsAtomicDefault.h'
1554--- src/libCom/osi/epicsAtomicDefault.h 1970-01-01 00:00:00 +0000
1555+++ src/libCom/osi/epicsAtomicDefault.h 2011-08-31 22:29:24 +0000
1556@@ -0,0 +1,235 @@
1557+
1558+/*************************************************************************\
1559+* Copyright (c) 2011 LANS LLC, as Operator of
1560+* Los Alamos National Laboratory.
1561+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
1562+* National Laboratory.
1563+* EPICS BASE is distributed subject to a Software License Agreement found
1564+* in file LICENSE that is included with this distribution.
1565+\*************************************************************************/
1566+
1567+/*
1568+ * Author Jeffrey O. Hill
1569+ * johill@lanl.gov
1570+ */
1571+
1572+#ifndef epicsAtomicDefault_h
1573+#define epicsAtomicDefault_h
1574+
1575+/*
1576+ * EPICS_ATOMIC_INLINE might be defined, but empty for an out-of-line
1577+ * instantiation
1578+ */
1579+#ifdef EPICS_ATOMIC_INLINE
1580+
1581+#ifdef __cpluplus
1582+extern "C" {
1583+#endif
1584+
1585+/*
1586+ * struct EpicsAtomicLockKey;
1587+ * epicsShareFunc void epicsAtomicReadMemoryBarrier ();
1588+ * epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
1589+ * epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
1590+ * epicsShareFunc void epicsAtomicUnock ( struct EpicsAtomicLockKey * );
1591+ */
1592+
1593+/*
1594+ * incr
1595+ */
1596+#ifndef EPICS_ATOMIC_INCR_INTT
1597+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
1598+{
1599+ EpicsAtomicLockKey key;
1600+ epicsAtomicLock ( & key );
1601+ const int result = ++(*pTarget);
1602+ epicsAtomicUnlock ( & key );
1603+ return result;
1604+}
1605+#endif
1606+
1607+#ifndef EPICS_ATOMIC_INCR_SIZET
1608+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
1609+{
1610+ EpicsAtomicLockKey key;
1611+ epicsAtomicLock ( & key );
1612+ const size_t result = ++(*pTarget);
1613+ epicsAtomicUnlock ( & key );
1614+ return result;
1615+}
1616+#endif
1617+
1618+/*
1619+ * decr
1620+ */
1621+#ifndef EPICS_ATOMIC_DECR_INTT
1622+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
1623+{
1624+ EpicsAtomicLockKey key;
1625+ epicsAtomicLock ( & key );
1626+ const int result = --(*pTarget);
1627+ epicsAtomicUnlock ( & key );
1628+ return result;
1629+}
1630+#endif
1631+
1632+#ifndef EPICS_ATOMIC_DECR_SIZET
1633+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
1634+{
1635+ EpicsAtomicLockKey key;
1636+ epicsAtomicLock ( & key );
1637+ const size_t result = --(*pTarget);
1638+ epicsAtomicUnlock ( & key );
1639+ return result;
1640+}
1641+#endif
1642+
1643+/*
1644+ * add/sub
1645+ */
1646+#ifndef EPICS_ATOMIC_ADD_INTT
1647+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
1648+{
1649+ EpicsAtomicLockKey key;
1650+ epicsAtomicLock ( & key );
1651+ const int result = *pTarget += delta;
1652+ epicsAtomicUnlock ( & key );
1653+ return result;
1654+}
1655+#endif
1656+
1657+#ifndef EPICS_ATOMIC_ADD_SIZET
1658+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
1659+{
1660+ EpicsAtomicLockKey key;
1661+ epicsAtomicLock ( & key );
1662+ const size_t result = *pTarget += delta;
1663+ epicsAtomicUnlock ( & key );
1664+ return result;
1665+}
1666+#endif
1667+
1668+#ifndef EPICS_ATOMIC_SUB_SIZET
1669+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
1670+{
1671+ EpicsAtomicLockKey key;
1672+ epicsAtomicLock ( & key );
1673+ const size_t result = *pTarget -= delta;
1674+ epicsAtomicUnlock ( & key );
1675+ return result;
1676+}
1677+#endif
1678+
1679+/*
1680+ * set
1681+ */
1682+#ifndef EPICS_ATOMIC_SET_INTT
1683+EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newVal )
1684+{
1685+ *pTarget = newVal;
1686+ epicsAtomicWriteMemoryBarrier ();
1687+}
1688+#endif
1689+
1690+#ifndef EPICS_ATOMIC_SET_SIZET
1691+EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal )
1692+{
1693+ *pTarget = newVal;
1694+ epicsAtomicWriteMemoryBarrier ();
1695+}
1696+#endif
1697+
1698+#ifndef EPICS_ATOMIC_SET_PTRT
1699+EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget,
1700+ EpicsAtomicPtrT newVal )
1701+{
1702+ *pTarget = newVal;
1703+ epicsAtomicWriteMemoryBarrier ();
1704+}
1705+#endif
1706+
1707+/*
1708+ * get
1709+ */
1710+#ifndef EPICS_ATOMIC_GET_INTT
1711+EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget )
1712+{
1713+ epicsAtomicReadMemoryBarrier ();
1714+ return *pTarget;
1715+}
1716+#endif
1717+
1718+#ifndef EPICS_ATOMIC_GET_SIZET
1719+EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget )
1720+{
1721+ epicsAtomicReadMemoryBarrier ();
1722+ return *pTarget;
1723+}
1724+#endif
1725+
1726+#ifndef EPICS_ATOMIC_GET_PTRT
1727+EPICS_ATOMIC_INLINE EpicsAtomicPtrT
1728+ epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget )
1729+{
1730+ epicsAtomicReadMemoryBarrier ();
1731+ return *pTarget;
1732+}
1733+#endif
1734+
1735+/*
1736+ * cmp and swap
1737+ */
1738+#ifndef EPICS_ATOMIC_CAS_INTT
1739+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldval, int newval )
1740+{
1741+ EpicsAtomicLockKey key;
1742+ epicsAtomicLock ( & key );
1743+ const int cur = *pTarget;
1744+ if ( cur == oldval ) {
1745+ *pTarget = newval;
1746+ }
1747+ epicsAtomicUnlock ( & key );
1748+ return cur;
1749+}
1750+#endif
1751+
1752+#ifndef EPICS_ATOMIC_CAS_SIZET
1753+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
1754+ size_t oldval, size_t newval )
1755+{
1756+ EpicsAtomicLockKey key;
1757+ epicsAtomicLock ( & key );
1758+ const size_t cur = *pTarget;
1759+ if ( cur == oldval ) {
1760+ *pTarget = newval;
1761+ }
1762+ epicsAtomicUnlock ( & key );
1763+ return cur;
1764+}
1765+#endif
1766+
1767+#ifndef EPICS_ATOMIC_CAS_PTRT
1768+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
1769+ EpicsAtomicPtrT * pTarget,
1770+ EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval )
1771+{
1772+ EpicsAtomicLockKey key;
1773+ epicsAtomicLock ( & key );
1774+ const EpicsAtomicPtrT cur = *pTarget;
1775+ if ( cur == oldval ) {
1776+ *pTarget = newval;
1777+ }
1778+ epicsAtomicUnlock ( & key );
1779+ return cur;
1780+}
1781+#endif
1782+
1783+#ifdef __cpluplus
1784+} /* end of extern "C" */
1785+#endif
1786+
1787+#endif /* EPICS_ATOMIC_INLINE */
1788+
1789+#endif /* epicsAtomicDefault_h */
1790+
1791+
1792
1793=== modified file 'src/libCom/osi/epicsThread.h'
1794--- src/libCom/osi/epicsThread.h 2010-04-26 20:38:11 +0000
1795+++ src/libCom/osi/epicsThread.h 2011-08-31 22:29:24 +0000
1796@@ -51,7 +51,7 @@
1797 /* (epicsThreadId)0 is guaranteed to be an invalid thread id */
1798 typedef struct epicsThreadOSD *epicsThreadId;
1799
1800-typedef epicsThreadId epicsThreadOnceId;
1801+typedef void * epicsThreadOnceId;
1802 #define EPICS_THREAD_ONCE_INIT 0
1803
1804 epicsShareFunc void epicsShareAPI epicsThreadOnce(
1805
1806=== added file 'src/libCom/osi/epicsThreadOnce.cpp'
1807--- src/libCom/osi/epicsThreadOnce.cpp 1970-01-01 00:00:00 +0000
1808+++ src/libCom/osi/epicsThreadOnce.cpp 2011-08-31 22:29:24 +0000
1809@@ -0,0 +1,129 @@
1810+
1811+/*************************************************************************\
1812+* Copyright (c) 2011 LANS LLC, as Operator of
1813+* Los Alamos National Laboratory.
1814+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
1815+* National Laboratory.
1816+* Copyright (c) 2002 The Regents of the University of California, as
1817+* Operator of Los Alamos National Laboratory.
1818+* EPICS BASE is distributed subject to a Software License Agreement found
1819+* in file LICENSE that is included with this distribution.
1820+\*************************************************************************/
1821+
1822+/*
1823+ * Author Jeffrey O. Hill johill@lanl.gov
1824+ * Original Authors (before converting to operating system independent code):
1825+ * Jeff Hill, Andrew Johnson, Marty Kraimer, Eric Norum
1826+ */
1827+
1828+#include <cstdlib>
1829+
1830+#define epicsExportSharedSymbols
1831+#include "errlog.h"
1832+#include "cantProceed.h"
1833+#include "epicsThread.h"
1834+#include "epicsAtomic.h"
1835+#include "epicsAssert.h"
1836+
1837+namespace {
1838+
1839+struct ThreadID {
1840+public:
1841+ ThreadID ();
1842+ ThreadID ( epicsThreadId id );
1843+ bool operator == ( const ThreadID & ) const;
1844+private:
1845+ epicsThreadId m_threadId;
1846+ ThreadID ( const ThreadID & ); // disabled
1847+ ThreadID & operator = ( const ThreadID & ); // disabled
1848+};
1849+
1850+inline ThreadID :: ThreadID ( epicsThreadId id ) :
1851+ m_threadId ( id )
1852+{
1853+}
1854+
1855+inline ThreadID :: ThreadID () : m_threadId ( 0 )
1856+{
1857+}
1858+
1859+inline bool ThreadID :: operator == ( const ThreadID & ctrl ) const
1860+{
1861+ return ctrl.m_threadId == m_threadId;
1862+}
1863+
1864+static ThreadID done;
1865+
1866+} // end of namespace annonymous
1867+
1868+using namespace epics;
1869+using namespace atomic;
1870+
1871+/*
1872+ * epicsThreadOnceOnly ()
1873+ */
1874+static void epicsShareAPI epicsThreadOnceOnly ( epicsThreadOnceId * pId,
1875+ void ( * pFunc )( void * ),
1876+ void * pArg )
1877+{
1878+ static const epicsThreadOnceId idStartup = EPICS_THREAD_ONCE_INIT;
1879+ ThreadID self ( epicsThreadGetIdSelf () );
1880+ epicsThreadOnceId pCurrent = compareAndSwap ( *pId, idStartup, & self );
1881+ if ( pCurrent != & done ) {
1882+ if ( pCurrent == idStartup ) {
1883+ ( *pFunc ) ( pArg );
1884+ set ( *pId, & done );
1885+ }
1886+ else {
1887+ {
1888+ ThreadID & initID =
1889+ * reinterpret_cast < ThreadID * > ( pCurrent );
1890+ if ( initID == self ) {
1891+ cantProceed( "epicsThreadOnce() once was called "
1892+ "recursively from the user's once fuction\n" );
1893+ }
1894+ }
1895+ static const std :: size_t spinDownInit = 1000u;
1896+ static const std :: size_t spinCount = 10u;
1897+ STATIC_ASSERT ( spinDownInit > spinCount );
1898+ static const std :: size_t spinThresh = spinDownInit - spinCount;
1899+ std :: size_t spinDown = spinDownInit;
1900+ do {
1901+ if ( spinDown <= spinThresh ) {
1902+ epicsThreadSleep ( epicsThreadSleepQuantum () );
1903+ }
1904+ if ( spinDown > 0u ) {
1905+ spinDown--;
1906+ }
1907+ else {
1908+ errlogPrintf ( "epicsThreadOnce: waiting for another "
1909+ "thread to finish calling the once function\n" );
1910+ spinDown = spinThresh;
1911+ }
1912+ pCurrent = get ( *pId );
1913+ } while ( pCurrent != & done );
1914+ }
1915+ }
1916+}
1917+
1918+//
1919+// we implement this as a separate function so that it is easy to see
1920+// that the performance impact of the primary (most commonly used) path
1921+// and that options for inlining this function are available (based on
1922+// source code organization)
1923+//
1924+// performance might be slightly better if this were implemented as an inline
1925+// function, but that would pull epicsAtomic.h into epicsThread.h, and on
1926+// windows this includes (the lean and mean version of) windows.h, so perhaps
1927+// its best to make this an out-of-line function as that type of instantiation
1928+// will probably have only a small negative impact on performance
1929+//
1930+extern "C" void epicsShareAPI epicsThreadOnce ( epicsThreadOnceId * pId,
1931+ void ( * pFunc )( void * ),
1932+ void * pArg )
1933+{
1934+ const epicsThreadOnceId pCurrent = get ( *pId );
1935+ if ( pCurrent != & done ) {
1936+ epicsThreadOnceOnly ( pId, pFunc, pArg );
1937+ }
1938+}
1939
1940=== modified file 'src/libCom/osi/os/RTEMS/osdThread.c'
1941--- src/libCom/osi/os/RTEMS/osdThread.c 2010-10-05 19:27:37 +0000
1942+++ src/libCom/osi/os/RTEMS/osdThread.c 2011-08-31 22:29:24 +0000
1943@@ -60,7 +60,6 @@
1944 * Support for `once-only' execution
1945 */
1946 static int initialized = 0;
1947-static epicsMutexId onceMutex;
1948
1949 /*
1950 * Just map osi 0 to 99 into RTEMS 199 to 100
1951@@ -231,7 +230,6 @@
1952 rtems_task_priority old;
1953
1954 rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
1955- onceMutex = epicsMutexMustCreate();
1956 taskVarMutex = epicsMutexMustCreate ();
1957 rtems_task_ident (RTEMS_SELF, 0, &tid);
1958 setThreadInfo (tid, "_main_", NULL, NULL);
1959@@ -471,36 +469,6 @@
1960 }
1961
1962 /*
1963- * Ensure func() is run only once.
1964- */
1965-void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
1966-{
1967- #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
1968-
1969- if (!initialized) epicsThreadInit();
1970- epicsMutexMustLock(onceMutex);
1971- if (*id != EPICS_THREAD_ONCE_DONE) {
1972- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
1973- *id = epicsThreadGetIdSelf(); /* mark active */
1974- epicsMutexUnlock(onceMutex);
1975- func(arg);
1976- epicsMutexMustLock(onceMutex);
1977- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
1978- } else if (*id == epicsThreadGetIdSelf()) {
1979- epicsMutexUnlock(onceMutex);
1980- cantProceed("Recursive epicsThreadOnce() initialization\n");
1981- } else
1982- while (*id != EPICS_THREAD_ONCE_DONE) {
1983- /* Another thread is in the above func(arg) call. */
1984- epicsMutexUnlock(onceMutex);
1985- epicsThreadSleep(epicsThreadSleepQuantum());
1986- epicsMutexMustLock(onceMutex);
1987- }
1988- }
1989- epicsMutexUnlock(onceMutex);
1990-}
1991-
1992-/*
1993 * Thread private storage implementation based on the vxWorks
1994 * implementation by Andrew Johnson APS/ASD.
1995 */
1996
1997=== added file 'src/libCom/osi/os/WIN32/epicsAtomicMS.h'
1998--- src/libCom/osi/os/WIN32/epicsAtomicMS.h 1970-01-01 00:00:00 +0000
1999+++ src/libCom/osi/os/WIN32/epicsAtomicMS.h 2011-08-31 22:29:24 +0000
2000@@ -0,0 +1,222 @@
2001+
2002+/*************************************************************************\
2003+* Copyright (c) 2011 LANS LLC, as Operator of
2004+* Los Alamos National Laboratory.
2005+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
2006+* National Laboratory.
2007+* EPICS BASE is distributed subject to a Software License Agreement found
2008+* in file LICENSE that is included with this distribution.
2009+\*************************************************************************/
2010+
2011+/*
2012+ * Author Jeffrey O. Hill
2013+ * johill@lanl.gov
2014+ */
2015+
2016+#ifndef epicsAtomicMS_h
2017+#define epicsAtomicMS_h
2018+
2019+#include "epicsAssert.h"
2020+
2021+#ifdef __cplusplus
2022+extern "C" {
2023+#endif /* __cplusplus */
2024+
2025+#ifndef EPICS_ATOMIC_INCR_INTT
2026+#define EPICS_ATOMIC_INCR_INTT
2027+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
2028+{
2029+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
2030+ MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
2031+ return MS_InterlockedIncrement ( pTarg );
2032+}
2033+#endif
2034+
2035+#ifndef EPICS_ATOMIC_DECR_INTT
2036+#define EPICS_ATOMIC_DECR_INTT
2037+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
2038+{
2039+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
2040+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2041+ return MS_InterlockedDecrement ( pTarg );
2042+}
2043+#endif
2044+
2045+#ifndef EPICS_ATOMIC_ADD_INTT
2046+#define EPICS_ATOMIC_ADD_INTT
2047+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
2048+{
2049+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
2050+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2051+ /* we dont use InterlockedAdd because only latest windows is supported */
2052+ return delta + ( int ) MS_InterlockedExchangeAdd ( pTarg,
2053+ ( MS_LONG ) delta );
2054+}
2055+#endif
2056+
2057+#ifndef EPICS_ATOMIC_CAS_INTT
2058+#define EPICS_ATOMIC_CAS_INTT
2059+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
2060+ int oldVal, int newVal )
2061+{
2062+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
2063+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2064+ return (int) MS_InterlockedCompareExchange ( pTarg,
2065+ (MS_LONG) newVal, (MS_LONG) oldVal );
2066+}
2067+#endif
2068+
2069+#if ! defined ( MS_ATOMIC_64 )
2070+
2071+/*
2072+ * necessary for next three functions
2073+ *
2074+ * looking at the MS documentation it appears that they will
2075+ * keep type long the same size as an int on 64 bit builds
2076+ */
2077+STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( size_t ) );
2078+
2079+#ifndef EPICS_ATOMIC_INCR_SIZET
2080+#define EPICS_ATOMIC_INCR_SIZET
2081+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
2082+{
2083+ MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
2084+ return MS_InterlockedIncrement ( pTarg );
2085+}
2086+#endif
2087+
2088+#ifndef EPICS_ATOMIC_DECR_SIZET
2089+#define EPICS_ATOMIC_DECR_SIZET
2090+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
2091+{
2092+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2093+ return MS_InterlockedDecrement ( pTarg );
2094+}
2095+#endif
2096+
2097+#ifndef EPICS_ATOMIC_ADD_SIZET
2098+#define EPICS_ATOMIC_ADD_SIZET
2099+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
2100+ size_t delta )
2101+{
2102+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2103+ /* we dont use InterlockedAdd because only latest windows is supported */
2104+ return delta + ( size_t ) MS_InterlockedExchangeAdd ( pTarg,
2105+ ( MS_LONG ) delta );
2106+}
2107+#endif
2108+
2109+#ifndef EPICS_ATOMIC_SUB_SIZET
2110+#define EPICS_ATOMIC_SUB_SIZET
2111+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
2112+{
2113+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2114+ MS_LONG ldelta = (MS_LONG) delta;
2115+ /* we dont use InterlockedAdd because only latest windows is supported */
2116+ return ( ( size_t ) MS_InterlockedExchangeAdd ( pTarg, -ldelta ) ) - delta;
2117+}
2118+#endif
2119+
2120+#ifndef EPICS_ATOMIC_CAS_SIZET
2121+#define EPICS_ATOMIC_CAS_SIZET
2122+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
2123+ size_t * pTarget,
2124+ size_t oldVal, size_t newVal )
2125+{
2126+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2127+ return (size_t) MS_InterlockedCompareExchange ( pTarg,
2128+ (MS_LONG) newVal, (MS_LONG) oldVal );
2129+}
2130+#endif
2131+
2132+#ifndef EPICS_ATOMIC_CAS_PTRT
2133+#define EPICS_ATOMIC_CAS_PTRT
2134+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
2135+ EpicsAtomicPtrT * pTarget,
2136+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
2137+{
2138+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
2139+ return (EpicsAtomicPtrT) MS_InterlockedCompareExchange ( pTarg,
2140+ (MS_LONG) newVal, (MS_LONG) oldVal );
2141+}
2142+#endif
2143+
2144+#else /* ! MS_ATOMIC_64 */
2145+
2146+/*
2147+ * necessary for next three functions
2148+ */
2149+STATIC_ASSERT ( sizeof ( MS_LONGLONG ) == sizeof ( size_t ) );
2150+
2151+#ifndef EPICS_ATOMIC_INCR_SIZET
2152+#define EPICS_ATOMIC_INCR_SIZET
2153+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
2154+{
2155+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) pTarget;
2156+ return ( size_t ) MS_InterlockedIncrement64 ( pTarg );
2157+}
2158+#endif
2159+
2160+#ifndef EPICS_ATOMIC_DECR_SIZET
2161+#define EPICS_ATOMIC_DECR_SIZET
2162+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
2163+{
2164+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
2165+ return ( size_t ) MS_InterlockedDecrement64 ( pTarg );
2166+}
2167+#endif
2168+
2169+#ifndef EPICS_ATOMIC_ADD_SIZET
2170+#define EPICS_ATOMIC_ADD_SIZET
2171+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
2172+{
2173+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
2174+ /* we dont use InterlockedAdd64 because only latest windows is supported */
2175+ return delta + ( size_t ) MS_InterlockedExchangeAdd64 ( pTarg,
2176+ ( MS_LONGLONG ) delta );
2177+}
2178+#endif
2179+
2180+#ifndef EPICS_ATOMIC_SUB_SIZET
2181+#define EPICS_ATOMIC_SUB_SIZET
2182+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
2183+{
2184+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
2185+ MS_LONGLONG ldelta = (MS_LONGLONG) delta;
2186+ /* we dont use InterlockedAdd64 because only latest windows is supported */
2187+ return (( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, -ldelta )) - delta;
2188+}
2189+#endif
2190+
2191+#ifndef EPICS_ATOMIC_CAS_SIZET
2192+#define EPICS_ATOMIC_CAS_SIZET
2193+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
2194+ size_t oldVal, size_t newVal )
2195+{
2196+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
2197+ return (size_t) MS_InterlockedCompareExchange64 ( pTarg,
2198+ (MS_LONGLONG) newVal,
2199+ (MS_LONGLONG) oldVal );
2200+}
2201+#endif
2202+
2203+#ifndef EPICS_ATOMIC_CAS_PTRT
2204+#define EPICS_ATOMIC_CAS_PTRT
2205+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
2206+ EpicsAtomicPtrT * pTarget,
2207+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
2208+{
2209+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
2210+ return (EpicsAtomicPtrT) MS_InterlockedCompareExchange64 ( pTarg,
2211+ (MS_LONGLONG) newVal, (MS_LONGLONG) oldVal );
2212+}
2213+#endif
2214+
2215+#endif /* ! MS_ATOMIC_64 */
2216+
2217+#ifdef __cplusplus
2218+} /* end of extern "C" */
2219+#endif /* __cplusplus */
2220+
2221+#endif /* ifdef epicsAtomicMS_h */
2222+
2223
2224=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp'
2225--- src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
2226+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000
2227@@ -0,0 +1,22 @@
2228+
2229+/*************************************************************************\
2230+* Copyright (c) 2011 LANS LLC, as Operator of
2231+* Los Alamos National Laboratory.
2232+* EPICS BASE is distributed subject to a Software License Agreement found
2233+* in file LICENSE that is included with this distribution.
2234+\*************************************************************************/
2235+
2236+/*
2237+ * Author Jeffrey O. Hill
2238+ * johill@lanl.gov
2239+ */
2240+
2241+#define epicsExportSharedSymbols
2242+#include "epicsAtomic.h"
2243+
2244+// if the compiler is unable to inline then instantiate out-of-line
2245+#ifndef EPICS_ATOMIC_INLINE
2246+#define EPICS_ATOMIC_INLINE
2247+#include "epicsAtomic.h"
2248+#endif
2249+
2250
2251=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.h'
2252--- src/libCom/osi/os/WIN32/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
2253+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000
2254@@ -0,0 +1,49 @@
2255+
2256+/*************************************************************************\
2257+* Copyright (c) 2011 LANS LLC, as Operator of
2258+* Los Alamos National Laboratory.
2259+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
2260+* National Laboratory.
2261+* EPICS BASE is distributed subject to a Software License Agreement found
2262+* in file LICENSE that is included with this distribution.
2263+\*************************************************************************/
2264+
2265+/*
2266+ * Author Jeffrey O. Hill
2267+ * johill@lanl.gov
2268+ */
2269+
2270+#ifndef epicsAtomicOSD_h
2271+#define epicsAtomicOSD_h
2272+
2273+#define VC_EXTRALEAN
2274+#define STRICT
2275+#include "windows.h"
2276+
2277+#if defined ( _WIN64 )
2278+# define MS_ATOMIC_64
2279+#endif
2280+
2281+#define MS_LONG LONG
2282+#define MS_InterlockedExchange InterlockedExchange
2283+#define MS_InterlockedCompareExchange InterlockedCompareExchange
2284+#define MS_InterlockedIncrement InterlockedIncrement
2285+#define MS_InterlockedDecrement InterlockedDecrement
2286+#define MS_InterlockedExchange InterlockedExchange
2287+#define MS_InterlockedExchangeAdd InterlockedExchangeAdd
2288+#if defined ( MS_ATOMIC_64 )
2289+# define MS_LONGLONG LONGLONG
2290+# define MS_InterlockedIncrement64 InterlockedIncrement64
2291+# define MS_InterlockedDecrement64 InterlockedDecrement64
2292+# define MS_InterlockedExchange64 InterlockedExchange64
2293+# define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64
2294+# define MS_InterlockedCompareExchange InterlockedCompareExchange64
2295+#endif
2296+
2297+#ifdef EPICS_ATOMIC_INLINE
2298+# include "epicsAtomicMS.h"
2299+# include "epicsAtomicDefault.h"
2300+#endif
2301+
2302+#endif /* epicsAtomicOSD_h */
2303+
2304
2305=== modified file 'src/libCom/osi/os/WIN32/osdThread.c'
2306--- src/libCom/osi/os/WIN32/osdThread.c 2011-02-11 22:33:58 +0000
2307+++ src/libCom/osi/os/WIN32/osdThread.c 2011-08-31 22:29:24 +0000
2308@@ -1008,41 +1008,6 @@
2309 }
2310
2311 /*
2312- * epicsThreadOnce ()
2313- */
2314-epicsShareFunc void epicsShareAPI epicsThreadOnce (
2315- epicsThreadOnceId *id, void (*func)(void *), void *arg )
2316-{
2317- static struct epicsThreadOSD threadOnceComplete;
2318- #define EPICS_THREAD_ONCE_DONE & threadOnceComplete
2319- win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
2320-
2321- assert ( pGbl );
2322-
2323- EnterCriticalSection ( & pGbl->mutex );
2324-
2325- if ( *id != EPICS_THREAD_ONCE_DONE ) {
2326- if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */
2327- *id = epicsThreadGetIdSelf(); /* mark active */
2328- LeaveCriticalSection ( & pGbl->mutex );
2329- func ( arg );
2330- EnterCriticalSection ( & pGbl->mutex );
2331- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
2332- } else if ( *id == epicsThreadGetIdSelf() ) {
2333- LeaveCriticalSection ( & pGbl->mutex );
2334- cantProceed( "Recursive epicsThreadOnce() initialization\n" );
2335- } else
2336- while ( *id != EPICS_THREAD_ONCE_DONE ) {
2337- /* Another thread is in the above func(arg) call. */
2338- LeaveCriticalSection ( & pGbl->mutex );
2339- epicsThreadSleep ( epicsThreadSleepQuantum() );
2340- EnterCriticalSection ( & pGbl->mutex );
2341- }
2342- }
2343- LeaveCriticalSection ( & pGbl->mutex );
2344-}
2345-
2346-/*
2347 * epicsThreadPrivateCreate ()
2348 */
2349 epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate ()
2350
2351=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.cpp'
2352--- src/libCom/osi/os/posix/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
2353+++ src/libCom/osi/os/posix/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000
2354@@ -0,0 +1,108 @@
2355+
2356+/*************************************************************************\
2357+* Copyright (c) 2011 LANS LLC, as Operator of
2358+* Los Alamos National Laboratory.
2359+* EPICS BASE is distributed subject to a Software License Agreement found
2360+* in file LICENSE that is included with this distribution.
2361+\*************************************************************************/
2362+
2363+/*
2364+ * Author Jeffrey O. Hill
2365+ * johill@lanl.gov
2366+ */
2367+
2368+#define epicsExportSharedSymbols
2369+#include "epicsAtomic.h"
2370+
2371+// if the compiler is unable to inline then instantiate out-of-line
2372+#ifndef EPICS_ATOMIC_INLINE
2373+#define EPICS_ATOMIC_INLINE
2374+#include "epicsAtomic.h"
2375+#endif
2376+
2377+/* Authors: Jeffrey O. Hill */
2378+#include <errno.h>
2379+#include <unistd.h>
2380+#include <pthread.h>
2381+
2382+#define epicsExportSharedSymbols
2383+#include "epicsAssert.h"
2384+
2385+// if the compiler is unable to inline then instantiate out-of-line
2386+#ifndef EPICS_ATOMIC_INLINE
2387+#define EPICS_ATOMIC_INLINE
2388+#include "epicsAtomic.h"
2389+#endif
2390+
2391+#ifndef EPICS_ATOMIC_LOCK
2392+
2393+/*
2394+ * Slow, but probably correct on all systems.
2395+ * Useful only if something more efficent isnt
2396+ * provided based on knowledge of the compiler
2397+ * or OS
2398+ *
2399+ * A statically initialized pthread mutex doesnt
2400+ * need to be destroyed
2401+ *
2402+ * !!!!!
2403+ * !!!!! WARNING
2404+ * !!!!!
2405+ * !!!!! Do not use this implementation on systems where
2406+ * !!!!! code runs at interrupt context. If so, then
2407+ * !!!!! an implementation must be provided that is based
2408+ * !!!!! on a compiler intrinsic or an interrpt lock and or
2409+ * !!!!! a spin lock primitive
2410+ * !!!!!
2411+ */
2412+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
2413+
2414+void epicsAtomicLock ( EpicsAtomicLockKey * )
2415+{
2416+ unsigned countDown = 1000u;
2417+ int status;
2418+ while ( true ) {
2419+ status = pthread_mutex_lock ( & mutex );
2420+ if ( status == 0 ) return;
2421+ assert ( status == EINTR );
2422+ static const useconds_t retryDelayUSec = 100000;
2423+ usleep ( retryDelayUSec );
2424+ countDown--;
2425+ assert ( countDown );
2426+ }
2427+}
2428+
2429+void epicsAtomicUnlock ( EpicsAtomicLockKey * )
2430+{
2431+ const int status = pthread_mutex_unlock ( & mutex );
2432+ assert ( status == 0 );
2433+}
2434+
2435+#endif // ifndef EPICS_ATOMIC_LOCK
2436+
2437+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
2438+// Slow, but probably correct on all systems.
2439+// Useful only if something more efficent isnt
2440+// provided based on knowledge of the compiler
2441+// or OS
2442+void epicsAtomicReadMemoryBarrier ()
2443+{
2444+ EpicsAtomicLockKey key;
2445+ epicsAtomicLock ( & key );
2446+ epicsAtomicUnlock ( & key );
2447+}
2448+#endif
2449+
2450+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
2451+// Slow, but probably correct on all systems.
2452+// Useful only if something more efficent isnt
2453+// provided based on knowledge of the compiler
2454+// or OS
2455+void epicsAtomicWriteMemoryBarrier ()
2456+{
2457+ EpicsAtomicLockKey key;
2458+ epicsAtomicLock ( & key );
2459+ epicsAtomicUnlock ( & key );
2460+}
2461+#endif
2462+
2463
2464=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.h'
2465--- src/libCom/osi/os/posix/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
2466+++ src/libCom/osi/os/posix/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000
2467@@ -0,0 +1,32 @@
2468+
2469+/*************************************************************************\
2470+* Copyright (c) 2011 LANS LLC, as Operator of
2471+* Los Alamos National Laboratory.
2472+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
2473+* National Laboratory.
2474+* EPICS BASE is distributed subject to a Software License Agreement found
2475+* in file LICENSE that is included with this distribution.
2476+\*************************************************************************/
2477+
2478+/*
2479+ * Author Jeffrey O. Hill
2480+ * johill@lanl.gov
2481+ */
2482+
2483+#ifndef epicsAtomicOSD_h
2484+#define epicsAtomicOSD_h
2485+
2486+struct EpicsAtomicLockKey {};
2487+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
2488+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
2489+epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
2490+epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * );
2491+
2492+#ifdef EPICS_ATOMIC_INLINE
2493+
2494+#include "epicsAtomicDefault.h"
2495+
2496+#endif /* ifdef EPICS_ATOMIC_INLINE */
2497+
2498+#endif /* epicsAtomicOSD_h */
2499+
2500
2501=== modified file 'src/libCom/osi/os/posix/osdThread.c'
2502--- src/libCom/osi/os/posix/osdThread.c 2010-05-14 22:26:54 +0000
2503+++ src/libCom/osi/os/posix/osdThread.c 2011-08-31 22:29:24 +0000
2504@@ -76,7 +76,6 @@
2505 } epicsThreadOSD;
2506
2507 static pthread_key_t getpthreadInfo;
2508-static pthread_mutex_t onceLock;
2509 static pthread_mutex_t listLock;
2510 static ELLLIST pthreadList = ELLLIST_INIT;
2511 static commonAttr *pcommonAttr = 0;
2512@@ -207,8 +206,6 @@
2513 int status;
2514
2515 pthread_key_create(&getpthreadInfo,0);
2516- status = pthread_mutex_init(&onceLock,0);
2517- checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
2518 status = pthread_mutex_init(&listLock,0);
2519 checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
2520 pcommonAttr = calloc(1,sizeof(commonAttr));
2521@@ -321,47 +318,6 @@
2522 #endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
2523 }
2524
2525
2526-epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
2527-{
2528- static struct epicsThreadOSD threadOnceComplete;
2529- #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
2530- int status;
2531-
2532- epicsThreadInit();
2533- status = mutexLock(&onceLock);
2534- if(status) {
2535- fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
2536- strerror(status));
2537- exit(-1);
2538- }
2539-
2540- if (*id != EPICS_THREAD_ONCE_DONE) {
2541- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
2542- *id = epicsThreadGetIdSelf(); /* mark active */
2543- status = pthread_mutex_unlock(&onceLock);
2544- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
2545- func(arg);
2546- status = mutexLock(&onceLock);
2547- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
2548- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
2549- } else if (*id == epicsThreadGetIdSelf()) {
2550- status = pthread_mutex_unlock(&onceLock);
2551- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
2552- cantProceed("Recursive epicsThreadOnce() initialization\n");
2553- } else
2554- while (*id != EPICS_THREAD_ONCE_DONE) {
2555- /* Another thread is in the above func(arg) call. */
2556- status = pthread_mutex_unlock(&onceLock);
2557- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
2558- epicsThreadSleep(epicsThreadSleepQuantum());
2559- status = mutexLock(&onceLock);
2560- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
2561- }
2562- }
2563- status = pthread_mutex_unlock(&onceLock);
2564- checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
2565-}
2566-
2567 epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
2568 unsigned int priority, unsigned int stackSize,
2569 EPICSTHREADFUNC funptr,void *parm)
2570
2571=== added file 'src/libCom/osi/os/solaris/epicsAtomicOSD.h'
2572--- src/libCom/osi/os/solaris/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
2573+++ src/libCom/osi/os/solaris/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000
2574@@ -0,0 +1,166 @@
2575+
2576+/*************************************************************************\
2577+* Copyright (c) 2011 LANS LLC, as Operator of
2578+* Los Alamos National Laboratory.
2579+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
2580+* National Laboratory.
2581+* EPICS BASE is distributed subject to a Software License Agreement found
2582+* in file LICENSE that is included with this distribution.
2583+\*************************************************************************/
2584+
2585+/*
2586+ * Author Jeffrey O. Hill
2587+ * johill@lanl.gov
2588+ */
2589+
2590+#ifndef epicsAtomicOSD_h
2591+#define epicsAtomicOSD_h
2592+
2593+#if defined ( EPICS_ATOMIC_INLINE )
2594+
2595+/*
2596+ * atomic.h exists only in Solaris 10 or higher
2597+ */
2598+#if defined ( __SunOS_5_10 )
2599+
2600+#include <atomic.h>
2601+
2602+#ifdef __cplusplus
2603+extern "C" {
2604+#endif /* __cplusplus */
2605+
2606+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
2607+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
2608+EPICS_ATOMIC_INLINE int epicsAtomicReadMemoryBarrier ()
2609+{
2610+ membar_consumer ();
2611+}
2612+#endif
2613+
2614+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
2615+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
2616+EPICS_ATOMIC_INLINE int epicsAtomicWriteMemoryBarrier ()
2617+{
2618+ membar_producer ();
2619+}
2620+#endif
2621+
2622+#ifndef EPICS_ATOMIC_CAS_INTT
2623+#define EPICS_ATOMIC_CAS_INTT
2624+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
2625+ int oldVal, int newVal )
2626+{
2627+ STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) );
2628+ return ( int ) atomic_cas_uint ( pTarget, ( unsigned ) oldVal,
2629+ ( unsigned ) newVal );
2630+}
2631+#endif
2632+
2633+#ifndef EPICS_ATOMIC_CAS_SIZET
2634+#define EPICS_ATOMIC_CAS_SIZET
2635+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapSizeT (
2636+ size_t * pTarget,
2637+ size_t oldVal, size_t newVal )
2638+{
2639+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
2640+ void ** ppPtr = (void **) pTarget;
2641+ return ( size_t ) atomic_cas_ptr ( ppPtr, ( void * )oldVal, ( void * )newVal );
2642+}
2643+#endif
2644+
2645+#ifndef EPICS_ATOMIC_CAS_PTRT
2646+#define EPICS_ATOMIC_CAS_PTRT
2647+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
2648+ EpicsAtomicPtrT * pTarget,
2649+ EpicsAtomicPtrT oldVal,
2650+ EpicsAtomicPtrT newVal )
2651+{
2652+ return atomic_cas_ptr ( pTarget, oldVal, newVal );
2653+}
2654+#endif
2655+
2656+#ifndef EPICS_ATOMIC_INCR_INTT
2657+#define EPICS_ATOMIC_INCR_INTT
2658+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
2659+{
2660+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
2661+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
2662+ return ( int ) atomic_inc_uint_nv ( pTarg );
2663+}
2664+#endif
2665+
2666+#ifndef EPICS_ATOMIC_INCR_SIZET
2667+#define EPICS_ATOMIC_INCR_SIZET
2668+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
2669+{
2670+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
2671+ void ** const ppTarg = ( void ** ) ( pTarget );
2672+ return ( size_t ) atomic_inc_ptr_nv ( ppTarg );
2673+}
2674+#endif
2675+
2676+#ifndef EPICS_ATOMIC_DECR_INTT
2677+#define EPICS_ATOMIC_DECR_INTT
2678+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
2679+{
2680+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
2681+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
2682+ return ( int ) atomic_dec_uint_nv ( pTarg );
2683+}
2684+#endif
2685+
2686+#ifndef EPICS_ATOMIC_DECR_SIZET
2687+#define EPICS_ATOMIC_DECR_SIZET
2688+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
2689+{
2690+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
2691+ void ** const pTarg = ( void ** ) ( pTarget );
2692+ return ( size_t ) atomic_dec_ptr_nv ( pTarg );
2693+}
2694+#endif
2695+
2696+#ifndef EPICS_ATOMIC_ADD_INTT
2697+#define EPICS_ATOMIC_ADD_INTT
2698+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
2699+{
2700+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
2701+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
2702+ return ( int ) atomic_add_int_nv ( pTarg, delta );
2703+}
2704+#endif
2705+
2706+#ifndef EPICS_ATOMIC_ADD_SIZET
2707+#define EPICS_ATOMIC_ADD_SIZET
2708+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
2709+ size_t delta )
2710+{
2711+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
2712+ void ** const pTarg = ( void ** ) ( pTarget );
2713+ return ( size_t ) atomic_add_ptr_nv ( pTarg, ( ssize_t ) delta );
2714+}
2715+#endif
2716+
2717+#ifndef EPICS_ATOMIC_SUB_SIZET
2718+#define EPICS_ATOMIC_SUB_SIZET
2719+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget,
2720+ size_t delta )
2721+{
2722+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
2723+ void ** const pTarg = ( void ** ) ( pTarget );
2724+ ssize_t = sdelta = ( ssize_t ) delta;
2725+ return ( size_t ) atomic_add_ptr_nv ( pTarg, -sdelta );
2726+}
2727+#endif
2728+
2729+#ifdef __cplusplus
2730+} /* end of extern "C" */
2731+#endif /* __cplusplus */
2732+
2733+#endif /* ifdef __SunOS_5_10 */
2734+
2735+#include "epicsAtomicDefault.h"
2736+
2737+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
2738+
2739+#endif /* epicsAtomicOSD_h */
2740+
2741
2742=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp'
2743--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
2744+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000
2745@@ -0,0 +1,22 @@
2746+
2747+/*************************************************************************\
2748+* Copyright (c) 2011 LANS LLC, as Operator of
2749+* Los Alamos National Laboratory.
2750+* EPICS BASE is distributed subject to a Software License Agreement found
2751+* in file LICENSE that is included with this distribution.
2752+\*************************************************************************/
2753+
2754+/*
2755+ * Author Jeffrey O. Hill
2756+ * johill@lanl.gov
2757+ */
2758+
2759+#define epicsExportSharedSymbols
2760+#include "epicsAtomic.h"
2761+
2762+// if the compiler is unable to inline then instantiate out-of-line
2763+#ifndef EPICS_ATOMIC_INLINE
2764+#define EPICS_ATOMIC_INLINE
2765+#include "epicsAtomic.h"
2766+#endif
2767+
2768
2769=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.h'
2770--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
2771+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000
2772@@ -0,0 +1,255 @@
2773+/*************************************************************************\
2774+* Copyright (c) 2011 LANS LLC, as Operator of
2775+* Los Alamos National Laboratory.
2776+* Copyright (c) 2011 UChicago Argonne, LLC, as Operator of
2777+* Argonne National Laboratory.
2778+* EPICS BASE is distributed subject to a Software License Agreement found
2779+* in file LICENSE that is included with this distribution.
2780+\*************************************************************************/
2781+
2782+/*
2783+ * Author Jeffrey O. Hill
2784+ * johill@lanl.gov
2785+ */
2786+
2787+#ifndef epicsAtomicOSD_h
2788+#define epicsAtomicOSD_h
2789+
2790+#if defined ( EPICS_ATOMIC_INLINE )
2791+
2792+#include "vxWorks.h" /* obtain the version of vxWorks */
2793+#include "epicsAssert.h"
2794+
2795+/*
2796+ * With vxWorks 6.6 and later we need to use vxAtomicLib
2797+ * to implement this functionality correctly on SMP systems
2798+ */
2799+#if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606
2800+
2801+#include <limits.h>
2802+#include <vxAtomicLib.h>
2803+
2804+#ifdef __cplusplus
2805+extern "C" {
2806+#endif /* __cplusplus */
2807+
2808+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
2809+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
2810+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
2811+{
2812+ VX_MEM_BARRIER_R ();
2813+}
2814+#endif
2815+
2816+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
2817+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
2818+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
2819+{
2820+ VX_MEM_BARRIER_W ();
2821+}
2822+#endif
2823+
2824+/*
2825+ * we make the probably correct guess that if ULONG_MAX
2826+ * is the same as UINT_MAX then sizeof ( atomic_t )
2827+ * will be the same as sizeof ( size_t )
2828+ *
2829+ * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and
2830+ * WRS doesnt not supply at this time the atomic interface
2831+ * for 8 byte integers that is needed - so that architecture
2832+ * receives the lock synchronized version
2833+ */
2834+#if ULONG_MAX == UINT_MAX
2835+
2836+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) );
2837+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) );
2838+
2839+
2840+#ifndef EPICS_ATOMIC_INCR_SIZET
2841+#define EPICS_ATOMIC_INCR_SIZET
2842+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
2843+{
2844+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2845+ const atomic_t oldVal = vxAtomicInc ( pTarg );
2846+ return 1 + ( size_t ) ( oldVal );
2847+}
2848+#endif
2849+
2850+#ifndef EPICS_ATOMIC_DECR_SIZET
2851+#define EPICS_ATOMIC_DECR_SIZET
2852+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
2853+{
2854+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2855+ const atomic_t oldVal = vxAtomicDec ( pTarg );
2856+ return ( ( size_t ) oldVal ) - 1u;
2857+}
2858+#endif
2859+
2860+#ifndef EPICS_ATOMIC_ADD_SIZET
2861+#define EPICS_ATOMIC_ADD_SIZET
2862+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
2863+{
2864+ /*
2865+ * vxAtomicLib doc indicates that vxAtomicAdd is
2866+ * implemented using signed arithmetic, but it
2867+ * does not change the end result because twos
2868+ * complement addition is used in either case
2869+ */
2870+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2871+ const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
2872+ return delta + ( size_t ) oldVal;
2873+}
2874+#endif
2875+
2876+#ifndef EPICS_ATOMIC_SUB_SIZET
2877+#define EPICS_ATOMIC_SUB_SIZET
2878+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
2879+{
2880+ /*
2881+ * vxAtomicLib doc indicates that vxAtomicSub is
2882+ * implemented using signed arithmetic, but it
2883+ * does not change the end result because twos
2884+ * complement subtraction is used in either case
2885+ */
2886+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2887+ const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta );
2888+ return ( ( size_t ) oldVal ) - delta;
2889+}
2890+#endif
2891+
2892+#ifndef EPICS_ATOMIC_CAS_SIZET
2893+#define EPICS_ATOMIC_CAS_SIZET
2894+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
2895+ size_t oldVal, size_t newVal )
2896+{
2897+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2898+ return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
2899+}
2900+#endif
2901+
2902+#ifndef EPICS_ATOMIC_CAS_PTRT
2903+#define EPICS_ATOMIC_CAS_PTRT
2904+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget,
2905+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
2906+{
2907+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2908+ return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
2909+}
2910+#endif
2911+
2912+#else /* ULONG_MAX == UINT_MAX */
2913+
2914+/*
2915+ * if its 64 bit SMP vxWorks and the compiler doesnt
2916+ * have an intrinsic then maybe there isnt any way to
2917+ * implement these without using a global lock because
2918+ * size_t is maybe bigger than atomic_t
2919+ *
2920+ * I dont yet have access to vxWorks manuals for
2921+ * 64 bit systems so this is still undecided, but is
2922+ * defaulting now to a global lock
2923+ */
2924+
2925+#endif /* ULONG_MAX == UINT_MAX */
2926+
2927+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) );
2928+
2929+#ifndef EPICS_ATOMIC_INCR_INTT
2930+#define EPICS_ATOMIC_INCR_INTT
2931+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
2932+{
2933+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2934+ const atomic_t oldVal = vxAtomicInc ( pTarg );
2935+ return 1 + ( int ) oldVal;
2936+}
2937+#endif
2938+
2939+#ifndef EPICS_ATOMIC_DECR_INTT
2940+#define EPICS_ATOMIC_DECR_INTT
2941+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
2942+{
2943+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2944+ const atomic_t oldVal = vxAtomicDec ( pTarg );
2945+ return ( ( int ) oldVal ) - 1;
2946+}
2947+#endif
2948+
2949+#ifndef EPICS_ATOMIC_ADD_INTT
2950+#define EPICS_ATOMIC_ADD_INTT
2951+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
2952+{
2953+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2954+ const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
2955+ return delta + ( int ) oldVal;
2956+}
2957+#endif
2958+
2959+#ifndef EPICS_ATOMIC_CAS_INTT
2960+#define EPICS_ATOMIC_CAS_INTT
2961+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
2962+ int oldVal, int newVal )
2963+{
2964+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
2965+ return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
2966+}
2967+#endif
2968+
2969+#ifdef __cplusplus
2970+} /* end of extern "C" */
2971+#endif /* __cplusplus */
2972+
2973+#else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
2974+
2975+#include "vxLib.h"
2976+#include "intLib.h"
2977+
2978+#ifdef __cplusplus
2979+extern "C" {
2980+#endif /* __cplusplus */
2981+
2982+#ifndef EPICS_ATOMIC_LOCK
2983+#define EPICS_ATOMIC_LOCK
2984+
2985+typedef struct EpicsAtomicLockKey { int m_key; } EpicsAtomicLockKey;
2986+
2987+EPICS_ATOMIC_INLINE void epicsAtomicLock ( EpicsAtomicLockKey * pKey )
2988+{
2989+ pKey->m_key = intLock ();
2990+}
2991+
2992+EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey )
2993+{
2994+ intUnlock ( pKey->m_key );
2995+}
2996+#endif
2997+
2998+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
2999+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
3000+/*
3001+ * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
3002+ * (we are not protecting against multiple access to memory mapped IO)
3003+ */
3004+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {}
3005+#endif
3006+
3007+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
3008+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
3009+/*
3010+ * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
3011+ * (we are not protecting against multiple access to memory mapped IO)
3012+ */
3013+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {}
3014+#endif
3015+
3016+#ifdef __cplusplus
3017+} /* end of extern "C" */
3018+#endif /* __cplusplus */
3019+
3020+#endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
3021+
3022+#include "epicsAtomicDefault.h"
3023+
3024+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
3025+
3026+#endif /* epicsAtomicOSD_h */
3027+
3028
3029=== modified file 'src/libCom/osi/os/vxWorks/osdThread.c'
3030--- src/libCom/osi/os/vxWorks/osdThread.c 2010-08-11 15:45:17 +0000
3031+++ src/libCom/osi/os/vxWorks/osdThread.c 2011-08-31 22:29:24 +0000
3032@@ -53,7 +53,6 @@
3033 static void **papTSD = 0;
3034 static int nepicsThreadPrivate = 0;
3035
3036-static SEM_ID epicsThreadOnceMutex = 0;
3037
3038
3039 /* Just map osi 0 to 99 into vx 100 to 199 */
3040 /* remember that for vxWorks lower number means higher priority */
3041@@ -83,19 +82,6 @@
3042 }
3043 }
3044
3045-static void epicsThreadInit(void)
3046-{
3047- static int lock = 0;
3048-
3049- while(!vxTas(&lock)) taskDelay(1);
3050- if(epicsThreadOnceMutex==0) {
3051- epicsThreadOnceMutex = semMCreate(
3052- SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
3053- assert(epicsThreadOnceMutex);
3054- }
3055- lock = 0;
3056-}
3057-
3058 unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
3059 {
3060
3061@@ -112,43 +98,6 @@
3062 return stackSizeTable[stackSizeClass];
3063 }
3064
3065-struct epicsThreadOSD {};
3066- /* Strictly speaking this should be a WIND_TCB, but we only need it to
3067- * be able to create an epicsThreadId that is guaranteed never to be
3068- * the same as any current TID, and since TIDs are pointers this works.
3069- */
3070-
3071-void epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
3072-{
3073- static struct epicsThreadOSD threadOnceComplete;
3074- #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
3075- int result;
3076-
3077- epicsThreadInit();
3078- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
3079- assert(result == OK);
3080- if (*id != EPICS_THREAD_ONCE_DONE) {
3081- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
3082- *id = epicsThreadGetIdSelf(); /* mark active */
3083- semGive(epicsThreadOnceMutex);
3084- func(arg);
3085- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
3086- assert(result == OK);
3087- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
3088- } else if (*id == epicsThreadGetIdSelf()) {
3089- semGive(epicsThreadOnceMutex);
3090- cantProceed("Recursive epicsThreadOnce() initialization\n");
3091- } else
3092- while (*id != EPICS_THREAD_ONCE_DONE) {
3093- /* Another thread is in the above func(arg) call. */
3094- semGive(epicsThreadOnceMutex);
3095- epicsThreadSleep(epicsThreadSleepQuantum());
3096- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
3097- assert(result == OK);
3098- }
3099- }
3100- semGive(epicsThreadOnceMutex);
3101-}
3102
3103
3104 static void createFunction(EPICSTHREADFUNC func, void *parm)
3105 {
3106@@ -173,7 +122,6 @@
3107 EPICSTHREADFUNC funptr,void *parm)
3108 {
3109 int tid;
3110- if(epicsThreadOnceMutex==0) epicsThreadInit();
3111 if(stackSize<100) {
3112 errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);
3113 return(0);
3114@@ -343,7 +291,6 @@
3115 static int lock = 0;
3116 epicsThreadPrivateId id;
3117
3118- epicsThreadInit();
3119 /*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/
3120 while(!vxTas(&lock)) taskDelay(1);
3121 id = (epicsThreadPrivateId)++nepicsThreadPrivate;
3122
3123=== modified file 'src/libCom/test/Makefile'
3124--- src/libCom/test/Makefile 2011-08-30 23:09:11 +0000
3125+++ src/libCom/test/Makefile 2011-08-31 22:29:24 +0000
3126@@ -108,6 +108,11 @@
3127 testHarness_SRCS += epicsMutexTest.cpp
3128 TESTS += epicsMutexTest
3129
3130+TESTPROD_HOST += epicsAtomicTest
3131+epicsAtomicTest_SRCS += epicsAtomicTest.c
3132+testHarness_SRCS += epicsAtomicTest.c
3133+TESTS += epicsAtomicTest
3134+
3135 TESTPROD_HOST += epicsExceptionTest
3136 epicsExceptionTest_SRCS += epicsExceptionTest.cpp
3137 testHarness_SRCS += epicsExceptionTest.cpp
3138@@ -178,6 +183,10 @@
3139 fdmgrTest_LIBS += ca
3140 # FIXME: program never exits.
3141
3142+TESTPROD_HOST += epicsAtomicPerform
3143+epicsAtomicPerform_SRCS += epicsAtomicPerform.cpp
3144+testHarness_SRCS += epicsAtomicPerform.cpp
3145+
3146 TESTPROD_HOST += cvtFastPerform
3147 cvtFastPerform_SRCS += cvtFastPerform.cpp
3148 testHarness_SRCS += cvtFastPerform.cpp
3149
3150=== added file 'src/libCom/test/epicsAtomicPerform.cpp'
3151--- src/libCom/test/epicsAtomicPerform.cpp 1970-01-01 00:00:00 +0000
3152+++ src/libCom/test/epicsAtomicPerform.cpp 2011-08-31 22:29:24 +0000
3153@@ -0,0 +1,506 @@
3154+
3155+#include <cstdlib>
3156+#include <cstdio>
3157+#include <cassert>
3158+#include <typeinfo>
3159+
3160+#include "epicsInterrupt.h"
3161+#include "epicsAtomic.h"
3162+#include "epicsTime.h"
3163+#include "epicsUnitTest.h"
3164+#include "testMain.h"
3165+
3166+using std :: size_t;
3167+using namespace epics;
3168+using namespace atomic;
3169+
3170+class RefCtr {
3171+public:
3172+ RefCtr ();
3173+ ~RefCtr ();
3174+ void reference ();
3175+ void unreference ();
3176+private:
3177+ size_t m_cnt;
3178+};
3179+
3180+class Ownership {
3181+public:
3182+ Ownership ();
3183+ Ownership ( RefCtr & refCtr );
3184+ Ownership ( const Ownership & );
3185+ ~Ownership ();
3186+ Ownership & operator = ( const Ownership & );
3187+private:
3188+ RefCtr * _pRefCtr;
3189+ static RefCtr m_noOwnership;
3190+};
3191+
3192+inline RefCtr :: RefCtr ()
3193+{
3194+ epicsAtomicSetSizeT ( & m_cnt, 0 );
3195+}
3196+
3197+inline RefCtr :: ~RefCtr ()
3198+{
3199+ unsigned cnt = epicsAtomicGetSizeT ( & m_cnt );
3200+ assert ( cnt == 0u );
3201+}
3202+
3203+inline void RefCtr :: reference ()
3204+{
3205+ epicsAtomicIncrSizeT ( & m_cnt );
3206+}
3207+
3208+inline void RefCtr :: unreference ()
3209+{
3210+ epicsAtomicDecrSizeT ( & m_cnt );
3211+}
3212+
3213+RefCtr Ownership :: m_noOwnership;
3214+
3215+inline Ownership :: Ownership () :
3216+ _pRefCtr ( & m_noOwnership )
3217+{
3218+ m_noOwnership.reference ();
3219+}
3220+
3221+inline Ownership :: Ownership ( RefCtr & refCtr ) :
3222+ _pRefCtr ( & refCtr )
3223+{
3224+ refCtr.reference ();
3225+}
3226+
3227+inline Ownership :: Ownership ( const Ownership & ownership ) :
3228+ _pRefCtr ( ownership._pRefCtr )
3229+{
3230+ _pRefCtr->reference ();
3231+}
3232+
3233+inline Ownership :: ~Ownership ()
3234+{
3235+ _pRefCtr->unreference ();
3236+}
3237+
3238+inline Ownership & Ownership ::
3239+ operator = ( const Ownership & ownership )
3240+{
3241+ RefCtr * const pOldRefCtr = _pRefCtr;
3242+ _pRefCtr = ownership._pRefCtr;
3243+ _pRefCtr->reference ();
3244+ pOldRefCtr->unreference ();
3245+ return *this;
3246+}
3247+
3248+inline Ownership retOwnership ( const Ownership & ownership )
3249+{
3250+ return Ownership ( ownership );
3251+}
3252+
3253+inline Ownership recurRetOwner10 ( const Ownership & ownershipIn )
3254+{
3255+ Ownership ownership =
3256+ retOwnership (
3257+ retOwnership (
3258+ retOwnership (
3259+ retOwnership (
3260+ retOwnership ( ownershipIn ) ) ) ) );
3261+ return retOwnership (
3262+ retOwnership (
3263+ retOwnership (
3264+ retOwnership (
3265+ retOwnership ( ownership ) ) ) ) );
3266+}
3267+
3268+inline Ownership recurRetOwner100 ( const Ownership & ownershipIn )
3269+{
3270+ Ownership ownership =
3271+ recurRetOwner10 (
3272+ recurRetOwner10 (
3273+ recurRetOwner10 (
3274+ recurRetOwner10 (
3275+ recurRetOwner10 ( ownershipIn ) ) ) ) );
3276+ return recurRetOwner10 (
3277+ recurRetOwner10 (
3278+ recurRetOwner10 (
3279+ recurRetOwner10 (
3280+ recurRetOwner10 ( ownership ) ) ) ) );
3281+}
3282+
3283+inline Ownership recurRetOwner1000 ( const Ownership & ownershipIn )
3284+{
3285+ Ownership ownership =
3286+ recurRetOwner100 (
3287+ recurRetOwner100 (
3288+ recurRetOwner100 (
3289+ recurRetOwner100 (
3290+ recurRetOwner100 ( ownershipIn ) ) ) ) );
3291+ return recurRetOwner100 (
3292+ recurRetOwner100 (
3293+ recurRetOwner100 (
3294+ recurRetOwner100 (
3295+ recurRetOwner100 ( ownership ) ) ) ) );
3296+}
3297+
3298+inline void passRefOwnership ( const Ownership & ownershipIn, Ownership & ownershipOut )
3299+{
3300+ ownershipOut = ownershipIn;
3301+}
3302+
3303+inline void passRefOwnership10 ( const Ownership & ownershipIn, Ownership & ownershipOut )
3304+{
3305+ Ownership ownershipTmp0;
3306+ passRefOwnership ( ownershipIn, ownershipTmp0 );
3307+ Ownership ownershipTmp1;
3308+ passRefOwnership ( ownershipTmp0, ownershipTmp1 );
3309+ Ownership ownershipTmp2;
3310+ passRefOwnership ( ownershipTmp1, ownershipTmp2 );
3311+ Ownership ownershipTmp3;
3312+ passRefOwnership ( ownershipTmp2, ownershipTmp3 );
3313+ Ownership ownershipTmp4;
3314+ passRefOwnership ( ownershipTmp3, ownershipTmp4 );
3315+ Ownership ownershipTmp5;
3316+ passRefOwnership ( ownershipTmp4, ownershipTmp5 );
3317+ Ownership ownershipTmp6;
3318+ passRefOwnership ( ownershipTmp5, ownershipTmp6 );
3319+ Ownership ownershipTmp7;
3320+ passRefOwnership ( ownershipTmp6, ownershipTmp7 );
3321+ Ownership ownershipTmp8;
3322+ passRefOwnership ( ownershipTmp7, ownershipTmp8 );
3323+ passRefOwnership ( ownershipTmp8, ownershipOut );
3324+}
3325+
3326+inline void passRefOwnership100 ( const Ownership & ownershipIn, Ownership & ownershipOut )
3327+{
3328+ Ownership ownershipTmp0;
3329+ passRefOwnership10 ( ownershipIn, ownershipTmp0 );
3330+ Ownership ownershipTmp1;
3331+ passRefOwnership10 ( ownershipTmp0, ownershipTmp1 );
3332+ Ownership ownershipTmp2;
3333+ passRefOwnership10 ( ownershipTmp1, ownershipTmp2 );
3334+ Ownership ownershipTmp3;
3335+ passRefOwnership10 ( ownershipTmp2, ownershipTmp3 );
3336+ Ownership ownershipTmp4;
3337+ passRefOwnership10 ( ownershipTmp3, ownershipTmp4 );
3338+ Ownership ownershipTmp5;
3339+ passRefOwnership10 ( ownershipTmp4, ownershipTmp5 );
3340+ Ownership ownershipTmp6;
3341+ passRefOwnership10 ( ownershipTmp5, ownershipTmp6 );
3342+ Ownership ownershipTmp7;
3343+ passRefOwnership10 ( ownershipTmp6, ownershipTmp7 );
3344+ Ownership ownershipTmp8;
3345+ passRefOwnership10 ( ownershipTmp7, ownershipTmp8 );
3346+ passRefOwnership10 ( ownershipTmp8, ownershipOut );
3347+}
3348+
3349+inline void passRefOwnership1000 ( const Ownership & ownershipIn, Ownership & ownershipOut )
3350+{
3351+ Ownership ownershipTmp0;
3352+ passRefOwnership100 ( ownershipIn, ownershipTmp0 );
3353+ Ownership ownershipTmp1;
3354+ passRefOwnership100 ( ownershipTmp0, ownershipTmp1 );
3355+ Ownership ownershipTmp2;
3356+ passRefOwnership100 ( ownershipTmp1, ownershipTmp2 );
3357+ Ownership ownershipTmp3;
3358+ passRefOwnership100 ( ownershipTmp2, ownershipTmp3 );
3359+ Ownership ownershipTmp4;
3360+ passRefOwnership100 ( ownershipTmp3, ownershipTmp4 );
3361+ Ownership ownershipTmp5;
3362+ passRefOwnership100 ( ownershipTmp4, ownershipTmp5 );
3363+ Ownership ownershipTmp6;
3364+ passRefOwnership100 ( ownershipTmp5, ownershipTmp6 );
3365+ Ownership ownershipTmp7;
3366+ passRefOwnership100 ( ownershipTmp6, ownershipTmp7 );
3367+ Ownership ownershipTmp8;
3368+ passRefOwnership100 ( ownershipTmp7, ownershipTmp8 );
3369+ passRefOwnership100 ( ownershipTmp8, ownershipOut );
3370+}
3371+
3372+time_t extTime = 0;
3373+
3374+template < class T >
3375+class OrdinaryIncr {
3376+public:
3377+ OrdinaryIncr () : m_target ( 0 ) {}
3378+ void run ();
3379+ void diagnostic ( double delay );
3380+private:
3381+ T m_target;
3382+};
3383+
3384+// tests the time it takes to perform a call to an external
3385+// function and also increment an integer word. The
3386+// epicsInterruptIsInterruptContext function is an
3387+// out-of-line function implemented in a sharable library
3388+// so hopefully it wont be optimized away.
3389+template < class T >
3390+inline void OrdinaryIncr < T > :: run ()
3391+{
3392+ m_target += epicsInterruptIsInterruptContext ();
3393+ m_target += epicsInterruptIsInterruptContext ();
3394+ m_target += epicsInterruptIsInterruptContext ();
3395+ m_target += epicsInterruptIsInterruptContext ();
3396+ m_target += epicsInterruptIsInterruptContext ();
3397+ m_target += epicsInterruptIsInterruptContext ();
3398+ m_target += epicsInterruptIsInterruptContext ();
3399+ m_target += epicsInterruptIsInterruptContext ();
3400+ m_target += epicsInterruptIsInterruptContext ();
3401+ m_target += epicsInterruptIsInterruptContext ();
3402+}
3403+
3404+template < class T >
3405+void OrdinaryIncr < T > :: diagnostic ( double delay )
3406+{
3407+ delay /= 10.0;
3408+ delay *= 1e6;
3409+ const char * const pName = typeid ( T ) . name ();
3410+ testDiag ( "raw incr of \"%s\" and a NOOP function call takes %f microseconds",
3411+ pName, delay );
3412+}
3413+
3414+template < class T >
3415+class AtomicIncr {
3416+public:
3417+ AtomicIncr () : m_target ( 0 ) {}
3418+ void run ();
3419+ void diagnostic ( double delay );
3420+private:
3421+ T m_target;
3422+};
3423+
3424+template < class T >
3425+inline void AtomicIncr < T > :: run ()
3426+{
3427+ increment ( m_target );
3428+ increment ( m_target );
3429+ increment ( m_target );
3430+ increment ( m_target );
3431+ increment ( m_target );
3432+ increment ( m_target );
3433+ increment ( m_target );
3434+ increment ( m_target );
3435+ increment ( m_target );
3436+ increment ( m_target );
3437+}
3438+
3439+template < class T >
3440+void AtomicIncr < T > :: diagnostic ( double delay )
3441+{
3442+ delay /= 10.0;
3443+ delay *= 1e6;
3444+ const char * const pName = typeid ( T ) . name ();
3445+ testDiag ( "epicsAtomicIncr \"%s\" takes %f microseconds",
3446+ pName, delay );
3447+}
3448+
3449+template < class T > T trueValue ();
3450+template < class T > T falseValue ();
3451+
3452+// int
3453+template <>
3454+inline int trueValue < int > () { return 1; }
3455+
3456+template <>
3457+inline int falseValue < int > () { return 0; }
3458+
3459+// size_t
3460+template <>
3461+inline size_t trueValue < size_t > () { return 1u; }
3462+
3463+template <>
3464+inline size_t falseValue < size_t > () { return 0u; }
3465+
3466+// EpicsAtomicPtrT
3467+template <>
3468+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
3469+{ static char c; return & c; }
3470+
3471+template <>
3472+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
3473+{ return 0u; }
3474+
3475+template < class T >
3476+class AtomicCmpAndSwap {
3477+public:
3478+ AtomicCmpAndSwap () : m_target ( 0 ) {}
3479+ void run ();
3480+ void diagnostic ( double delay );
3481+private:
3482+ T m_target;
3483+};
3484+
3485+template < class T >
3486+inline void AtomicCmpAndSwap < T > :: run ()
3487+{
3488+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3489+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3490+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3491+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3492+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3493+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3494+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3495+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3496+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3497+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
3498+}
3499+
3500+template < class T >
3501+void AtomicCmpAndSwap < T > :: diagnostic ( double delay )
3502+{
3503+ delay /= 10.0;
3504+ delay *= 1e6;
3505+ const char * const pName = typeid ( T ) . name ();
3506+ testDiag ( "epicsAtomicCmpAndSwap of \"%s\" takes %f microseconds",
3507+ pName, delay );
3508+}
3509+
3510+template < class T >
3511+class AtomicSet {
3512+public:
3513+ AtomicSet () : m_target ( 0 ) {}
3514+ void run ();
3515+ void diagnostic ( double delay );
3516+private:
3517+ T m_target;
3518+};
3519+
3520+template < class T >
3521+inline void AtomicSet < T > :: run ()
3522+{
3523+ set ( m_target, 0 );
3524+ set ( m_target, 0 );
3525+ set ( m_target, 0 );
3526+ set ( m_target, 0 );
3527+ set ( m_target, 0 );
3528+ set ( m_target, 0 );
3529+ set ( m_target, 0 );
3530+ set ( m_target, 0 );
3531+ set ( m_target, 0 );
3532+ set ( m_target, 0 );
3533+}
3534+
3535+template < class T >
3536+void AtomicSet < T > :: diagnostic ( double delay )
3537+{
3538+ delay /= 10.0;
3539+ delay *= 1e6;
3540+ const char * const pName = typeid ( T ) . name ();
3541+ testDiag ( "epicsAtomicSet of \"%s\" takes %f microseconds",
3542+ pName, delay );
3543+}
3544+
3545+static const unsigned N = 10000;
3546+
3547+void recursiveOwnershipRetPerformance ()
3548+{
3549+ RefCtr refCtr;
3550+ epicsTime begin = epicsTime::getCurrent ();
3551+ for ( size_t i = 0; i < N; i++ ) {
3552+ Ownership ownership ( refCtr );
3553+ recurRetOwner1000 ( ownership );
3554+ }
3555+ double delay = epicsTime::getCurrent () - begin;
3556+ delay /= N * 1000u; // convert to delay per call
3557+ delay *= 1e6; // convert to micro seconds
3558+ testDiag ( "retOwnership() takes %f microseconds", delay );
3559+}
3560+
3561+void ownershipPassRefPerformance ()
3562+{
3563+ RefCtr refCtr;
3564+ epicsTime begin = epicsTime::getCurrent ();
3565+ for ( size_t i = 0; i < N; i++ ) {
3566+ Ownership ownershipSrc ( refCtr );
3567+ Ownership ownershipDest;
3568+ passRefOwnership1000 ( ownershipSrc, ownershipDest );
3569+ }
3570+ double delay = epicsTime::getCurrent () - begin;
3571+ delay /= N * 1000u; // convert to delay per call
3572+ delay *= 1e6; // convert to micro seconds
3573+ testDiag ( "passRefOwnership() takes %f microseconds", delay );
3574+}
3575+
3576+template < class T >
3577+class Ten
3578+{
3579+public:
3580+ void run ();
3581+ void diagnostic ( double delay );
3582+ typedef Ten < Ten < T > > Hundred;
3583+ typedef Ten < Hundred > Thousand;
3584+private:
3585+ T m_target;
3586+};
3587+
3588+template < class T >
3589+inline void Ten < T > :: run ()
3590+{
3591+ m_target.run ();
3592+ m_target.run ();
3593+ m_target.run ();
3594+ m_target.run ();
3595+ m_target.run ();
3596+ m_target.run ();
3597+ m_target.run ();
3598+ m_target.run ();
3599+ m_target.run ();
3600+ m_target.run ();
3601+}
3602+
3603+template < class T >
3604+void Ten < T > :: diagnostic ( double delay )
3605+{
3606+ m_target.diagnostic ( delay / 10.0 );
3607+}
3608+
3609+template < class T >
3610+void measurePerformance ()
3611+{
3612+ epicsTime begin = epicsTime::getCurrent ();
3613+ T target;
3614+ for ( size_t i = 0; i < N; i++ ) {
3615+ target.run ();
3616+ target.run ();
3617+ target.run ();
3618+ target.run ();
3619+ target.run ();
3620+ target.run ();
3621+ target.run ();
3622+ target.run ();
3623+ target.run ();
3624+ target.run ();
3625+ }
3626+ double delay = epicsTime::getCurrent () - begin;
3627+ delay /= ( N * 10u ); // convert to delay per call
3628+ target.diagnostic ( delay );
3629+}
3630+
3631+template < class T >
3632+void measure ()
3633+{
3634+ measurePerformance < typename Ten < T > :: Hundred > ();
3635+}
3636+
3637+MAIN ( epicsAtomicPerform )
3638+{
3639+ testPlan ( 0 );
3640+ //
3641+ // The tests running here are measuring fast
3642+ // functions so they tend to be impacted
3643+ // by where the cache lines are wrt to the
3644+ // virtual pages perhap
3645+ //
3646+ measure < AtomicSet < int > > ();
3647+ measure < AtomicSet < size_t > > ();
3648+ measure < AtomicSet < void * > > ();
3649+ measure < OrdinaryIncr < int > > ();
3650+ measure < OrdinaryIncr < size_t > > ();
3651+ measure < AtomicIncr < int > > ();
3652+ measure < AtomicIncr < size_t > > ();
3653+ measure < AtomicCmpAndSwap < int > > ();
3654+ measure < AtomicCmpAndSwap < size_t > > ();
3655+ measure < AtomicCmpAndSwap < void * > > ();
3656+ recursiveOwnershipRetPerformance ();
3657+ ownershipPassRefPerformance ();
3658+ return testDone();
3659+}
3660
3661=== added file 'src/libCom/test/epicsAtomicTest.cpp'
3662--- src/libCom/test/epicsAtomicTest.cpp 1970-01-01 00:00:00 +0000
3663+++ src/libCom/test/epicsAtomicTest.cpp 2011-08-31 22:29:24 +0000
3664@@ -0,0 +1,238 @@
3665+
3666+#include <stdlib.h>
3667+#include <assert.h>
3668+
3669+#include "epicsAtomic.h"
3670+#include "epicsTime.h"
3671+#include "epicsThread.h"
3672+#include "epicsUnitTest.h"
3673+#include "testMain.h"
3674+
3675+using namespace epics;
3676+using namespace atomic;
3677+
3678+template < class T >
3679+struct TestDataIncrDecr {
3680+ T m_testValue;
3681+ size_t m_testIterations;
3682+};
3683+
3684+template < class T >
3685+struct TestDataAddSub {
3686+ T m_testValue;
3687+ size_t m_testIterations;
3688+ static const T delta = 17;
3689+};
3690+
3691+template < class T >
3692+static void incr ( void *arg )
3693+{
3694+ TestDataIncrDecr < T > * const pTestData =
3695+ reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
3696+ increment ( pTestData->m_testValue );
3697+ increment ( pTestData->m_testIterations );
3698+}
3699+
3700+template < class T >
3701+static void decr ( void *arg )
3702+{
3703+ TestDataIncrDecr < T > * const pTestData =
3704+ reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
3705+ decrement ( pTestData->m_testValue );
3706+ increment ( pTestData->m_testIterations );
3707+}
3708+
3709+
3710+template < class T >
3711+static void add ( void *arg )
3712+{
3713+ TestDataAddSub < T > * const pTestData =
3714+ reinterpret_cast < TestDataAddSub < T > * > ( arg );
3715+ add ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
3716+ increment ( pTestData->m_testIterations );
3717+}
3718+
3719+template < class T >
3720+static void sub ( void *arg )
3721+{
3722+ TestDataAddSub < T > * const pTestData =
3723+ reinterpret_cast < TestDataAddSub < T > * > ( arg );
3724+ subtract ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
3725+ increment ( pTestData->m_testIterations );
3726+}
3727+
3728+template < class T >
3729+struct TestDataCAS {
3730+ T m_testValue;
3731+ size_t m_testIterationsSet;
3732+ size_t m_testIterationsNotSet;
3733+};
3734+
3735+int isModulo ( size_t N, size_t n )
3736+{
3737+ return ( n % N ) == 0u;
3738+}
3739+
3740+template < class T >
3741+static T trueValue ();
3742+template < class T >
3743+static T falseValue ();
3744+
3745+// int
3746+template <>
3747+inline int trueValue < int > () { return 1; }
3748+
3749+template <>
3750+inline int falseValue < int > () { return 0; }
3751+
3752+// size_t
3753+template <>
3754+inline size_t trueValue < size_t > () { return 1u; }
3755+
3756+template <>
3757+inline size_t falseValue < size_t > () { return 0u; }
3758+
3759+// EpicsAtomicPtrT
3760+template <>
3761+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
3762+{ static char c; return & c; }
3763+
3764+template <>
3765+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
3766+{ return 0u; }
3767+
3768+template < class T >
3769+static void cas ( void *arg )
3770+{
3771+ TestDataCAS < T > * const pTestData =
3772+ reinterpret_cast < TestDataCAS < T > * > ( arg );
3773+ /*
3774+ * intentionally waste cpu and maximize
3775+ * contention for the shared data
3776+ */
3777+ increment ( pTestData->m_testIterationsNotSet );
3778+ while ( ! compareAndSwap ( pTestData->m_testValue,
3779+ falseValue < T > (),
3780+ trueValue < T > () ) ) {
3781+ }
3782+ decrement ( pTestData->m_testIterationsNotSet );
3783+ set ( pTestData->m_testValue, falseValue < T > () );
3784+ increment ( pTestData->m_testIterationsSet );
3785+}
3786+
3787+template < class T >
3788+void testIncrDecr ()
3789+{
3790+ static const size_t N = 100;
3791+ static const T NT = static_cast < T > ( N );
3792+
3793+ const unsigned int stackSize =
3794+ epicsThreadGetStackSize ( epicsThreadStackSmall );
3795+
3796+ TestDataIncrDecr < T > testData = { 0, N };
3797+ set ( testData.m_testValue, NT );
3798+ testOk ( get ( testData.m_testValue ) == NT,
3799+ "set/get %u", testData.m_testValue );
3800+ set ( testData.m_testIterations, 0u );
3801+ testOk ( get ( testData.m_testIterations ) == 0u,
3802+ "set/get %u", testData.m_testIterations );
3803+ for ( size_t i = 0u; i < N; i++ ) {
3804+ epicsThreadCreate ( "incr",
3805+ 50, stackSize, incr < T >, & testData );
3806+ epicsThreadCreate ( "decr",
3807+ 50, stackSize, decr < T >, & testData );
3808+ }
3809+ while ( testData.m_testIterations < 2 * N ) {
3810+ epicsThreadSleep ( 0.01 );
3811+ }
3812+ testOk ( get ( testData.m_testIterations ) == 2 * N,
3813+ "incr/decr iterations %u",
3814+ testData.m_testIterations );
3815+ testOk ( get ( testData.m_testValue ) == NT,
3816+ "incr/decr final value %u",
3817+ testData.m_testValue );
3818+}
3819+
3820+template < class T >
3821+void testAddSub ()
3822+{
3823+ static const size_t N = 100;
3824+ static const T NDT = TestDataAddSub < T > :: delta *
3825+ static_cast < T > ( N );
3826+
3827+ const unsigned int stackSize =
3828+ epicsThreadGetStackSize ( epicsThreadStackSmall );
3829+
3830+ TestDataIncrDecr < T > testData = { 0, N };
3831+ set ( testData.m_testValue, NDT );
3832+ testOk ( get ( testData.m_testValue ) == NDT,
3833+ "set/get %u", testData.m_testValue );
3834+ set ( testData.m_testIterations, 0u );
3835+ testOk ( get ( testData.m_testIterations ) == 0u,
3836+ "set/get %u", testData.m_testIterations );
3837+ for ( size_t i = 0u; i < N; i++ ) {
3838+ epicsThreadCreate ( "add",
3839+ 50, stackSize, add < T >, & testData );
3840+ epicsThreadCreate ( "sub",
3841+ 50, stackSize, sub < T >, & testData );
3842+ }
3843+ while ( testData.m_testIterations < 2 * N ) {
3844+ epicsThreadSleep ( 0.01 );
3845+ }
3846+ testOk ( get ( testData.m_testIterations ) == 2 * N,
3847+ "add/sub iterations %u",
3848+ testData.m_testIterations );
3849+ testOk ( get ( testData.m_testValue ) == NDT,
3850+ "add/sub final value %u",
3851+ testData.m_testValue );
3852+}
3853+
3854+template < class T >
3855+void testCAS ()
3856+{
3857+ static const size_t N = 10;
3858+
3859+ const unsigned int stackSize =
3860+ epicsThreadGetStackSize ( epicsThreadStackSmall );
3861+
3862+ TestDataCAS < T > testData = { 0, N, N };
3863+ set ( testData.m_testIterationsSet, 0 );
3864+ testOk ( get ( testData.m_testIterationsSet ) == 0u,
3865+ "set/get %u", testData.m_testIterationsSet );
3866+ set ( testData.m_testIterationsNotSet, 0 );
3867+ testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
3868+ "set/get %u", testData.m_testIterationsNotSet );
3869+ set ( testData.m_testValue, trueValue < T > () );
3870+ testOk ( get ( testData.m_testValue ) == trueValue < T > (),
3871+ "set/get a true value" );
3872+ for ( size_t i = 0u; i < N; i++ ) {
3873+ epicsThreadCreate ( "tns",
3874+ 50, stackSize, cas < T >, & testData );
3875+ }
3876+ set ( testData.m_testValue, falseValue < T > () );
3877+ while ( testData.m_testIterationsSet < N ) {
3878+ epicsThreadSleep ( 0.01 );
3879+ }
3880+ testOk ( get ( testData.m_testIterationsSet ) == N,
3881+ "test and set iterations %u",
3882+ testData.m_testIterationsSet );
3883+ testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
3884+ "test and set not-set tracking = %u",
3885+ testData.m_testIterationsNotSet );
3886+}
3887+
3888+MAIN ( epicsAtomicTest )
3889+{
3890+
3891+ testPlan ( 31 );
3892+
3893+ testIncrDecr < int > ();
3894+ testIncrDecr < size_t > ();
3895+ testAddSub < int > ();
3896+ testAddSub < size_t > ();
3897+ testCAS < int > ();
3898+ testCAS < size_t > ();
3899+ testCAS < EpicsAtomicPtrT > ();
3900+
3901+ return testDone ();
3902+}

Subscribers

People subscribed via source and target branches